66
77namespace ticcd {
88
9+ static constexpr uint8_t MAX_DENOM_POWER = 8 * sizeof (uint64_t ) - 1 ;
10+
911 // calculate a*(2^b)
1012 uint64_t power (const uint64_t a, const uint8_t b)
1113 {
1214 // The fast bit shifting power trick only works if b is not too larger.
13- assert (b < 8 * sizeof ( uint64_t ) - 1 );
14- // WARNING: Technically this can still fail with `b < 8 * sizeof(uint64_t) - 1 ` if `a > 1`.
15+ assert (b < MAX_DENOM_POWER );
16+ // WARNING: Technically this can still fail with `b < MAX_DENOM_POWER ` if `a > 1`.
1517 return a << b;
1618 }
1719
@@ -27,56 +29,39 @@ namespace ticcd {
2729 return t;
2830 }
2931
30- NumCCD::NumCCD (float p_x )
32+ NumCCD::NumCCD (Scalar x )
3133 {
32- union {
33- double val;
34- struct {
35- uint64_t mantisa : 23 ;
36- uint16_t exponent : 8 ;
37- uint8_t sign : 1 ;
38- } parts;
39- } x;
40- x.val = p_x;
41-
42- denom_power = abs (x.parts .exponent - 127 ) + 23 ;
43- numerator = x.parts .mantisa | (uint32_t (1 ) << 23 );
44- for (int i = 0 ; i < 23 ; i++) {
45- if ((numerator & 1 ) == 0 ) {
46- numerator >>= 1 ;
47- denom_power--;
48- } else {
49- break ;
50- }
34+ // Use bisection to find an upper bound of x.
35+ assert (x >= 0 && x <= 1 );
36+ NumCCD low (0 , 0 ), high (1 , 0 ), mid;
37+
38+ // Hard code these cases for better accuracy.
39+ if (x == 0 ) {
40+ *this = low;
41+ return ;
42+ } else if (x == 1 ) {
43+ *this = high;
44+ return ;
5145 }
5246
53- assert (value () == p_x);
54- }
47+ do {
48+ mid = low + high;
49+ mid.denom_power ++;
5550
56- NumCCD::NumCCD (double p_x)
57- {
58- union {
59- double val;
60- struct {
61- uint64_t mantisa : 52 ;
62- uint16_t exponent : 11 ;
63- uint8_t sign : 1 ;
64- } parts;
65- } x;
66- x.val = p_x;
67-
68- denom_power = abs (x.parts .exponent - 1023 ) + 52 ;
69- numerator = x.parts .mantisa | (uint64_t (1 ) << 52 );
70- for (int i = 0 ; i < 52 ; i++) {
71- if ((numerator & 1 ) == 0 ) {
72- numerator >>= 1 ;
73- denom_power--;
74- } else {
51+ if (mid.denom_power >= MAX_DENOM_POWER) {
7552 break ;
7653 }
77- }
7854
79- assert (value () == p_x);
55+ if (x > mid) {
56+ low = mid;
57+ } else if (x < mid) {
58+ high = mid;
59+ } else {
60+ break ;
61+ }
62+ } while (mid.denom_power < MAX_DENOM_POWER);
63+ *this = high;
64+ assert (x <= value ());
8065 }
8166
8267 NumCCD NumCCD::operator +(const NumCCD &other) const
0 commit comments