2019
John McFarlane
johnmcfarlane.github.io/slides/2019-accu
Software Engineer, Jaguar Land Rover, Shannon, Ireland
BSI, MISRA C++, WG21 (SG14 & SG6)
BBC BASIC, 6502, C, 80286/7, C++, Python
Games, Fractals, AI, Simulation, APIs, Numerics, CI
…0.0…^
Question:
how many digits in uint8_t?
Answer:
…00000000000101010
=
32 + 8 + 2
…00000000000101010
=
42
000000…
…00000000000000101010.00000000000000…
…00000000000000101010.00000000000000…
…00000000000000101010.00000000000000…
Question:
how many digits in uint8_t?
Answer:
∞+8+∞ = 2∞+8
Question:
how many sign bits in int8_t?
Answer:
∞+1
…1111111111111010110
=
-128+64+16+4+2
…1111111111111010110
=
-420000000000…
…1111111111111010110.000000000000000…
…1111111111111010110.000000000000000…
…1111111111111010110.000000000000000…
…1111111111111010110.000000000000000…
Question:
how many sign bits in int8_t?
Answer:
∞+1
π?
…0000011.001001000011111101101010100…
…0000011.001001000011111101101010100…
…0000011.001001000011111101101010100…
π?
float?
…0000011.001001000011111101101010100…
…0000011.001001000011111101101010100…
…0000011.001001000011111101101010100…
float?
Answer:
3
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
…00000000000101010.000000…
✓
Answer:
3
git clone https://github.com/johnmcfarlane/cnl.git
c++ -std=c++17 -Wall -Wextra -Werror -Wpedantic slide_code.cpp
#include <cnl/all.h>
#include <cnl/_impl/type_traits/identical.h>
using namespace cnl;
using namespace cnl::literals;
using namespace cnl::math;
using namespace std;
<O,0>-
Question:
how do you write 'forty-two'?
Answer:
scaled_integer{42_c}
template<int Exponent=0, int Radix=2>
class power;
template<typename Rep=int, typename Scale=power<>>
class scaled_integer;
template<typename Rep, int Exponent, int Radix>
class scaled_integer<Rep, power<Exponent, Radix>> {
// ...
private:
Rep n;
};
value = n×RadixExponent
…00000000000101010.000000…
✓
int8_t{42}
scaled_integer<int8_t, power<1>>{42}
scaled_integer<int, power<1>>{42}
scaled_integer<int8_t, power<1>>
a(float value)
{
return value;
}a(float):
push {r4, lr}
mov r1, #1056964608
bl __aeabi_fmul
bl __aeabi_f2iz
pop {r4, pc}int8_t b(float value)
{
return value * .5f;
}b(float):
push {r4, lr}
mov r1, #1056964608
bl __aeabi_fmul
bl __aeabi_f2iz
lsl r0, r0, #24
asr r0, r0, #24
pop {r4, pc}scaled_integer<int , power<1>>
a(float value)
{
return value;
}a(float):
push {r4, lr}
mov r1, #1056964608
bl __aeabi_fmul
bl __aeabi_f2iz
pop {r4, pc}int b(float value)
{
return value * .5f;
}b(float):
push {r4, lr}
mov r1, #1056964608
bl __aeabi_fmul
bl __aeabi_f2iz
pop {r4, pc}…00000000000101010.000000…
✓
int8_t{42}
scaled_integer<int8_t, power<1>>{42}
scaled_integer<int, power<1>>{42}
namespace cnl::literals {
template<char ... Chars>
constexpr auto operator ""_c() noexcept;
}
// constant<42>
auto forty_two = 42_c;
// scaled_integer<int, power<1>>{42}
auto a = scaled_integer{forty_two};
godbolt.org/z/x6PbFK
int8_t{42}

scaled_integer<int8_t, power<1>>{42}

scaled_integer<int, power<1>>{42}

scaled_integer{42_c}

Answer:
scaled_integer{42_c}
Question:
how many bits in a megabyte?
Answer:
1M
1000×1000
1111101000×1111101000
=11110100001001000000
1M
1000×1000
1111101000×1111101000
=11110100001001000000
1M
1000×1000
1111101000×1111101000
=11110100001001000000
1M
1000×1000
1111101000×1111101000
=11110100001001000000
// scaled_integer<int, power<3>>{1000}
auto k = scaled_integer{1000_c};
// scaled_integer<int, power<6>>{1000000}
auto m = k*k;
godbolt.org/z/xWwhNz
1M
1000×1000
=1000000
1M
1000×1000
=1000000
1M
1000×1000
=1000000
// scaled_integer<int, power<3, 10>>{1000}
auto k = scaled_integer<int, power<3, 10>>{1000};
// scaled_integer<int, power<6, 10>>{1000000}
auto m = k*k;
godbolt.org/z/zzg7BC
Question:
how far does the queen really move in Chess?
1.414213562373095048801688724209698078569671875……001.01101010000010011110011001100111111100111011…sqrt2_v<scaled_integer<int, power<-30>>>(5.8284270763397216796875)
wandbox.org/permlink/GBY1czkvkZ8jytlSusing Distance = scaled_integer<int, power<-24>>;
Distance queens_distance(int columns, int rows)
{
columns = std::abs(columns);
rows = std::abs(rows);
int diagonal = std::min(columns, rows);
int axial = std::max(columns, rows)-diagonal;
return sqrt2_v<Distance>*diagonal+axial;
}
godbolt.org/z/9xcJWK
queens_distance(int, int):
cmp r0, #0
rsblt r0, r0, #0
cmp r1, #0
rsblt r1, r1, #0
cmp r0, r1
movlt ip, r0
movge ip, r1
cmp r0, r1
rsbge r0, ip, r0
rsblt r0, ip, r1
ldr r2, .L3
mul r3, r2, ip
add r0, r3, r0, lsl #24
bx lr
.L3:
.word 23726566
Question:
how far does the queen really move in Chess?
(0/0) o …00001.0110101000001001111001100110011111110…
auto root2 = sqrt2_v<scaled_integer<int, power<-30>>>;
…00001.0110101000001001111001100110010000000…
auto root32 = root2 * 4;
…00101.1010100000100111100110011001000000000…
<source>:10:39: error: overflow in constant expression [-fpermissive]
constexpr auto root32 = root2 * 4;
^
…00001.0110101000001001111001100110011111110…
constexpr auto root2 = sqrt2_v<scaled_integer<int, power<-30>>>;
…00001.0110101000001001111001100110010000000…
constexpr auto root32 = root2 * 4;
…0101.1010100000100111100110011001000000000…
<source>:8:33: error: overflow in constant expression [-fpermissive]
constexpr auto root32 = root2 * 4;
^
c++ -std=c++17
-Wall -Wextra -Werror
-fsanitize=address,undefined
all_your_source_files.cpp
auto root2 = sqrt2_v<scaled_integer<int, power<-30>>>;
auto root32 = root2 * 4;
cnl.h:2903:51: runtime error: signed integer overflow:
1518500249 * 4 cannot be represented in type 'int'
wandbox.org/permlink/womtuT7zYstKiLhK
unsigned mu = 0;
cout << (mu-1);
4294967295
int s = 1;
cout << (s << 31);
-2147483648
int ms = 100000;
cout << short(ms);
-31072
// cnl/overflow_integer.h
namespace cnl {
template<
typename Rep,
class OverflowTag=undefined_overflow_tag>
class overflow_integer;
}
overflow_integer<unsigned> mu = 0;
cout << (mu-1);
runtime error: execution reached an unreachable program point
overflow_integer<int> s = 1;
cout << (s<<31);
runtime error: execution reached an unreachable program point
overflow_integer<int> ms = 100000;
cout << short(ms);
runtime error: execution reached an unreachable program point
// cnl/overflow_integer.h
namespace cnl {
template<typename Rep, class OverflowTag=undefined_overflow_tag>
class overflow_integer;
}
overflow_integer<unsigned> mu = 0;
cout << (mu-1);
runtime error: execution reached an unreachable program point
overflow_integer<int> s = 1;
cout << (s<<31);
runtime error: execution reached an unreachable program point
overflow_integer<int> ms = 100000;
cout << short(ms);
runtime error: execution reached an unreachable program point
// cnl/elastic_integer.h
namespace cnl {
template<int Digits, typename Narrowest=int>
class elastic_integer;
}
11111010004
=111101000010010000002
=1110100011010100101001010001000000000000
// elastic_integer<10>{1000}
auto k = elastic_integer{1000_c};
// elastic_integer<20>{1000000}
auto m = k*k;
// elastic_integer<40>{1000000000000LL}
auto t = m*m;
godbolt.org/z/WKEkRk
// cnl/elastic_integer.h
namespace cnl {
template<int Digits, typename Narrowest=int>
class elastic_integer;
}
11111010004
=111101000010010000002
=1110100011010100101001010001000000000000
// elastic_integer<10>{1000}
auto k = elastic_integer{1000_c};
// elastic_integer<20>{1000000}
auto m = k*k;
// elastic_integer<40>{1000000000000LL}
auto t = m*m;
godbolt.org/z/WKEkRk
// cnl/elastic_number.h
namespace cnl {
template<int Digits, int Exponent>
using elastic_number =
scaled_integer<elastic_integer<Digits>, power<Exponent>>;
namespace literals {
template<char ... Chars>
constexpr auto operator ""_elastic() noexcept;
}
}
// user code
using namespace cnl::literals;
// elastic_number<7, 3>
constexpr auto k = 1000_elastic;
godbolt.org/z/tBYdGE
// cnl/elastic_integer.h
namespace cnl {
template<int Digits, typename Narrowest=int>
class elastic_integer;
}
11111010004
=111101000010010000002
=1110100011010100101001010001000000000000
// elastic_integer<10>{1000}
auto k = elastic_integer{1000_c};
// elastic_integer<20>{1000000}
auto m = k*k;
// elastic_integer<40>{1000000000000LL}
auto t = m*m;
godbolt.org/z/WKEkRk
// cnl/elastic_number.h
namespace cnl {
template<int Digits, int Exponent>
using elastic_number = ...;
}
11111010004
=111101000010010000002
=1110100011010100101001010001000000000000
// elastic_number<7, 3>{1000}
auto k = 1000_elastic;
// elastic_number<14, 6>{1000000}
auto m = k*k;
// elastic_number<28, 12>{1000000000000LL}
auto t = m*m;
godbolt.org/z/eRZs77
auto root2 = sqrt2_v<scaled_integer<int, power<-30>>>;
…00001.0110101000001001111001100110010000000…
// scaled_integer<int, power<-28>>
auto root32 = root2 << 2_c;
…0000101.10101000001001111001100110010000000…
// elastic_number<31, -28>
auto root32 = root2 * 4_elastic;
…0000101.10101000001001111001100110010000000…
auto f(scaled_integer<int, power<-30>> n) {
return n << 2_c;
}f:
bx lrauto g(scaled_integer<int, power<-30>> n) {
return n * 4_elastic;
}g:
bx lr
2∞+8
∞+1
3
scaled_integer{42_c}