Skip to content

Commit 0379870

Browse files
committed
Switched to bisection for double -> NumCCD
1 parent d820fe1 commit 0379870

File tree

2 files changed

+35
-47
lines changed

2 files changed

+35
-47
lines changed

tight_inclusion/interval.cpp

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66

77
namespace 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

tight_inclusion/interval.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ namespace ticcd {
2929
{
3030
}
3131

32-
NumCCD(float x);
33-
NumCCD(double x);
32+
NumCCD(Scalar x);
3433

3534
~NumCCD() {}
3635

@@ -39,6 +38,8 @@ namespace ticcd {
3938
// convert NumCCD to double number
4039
Scalar value() const { return Scalar(numerator) / denominator(); }
4140

41+
operator double() const { return value(); }
42+
4243
NumCCD operator+(const NumCCD &other) const;
4344

4445
bool operator==(const NumCCD &other) const
@@ -56,6 +57,8 @@ namespace ticcd {
5657
bool operator>(const NumCCD &other) const { return !(*this <= other); }
5758

5859
bool operator<(const Scalar other) const { return value() < other; }
60+
bool operator>(const Scalar other) const { return value() > other; }
61+
bool operator==(const Scalar other) const { return value() == other; }
5962

6063
static bool is_sum_leq_1(const NumCCD &num1, const NumCCD &num2);
6164
};

0 commit comments

Comments
 (0)