return hi + carry, mid, lo
}
-// pow10 returns the 128-bit mantissa and binary exponent of 10**e
+// pow10 returns the 128-bit mantissa and binary exponent of 10**e.
+// That is, 10^e = mant/2^128 * 2**exp.
// If e is out of range, pow10 returns ok=false.
func pow10(e int) (mant uint128, exp int, ok bool) {
if e < pow10Min || e > pow10Max {
return
}
- return pow10Tab[e-pow10Min], mulLog2_10(e), true
+ return pow10Tab[e-pow10Min], 1 + mulLog2_10(e), true
}
// mulLog10_2 returns math.Floor(x * log(2)/log(10)) for an integer x in
package strconv_test
import (
- "math"
. "internal/strconv"
+ "math"
"testing"
)
ok bool
}{
{-349, uint128{0, 0}, 0, false},
- {-348, uint128{0xFA8FD5A0081C0288, 0x1732C869CD60E453}, -1157, true},
- {0, uint128{0x8000000000000000, 0x0000000000000000}, 0, true},
- {347, uint128{0xD13EB46469447567, 0x4B7195F2D2D1A9FB}, 1152, true},
+ {-348, uint128{0xFA8FD5A0081C0288, 0x1732C869CD60E453}, -1156, true},
+ {0, uint128{0x8000000000000000, 0x0000000000000000}, 1, true},
+ {347, uint128{0xD13EB46469447567, 0x4B7195F2D2D1A9FB}, 1153, true},
{348, uint128{0, 0}, 0, false},
}
func TestPow10(t *testing.T) {
for _, tt := range pow10Tests {
- mant, exp2, ok := Pow10(tt.exp10)
+ mant, exp2, ok := pow10(tt.exp10)
if mant != tt.mant || exp2 != tt.exp2 {
t.Errorf("pow10(%d) = %#016x, %#016x, %d, %v want %#016x,%#016x, %d, %v",
tt.exp10, mant.Hi, mant.Lo, exp2, ok,
tt.mant.Hi, tt.mant.Lo, tt.exp2, tt.ok)
}
}
+
+ for p := pow10Min; p <= pow10Max; p++ {
+ mant, exp2, ok := pow10(p)
+ if !ok {
+ t.Errorf("pow10(%d) not ok", p)
+ continue
+ }
+ // Note: -64 instead of -128 because we only used mant.Hi, not all of mant.
+ have := math.Ldexp(float64(mant.Hi), exp2-64)
+ want := math.Pow(10, float64(p))
+ if math.Abs(have-want)/want > 0.00001 {
+ t.Errorf("pow10(%d) = %#016x%016x/2^128 * 2^%d = %g want ~%g", p, mant.Hi, mant.Lo, exp2, have, want)
+ }
+ }
+
}
func u128(hi, lo uint64) uint128 {