@@ -218,6 +218,109 @@ func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int
218
218
d .dp = d .nd + trimmed
219
219
}
220
220
221
+ // ryuFtoaShortest formats mant*2^exp with prec decimal digits.
222
+ func ryuFtoaShortest (d * decimalSlice , mant uint64 , exp int , flt * floatInfo ) {
223
+ if mant == 0 {
224
+ d .nd , d .dp = 0 , 0
225
+ return
226
+ }
227
+ // If input is an exact integer with fewer bits than the mantissa,
228
+ // the previous and next integer are not admissible representations.
229
+ if exp <= 0 && bits .TrailingZeros64 (mant ) >= - exp {
230
+ mant >>= uint (- exp )
231
+ ryuDigits (d , mant , mant , mant , true , false )
232
+ return
233
+ }
234
+ ml , mc , mu , e2 := computeBounds (mant , exp , flt )
235
+ if e2 == 0 {
236
+ ryuDigits (d , ml , mc , mu , true , false )
237
+ return
238
+ }
239
+ // Find 10^q *larger* than 2^-e2
240
+ q := mulByLog2Log10 (- e2 ) + 1
241
+
242
+ // We are going to multiply by 10^q using 128-bit arithmetic.
243
+ // The exponent is the same for all 3 numbers.
244
+ var dl , dc , du uint64
245
+ var dl0 , dc0 , du0 bool
246
+ if flt == & float32info {
247
+ var dl32 , dc32 , du32 uint32
248
+ dl32 , _ , dl0 = mult64bitPow10 (uint32 (ml ), e2 , q )
249
+ dc32 , _ , dc0 = mult64bitPow10 (uint32 (mc ), e2 , q )
250
+ du32 , e2 , du0 = mult64bitPow10 (uint32 (mu ), e2 , q )
251
+ dl , dc , du = uint64 (dl32 ), uint64 (dc32 ), uint64 (du32 )
252
+ } else {
253
+ dl , _ , dl0 = mult128bitPow10 (ml , e2 , q )
254
+ dc , _ , dc0 = mult128bitPow10 (mc , e2 , q )
255
+ du , e2 , du0 = mult128bitPow10 (mu , e2 , q )
256
+ }
257
+ if e2 >= 0 {
258
+ panic ("not enough significant bits after mult128bitPow10" )
259
+ }
260
+ // Is it an exact computation?
261
+ if q > 55 {
262
+ // Large positive powers of ten are not exact
263
+ dl0 , dc0 , du0 = false , false , false
264
+ }
265
+ if q < 0 && q >= - 24 {
266
+ // Division by a power of ten may be exact.
267
+ // (note that 5^25 is a 59-bit number so division by 5^25 is never exact).
268
+ if divisibleByPower5 (ml , - q ) {
269
+ dl0 = true
270
+ }
271
+ if divisibleByPower5 (mc , - q ) {
272
+ dc0 = true
273
+ }
274
+ if divisibleByPower5 (mu , - q ) {
275
+ du0 = true
276
+ }
277
+ }
278
+ // Express the results (dl, dc, du)*2^e2 as integers.
279
+ // Extra bits must be removed and rounding hints computed.
280
+ extra := uint (- e2 )
281
+ extraMask := uint64 (1 << extra - 1 )
282
+ // Now compute the floored, integral base 10 mantissas.
283
+ dl , fracl := dl >> extra , dl & extraMask
284
+ dc , fracc := dc >> extra , dc & extraMask
285
+ du , fracu := du >> extra , du & extraMask
286
+ // Is it allowed to use 'du' as a result?
287
+ // It is always allowed when it is truncated, but also
288
+ // if it is exact and the original binary mantissa is even
289
+ // When disallowed, we can substract 1.
290
+ uok := ! du0 || fracu > 0
291
+ if du0 && fracu == 0 {
292
+ uok = mant & 1 == 0
293
+ }
294
+ if ! uok {
295
+ du --
296
+ }
297
+ // Is 'dc' the correctly rounded base 10 mantissa?
298
+ // The correct rounding might be dc+1
299
+ cup := false // don't round up.
300
+ if dc0 {
301
+ // If we computed an exact product, the half integer
302
+ // should round to next (even) integer if 'dc' is odd.
303
+ cup = fracc > 1 << (extra - 1 ) ||
304
+ (fracc == 1 << (extra - 1 ) && dc & 1 == 1 )
305
+ } else {
306
+ // otherwise, the result is a lower truncation of the ideal
307
+ // result.
308
+ cup = fracc >> (extra - 1 ) == 1
309
+ }
310
+ // Is 'dl' an allowed representation?
311
+ // Only if it is an exact value, and if the original binary mantissa
312
+ // was even.
313
+ lok := dl0 && fracl == 0 && (mant & 1 == 0 )
314
+ if ! lok {
315
+ dl ++
316
+ }
317
+ // We need to remember whether the trimmed digits of 'dc' are zero.
318
+ c0 := dc0 && fracc == 0
319
+ // render digits
320
+ ryuDigits (d , dl , dc , du , c0 , cup )
321
+ d .dp -= q
322
+ }
323
+
221
324
// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in
222
325
// the range -1600 <= x && x <= +1600.
223
326
//
@@ -238,6 +341,140 @@ func mulByLog10Log2(x int) int {
238
341
return (x * 108853 ) >> 15
239
342
}
240
343
344
+ // computeBounds returns a floating-point vector (l, c, u)×2^e2
345
+ // where the mantissas are 55-bit (or 26-bit) integers, describing the interval
346
+ // represented by the input float64 or float32.
347
+ func computeBounds (mant uint64 , exp int , flt * floatInfo ) (lower , central , upper uint64 , e2 int ) {
348
+ if mant != 1 << flt .mantbits || exp == flt .bias + 1 - int (flt .mantbits ) {
349
+ // regular case (or denormals)
350
+ lower , central , upper = 2 * mant - 1 , 2 * mant , 2 * mant + 1
351
+ e2 = exp - 1
352
+ return
353
+ } else {
354
+ // border of an exponent
355
+ lower , central , upper = 4 * mant - 1 , 4 * mant , 4 * mant + 2
356
+ e2 = exp - 2
357
+ return
358
+ }
359
+ }
360
+
361
+ func ryuDigits (d * decimalSlice , lower , central , upper uint64 ,
362
+ c0 , cup bool ) {
363
+ lhi , llo := divmod1e9 (lower )
364
+ chi , clo := divmod1e9 (central )
365
+ uhi , ulo := divmod1e9 (upper )
366
+ if uhi == 0 {
367
+ // only low digits (for denormals)
368
+ ryuDigits32 (d , llo , clo , ulo , c0 , cup , 8 )
369
+ } else if lhi < uhi {
370
+ // truncate 9 digits at once.
371
+ if llo != 0 {
372
+ lhi ++
373
+ }
374
+ c0 = c0 && clo == 0
375
+ cup = (clo > 5e8 ) || (clo == 5e8 && cup )
376
+ ryuDigits32 (d , lhi , chi , uhi , c0 , cup , 8 )
377
+ d .dp += 9
378
+ } else {
379
+ d .nd = 0
380
+ // emit high part
381
+ n := uint (9 )
382
+ for v := chi ; v > 0 ; {
383
+ v1 , v2 := v / 10 , v % 10
384
+ v = v1
385
+ n --
386
+ d .d [n ] = byte (v2 + '0' )
387
+ }
388
+ d .d = d .d [n :]
389
+ d .nd = int (9 - n )
390
+ // emit low part
391
+ ryuDigits32 (d , llo , clo , ulo ,
392
+ c0 , cup , d .nd + 8 )
393
+ }
394
+ // trim trailing zeros
395
+ for d .nd > 0 && d .d [d .nd - 1 ] == '0' {
396
+ d .nd --
397
+ }
398
+ // trim initial zeros
399
+ for d .nd > 0 && d .d [0 ] == '0' {
400
+ d .nd --
401
+ d .dp --
402
+ d .d = d .d [1 :]
403
+ }
404
+ }
405
+
406
+ // ryuDigits32 emits decimal digits for a number less than 1e9.
407
+ func ryuDigits32 (d * decimalSlice , lower , central , upper uint32 ,
408
+ c0 , cup bool , endindex int ) {
409
+ if upper == 0 {
410
+ d .dp = endindex + 1
411
+ return
412
+ }
413
+ trimmed := 0
414
+ // Remember last trimmed digit to check for round-up.
415
+ // c0 will be used to remember zeroness of following digits.
416
+ cNextDigit := 0
417
+ for upper > 0 {
418
+ // Repeatedly compute:
419
+ // l = Ceil(lower / 10^k)
420
+ // c = Round(central / 10^k)
421
+ // u = Floor(upper / 10^k)
422
+ // and stop when c goes out of the (l, u) interval.
423
+ l := (lower + 9 ) / 10
424
+ c , cdigit := central / 10 , central % 10
425
+ u := upper / 10
426
+ if l > u {
427
+ // don't trim the last digit as it is forbidden to go below l
428
+ // other, trim and exit now.
429
+ break
430
+ }
431
+ // Check that we didn't cross the lower boundary.
432
+ // The case where l < u but c == l-1 is essentially impossible,
433
+ // but may happen if:
434
+ // lower = ..11
435
+ // central = ..19
436
+ // upper = ..31
437
+ // and means that 'central' is very close but less than
438
+ // an integer ending with many zeros, and usually
439
+ // the "round-up" logic hides the problem.
440
+ if l == c + 1 && c < u {
441
+ c ++
442
+ cdigit = 0
443
+ cup = false
444
+ }
445
+ trimmed ++
446
+ // Remember trimmed digits of c
447
+ c0 = c0 && cNextDigit == 0
448
+ cNextDigit = int (cdigit )
449
+ lower , central , upper = l , c , u
450
+ }
451
+ // should we round up?
452
+ if trimmed > 0 {
453
+ cup = cNextDigit > 5 ||
454
+ (cNextDigit == 5 && ! c0 ) ||
455
+ (cNextDigit == 5 && c0 && central & 1 == 1 )
456
+ }
457
+ if central < upper && cup {
458
+ central ++
459
+ }
460
+ // We know where the number ends, fill directly
461
+ endindex -= trimmed
462
+ v := central
463
+ n := endindex
464
+ for n > d .nd {
465
+ v1 , v2 := v / 100 , v % 100
466
+ d .d [n ] = smallsString [2 * v2 + 1 ]
467
+ d .d [n - 1 ] = smallsString [2 * v2 + 0 ]
468
+ n -= 2
469
+ v = v1
470
+ }
471
+ if n == d .nd {
472
+ d .d [n ] = byte (v + '0' )
473
+ }
474
+ d .nd = endindex + 1
475
+ d .dp = d .nd + trimmed
476
+ }
477
+
241
478
// mult64bitPow10 takes a floating-point input with a 25-bit
242
479
// mantissa and multiplies it with 10^q. The resulting mantissa
243
480
// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables.
@@ -249,7 +486,8 @@ func mulByLog10Log2(x int) int {
249
486
// exact = ε == 0
250
487
func mult64bitPow10 (m uint32 , e2 , q int ) (resM uint32 , resE int , exact bool ) {
251
488
if q == 0 {
252
- return m << 7 , e2 - 7 , true
489
+ // P == 1<<63
490
+ return m << 6 , e2 - 6 , true
253
491
}
254
492
if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q {
255
493
// This never happens due to the range of float32/float64 exponent
@@ -276,7 +514,8 @@ func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) {
276
514
// exact = ε == 0
277
515
func mult128bitPow10 (m uint64 , e2 , q int ) (resM uint64 , resE int , exact bool ) {
278
516
if q == 0 {
279
- return m << 9 , e2 - 9 , true
517
+ // P == 1<<127
518
+ return m << 8 , e2 - 8 , true
280
519
}
281
520
if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q {
282
521
// This never happens due to the range of float32/float64 exponent
@@ -309,3 +548,15 @@ func divisibleByPower5(m uint64, k int) bool {
309
548
}
310
549
return true
311
550
}
551
+
552
+ // divmod1e9 computes quotient and remainder of division by 1e9,
553
+ // avoiding runtime uint64 division on 32-bit platforms.
554
+ func divmod1e9 (x uint64 ) (uint32 , uint32 ) {
555
+ if ! host32bit {
556
+ return uint32 (x / 1e9 ), uint32 (x % 1e9 )
557
+ }
558
+ // Use the same sequence of operations as the amd64 compiler.
559
+ hi , _ := bits .Mul64 (x >> 1 , 0x89705f4136b4a598 ) // binary digits of 1e-9
560
+ q := hi >> 28
561
+ return uint32 (q ), uint32 (x - q * 1e9 )
562
+ }
0 commit comments