55#if !defined(HAVE_INT128) && defined(_MSC_VER) \
56 && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
57#define HAS_64_BIT_INTRINSICS
65#define DOUBLE_MANTISSA_BITS 52
66#define DOUBLE_EXPONENT_BITS 11
67#define DOUBLE_BIAS 1023
69#define DOUBLE_POW5_INV_BITCOUNT 122
70#define DOUBLE_POW5_BITCOUNT 121
158#if defined(HAVE_INT128)
164 const uint128 b0 = ((uint128) m) * mul[0];
165 const uint128 b2 = ((uint128) m) * mul[1];
167 return (
uint64) (((b0 >> 64) + b2) >> (
j - 64));
175 *vm =
mulShift(4 * m - 1 - mmShift, mul,
j);
179#elif defined(HAS_64_BIT_INTRINSICS)
212 *vm =
mulShift(4 * m - 1 - mmShift, mul,
j);
232 const uint64 lo2 = lo + mul[0];
233 const uint64 mid2 = mid + mul[1] + (lo2 < lo);
234 const uint64 hi2 = hi + (mid2 < mid);
240 const uint64 lo3 = lo - mul[0];
241 const uint64 mid3 = mid - mul[1] - (lo3 > lo);
242 const uint64 hi3 = hi - (mid3 > mid);
248 const uint64 lo3 = lo + lo;
249 const uint64 mid3 = mid + mid + (lo3 < lo);
250 const uint64 hi3 = hi + hi + (mid3 < mid);
251 const uint64 lo4 = lo3 - mul[0];
252 const uint64 mid4 = mid3 - mul[1] - (lo4 > lo3);
253 const uint64 hi4 = hi3 - (mid4 > mid3);
270 Assert(v < 100000000000000000L);
271 if (v >= 10000000000000000L)
275 if (v >= 1000000000000000L)
279 if (v >= 100000000000000L)
283 if (v >= 10000000000000L)
287 if (v >= 1000000000000L)
291 if (v >= 100000000000L)
295 if (v >= 10000000000L)
299 if (v >= 1000000000L)
351 if (ieeeExponent == 0)
364 const bool even = (m2 & 1) == 0;
365 const bool acceptBounds = even;
367 const bool acceptBounds =
false;
374 const uint32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
385 bool vmIsTrailingZeros =
false;
386 bool vrIsTrailingZeros =
false;
398 const int32 i = -e2 + q + k;
419 else if (acceptBounds)
457 vrIsTrailingZeros =
true;
464 vmIsTrailingZeros = mmShift == 1;
497 uint8 lastRemovedDigit = 0;
501 if (vmIsTrailingZeros || vrIsTrailingZeros)
509 if (vpDiv10 <= vmDiv10)
516 vmIsTrailingZeros &= vmMod10 == 0;
517 vrIsTrailingZeros &= lastRemovedDigit == 0;
518 lastRemovedDigit = (
uint8) vrMod10;
525 if (vmIsTrailingZeros)
539 vrIsTrailingZeros &= lastRemovedDigit == 0;
540 lastRemovedDigit = (
uint8) vrMod10;
548 if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
551 lastRemovedDigit = 4;
558 output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
566 bool roundUp =
false;
570 if (vpDiv100 > vmDiv100)
576 roundUp = vrMod100 >= 50;
601 if (vpDiv10 <= vmDiv10)
607 roundUp = vrMod10 >= 5;
618 output = vr + (vr == vm || roundUp);
621 const int32 exp = e10 + removed;
653 int32 nexp = exp + olength;
662 memcpy(result,
"0.000000", 8);
678 Assert(exp < 16 && exp + olength <= 16);
679 memset(result,
'0', 16);
692 const uint32 c = output2 % 10000;
697 const uint32 d = output2 % 10000;
698 const uint32 c0 = (
c % 100) << 1;
699 const uint32 c1 = (
c / 100) << 1;
700 const uint32 d0 = (d % 100) << 1;
701 const uint32 d1 = (d / 100) << 1;
712 while (output2 >= 10000)
714 const uint32 c = output2 - 10000 * (output2 / 10000);
715 const uint32 c0 = (
c % 100) << 1;
716 const uint32 c1 = (
c / 100) << 1;
725 const uint32 c = (output2 % 100) << 1;
739 result[
index] = (char) (
'0' + output2);
753 memmove(result +
index - 1, result +
index, 8);
758 memmove(result +
index - 1, result +
index, 4);
763 memmove(result +
index - 1, result +
index, 2);
776 index = olength + exp;
780 index = olength + (2 - nexp);
798 result[
index++] =
'-';
806 if (exp >= -4 && exp < 15)
867 const uint32 c = output2 % 10000;
871 const uint32 d = output2 % 10000;
872 const uint32 c0 = (
c % 100) << 1;
873 const uint32 c1 = (
c / 100) << 1;
874 const uint32 d0 = (d % 100) << 1;
875 const uint32 d1 = (d / 100) << 1;
886 while (output2 >= 10000)
888 const uint32 c = output2 - 10000 * (output2 / 10000);
892 const uint32 c0 = (
c % 100) << 1;
893 const uint32 c1 = (
c / 100) << 1;
901 const uint32 c = (output2 % 100) << 1;
920 result[
index] = (char) (
'0' + output2);
926 result[
index + 1] =
'.';
927 index += olength + 1;
935 result[
index++] =
'e';
938 result[
index++] =
'-';
942 result[
index++] =
'+';
949 result[
index + 2] = (char) (
'0' +
c);
963 const uint32 ieeeExponent,
986 const uint64 fraction = ieeeMantissa & mask;
1029 if (ieeeExponent == ((1u <<
DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0))
1031 return copy_special_str(result, ieeeSign, (ieeeExponent != 0), (ieeeMantissa != 0));
1035 const bool isSmallInt =
d2d_small_int(ieeeMantissa, ieeeExponent, &v);
1039 v =
d2d(ieeeMantissa, ieeeExponent);
1042 return to_chars(v, ieeeSign, result);
1059 result[
index] =
'\0';
int double_to_shortest_decimal_bufn(double f, char *result)
#define DOUBLE_POW5_BITCOUNT
static int to_chars_df(const floating_decimal_64 v, const uint32 olength, char *const result)
#define DOUBLE_POW5_INV_BITCOUNT
#define DOUBLE_EXPONENT_BITS
static floating_decimal_64 d2d(const uint64 ieeeMantissa, const uint32 ieeeExponent)
static uint64 mulShiftAll(uint64 m, const uint64 *const mul, const int32 j, uint64 *const vp, uint64 *const vm, const uint32 mmShift)
static bool multipleOfPowerOf5(const uint64 value, const uint32 p)
struct floating_decimal_64 floating_decimal_64
#define DOUBLE_MANTISSA_BITS
static bool multipleOfPowerOf2(const uint64 value, const uint32 p)
static uint32 pow5Factor(uint64 value)
static uint32 decimalLength(const uint64 v)
static bool d2d_small_int(const uint64 ieeeMantissa, const uint32 ieeeExponent, floating_decimal_64 *v)
int double_to_shortest_decimal_buf(double f, char *result)
static int to_chars(floating_decimal_64 v, const bool sign, char *const result)
char * double_to_shortest_decimal(double f)
static const uint64 DOUBLE_POW5_SPLIT[326][2]
static const uint64 DOUBLE_POW5_INV_SPLIT[292][2]
static uint64 div1e8(const uint64 x)
static uint64 div10(const uint64 x)
static uint64 umul128(const uint64 a, const uint64 b, uint64 *const productHi)
static uint64 div5(const uint64 x)
static uint64 shiftright128(const uint64 lo, const uint64 hi, const uint32 dist)
static uint64 div100(const uint64 x)
static uint32 mulShift(const uint32 m, const uint64 factor, const int32 shift)
Assert(PointerIsAligned(start, uint64))
static const char DIGIT_TABLE[200]
static int fd(const char *x, int i)
static uint64 double_to_bits(const double d)
static uint32 pow5bits(const int32 e)
static int32 log10Pow5(const int32 e)
static int copy_special_str(char *const result, const bool sign, const bool exponent, const bool mantissa)
static int32 log10Pow2(const int32 e)
#define DOUBLE_SHORTEST_DECIMAL_LEN