@@ -201,7 +201,7 @@ namespace simple_dragonbox {
201
201
static constexpr int min_k = -31 ;
202
202
static constexpr int max_k = 46 ;
203
203
204
- static void remove_trailing_zeros (uint32_t & significand, int & exponent) {
204
+ static constexpr void remove_trailing_zeros (uint32_t & significand, int & exponent) {
205
205
// See https://github.com/jk-jeon/rtz_benchmark.
206
206
// The idea of branchless search below is by reddit users r/pigeon768 and
207
207
// r/TheoreticalDumbass.
@@ -224,40 +224,40 @@ namespace simple_dragonbox {
224
224
exponent += s;
225
225
}
226
226
227
- static compute_mul_result<uint32_t > compute_mul (uint32_t u, uint64_t cache) {
227
+ static constexpr compute_mul_result<uint32_t > compute_mul (uint32_t u, uint64_t cache) {
228
228
auto const r = umul96_upper64 (u, cache);
229
229
return {uint32_t (r >> 32 ), uint32_t (r) == 0 };
230
230
}
231
231
232
- static uint32_t compute_delta (uint64_t cache, int beta) {
232
+ static constexpr uint32_t compute_delta (uint64_t cache, int beta) {
233
233
return uint32_t (cache >> (cache_bits - 1 - beta));
234
234
}
235
235
236
- static compute_mul_parity_result compute_mul_parity (uint32_t two_f, uint64_t cache,
237
- int beta) {
236
+ static constexpr compute_mul_parity_result compute_mul_parity (uint32_t two_f, uint64_t cache,
237
+ int beta) {
238
238
assert (beta >= 1 );
239
239
assert (beta <= 32 );
240
240
auto const r = umul96_lower64 (two_f, cache);
241
241
return {((r >> (64 - beta)) & 1 ) != 0 ,
242
242
(UINT32_C (0xffffffff ) & (r >> (32 - beta))) == 0 };
243
243
}
244
244
245
- static uint32_t compute_left_endpoint_for_shorter_interval_case (uint64_t cache, int beta) {
245
+ static constexpr uint32_t compute_left_endpoint_for_shorter_interval_case (uint64_t cache, int beta) {
246
246
return (cache - (cache >> (significand_bits + 2 ))) >>
247
247
(cache_bits - significand_bits - 1 - beta);
248
248
}
249
249
250
- static uint32_t compute_right_endpoint_for_shorter_interval_case (uint64_t cache, int beta) {
250
+ static constexpr uint32_t compute_right_endpoint_for_shorter_interval_case (uint64_t cache, int beta) {
251
251
return (cache + (cache >> (significand_bits + 1 ))) >>
252
252
(cache_bits - significand_bits - 1 - beta);
253
253
}
254
254
255
- static uint32_t compute_round_up_for_shorter_interval_case (uint64_t cache, int beta) {
255
+ static constexpr uint32_t compute_round_up_for_shorter_interval_case (uint64_t cache, int beta) {
256
256
return (uint32_t (cache >> (cache_bits - significand_bits - 2 - beta)) + 1 ) / 2 ;
257
257
}
258
258
259
259
template <int N, uint32_t n_max>
260
- static uint32_t divide_by_pow10 (uint32_t n) {
260
+ static constexpr uint32_t divide_by_pow10 (uint32_t n) {
261
261
static_assert (N >= 0 , " " );
262
262
263
263
// Specialize for 32-bit division by 10.
@@ -353,7 +353,7 @@ namespace simple_dragonbox {
353
353
}
354
354
}
355
355
356
- uint64_t get_cache (int k) const {
356
+ constexpr uint64_t get_cache (int k) const {
357
357
assert (k >= min_k && k <= max_k);
358
358
359
359
// Compute the base index.
@@ -406,7 +406,7 @@ namespace simple_dragonbox {
406
406
static constexpr int min_k = -292 ;
407
407
static constexpr int max_k = 326 ;
408
408
409
- static void remove_trailing_zeros (uint64_t & significand, int & exponent) {
409
+ static constexpr void remove_trailing_zeros (uint64_t & significand, int & exponent) {
410
410
// See https://github.com/jk-jeon/rtz_benchmark.
411
411
// The idea of branchless search below is by reddit users r/pigeon768 and
412
412
// r/TheoreticalDumbass.
@@ -434,17 +434,17 @@ namespace simple_dragonbox {
434
434
exponent += s;
435
435
}
436
436
437
- static compute_mul_result<uint64_t > compute_mul (uint64_t u, uint128 cache) {
437
+ static constexpr compute_mul_result<uint64_t > compute_mul (uint64_t u, uint128 cache) {
438
438
auto const r = umul192_upper128 (u, cache);
439
439
return {r.high , r.low == 0 };
440
440
}
441
441
442
- static uint64_t compute_delta (uint128 cache, int beta) {
442
+ static constexpr uint64_t compute_delta (uint128 cache, int beta) {
443
443
return cache.high >> (total_bits - 1 - beta);
444
444
}
445
445
446
- static compute_mul_parity_result compute_mul_parity (uint64_t two_f, uint128 cache,
447
- int beta) {
446
+ static constexpr compute_mul_parity_result compute_mul_parity (uint64_t two_f, uint128 cache,
447
+ int beta) {
448
448
assert (beta >= 1 );
449
449
assert (beta < 64 );
450
450
auto const r = umul192_lower128 (two_f, cache);
@@ -453,22 +453,22 @@ namespace simple_dragonbox {
453
453
0 };
454
454
}
455
455
456
- static uint64_t compute_left_endpoint_for_shorter_interval_case (uint128 cache, int beta) {
456
+ static constexpr uint64_t compute_left_endpoint_for_shorter_interval_case (uint128 cache, int beta) {
457
457
return (cache.high - (cache.high >> (significand_bits + 2 ))) >>
458
458
(total_bits - significand_bits - 1 - beta);
459
459
}
460
460
461
- static uint64_t compute_right_endpoint_for_shorter_interval_case (uint128 cache, int beta) {
461
+ static constexpr uint64_t compute_right_endpoint_for_shorter_interval_case (uint128 cache, int beta) {
462
462
return (cache.high + (cache.high >> (significand_bits + 1 ))) >>
463
463
(total_bits - significand_bits - 1 - beta);
464
464
}
465
465
466
- static uint64_t compute_round_up_for_shorter_interval_case (uint128 cache, int beta) {
466
+ static constexpr uint64_t compute_round_up_for_shorter_interval_case (uint128 cache, int beta) {
467
467
return ((cache.high >> (total_bits - significand_bits - 2 - beta)) + 1 ) / 2 ;
468
468
}
469
469
470
470
template <int N, uint64_t n_max>
471
- static uint64_t divide_by_pow10 (uint64_t n) {
471
+ static constexpr uint64_t divide_by_pow10 (uint64_t n) {
472
472
static_assert (N >= 0 , " " );
473
473
474
474
// Specialize for 64-bit division by 10.
@@ -1114,7 +1114,7 @@ namespace simple_dragonbox {
1114
1114
1115
1115
template <>
1116
1116
struct cache_holder <cache_type::full> {
1117
- uint128 get_cache (int k) const {
1117
+ constexpr uint128 get_cache (int k) const {
1118
1118
assert (k >= min_k && k <= max_k);
1119
1119
return cache[k - min_k];
1120
1120
}
@@ -1141,7 +1141,7 @@ namespace simple_dragonbox {
1141
1141
}
1142
1142
}
1143
1143
1144
- uint128 get_cache (int k) const {
1144
+ constexpr uint128 get_cache (int k) const {
1145
1145
assert (k >= min_k && k <= max_k);
1146
1146
1147
1147
// Compute the base index.
@@ -1306,7 +1306,7 @@ namespace simple_dragonbox {
1306
1306
static constexpr typename format::template cache_holder<CacheType> cache_;
1307
1307
1308
1308
template <int N>
1309
- static bool check_divisibility_and_divide_by_pow10 (carrier_uint& n) {
1309
+ static constexpr bool check_divisibility_and_divide_by_pow10 (carrier_uint& n) {
1310
1310
// Make sure the computation for max_n does not overflow.
1311
1311
static_assert (N + 1 <= floor_log10_pow2 (carrier_bits), " " );
1312
1312
assert (n <= compute_power<N + 1 >(carrier_uint (10 )));
@@ -1324,14 +1324,14 @@ namespace simple_dragonbox {
1324
1324
// Compute floor(n / 10^N) for small n and N.
1325
1325
// Precondition: n <= 10^(N+1)
1326
1326
template <int N>
1327
- static carrier_uint small_division_by_pow10 (carrier_uint n) {
1327
+ static constexpr carrier_uint small_division_by_pow10 (carrier_uint n) {
1328
1328
// Make sure the computation for max_n does not overflow.
1329
1329
static_assert (N + 1 <= floor_log10_pow2 (carrier_bits), " " );
1330
1330
assert (n <= compute_power<N + 1 >(carrier_uint (10 )));
1331
1331
return carrier_uint ((n * divide_magic_number[N - 1 ]) >> 16 );
1332
1332
}
1333
1333
1334
- static bool prefer_round_down (carrier_uint decimal_significand) {
1334
+ static constexpr bool prefer_round_down (carrier_uint decimal_significand) {
1335
1335
using e = decimal_round_mode;
1336
1336
switch (DecimalRoundMode) {
1337
1337
case e::dont_care:
@@ -1351,7 +1351,7 @@ namespace simple_dragonbox {
1351
1351
int exponent;
1352
1352
bool sign;
1353
1353
1354
- constexpr impl (Float x) {
1354
+ constexpr constexpr impl (Float x) {
1355
1355
carrier_uint bits;
1356
1356
static_assert (sizeof (x) == sizeof (bits));
1357
1357
std::memcpy (&bits, &x, sizeof (x));
@@ -1360,15 +1360,15 @@ namespace simple_dragonbox {
1360
1360
sign = bits >> (format::significand_bits + format::exponent_bits);
1361
1361
}
1362
1362
1363
- bool is_finite () const { return exponent != (1u << format::exponent_bits) - 1 ; }
1363
+ constexpr bool is_finite () const { return exponent != (1u << format::exponent_bits) - 1 ; }
1364
1364
1365
1365
struct decimal_result {
1366
1366
carrier_uint significand;
1367
1367
int exponent;
1368
1368
bool sign;
1369
1369
};
1370
1370
1371
- decimal_result to_decimal () {
1371
+ constexpr decimal_result to_decimal () {
1372
1372
assert (is_finite () && (significand || exponent));
1373
1373
bool even = significand % 2 == 0 ;
1374
1374
using e = binary_round_mode;
@@ -1404,41 +1404,40 @@ namespace simple_dragonbox {
1404
1404
}
1405
1405
}
1406
1406
1407
- auto nearest_to_even () {
1407
+ constexpr auto nearest_to_even () {
1408
1408
bool even = significand % 2 == 0 ;
1409
1409
return nearest ({even, even}, {true , true });
1410
1410
}
1411
1411
1412
- auto nearest_to_odd () {
1412
+ constexpr auto nearest_to_odd () {
1413
1413
bool even = significand % 2 == 0 ;
1414
1414
return nearest ({!even, even}, {false , false });
1415
1415
}
1416
1416
1417
- auto nearest_toward_plus_infinity () { return nearest ({!sign, sign}, {!sign, sign}); }
1417
+ constexpr auto nearest_toward_plus_infinity () { return nearest ({!sign, sign}, {!sign, sign}); }
1418
1418
1419
- auto nearest_toward_minus_infinity () { return nearest ({sign, !sign}, {sign, !sign}); }
1419
+ constexpr auto nearest_toward_minus_infinity () { return nearest ({sign, !sign}, {sign, !sign}); }
1420
1420
1421
- auto nearest_toward_zero () { return nearest ({false , true }, {false , true }); }
1421
+ constexpr auto nearest_toward_zero () { return nearest ({false , true }, {false , true }); }
1422
1422
1423
- auto nearest_away_from_zero () { return nearest ({true , false }, {true , false }); }
1423
+ constexpr auto nearest_away_from_zero () { return nearest ({true , false }, {true , false }); }
1424
1424
1425
- auto nearest_always_closed () { return nearest ({true , true }, {true , true }); }
1425
+ constexpr auto nearest_always_closed () { return nearest ({true , true }, {true , true }); }
1426
1426
1427
- auto nearest_always_open () { return nearest ({false , false }, {false , false }); }
1427
+ constexpr auto nearest_always_open () { return nearest ({false , false }, {false , false }); }
1428
1428
1429
- decimal_result no_trailing_zeros (carrier_uint significand, int exponent) {
1429
+ constexpr decimal_result no_trailing_zeros (carrier_uint significand, int exponent) {
1430
1430
return {significand , exponent, sign};
1431
1431
}
1432
1432
1433
- decimal_result may_have_trailing_zeros (carrier_uint significand, int exponent) {
1433
+ constexpr decimal_result may_have_trailing_zeros (carrier_uint significand, int exponent) {
1434
1434
format::remove_trailing_zeros (significand , exponent);
1435
1435
return {significand , exponent, sign};
1436
1436
}
1437
1437
1438
1438
// // The main algorithm assumes the input is a normal/subnormal finite number.
1439
1439
1440
- auto nearest (interval normal_interval, interval shorter_interval) {
1441
-
1440
+ constexpr auto nearest (interval normal_interval, interval shorter_interval) {
1442
1441
carrier_uint two_fc = significand * 2 ;
1443
1442
auto binary_exponent = exponent;
1444
1443
@@ -1674,8 +1673,7 @@ namespace simple_dragonbox {
1674
1673
return no_trailing_zeros (decimal_significand, minus_k + kappa);
1675
1674
}
1676
1675
1677
- auto left_closed_directed () {
1678
-
1676
+ constexpr auto left_closed_directed () {
1679
1677
carrier_uint two_fc = significand * 2 ;
1680
1678
auto binary_exponent = exponent;
1681
1679
@@ -1780,8 +1778,7 @@ namespace simple_dragonbox {
1780
1778
return no_trailing_zeros (decimal_significand, minus_k + kappa);
1781
1779
}
1782
1780
1783
- auto right_closed_directed () {
1784
-
1781
+ constexpr auto right_closed_directed () {
1785
1782
carrier_uint two_fc = significand * 2 ;
1786
1783
auto binary_exponent = exponent;
1787
1784
bool shorter_interval = false ;
@@ -1855,17 +1852,17 @@ namespace simple_dragonbox {
1855
1852
return no_trailing_zeros (decimal_significand, minus_k + kappa);
1856
1853
}
1857
1854
1858
- static bool is_right_endpoint_integer_shorter_interval (int binary_exponent) {
1855
+ static constexpr bool is_right_endpoint_integer_shorter_interval (int binary_exponent) {
1859
1856
return binary_exponent >= case_shorter_interval_right_endpoint_lower_threshold &&
1860
1857
binary_exponent <= case_shorter_interval_right_endpoint_upper_threshold;
1861
1858
}
1862
1859
1863
- static bool is_left_endpoint_integer_shorter_interval (int binary_exponent) {
1860
+ static constexpr bool is_left_endpoint_integer_shorter_interval (int binary_exponent) {
1864
1861
return binary_exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
1865
1862
binary_exponent <= case_shorter_interval_left_endpoint_upper_threshold;
1866
1863
}
1867
1864
1868
- char * to_chars (char * buffer) {
1865
+ constexpr char * to_chars (char * buffer) {
1869
1866
if (!is_finite ()) {
1870
1867
if (!significand ) {
1871
1868
if (sign) {
0 commit comments