4 #include "util/math/float2decimal.h" 5 #include "base/logging.h" 7 #define FAST_DTOA_UNREACHABLE() __builtin_unreachable(); 90 constexpr
int const kAlpha = -60;
91 constexpr
int const kGamma = -32;
147 CachedPower GetCachedPowerForBinaryExponent(
int e) {
151 static constexpr CachedPower
const kCachedPowers[] = {
152 {0xAB70FE17C79AC6CA, -1060, -300},
153 {0xFF77B1FCBEBCDC4F, -1034, -292}, {0xBE5691EF416BD60C, -1007, -284},
154 {0x8DD01FAD907FFC3C, -980, -276}, {0xD3515C2831559A83, -954, -268},
155 {0x9D71AC8FADA6C9B5, -927, -260}, {0xEA9C227723EE8BCB, -901, -252},
156 {0xAECC49914078536D, -874, -244}, {0x823C12795DB6CE57, -847, -236},
157 {0xC21094364DFB5637, -821, -228}, {0x9096EA6F3848984F, -794, -220},
158 {0xD77485CB25823AC7, -768, -212}, {0xA086CFCD97BF97F4, -741, -204},
159 {0xEF340A98172AACE5, -715, -196}, {0xB23867FB2A35B28E, -688, -188},
160 {0x84C8D4DFD2C63F3B, -661, -180}, {0xC5DD44271AD3CDBA, -635, -172},
161 {0x936B9FCEBB25C996, -608, -164}, {0xDBAC6C247D62A584, -582, -156},
162 {0xA3AB66580D5FDAF6, -555, -148}, {0xF3E2F893DEC3F126, -529, -140},
163 {0xB5B5ADA8AAFF80B8, -502, -132}, {0x87625F056C7C4A8B, -475, -124},
164 {0xC9BCFF6034C13053, -449, -116}, {0x964E858C91BA2655, -422, -108},
165 {0xDFF9772470297EBD, -396, -100}, {0xA6DFBD9FB8E5B88F, -369, -92},
166 {0xF8A95FCF88747D94, -343, -84}, {0xB94470938FA89BCF, -316, -76},
167 {0x8A08F0F8BF0F156B, -289, -68}, {0xCDB02555653131B6, -263, -60},
168 {0x993FE2C6D07B7FAC, -236, -52}, {0xE45C10C42A2B3B06, -210, -44},
169 {0xAA242499697392D3, -183, -36},
170 {0xFD87B5F28300CA0E, -157, -28},
171 {0xBCE5086492111AEB, -130, -20},
172 {0x8CBCCC096F5088CC, -103, -12},
173 {0xD1B71758E219652C, -77, -4},
174 {0x9C40000000000000, -50, 4},
175 {0xE8D4A51000000000, -24, 12},
176 {0xAD78EBC5AC620000, 3, 20},
177 {0x813F3978F8940984, 30, 28},
178 {0xC097CE7BC90715B3, 56, 36},
179 {0x8F7E32CE7BEA5C70, 83, 44},
180 {0xD5D238A4ABE98068, 109, 52}, {0x9F4F2726179A2245, 136, 60},
181 {0xED63A231D4C4FB27, 162, 68}, {0xB0DE65388CC8ADA8, 189, 76},
182 {0x83C7088E1AAB65DB, 216, 84}, {0xC45D1DF942711D9A, 242, 92},
183 {0x924D692CA61BE758, 269, 100}, {0xDA01EE641A708DEA, 295, 108},
184 {0xA26DA3999AEF774A, 322, 116}, {0xF209787BB47D6B85, 348, 124},
185 {0xB454E4A179DD1877, 375, 132}, {0x865B86925B9BC5C2, 402, 140},
186 {0xC83553C5C8965D3D, 428, 148}, {0x952AB45CFA97A0B3, 455, 156},
187 {0xDE469FBD99A05FE3, 481, 164}, {0xA59BC234DB398C25, 508, 172},
188 {0xF6C69A72A3989F5C, 534, 180}, {0xB7DCBF5354E9BECE, 561, 188},
189 {0x88FCF317F22241E2, 588, 196}, {0xCC20CE9BD35C78A5, 614, 204},
190 {0x98165AF37B2153DF, 641, 212}, {0xE2A0B5DC971F303A, 667, 220},
191 {0xA8D9D1535CE3B396, 694, 228}, {0xFB9B7CD9A4A7443C, 720, 236},
192 {0xBB764C4CA7A44410, 747, 244}, {0x8BAB8EEFB6409C1A, 774, 252},
193 {0xD01FEF10A657842C, 800, 260}, {0x9B10A4E5E9913129, 827, 268},
194 {0xE7109BFBA19C0C9D, 853, 276}, {0xAC2820D9623BF429, 880, 284},
195 {0x80444B5E7AA7CF85, 907, 292}, {0xBF21E44003ACDD2D, 933, 300},
196 {0x8E679C2F5E44FF8F, 960, 308}, {0xD433179D9C8CB841, 986, 316},
197 {0x9E19DB92B4E31BA9, 1013, 324},
200 constexpr
int const kCachedPowersSize = 79;
201 constexpr
int const kCachedPowersMinDecExp = -300;
211 int const f = kAlpha - e - 1;
212 int const k = (f * 78913) / (1 << 18) + (f > 0);
214 int const index = (-kCachedPowersMinDecExp + k + (8 - 1)) / 8;
216 assert(index < kCachedPowersSize);
217 static_cast<void>(kCachedPowersSize);
219 CachedPower
const cached = kCachedPowers[index];
220 assert(kAlpha <= cached.e + e + 64);
221 assert(kGamma >= cached.e + e + 64);
231 inline unsigned InitKappa(uint32_t n) {
232 return base::CountDecimalDigit32(n);
235 inline void Grisu2Round(
char& digit, uint64_t dist, uint64_t delta, uint64_t rest,
239 assert(dist <= delta);
240 assert(rest <= delta);
261 while (rest < dist && delta - rest >= ten_k &&
262 (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
263 DCHECK_NE(
'0', digit);
269 void SetDigits(uint32_t value,
unsigned num_digits,
char* buffer) {
270 const char DIGITS[] =
271 "0001020304050607080910111213141516171819" 272 "2021222324252627282930313233343536373839" 273 "4041424344454647484950515253545556575859" 274 "6061626364656667686970717273747576777879" 275 "8081828384858687888990919293949596979899";
277 buffer += num_digits;
279 while (value >= 100) {
283 unsigned index = static_cast<unsigned>((value % 100) * 2);
285 *--buffer = DIGITS[index + 1];
286 *--buffer = DIGITS[index];
289 *--buffer = static_cast<char>(
'0' + value);
292 unsigned index = static_cast<unsigned>(value * 2);
293 *--buffer = DIGITS[index + 1];
294 *--buffer = DIGITS[index];
297 std::pair<unsigned, int> Grisu2DigitGen(
char* buffer,
int decimal_exponent,
298 const Fp& M_minus,
const Fp& w,
const Fp& M_plus) {
299 static constexpr
char const*
const kDigits =
"0123456789";
301 static_assert(kAlpha >= -60,
"invalid parameter");
302 static_assert(kGamma <= -32,
"invalid parameter");
304 assert(M_plus.e >= kAlpha);
305 assert(M_plus.e <= kGamma);
307 uint64_t delta = M_plus.f - M_minus.f;
308 uint64_t dist = M_plus.f - w.f;
323 const uint64_t e_shift = -M_plus.e;
324 const uint64_t e_mask = (1ULL << e_shift) - 1;
326 uint32_t p1 = M_plus.f >> e_shift;
327 uint64_t p2 = M_plus.f & e_mask;
336 unsigned kappa = InitKappa(p1);
357 bool cut_early = delta >= p2;
358 uint32_t length = kappa;
361 uint32_t p1_remainder = 0;
364 uint32_t delta_shifted = (delta - p2) >> e_shift;
365 bool check_increase_power =
true;
367 if (delta_shifted > 0) {
368 power = base::CountDecimalDigit32(delta_shifted);
369 ten_n = base::Power10(power);
370 p1_remainder = p1 % ten_n;
371 if (p1_remainder > delta_shifted) {
374 p1_remainder %= ten_n;
375 check_increase_power =
false;
377 DCHECK_LE(p1_remainder, delta_shifted);
382 if (check_increase_power) {
383 while (p1 % 10 == 0) {
391 SetDigits(p1, length, buffer);
396 decimal_exponent += power;
412 uint64_t rest = (uint64_t(p1_remainder) << e_shift) + p2;
413 uint64_t ten_n64 = uint64_t(ten_n) << e_shift;
415 while (rest < dist && delta - rest >= ten_n64 &&
416 ten_n64 / 2 < (dist - rest)) {
417 DCHECK_NE(
'0', buffer[length-1]);
423 return std::pair<unsigned, int>(length, decimal_exponent);
426 SetDigits(p1, length, buffer);
456 DCHECK_GT(p2, delta);
464 DCHECK_LE(p2, e_mask);
467 uint64_t
const d = p2 >> e_shift;
468 uint64_t
const r = p2 & e_mask;
477 buffer[length++] = kDigits[d];
493 uint64_t
const rest = p2;
497 decimal_exponent += m;
513 uint64_t
const ten_m = 1ULL << e_shift;
514 Grisu2Round(buffer[length-1], dist, delta, rest, ten_m);
515 return std::pair<unsigned, int>(length, decimal_exponent);
538 std::pair<unsigned, int> Grisu2(Fp m_minus, Fp v, Fp m_plus,
char* buf) {
539 assert(v.e == m_minus.e);
540 assert(v.e == m_plus.e);
552 CachedPower
const cached = GetCachedPowerForBinaryExponent(m_plus.e);
554 Fp
const c_minus_k(cached.f, cached.e);
556 Fp
const w = v.Mul(c_minus_k);
557 Fp
const w_minus = m_minus.Mul(c_minus_k);
558 Fp
const w_plus = m_plus.Mul(c_minus_k);
583 Fp
const M_minus = Fp(w_minus.f + 1, w_minus.e);
584 Fp
const M_plus = Fp(w_plus.f - 1, w_plus.e);
586 return Grisu2DigitGen(buf, -cached.k, M_minus, w, M_plus);
594 char* AppendExponent(
char* buf,
int e) {
595 static constexpr
char const*
const kDigits =
"0123456789";
596 static constexpr
char const*
const kDigits100 =
597 "00010203040506070809" 598 "10111213141516171819" 599 "20212223242526272829" 600 "30313233343536373839" 601 "40414243444546474849" 602 "50515253545556575859" 603 "60616263646566676869" 604 "70717273747576777879" 605 "80818283848586878889" 606 "90919293949596979899";
612 *buf++ =
'-', e = -e;
616 uint32_t
const k = static_cast<uint32_t>(e);
620 }
else if (k < 100) {
621 *buf++ = kDigits100[2 * k + 0];
622 *buf++ = kDigits100[2 * k + 1];
624 uint32_t
const q = k / 100;
625 uint32_t
const r = k % 100;
627 *buf++ = kDigits100[2 * r + 0];
628 *buf++ = kDigits100[2 * r + 1];
634 char* FormatBuffer(
char* buf,
int k,
int n) {
645 if (k <= n && n <= 21) {
648 std::memset(buf + k,
'0', static_cast<size_t>(n - k));
657 if (0 < n && n <= 21) {
661 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
663 return buf + (k + 1);
666 if (-6 < n && n <= 0) {
669 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
672 std::memset(buf + 2,
'0', static_cast<size_t>(-n));
673 return buf + (2 + (-n) + k);
683 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
689 return AppendExponent(buf, n - 1);