1#include "prism/internal/double.h"
3#include "prism/internal/bignum.h"
4#include "prism/internal/bit.h"
14#if FLT_RADIX != 2 || DBL_MANT_DIG != 53 || DBL_MIN_EXP != -1021 || DBL_MAX_EXP != 1024
15#error "prism requires IEEE 754 binary64 doubles"
21#define PM_DOUBLE_DIGITS 768
26#define PM_DOUBLE_WORDS 84
34#define PM_DOUBLE_EXPONENT_MAXIMUM 100000000000000000
39#define PM_DOUBLE_INFINITY ((uint64_t) 0x7FF0000000000000)
44#define PM_DOUBLE_POWER5_13 1220703125
49static const double pm_double_powers[] = {
50 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
51 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
59 assert(bignum->length > 0);
60 return (uint64_t) (bignum->length - 1) * 32 + pm_bsrll(bignum->words[bignum->length - 1]) + 1;
67pm_double_multiply_powof5(
pm_bignum_t *bignum, uint64_t power) {
68 for (; power >= 13; power -= 13) pm_bignum_mul_add(bignum, PM_DOUBLE_POWER5_13, 0);
70 uint32_t multiplier = 1;
71 for (; power > 0; power--) multiplier *= 5;
72 if (multiplier > 1) pm_bignum_mul_add(bignum, multiplier, 0);
85 uint32_t *numerator_words = numerator->words;
86 const uint32_t *divisor_words = divisor->words;
87 uint32_t numerator_length = numerator->length;
88 uint32_t divisor_length = divisor->length;
90 assert(divisor_length >= 2 && numerator_length >= divisor_length && (divisor_words[divisor_length - 1] >> 31) == 1);
92 uint64_t top = divisor_words[divisor_length - 1];
93 uint64_t next = divisor_words[divisor_length - 2];
94 uint64_t quotient = 0;
95 numerator_words[numerator_length] = 0;
97 for (uint32_t index = numerator_length - divisor_length + 1; index > 0; index--) {
98 uint32_t *window = numerator_words + index - 1;
99 uint64_t current = ((uint64_t) window[divisor_length] << 32) | window[divisor_length - 1];
100 uint64_t estimate = current / top;
101 uint64_t remainder = current % top;
103 while (estimate > UINT32_MAX || estimate * next > ((remainder << 32) | window[divisor_length - 2])) {
106 if (remainder > UINT32_MAX)
break;
113 for (uint32_t offset = 0; offset < divisor_length; offset++) {
114 uint64_t product = estimate * divisor_words[offset] + carry;
115 carry = product >> 32;
117 uint64_t difference = (uint64_t) window[offset] - (uint32_t) product - borrow;
118 window[offset] = (uint32_t) difference;
119 borrow = difference >> 63;
122 uint64_t difference = (uint64_t) window[divisor_length] - carry - borrow;
123 window[divisor_length] = (uint32_t) difference;
125 if ((difference >> 63) != 0) {
129 for (uint32_t offset = 0; offset < divisor_length; offset++) {
130 uint64_t sum = (uint64_t) window[offset] + divisor_words[offset] + carry;
131 window[offset] = (uint32_t) sum;
135 window[divisor_length] += (uint32_t) carry;
138 assert((quotient >> 32) == 0);
139 quotient = (quotient << 32) | estimate;
142 for (uint32_t index = 0; index < divisor_length; index++) {
143 if (numerator_words[index] != 0) {
159pm_double_round(uint64_t mantissa, int64_t exponent,
bool inexact) {
160 assert(mantissa != 0);
164 int64_t shift = (int64_t) pm_bsrll(mantissa) + 1 - 53;
165 if (shift < -1074 - exponent) shift = -1074 - exponent;
170 bits = mantissa << -shift;
171 }
else if (shift > 64) {
174 uint64_t half = (uint64_t) 1 << (shift - 1);
175 uint64_t rest = mantissa & (half - 1 + half);
176 bits = shift == 64 ? 0 : mantissa >> shift;
177 if (rest > half || (rest == half && (inexact || (bits & 1)))) bits++;
184 int64_t scale = exponent + shift;
185 if (scale > 971)
return PM_DOUBLE_INFINITY;
187 bits += (uint64_t) (scale + 1074) << 52;
188 return bits < PM_DOUBLE_INFINITY ? bits : PM_DOUBLE_INFINITY;
196pm_double_exact(
const uint8_t *start, uint32_t digits, int64_t exponent, uint64_t value) {
197 uint32_t numerator_words[PM_DOUBLE_WORDS] = { 0 };
198 pm_bignum_t numerator = { .length = 0, .words = numerator_words };
201 numerator_words[0] = (uint32_t) value;
202 numerator_words[1] = (uint32_t) (value >> 32);
203 numerator.length = value > UINT32_MAX ? 2 : 1;
205 uint32_t remaining = digits > PM_DOUBLE_DIGITS ? PM_DOUBLE_DIGITS : digits;
207 uint32_t multiplier = 1;
209 for (
const uint8_t *cursor = start; remaining > 0; cursor++) {
210 if (*cursor <
'0' || *cursor >
'9')
continue;
212 chunk = chunk * 10 + (uint32_t) (*cursor -
'0');
216 if (multiplier == 1000000000) {
217 pm_bignum_mul_add(&numerator, multiplier, chunk);
223 if (digits > PM_DOUBLE_DIGITS) {
224 chunk = chunk * 10 + 1;
226 exponent += (int64_t) (digits - PM_DOUBLE_DIGITS) - 1;
229 if (multiplier > 1) pm_bignum_mul_add(&numerator, multiplier, chunk);
232 bool inexact =
false;
240 pm_double_multiply_powof5(&numerator, (uint64_t) exponent);
242 uint64_t length = pm_double_bit_length(&numerator);
246 uint64_t dropped = length - 64;
247 inexact = pm_bignum_trailing_zeros(&numerator) < dropped;
248 pm_bignum_shift_right(&numerator, (
size_t) dropped);
249 binary += (int64_t) dropped;
252 mantissa = pm_bignum_uint64(&numerator);
255 uint32_t denominator_words[PM_DOUBLE_WORDS];
256 pm_bignum_t denominator = { .length = 1, .words = denominator_words };
258 denominator_words[0] = 1;
259 pm_double_multiply_powof5(&denominator, (uint64_t) -exponent);
265 int64_t numerator_bits = (int64_t) pm_double_bit_length(&numerator);
266 int64_t denominator_bits = (int64_t) pm_double_bit_length(&denominator);
268 int64_t denominator_shift = (32 - denominator_bits % 32) % 32;
269 if (denominator_bits + denominator_shift == 32) denominator_shift += 32;
271 int64_t numerator_shift = 63 + denominator_bits + denominator_shift - numerator_bits;
272 if (numerator_shift < 0) {
273 denominator_shift += (31 - numerator_shift) / 32 * 32;
274 numerator_shift = 63 + denominator_bits + denominator_shift - numerator_bits;
277 pm_bignum_shift_left(&numerator, (
size_t) numerator_shift);
278 pm_bignum_shift_left(&denominator, (
size_t) denominator_shift);
279 assert(numerator.length < PM_DOUBLE_WORDS && denominator.length <= PM_DOUBLE_WORDS);
281 mantissa = pm_double_divide(&numerator, &denominator, &inexact);
282 binary = exponent + denominator_shift - numerator_shift;
285 return pm_double_round(mantissa, binary, inexact);
292pm_double_parse(
const uint8_t *start,
const uint8_t *end,
bool *out_of_range) {
293 *out_of_range =
false;
294 if (start < end && *start ==
'+') start++;
296 const uint8_t *first = NULL;
297 const uint8_t *cursor = start;
303 int64_t exponent = 0;
305 bool fraction =
false;
308 for (; !e && cursor < end; cursor++) {
319 if (fraction) exponent--;
320 if (first != NULL) zeros++;
322 case '1':
case '2':
case '3':
case '4':
case '5':
323 case '6':
case '7':
case '8':
case '9':
324 if (fraction) exponent--;
325 if (first == NULL) first = cursor;
329 for (; zeros > 0; zeros--) value *= 10;
330 value = value * 10 + (uint64_t) (*cursor -
'0');
336 assert(
false &&
"unreachable");
341 exponent += (int64_t) zeros;
342 if (digits == 0)
return 0.0;
345 bool positive =
true;
346 if (cursor < end && (*cursor ==
'+' || *cursor ==
'-')) {
347 positive = *cursor ==
'+';
352 for (; cursor < end; cursor++) {
353 if (*cursor !=
'_' && power < PM_DOUBLE_EXPONENT_MAXIMUM) power = power * 10 + (*cursor -
'0');
356 exponent += positive ? power : -power;
359 int64_t magnitude = (int64_t) digits + exponent;
362 if (magnitude > 309) {
363 bits = PM_DOUBLE_INFINITY;
364 }
else if (magnitude < -323) {
372#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD == 0
373 if (digits <= 19 && value <= ((uint64_t) 1 << 53)) {
374 if (exponent >= -22 && exponent < 0) {
375 return (
double) value / pm_double_powers[-exponent];
376 }
else if (exponent >= 0 && exponent <= 22) {
377 return (
double) value * pm_double_powers[exponent];
378 }
else if (exponent > 22 && exponent <= 22 + 15) {
379 uint64_t scaled = value;
380 for (int64_t power = exponent; power > 22 && scaled <= ((uint64_t) 1 << 53); power--) scaled *= 10;
381 if (scaled <= ((uint64_t) 1 << 53))
return (
double) scaled * 1e22;
386 bits = pm_double_exact(first, digits, exponent, value);
389 *out_of_range = bits == 0 || bits == PM_DOUBLE_INFINITY;
392 memcpy(&result, &bits,
sizeof(
double));