43 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
44 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
71 static constexpr fltp08 kLog2_10 = 0.30102999566398119521373889472449;
72 static constexpr uint04 maxBase2Precision = 53;
73 static constexpr uint08 two_pow_maxBase2PrecisionMinus1 =
uint08(1) << (maxBase2Precision - 1);
82 if (0 < exp && exp < 64)
95 D2A(
const fltp08 avalue,
bool fixedPrecision,
uint04 minPrecision)
100 mantissa = n_frexp(value, &e);
104 lowOk = highOk =
true;
108 bool round = (mantissa & 1) == 0;
109 lowOk = highOk = round;
112 mantissaPrec = maxBase2Precision;
113 while (mantissaPrec != 0 && (((mantissa >> --mantissaPrec) & 1) == 0)) {}
117 if (mantissa != two_pow_maxBase2PrecisionMinus1)
119 const fltp08 be = quickPowTwo(e);
128 fltp08 be = quickPowTwo(e);
137 else if (mantissa != two_pow_maxBase2PrecisionMinus1)
141 ds = quickPowTwo(1 - e);
148 ds = quickPowTwo(2 - e);
154 const fltp08 fixedPrecisionPowTen = QuickPowTen(minPrecision);
155 ds *= fixedPrecisionPowTen;
156 dr *= fixedPrecisionPowTen;
167 uint08 n_frexp(
double v,
int* eptr)
const
169 fltp08 fracMantissa = std::frexp(v, eptr);
171 return (uint64_t)(fracMantissa * (double)(1LL << 53));
181 return Constant<uint01>::Invalid;
183 bool withinLowEndRoundRange;
184 bool withinHighEndRoundRange;
188 lib_assert(quotient < 10, "quotient cannot be > 9
");
189 double mod = fmod(dr, ds);
192 // check if remaining ratio r/s is within the range of floats which would round to the value we have output
193 // so far when read in from a string.
194 withinLowEndRoundRange = (lowOk ? (dr <= dMMinus) : (dr < dMMinus));
195 withinHighEndRoundRange = (highOk ? (dr + dMPlus >= ds) : (dr + dMPlus > ds));
198 if (!withinLowEndRoundRange)
200 if (!withinHighEndRoundRange) // if not within either error range, set up to generate the next digit.
212 else if (!withinHighEndRoundRange)
218 if (dr * 2 < ds) // if (r*2 < s) todo: faster to do lshift and compare?
235 sint04 expBase10() { return base10Exp; }
237 fltp08 value; ///< The original double value being converted.
238 sint04 e; ///< The binary exponent from decomposition.
239 uint08 mantissa; ///< On input, value = mantissa*2^e; Only last 53 bits are used.
240 sint04 mantissaPrec; ///< The number of bits of precision that are present in the mantissa.
241 sint04 base10Exp; ///< The (derived) base 10 exponent of value.
242 bool finished; ///< Set to true when we've output all relevant digits.
245 bool lowOk; ///< For IEEE unbiased rounding, this is true when mantissa is even. When true, use >= in mMinus test instead of >
246 bool highOk; ///< Ditto, but for mPlus test.
248 // If !bFastEstimateOk, use these.
250 // If bFastEstimateOk, use these - same as above, but integer value stored in double.
251 fltp08 dr; ///< Scaled remainder value used during digit generation.
252 fltp08 ds; ///< Scaled divisor value used during digit generation.
253 fltp08 dMPlus; ///< Upper error bound for rounding during digit generation.
254 fltp08 dMMinus; ///< Lower error bound for rounding during digit generation.
256 // Estimate base 10 exponent of number, scale r,s,mPlus,mMinus appropriately.
257 // Returns result of fixup_ExponentEstimate(est).
264 // estimate base10 exponent:
265 sint04 base2Exponent = e + mantissaPrec - 1;
266 sint04 exponentEstimate = (sint04)ceil((base2Exponent * kLog2_10) - 0.0000000001);
268 fltp08 scale = QuickPowTen((exponentEstimate > 0) ? exponentEstimate : -exponentEstimate);
270 if (exponentEstimate >= 0)
273 return fixup_ExponentEstimate(exponentEstimate);
280 return fixup_ExponentEstimate(exponentEstimate);
284 // Used by scale to adjust for possible off-by-one error in the base 10 exponent estimate.
285 // Returns exact base10 exponent of number.
291 sint04 fixup_ExponentEstimate(sint04 exponentEstimate)
293 sint04 correctedEstimate;
294 uint01 quotient = cast<uint01>((dr * 10) / ds);
295 if ((highOk ? (dr + dMPlus) >= ds : dr + dMPlus > ds) || quotient >= 10)
297 correctedEstimate = exponentEstimate + 1;
304 correctedEstimate = exponentEstimate;
306 quotient = cast<uint01>(dr / ds);
307 lib_assert(quotient < 10, "quotient cannot be > 9
");
308 return correctedEstimate;
316 DTOSTR_NORMAL, ///< Default formatting, choosing the shortest accurate representation.
317 DTOSTR_FIXED, ///< Fixed-point notation with a specified number of decimal places.
318 DTOSTR_PRECISION, ///< Precision mode with a specified number of significant digits.
319 DTOSTR_EXPONENTIAL ///< Scientific/exponential notation (e.g. 1.23e+4).
327 template<class t_type>
328 constexpr static void writeInt(String& string, t_type initial_value)
330 t_type value = initial_value;
331 constexpr uint04 max_digits = MaxDigits<t_type>() + (ObjectInfo<t_type>::Unsigned ? 0 : 1U);
332 char digits[max_digits];
333 uint04 index = max_digits;
334 if constexpr (!ObjectInfo<t_type>::Unsigned)
336 if (initial_value < cast<t_type>(0))
337 value = cast<t_type>(0) - value;
347 value = value / cast<t_type>(10);
348 j -= (value * cast<t_type>(10));
349 digits[--index] = (cast<char>(j) + '0');
350 if (value == cast<t_type>(0))
353 if constexpr ((!ObjectInfo<t_type>::Unsigned))
355 if(initial_value < cast<t_type>(0))
356 digits[--index] = '-';
358 string.addAll(&digits[index], max_digits - index);
366 template<class t_type>
367 constexpr static void writeHex(String& string, t_type initial_value)
369 t_type value = initial_value;
370 constexpr uint04 max_digits = MaxDigits<t_type>() + (ObjectInfo<t_type>::Unsigned ? 0 : 1U);
371 char digits[max_digits];
372 uint04 index = max_digits;
373 if ((!ObjectInfo<t_type>::Unsigned) && initial_value < cast<t_type>(0))
375 value = cast<t_type>(0) - value;
385 value = value / cast<t_type>(16);
386 j -= (value * cast<t_type>(16));
389 digits[--index] = '0' + cast<char>(j);
394 case 10: digits[--index] = 'A'; break;
395 case 11: digits[--index] = 'B'; break;
396 case 12: digits[--index] = 'C'; break;
397 case 13: digits[--index] = 'D'; break;
398 case 14: digits[--index] = 'E'; break;
399 case 15: digits[--index] = 'F'; break;
402 if (value == cast<t_type>(0))
405 string.addAll(&digits[index], max_digits - index);
415 static void writeFloat(String& string, fltp08 value, flt_to_string mode = DTOSTR_NORMAL, uint01 precision = 10)
417 if (value > Constant<fltp08>::Max)
419 string.addAll("-Infinity
");
422 if (value < Constant<fltp08>::Min)
424 string.addAll("Infinity
");
427 if (IsInvalid(value))
429 string.addAll("NaN
");
432 if (mode == DTOSTR_NORMAL)
434 sint08 intValue = cast<sint08>(value);
435 if ((value == (double)(intValue)) && ((uint32_t)intValue != 0x80000000))
437 writeInt(string, intValue);
441 const bool negative = value < 0.0;
442 const bool zero = value == 0.0;
447 D2A d2a = D2A(value, mode != DTOSTR_NORMAL, precision);
448 int32_t exp10 = d2a.expBase10() - 1;
454 kNormal, ///< Standard decimal notation.
455 kExponential, ///< Scientific notation with exponent.
456 kFraction, ///< Fractional form (0.xxxx).
457 kFixedFraction ///< Fixed fractional form with specified decimal places.
465 format = kFixedFraction;
473 case DTOSTR_PRECISION:
478 else if (exp10 >= precision) {
479 format = kExponential;
486 case DTOSTR_EXPONENTIAL:
487 format = kExponential;
491 if (exp10 < 0 && exp10 > -7) {
492 // Number is of form 0.######
493 if (exp10 < -precision) {
494 exp10 = -precision - 1;
498 else if (std::abs(exp10) > 20) { // ECMA spec 9.8.1
499 format = kExponential;
512 digit = d2a.nextDigit();
514 string.add((char)(digit + '0'));
517 digit = (d2a.finished) ? 0 : d2a.nextDigit();
518 string.add((char)(digit + '0'));
522 if (mode == DTOSTR_FIXED)
526 if (mode == DTOSTR_NORMAL)
531 while (!d2a.finished)
532 string.add((char)(d2a.nextDigit() + '0'));
535 else if (digits < precision - 1)
538 for (; digits < precision - 1; digits++)
540 digit = d2a.finished ? 0 : d2a.nextDigit();
541 string.add((char)(digit + '0'));
548 string.add('0'); // Sentinel
550 // Write out leading zeroes
553 while (++exp10 < 10 && digits < precision) {
558 else if (exp10 < 0) {
559 while ((++exp10 < 0) && (precision-- > 0))
562 if (IsValid(precision))
564 // Write out significand
565 for (; digits < precision; digits++) {
568 if (mode == DTOSTR_NORMAL)
573 string.add((char)(d2a.nextDigit() + '0'));
582 string.add('0'); // Sentinel
585 // Write out leading zeros
588 for (int32_t i = exp10; i < -1; i++) {
593 // Write out significand
595 while (!d2a.finished)
597 string.add((char)(d2a.nextDigit() + '0'));
598 if (mode != DTOSTR_NORMAL && ++i >= precision)
601 if (mode == DTOSTR_PRECISION)
603 while (i++ < precision)
604 string.add((char)(d2a.finished ? '0' : d2a.nextDigit() + '0'));
612 digit = d2a.finished ? 0 : d2a.nextDigit();
613 string.add((char)(digit + '0'));
614 if (((mode == DTOSTR_NORMAL) && !d2a.finished) ||
615 ((mode != DTOSTR_NORMAL) && precision > 1)) {
617 for (int32_t i = 0; i < precision - 1; i++) {
620 if (mode == DTOSTR_NORMAL)
625 string.add((char)(d2a.nextDigit() + '0'));
632 // Clean up zeroes, and place the exponent
637 // Remove trailing zeroes, as might appear in 10e+95
638 while (string.size() > 0 && string.last() == '0')
645 // Place the exponent
650 writeInt(string, exp10);