summaryrefslogtreecommitdiff
path: root/libgo/go/math
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2015-10-31 00:59:47 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-10-31 00:59:47 +0000
commitaf146490bb04205107cb23e301ec7a8ff927b5fc (patch)
tree13beeaed3698c61903fe93fb1ce70bd9b18d4e7f /libgo/go/math
parent725e1be3406315d9bcc8195d7eef0a7082b3c7cc (diff)
runtime: Remove now unnecessary pad field from ParFor.
It is not needed due to the removal of the ctx field. Reviewed-on: https://go-review.googlesource.com/16525 From-SVN: r229616
Diffstat (limited to 'libgo/go/math')
-rw-r--r--libgo/go/math/all_test.go90
-rw-r--r--libgo/go/math/big/accuracy_string.go17
-rw-r--r--libgo/go/math/big/arith.go103
-rw-r--r--libgo/go/math/big/arith_decl.go2
-rw-r--r--libgo/go/math/big/arith_decl_pure.go55
-rw-r--r--libgo/go/math/big/arith_test.go3
-rw-r--r--libgo/go/math/big/bits_test.go224
-rw-r--r--libgo/go/math/big/decimal.go264
-rw-r--r--libgo/go/math/big/decimal_test.go106
-rw-r--r--libgo/go/math/big/float.go1693
-rw-r--r--libgo/go/math/big/float_test.go1694
-rw-r--r--libgo/go/math/big/floatconv.go239
-rw-r--r--libgo/go/math/big/floatconv_test.go573
-rw-r--r--libgo/go/math/big/floatexample_test.go113
-rw-r--r--libgo/go/math/big/ftoa.go393
-rw-r--r--libgo/go/math/big/int.go331
-rw-r--r--libgo/go/math/big/int_test.go574
-rw-r--r--libgo/go/math/big/intconv.go228
-rw-r--r--libgo/go/math/big/intconv_test.go342
-rw-r--r--libgo/go/math/big/nat.go590
-rw-r--r--libgo/go/math/big/nat_test.go608
-rw-r--r--libgo/go/math/big/natconv.go495
-rw-r--r--libgo/go/math/big/natconv_test.go425
-rw-r--r--libgo/go/math/big/rat.go164
-rw-r--r--libgo/go/math/big/rat_test.go424
-rw-r--r--libgo/go/math/big/ratconv.go252
-rw-r--r--libgo/go/math/big/ratconv_test.go453
-rw-r--r--libgo/go/math/big/roundingmode_string.go16
-rw-r--r--libgo/go/math/cbrt.go91
-rw-r--r--libgo/go/math/const.go19
-rw-r--r--libgo/go/math/expm1.go8
-rw-r--r--libgo/go/math/log10.go5
-rw-r--r--libgo/go/math/nextafter.go16
-rw-r--r--libgo/go/math/rand/rand.go3
-rw-r--r--libgo/go/math/rand/rand_test.go13
-rw-r--r--libgo/go/math/rand/zipf.go6
-rw-r--r--libgo/go/math/sqrt.go6
37 files changed, 8618 insertions, 2020 deletions
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index 763efb2e647..e18e45e0202 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -946,16 +946,20 @@ var expSC = []float64{
var vfexpm1SC = []float64{
Inf(-1),
+ -710,
Copysign(0, -1),
0,
+ 710,
Inf(1),
NaN(),
}
var expm1SC = []float64{
-1,
+ -1,
Copysign(0, -1),
0,
Inf(1),
+ Inf(1),
NaN(),
}
@@ -991,6 +995,24 @@ var vffdimSC = [][2]float64{
{NaN(), Inf(1)},
{NaN(), NaN()},
}
+var nan = Float64frombits(0xFFF8000000000000) // SSE2 DIVSD 0/0
+var vffdim2SC = [][2]float64{
+ {Inf(-1), Inf(-1)},
+ {Inf(-1), Inf(1)},
+ {Inf(-1), nan},
+ {Copysign(0, -1), Copysign(0, -1)},
+ {Copysign(0, -1), 0},
+ {0, Copysign(0, -1)},
+ {0, 0},
+ {Inf(1), Inf(-1)},
+ {Inf(1), Inf(1)},
+ {Inf(1), nan},
+ {nan, Inf(-1)},
+ {nan, Copysign(0, -1)},
+ {nan, 0},
+ {nan, Inf(1)},
+ {nan, nan},
+}
var fdimSC = []float64{
NaN(),
0,
@@ -1708,8 +1730,10 @@ func tolerance(a, b, e float64) bool {
d = -d
}
- if a != 0 {
- e = e * a
+ // note: b is correct (expected) value, a is actual value.
+ // make error tolerance a fraction of b, not a.
+ if b != 0 {
+ e = e * b
if e < 0 {
e = -e
}
@@ -2015,6 +2039,11 @@ func TestDim(t *testing.T) {
t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i])
}
}
+ for i := 0; i < len(vffdim2SC); i++ {
+ if f := Dim(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fdimSC[i], f) {
+ t.Errorf("Dim(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fdimSC[i])
+ }
+ }
}
func TestFloor(t *testing.T) {
@@ -2041,6 +2070,11 @@ func TestMax(t *testing.T) {
t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i])
}
}
+ for i := 0; i < len(vffdim2SC); i++ {
+ if f := Max(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fmaxSC[i], f) {
+ t.Errorf("Max(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fmaxSC[i])
+ }
+ }
}
func TestMin(t *testing.T) {
@@ -2054,6 +2088,11 @@ func TestMin(t *testing.T) {
t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i])
}
}
+ for i := 0; i < len(vffdim2SC); i++ {
+ if f := Min(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fminSC[i], f) {
+ t.Errorf("Min(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fminSC[i])
+ }
+ }
}
func TestMod(t *testing.T) {
@@ -2606,7 +2645,7 @@ func TestLargeTan(t *testing.T) {
// Check that math constants are accepted by compiler
// and have right value (assumes strconv.ParseFloat works).
-// http://code.google.com/p/go/issues/detail?id=201
+// https://golang.org/issue/201
type floatTest struct {
val interface{}
@@ -2944,15 +2983,56 @@ func BenchmarkSinh(b *testing.B) {
}
}
+var Global float64
+
func BenchmarkSqrt(b *testing.B) {
+ x, y := 0.0, 10.0
+ for i := 0; i < b.N; i++ {
+ x += Sqrt(y)
+ }
+ Global = x
+}
+
+func BenchmarkSqrtIndirect(b *testing.B) {
+ x, y := 0.0, 10.0
+ f := Sqrt
for i := 0; i < b.N; i++ {
- Sqrt(10)
+ x += f(y)
}
+ Global = x
}
func BenchmarkSqrtGo(b *testing.B) {
+ x, y := 0.0, 10.0
+ for i := 0; i < b.N; i++ {
+ x += SqrtGo(y)
+ }
+ Global = x
+}
+
+func isPrime(i int) bool {
+ // Yes, this is a dumb way to write this code,
+ // but calling Sqrt repeatedly in this way demonstrates
+ // the benefit of using a direct SQRT instruction on systems
+ // that have one, whereas the obvious loop seems not to
+ // demonstrate such a benefit.
+ for j := 2; float64(j) <= Sqrt(float64(i)); j++ {
+ if i%j == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+func BenchmarkSqrtPrime(b *testing.B) {
+ any := false
for i := 0; i < b.N; i++ {
- SqrtGo(10)
+ if isPrime(100003) {
+ any = true
+ }
+ }
+ if any {
+ Global = 1
}
}
diff --git a/libgo/go/math/big/accuracy_string.go b/libgo/go/math/big/accuracy_string.go
new file mode 100644
index 00000000000..24ef7f10770
--- /dev/null
+++ b/libgo/go/math/big/accuracy_string.go
@@ -0,0 +1,17 @@
+// generated by stringer -type=Accuracy; DO NOT EDIT
+
+package big
+
+import "fmt"
+
+const _Accuracy_name = "BelowExactAbove"
+
+var _Accuracy_index = [...]uint8{0, 5, 10, 15}
+
+func (i Accuracy) String() string {
+ i -= -1
+ if i < 0 || i+1 >= Accuracy(len(_Accuracy_index)) {
+ return fmt.Sprintf("Accuracy(%d)", i+-1)
+ }
+ return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]]
+}
diff --git a/libgo/go/math/big/arith.go b/libgo/go/math/big/arith.go
index c5ff4252d50..d7ea8381e7c 100644
--- a/libgo/go/math/big/arith.go
+++ b/libgo/go/math/big/arith.go
@@ -52,8 +52,6 @@ func subWW_g(x, y, c Word) (z1, z0 Word) {
}
// z1<<_W + z0 = x*y
-func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) }
-
// Adapted from Warren, Hacker's Delight, p. 132.
func mulWW_g(x, y Word) (z1, z0 Word) {
x0 := x & _M2
@@ -72,7 +70,7 @@ func mulWW_g(x, y Word) (z1, z0 Word) {
// z1<<_W + z0 = x*y + c
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
- z1, zz0 := mulWW(x, y)
+ z1, zz0 := mulWW_g(x, y)
if z0 = zz0 + c; z0 < zz0 {
z1++
}
@@ -80,7 +78,6 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
}
// Length of x in bits.
-func bitLen(x Word) (n int) { return bitLen_g(x) }
func bitLen_g(x Word) (n int) {
for ; x >= 0x8000; x >>= 16 {
n += 16
@@ -110,21 +107,34 @@ func log2(x Word) int {
return bitLen(x) - 1
}
-// Number of leading zeros in x.
-func leadingZeros(x Word) uint {
+// nlz returns the number of leading zeros in x.
+func nlz(x Word) uint {
return uint(_W - bitLen(x))
}
-// q = (u1<<_W + u0 - r)/y
-func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) }
+// nlz64 returns the number of leading zeros in x.
+func nlz64(x uint64) uint {
+ switch _W {
+ case 32:
+ w := x >> 32
+ if w == 0 {
+ return 32 + nlz(Word(x))
+ }
+ return nlz(Word(w))
+ case 64:
+ return nlz(Word(x))
+ }
+ panic("unreachable")
+}
+// q = (u1<<_W + u0 - r)/y
// Adapted from Warren, Hacker's Delight, p. 152.
func divWW_g(u1, u0, v Word) (q, r Word) {
if u1 >= v {
return 1<<_W - 1, 1<<_W - 1
}
- s := leadingZeros(v)
+ s := nlz(v)
v <<= s
vn1 := v >> _W2
@@ -159,41 +169,85 @@ func divWW_g(u1, u0, v Word) (q, r Word) {
return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
}
-func addVV(z, x, y []Word) (c Word) { return addVV_g(z, x, y) }
+// Keep for performance debugging.
+// Using addWW_g is likely slower.
+const use_addWW_g = false
+
+// The resulting carry c is either 0 or 1.
func addVV_g(z, x, y []Word) (c Word) {
- for i := range z {
- c, z[i] = addWW_g(x[i], y[i], c)
+ if use_addWW_g {
+ for i := range z {
+ c, z[i] = addWW_g(x[i], y[i], c)
+ }
+ return
+ }
+
+ for i, xi := range x[:len(z)] {
+ yi := y[i]
+ zi := xi + yi + c
+ z[i] = zi
+ // see "Hacker's Delight", section 2-12 (overflow detection)
+ c = (xi&yi | (xi|yi)&^zi) >> (_W - 1)
}
return
}
-func subVV(z, x, y []Word) (c Word) { return subVV_g(z, x, y) }
+// The resulting carry c is either 0 or 1.
func subVV_g(z, x, y []Word) (c Word) {
- for i := range z {
- c, z[i] = subWW_g(x[i], y[i], c)
+ if use_addWW_g {
+ for i := range z {
+ c, z[i] = subWW_g(x[i], y[i], c)
+ }
+ return
+ }
+
+ for i, xi := range x[:len(z)] {
+ yi := y[i]
+ zi := xi - yi - c
+ z[i] = zi
+ // see "Hacker's Delight", section 2-12 (overflow detection)
+ c = (yi&^xi | (yi|^xi)&zi) >> (_W - 1)
}
return
}
-func addVW(z, x []Word, y Word) (c Word) { return addVW_g(z, x, y) }
+// The resulting carry c is either 0 or 1.
func addVW_g(z, x []Word, y Word) (c Word) {
+ if use_addWW_g {
+ c = y
+ for i := range z {
+ c, z[i] = addWW_g(x[i], c, 0)
+ }
+ return
+ }
+
c = y
- for i := range z {
- c, z[i] = addWW_g(x[i], c, 0)
+ for i, xi := range x[:len(z)] {
+ zi := xi + c
+ z[i] = zi
+ c = xi &^ zi >> (_W - 1)
}
return
}
-func subVW(z, x []Word, y Word) (c Word) { return subVW_g(z, x, y) }
func subVW_g(z, x []Word, y Word) (c Word) {
+ if use_addWW_g {
+ c = y
+ for i := range z {
+ c, z[i] = subWW_g(x[i], c, 0)
+ }
+ return
+ }
+
c = y
- for i := range z {
- c, z[i] = subWW_g(x[i], c, 0)
+ for i, xi := range x[:len(z)] {
+ zi := xi - c
+ z[i] = zi
+ c = (zi &^ xi) >> (_W - 1)
}
return
}
-func shlVU(z, x []Word, s uint) (c Word) { return shlVU_g(z, x, s) }
func shlVU_g(z, x []Word, s uint) (c Word) {
if n := len(z); n > 0 {
ŝ := _W - s
@@ -209,7 +263,6 @@ func shlVU_g(z, x []Word, s uint) (c Word) {
return
}
-func shrVU(z, x []Word, s uint) (c Word) { return shrVU_g(z, x, s) }
func shrVU_g(z, x []Word, s uint) (c Word) {
if n := len(z); n > 0 {
ŝ := _W - s
@@ -225,7 +278,6 @@ func shrVU_g(z, x []Word, s uint) (c Word) {
return
}
-func mulAddVWW(z, x []Word, y, r Word) (c Word) { return mulAddVWW_g(z, x, y, r) }
func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
c = r
for i := range z {
@@ -234,7 +286,7 @@ func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
return
}
-func addMulVVW(z, x []Word, y Word) (c Word) { return addMulVVW_g(z, x, y) }
+// TODO(gri) Remove use of addWW_g here and then we can remove addWW_g and subWW_g.
func addMulVVW_g(z, x []Word, y Word) (c Word) {
for i := range z {
z1, z0 := mulAddWWW_g(x[i], y, z[i])
@@ -244,7 +296,6 @@ func addMulVVW_g(z, x []Word, y Word) (c Word) {
return
}
-func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { return divWVW_g(z, xn, x, y) }
func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
r = xn
for i := len(z) - 1; i >= 0; i-- {
diff --git a/libgo/go/math/big/arith_decl.go b/libgo/go/math/big/arith_decl.go
index 068cc8d9388..1707aa4e209 100644
--- a/libgo/go/math/big/arith_decl.go
+++ b/libgo/go/math/big/arith_decl.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !math_big_pure_go
+
package big
// implemented in arith_$GOARCH.s
diff --git a/libgo/go/math/big/arith_decl_pure.go b/libgo/go/math/big/arith_decl_pure.go
new file mode 100644
index 00000000000..e760a3816b3
--- /dev/null
+++ b/libgo/go/math/big/arith_decl_pure.go
@@ -0,0 +1,55 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build math_big_pure_go
+
+package big
+
+func mulWW(x, y Word) (z1, z0 Word) {
+ return mulWW_g(x, y)
+}
+
+func divWW(x1, x0, y Word) (q, r Word) {
+ return divWW_g(x1, x0, y)
+}
+
+func addVV(z, x, y []Word) (c Word) {
+ return addVV_g(z, x, y)
+}
+
+func subVV(z, x, y []Word) (c Word) {
+ return subVV_g(z, x, y)
+}
+
+func addVW(z, x []Word, y Word) (c Word) {
+ return addVW_g(z, x, y)
+}
+
+func subVW(z, x []Word, y Word) (c Word) {
+ return subVW_g(z, x, y)
+}
+
+func shlVU(z, x []Word, s uint) (c Word) {
+ return shlVU_g(z, x, s)
+}
+
+func shrVU(z, x []Word, s uint) (c Word) {
+ return shrVU_g(z, x, s)
+}
+
+func mulAddVWW(z, x []Word, y, r Word) (c Word) {
+ return mulAddVWW_g(z, x, y, r)
+}
+
+func addMulVVW(z, x []Word, y Word) (c Word) {
+ return addMulVVW_g(z, x, y)
+}
+
+func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
+ return divWVW_g(z, xn, x, y)
+}
+
+func bitLen(x Word) (n int) {
+ return bitLen_g(x)
+}
diff --git a/libgo/go/math/big/arith_test.go b/libgo/go/math/big/arith_test.go
index 3615a659c3b..f46a494f175 100644
--- a/libgo/go/math/big/arith_test.go
+++ b/libgo/go/math/big/arith_test.go
@@ -155,6 +155,7 @@ var sumVW = []argVW{
{nat{1}, nat{1}, 0, 0},
{nat{0}, nat{_M}, 1, 1},
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
+ {nat{585}, nat{314}, 271, 0},
}
var prodVW = []argVW{
@@ -254,7 +255,7 @@ func benchmarkFunVW(b *testing.B, f funVW, n int) {
x := rndV(n)
y := rndW()
z := make([]Word, n)
- b.SetBytes(int64(n * _W))
+ b.SetBytes(int64(n * _S))
b.ResetTimer()
for i := 0; i < b.N; i++ {
f(z, x, y)
diff --git a/libgo/go/math/big/bits_test.go b/libgo/go/math/big/bits_test.go
new file mode 100644
index 00000000000..985b60bd4b7
--- /dev/null
+++ b/libgo/go/math/big/bits_test.go
@@ -0,0 +1,224 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements the Bits type used for testing Float operations
+// via an independent (albeit slower) representations for floating-point
+// numbers.
+
+package big
+
+import (
+ "fmt"
+ "sort"
+ "testing"
+)
+
+// A Bits value b represents a finite floating-point number x of the form
+//
+// x = 2**b[0] + 2**b[1] + ... 2**b[len(b)-1]
+//
+// The order of slice elements is not significant. Negative elements may be
+// used to form fractions. A Bits value is normalized if each b[i] occurs at
+// most once. For instance Bits{0, 0, 1} is not normalized but represents the
+// same floating-point number as Bits{2}, which is normalized. The zero (nil)
+// value of Bits is a ready to use Bits value and represents the value 0.
+type Bits []int
+
+func (x Bits) add(y Bits) Bits {
+ return append(x, y...)
+}
+
+func (x Bits) mul(y Bits) Bits {
+ var p Bits
+ for _, x := range x {
+ for _, y := range y {
+ p = append(p, x+y)
+ }
+ }
+ return p
+}
+
+func TestMulBits(t *testing.T) {
+ for _, test := range []struct {
+ x, y, want Bits
+ }{
+ {nil, nil, nil},
+ {Bits{}, Bits{}, nil},
+ {Bits{0}, Bits{0}, Bits{0}},
+ {Bits{0}, Bits{1}, Bits{1}},
+ {Bits{1}, Bits{1, 2, 3}, Bits{2, 3, 4}},
+ {Bits{-1}, Bits{1}, Bits{0}},
+ {Bits{-10, -1, 0, 1, 10}, Bits{1, 2, 3}, Bits{-9, -8, -7, 0, 1, 2, 1, 2, 3, 2, 3, 4, 11, 12, 13}},
+ } {
+ got := fmt.Sprintf("%v", test.x.mul(test.y))
+ want := fmt.Sprintf("%v", test.want)
+ if got != want {
+ t.Errorf("%v * %v = %s; want %s", test.x, test.y, got, want)
+ }
+
+ }
+}
+
+// norm returns the normalized bits for x: It removes multiple equal entries
+// by treating them as an addition (e.g., Bits{5, 5} => Bits{6}), and it sorts
+// the result list for reproducible results.
+func (x Bits) norm() Bits {
+ m := make(map[int]bool)
+ for _, b := range x {
+ for m[b] {
+ m[b] = false
+ b++
+ }
+ m[b] = true
+ }
+ var z Bits
+ for b, set := range m {
+ if set {
+ z = append(z, b)
+ }
+ }
+ sort.Ints([]int(z))
+ return z
+}
+
+func TestNormBits(t *testing.T) {
+ for _, test := range []struct {
+ x, want Bits
+ }{
+ {nil, nil},
+ {Bits{}, Bits{}},
+ {Bits{0}, Bits{0}},
+ {Bits{0, 0}, Bits{1}},
+ {Bits{3, 1, 1}, Bits{2, 3}},
+ {Bits{10, 9, 8, 7, 6, 6}, Bits{11}},
+ } {
+ got := fmt.Sprintf("%v", test.x.norm())
+ want := fmt.Sprintf("%v", test.want)
+ if got != want {
+ t.Errorf("normBits(%v) = %s; want %s", test.x, got, want)
+ }
+
+ }
+}
+
+// round returns the Float value corresponding to x after rounding x
+// to prec bits according to mode.
+func (x Bits) round(prec uint, mode RoundingMode) *Float {
+ x = x.norm()
+
+ // determine range
+ var min, max int
+ for i, b := range x {
+ if i == 0 || b < min {
+ min = b
+ }
+ if i == 0 || b > max {
+ max = b
+ }
+ }
+ prec0 := uint(max + 1 - min)
+ if prec >= prec0 {
+ return x.Float()
+ }
+ // prec < prec0
+
+ // determine bit 0, rounding, and sticky bit, and result bits z
+ var bit0, rbit, sbit uint
+ var z Bits
+ r := max - int(prec)
+ for _, b := range x {
+ switch {
+ case b == r:
+ rbit = 1
+ case b < r:
+ sbit = 1
+ default:
+ // b > r
+ if b == r+1 {
+ bit0 = 1
+ }
+ z = append(z, b)
+ }
+ }
+
+ // round
+ f := z.Float() // rounded to zero
+ if mode == ToNearestAway {
+ panic("not yet implemented")
+ }
+ if mode == ToNearestEven && rbit == 1 && (sbit == 1 || sbit == 0 && bit0 != 0) || mode == AwayFromZero {
+ // round away from zero
+ f.SetMode(ToZero).SetPrec(prec)
+ f.Add(f, Bits{int(r) + 1}.Float())
+ }
+ return f
+}
+
+// Float returns the *Float z of the smallest possible precision such that
+// z = sum(2**bits[i]), with i = range bits. If multiple bits[i] are equal,
+// they are added: Bits{0, 1, 0}.Float() == 2**0 + 2**1 + 2**0 = 4.
+func (bits Bits) Float() *Float {
+ // handle 0
+ if len(bits) == 0 {
+ return new(Float)
+ }
+ // len(bits) > 0
+
+ // determine lsb exponent
+ var min int
+ for i, b := range bits {
+ if i == 0 || b < min {
+ min = b
+ }
+ }
+
+ // create bit pattern
+ x := NewInt(0)
+ for _, b := range bits {
+ badj := b - min
+ // propagate carry if necessary
+ for x.Bit(badj) != 0 {
+ x.SetBit(x, badj, 0)
+ badj++
+ }
+ x.SetBit(x, badj, 1)
+ }
+
+ // create corresponding float
+ z := new(Float).SetInt(x) // normalized
+ if e := int64(z.exp) + int64(min); MinExp <= e && e <= MaxExp {
+ z.exp = int32(e)
+ } else {
+ // this should never happen for our test cases
+ panic("exponent out of range")
+ }
+ return z
+}
+
+func TestFromBits(t *testing.T) {
+ for _, test := range []struct {
+ bits Bits
+ want string
+ }{
+ // all different bit numbers
+ {nil, "0"},
+ {Bits{0}, "0x.8p+1"},
+ {Bits{1}, "0x.8p+2"},
+ {Bits{-1}, "0x.8p+0"},
+ {Bits{63}, "0x.8p+64"},
+ {Bits{33, -30}, "0x.8000000000000001p+34"},
+ {Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p+256"},
+
+ // multiple equal bit numbers
+ {Bits{0, 0}, "0x.8p+2"},
+ {Bits{0, 0, 0, 0}, "0x.8p+3"},
+ {Bits{0, 1, 0}, "0x.8p+3"},
+ {append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p+5" /* 17 */},
+ } {
+ f := test.bits.Float()
+ if got := f.Text('p', 0); got != test.want {
+ t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
+ }
+ }
+}
diff --git a/libgo/go/math/big/decimal.go b/libgo/go/math/big/decimal.go
new file mode 100644
index 00000000000..2595e5f8c12
--- /dev/null
+++ b/libgo/go/math/big/decimal.go
@@ -0,0 +1,264 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements multi-precision decimal numbers.
+// The implementation is for float to decimal conversion only;
+// not general purpose use.
+// The only operations are precise conversion from binary to
+// decimal and rounding.
+//
+// The key observation and some code (shr) is borrowed from
+// strconv/decimal.go: conversion of binary fractional values can be done
+// precisely in multi-precision decimal because 2 divides 10 (required for
+// >> of mantissa); but conversion of decimal floating-point values cannot
+// be done precisely in binary representation.
+//
+// In contrast to strconv/decimal.go, only right shift is implemented in
+// decimal format - left shift can be done precisely in binary format.
+
+package big
+
+// A decimal represents an unsigned floating-point number in decimal representation.
+// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// with the most-significant mantissa digit at index 0. For the zero decimal, the
+// mantissa length and exponent are 0.
+// The zero value for decimal represents a ready-to-use 0.0.
+type decimal struct {
+ mant []byte // mantissa ASCII digits, big-endian
+ exp int // exponent
+}
+
+// Maximum shift amount that can be done in one pass without overflow.
+// A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
+const maxShift = _W - 4
+
+// TODO(gri) Since we know the desired decimal precision when converting
+// a floating-point number, we may be able to limit the number of decimal
+// digits that need to be computed by init by providing an additional
+// precision argument and keeping track of when a number was truncated early
+// (equivalent of "sticky bit" in binary rounding).
+
+// TODO(gri) Along the same lines, enforce some limit to shift magnitudes
+// to avoid "infinitely" long running conversions (until we run out of space).
+
+// Init initializes x to the decimal representation of m << shift (for
+// shift >= 0), or m >> -shift (for shift < 0).
+func (x *decimal) init(m nat, shift int) {
+ // special case 0
+ if len(m) == 0 {
+ x.mant = x.mant[:0]
+ x.exp = 0
+ return
+ }
+
+ // Optimization: If we need to shift right, first remove any trailing
+ // zero bits from m to reduce shift amount that needs to be done in
+ // decimal format (since that is likely slower).
+ if shift < 0 {
+ ntz := m.trailingZeroBits()
+ s := uint(-shift)
+ if s >= ntz {
+ s = ntz // shift at most ntz bits
+ }
+ m = nat(nil).shr(m, s)
+ shift += int(s)
+ }
+
+ // Do any shift left in binary representation.
+ if shift > 0 {
+ m = nat(nil).shl(m, uint(shift))
+ shift = 0
+ }
+
+ // Convert mantissa into decimal representation.
+ s := m.decimalString() // TODO(gri) avoid string conversion here
+ n := len(s)
+ x.exp = n
+ // Trim trailing zeros; instead the exponent is tracking
+ // the decimal point independent of the number of digits.
+ for n > 0 && s[n-1] == '0' {
+ n--
+ }
+ x.mant = append(x.mant[:0], s[:n]...)
+
+ // Do any (remaining) shift right in decimal representation.
+ if shift < 0 {
+ for shift < -maxShift {
+ shr(x, maxShift)
+ shift += maxShift
+ }
+ shr(x, uint(-shift))
+ }
+}
+
+// Possibly optimization: The current implementation of nat.string takes
+// a charset argument. When a right shift is needed, we could provide
+// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
+// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
+// single +'0' pass at the end).
+
+// shr implements x >> s, for s <= maxShift.
+func shr(x *decimal, s uint) {
+ // Division by 1<<s using shift-and-subtract algorithm.
+
+ // pick up enough leading digits to cover first shift
+ r := 0 // read index
+ var n Word
+ for n>>s == 0 && r < len(x.mant) {
+ ch := Word(x.mant[r])
+ r++
+ n = n*10 + ch - '0'
+ }
+ if n == 0 {
+ // x == 0; shouldn't get here, but handle anyway
+ x.mant = x.mant[:0]
+ return
+ }
+ for n>>s == 0 {
+ r++
+ n *= 10
+ }
+ x.exp += 1 - r
+
+ // read a digit, write a digit
+ w := 0 // write index
+ for r < len(x.mant) {
+ ch := Word(x.mant[r])
+ r++
+ d := n >> s
+ n -= d << s
+ x.mant[w] = byte(d + '0')
+ w++
+ n = n*10 + ch - '0'
+ }
+
+ // write extra digits that still fit
+ for n > 0 && w < len(x.mant) {
+ d := n >> s
+ n -= d << s
+ x.mant[w] = byte(d + '0')
+ w++
+ n = n * 10
+ }
+ x.mant = x.mant[:w] // the number may be shorter (e.g. 1024 >> 10)
+
+ // append additional digits that didn't fit
+ for n > 0 {
+ d := n >> s
+ n -= d << s
+ x.mant = append(x.mant, byte(d+'0'))
+ n = n * 10
+ }
+
+ trim(x)
+}
+
+func (x *decimal) String() string {
+ if len(x.mant) == 0 {
+ return "0"
+ }
+
+ var buf []byte
+ switch {
+ case x.exp <= 0:
+ // 0.00ddd
+ buf = append(buf, "0."...)
+ buf = appendZeros(buf, -x.exp)
+ buf = append(buf, x.mant...)
+
+ case /* 0 < */ x.exp < len(x.mant):
+ // dd.ddd
+ buf = append(buf, x.mant[:x.exp]...)
+ buf = append(buf, '.')
+ buf = append(buf, x.mant[x.exp:]...)
+
+ default: // len(x.mant) <= x.exp
+ // ddd00
+ buf = append(buf, x.mant...)
+ buf = appendZeros(buf, x.exp-len(x.mant))
+ }
+
+ return string(buf)
+}
+
+// appendZeros appends n 0 digits to buf and returns buf.
+func appendZeros(buf []byte, n int) []byte {
+ for ; n > 0; n-- {
+ buf = append(buf, '0')
+ }
+ return buf
+}
+
+// shouldRoundUp reports if x should be rounded up
+// if shortened to n digits. n must be a valid index
+// for x.mant.
+func shouldRoundUp(x *decimal, n int) bool {
+ if x.mant[n] == '5' && n+1 == len(x.mant) {
+ // exactly halfway - round to even
+ return n > 0 && (x.mant[n-1]-'0')&1 != 0
+ }
+ // not halfway - digit tells all (x.mant has no trailing zeros)
+ return x.mant[n] >= '5'
+}
+
+// round sets x to (at most) n mantissa digits by rounding it
+// to the nearest even value with n (or fever) mantissa digits.
+// If n < 0, x remains unchanged.
+func (x *decimal) round(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+
+ if shouldRoundUp(x, n) {
+ x.roundUp(n)
+ } else {
+ x.roundDown(n)
+ }
+}
+
+func (x *decimal) roundUp(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+ // 0 <= n < len(x.mant)
+
+ // find first digit < '9'
+ for n > 0 && x.mant[n-1] >= '9' {
+ n--
+ }
+
+ if n == 0 {
+ // all digits are '9's => round up to '1' and update exponent
+ x.mant[0] = '1' // ok since len(x.mant) > n
+ x.mant = x.mant[:1]
+ x.exp++
+ return
+ }
+
+ // n > 0 && x.mant[n-1] < '9'
+ x.mant[n-1]++
+ x.mant = x.mant[:n]
+ // x already trimmed
+}
+
+func (x *decimal) roundDown(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+ x.mant = x.mant[:n]
+ trim(x)
+}
+
+// trim cuts off any trailing zeros from x's mantissa;
+// they are meaningless for the value of x.
+func trim(x *decimal) {
+ i := len(x.mant)
+ for i > 0 && x.mant[i-1] == '0' {
+ i--
+ }
+ x.mant = x.mant[:i]
+ if i == 0 {
+ x.exp = 0
+ }
+}
diff --git a/libgo/go/math/big/decimal_test.go b/libgo/go/math/big/decimal_test.go
new file mode 100644
index 00000000000..81e022a47dd
--- /dev/null
+++ b/libgo/go/math/big/decimal_test.go
@@ -0,0 +1,106 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import "testing"
+
+func TestDecimalString(t *testing.T) {
+ for _, test := range []struct {
+ x decimal
+ want string
+ }{
+ {want: "0"},
+ {decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
+ {decimal{[]byte("12345"), 0}, "0.12345"},
+ {decimal{[]byte("12345"), -3}, "0.00012345"},
+ {decimal{[]byte("12345"), +3}, "123.45"},
+ {decimal{[]byte("12345"), +10}, "1234500000"},
+ } {
+ if got := test.x.String(); got != test.want {
+ t.Errorf("%v == %s; want %s", test.x, got, test.want)
+ }
+ }
+}
+
+func TestDecimalInit(t *testing.T) {
+ for _, test := range []struct {
+ x Word
+ shift int
+ want string
+ }{
+ {0, 0, "0"},
+ {0, -100, "0"},
+ {0, 100, "0"},
+ {1, 0, "1"},
+ {1, 10, "1024"},
+ {1, 100, "1267650600228229401496703205376"},
+ {1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
+ {12345678, 8, "3160493568"},
+ {12345678, -8, "48225.3046875"},
+ {195312, 9, "99999744"},
+ {1953125, 9, "1000000000"},
+ } {
+ var d decimal
+ d.init(nat{test.x}.norm(), test.shift)
+ if got := d.String(); got != test.want {
+ t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
+ }
+ }
+}
+
+func TestDecimalRounding(t *testing.T) {
+ for _, test := range []struct {
+ x uint64
+ n int
+ down, even, up string
+ }{
+ {0, 0, "0", "0", "0"},
+ {0, 1, "0", "0", "0"},
+
+ {1, 0, "0", "0", "10"},
+ {5, 0, "0", "0", "10"},
+ {9, 0, "0", "10", "10"},
+
+ {15, 1, "10", "20", "20"},
+ {45, 1, "40", "40", "50"},
+ {95, 1, "90", "100", "100"},
+
+ {12344999, 4, "12340000", "12340000", "12350000"},
+ {12345000, 4, "12340000", "12340000", "12350000"},
+ {12345001, 4, "12340000", "12350000", "12350000"},
+ {23454999, 4, "23450000", "23450000", "23460000"},
+ {23455000, 4, "23450000", "23460000", "23460000"},
+ {23455001, 4, "23450000", "23460000", "23460000"},
+
+ {99994999, 4, "99990000", "99990000", "100000000"},
+ {99995000, 4, "99990000", "100000000", "100000000"},
+ {99999999, 4, "99990000", "100000000", "100000000"},
+
+ {12994999, 4, "12990000", "12990000", "13000000"},
+ {12995000, 4, "12990000", "13000000", "13000000"},
+ {12999999, 4, "12990000", "13000000", "13000000"},
+ } {
+ x := nat(nil).setUint64(test.x)
+
+ var d decimal
+ d.init(x, 0)
+ d.roundDown(test.n)
+ if got := d.String(); got != test.down {
+ t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
+ }
+
+ d.init(x, 0)
+ d.round(test.n)
+ if got := d.String(); got != test.even {
+ t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
+ }
+
+ d.init(x, 0)
+ d.roundUp(test.n)
+ if got := d.String(); got != test.up {
+ t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
+ }
+ }
+}
diff --git a/libgo/go/math/big/float.go b/libgo/go/math/big/float.go
new file mode 100644
index 00000000000..d7aa8953c43
--- /dev/null
+++ b/libgo/go/math/big/float.go
@@ -0,0 +1,1693 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements multi-precision floating-point numbers.
+// Like in the GNU MPFR library (http://www.mpfr.org/), operands
+// can be of mixed precision. Unlike MPFR, the rounding mode is
+// not specified with each operation, but with each operand. The
+// rounding mode of the result operand determines the rounding
+// mode of an operation. This is a from-scratch implementation.
+
+package big
+
+import (
+ "fmt"
+ "math"
+)
+
+const debugFloat = false // enable for debugging
+
+// A nonzero finite Float represents a multi-precision floating point number
+//
+// sign × mantissa × 2**exponent
+//
+// with 0.5 <= mantissa < 1.0, and MinExp <= exponent <= MaxExp.
+// A Float may also be zero (+0, -0) or infinite (+Inf, -Inf).
+// All Floats are ordered, and the ordering of two Floats x and y
+// is defined by x.Cmp(y).
+//
+// Each Float value also has a precision, rounding mode, and accuracy.
+// The precision is the maximum number of mantissa bits available to
+// represent the value. The rounding mode specifies how a result should
+// be rounded to fit into the mantissa bits, and accuracy describes the
+// rounding error with respect to the exact result.
+//
+// Unless specified otherwise, all operations (including setters) that
+// specify a *Float variable for the result (usually via the receiver
+// with the exception of MantExp), round the numeric result according
+// to the precision and rounding mode of the result variable.
+//
+// If the provided result precision is 0 (see below), it is set to the
+// precision of the argument with the largest precision value before any
+// rounding takes place, and the rounding mode remains unchanged. Thus,
+// uninitialized Floats provided as result arguments will have their
+// precision set to a reasonable value determined by the operands and
+// their mode is the zero value for RoundingMode (ToNearestEven).
+//
+// By setting the desired precision to 24 or 53 and using matching rounding
+// mode (typically ToNearestEven), Float operations produce the same results
+// as the corresponding float32 or float64 IEEE-754 arithmetic for operands
+// that correspond to normal (i.e., not denormal) float32 or float64 numbers.
+// Exponent underflow and overflow lead to a 0 or an Infinity for different
+// values than IEEE-754 because Float exponents have a much larger range.
+//
+// The zero (uninitialized) value for a Float is ready to use and represents
+// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
+//
+type Float struct {
+ prec uint32
+ mode RoundingMode
+ acc Accuracy
+ form form
+ neg bool
+ mant nat
+ exp int32
+}
+
+// An ErrNaN panic is raised by a Float operation that would lead to
+// a NaN under IEEE-754 rules. An ErrNaN implements the error interface.
+type ErrNaN struct {
+ msg string
+}
+
+func (err ErrNaN) Error() string {
+ return err.msg
+}
+
+// NewFloat allocates and returns a new Float set to x,
+// with precision 53 and rounding mode ToNearestEven.
+// NewFloat panics with ErrNaN if x is a NaN.
+func NewFloat(x float64) *Float {
+ if math.IsNaN(x) {
+ panic(ErrNaN{"NewFloat(NaN)"})
+ }
+ return new(Float).SetFloat64(x)
+}
+
+// Exponent and precision limits.
+const (
+ MaxExp = math.MaxInt32 // largest supported exponent
+ MinExp = math.MinInt32 // smallest supported exponent
+ MaxPrec = math.MaxUint32 // largest (theoretically) supported precision; likely memory-limited
+)
+
+// Internal representation: The mantissa bits x.mant of a nonzero finite
+// Float x are stored in a nat slice long enough to hold up to x.prec bits;
+// the slice may (but doesn't have to) be shorter if the mantissa contains
+// trailing 0 bits. x.mant is normalized if the msb of x.mant == 1 (i.e.,
+// the msb is shifted all the way "to the left"). Thus, if the mantissa has
+// trailing 0 bits or x.prec is not a multiple of the the Word size _W,
+// x.mant[0] has trailing zero bits. The msb of the mantissa corresponds
+// to the value 0.5; the exponent x.exp shifts the binary point as needed.
+//
+// A zero or non-finite Float x ignores x.mant and x.exp.
+//
+// x form neg mant exp
+// ----------------------------------------------------------
+// ±0 zero sign - -
+// 0 < |x| < +Inf finite sign mantissa exponent
+// ±Inf inf sign - -
+
+// A form value describes the internal representation.
+type form byte
+
+// The form value order is relevant - do not change!
+const (
+ zero form = iota
+ finite
+ inf
+)
+
+// RoundingMode determines how a Float value is rounded to the
+// desired precision. Rounding may change the Float value; the
+// rounding error is described by the Float's Accuracy.
+type RoundingMode byte
+
+// The following rounding modes are supported.
+const (
+ ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
+ ToNearestAway // == IEEE 754-2008 roundTiesToAway
+ ToZero // == IEEE 754-2008 roundTowardZero
+ AwayFromZero // no IEEE 754-2008 equivalent
+ ToNegativeInf // == IEEE 754-2008 roundTowardNegative
+ ToPositiveInf // == IEEE 754-2008 roundTowardPositive
+)
+
+//go:generate stringer -type=RoundingMode
+
+// Accuracy describes the rounding error produced by the most recent
+// operation that generated a Float value, relative to the exact value.
+type Accuracy int8
+
+// Constants describing the Accuracy of a Float.
+const (
+ Below Accuracy = -1
+ Exact Accuracy = 0
+ Above Accuracy = +1
+)
+
+//go:generate stringer -type=Accuracy
+
+// SetPrec sets z's precision to prec and returns the (possibly) rounded
+// value of z. Rounding occurs according to z's rounding mode if the mantissa
+// cannot be represented in prec bits without loss of precision.
+// SetPrec(0) maps all finite values to ±0; infinite values remain unchanged.
+// If prec > MaxPrec, it is set to MaxPrec.
+func (z *Float) SetPrec(prec uint) *Float {
+ z.acc = Exact // optimistically assume no rounding is needed
+
+ // special case
+ if prec == 0 {
+ z.prec = 0
+ if z.form == finite {
+ // truncate z to 0
+ z.acc = makeAcc(z.neg)
+ z.form = zero
+ }
+ return z
+ }
+
+ // general case
+ if prec > MaxPrec {
+ prec = MaxPrec
+ }
+ old := z.prec
+ z.prec = uint32(prec)
+ if z.prec < old {
+ z.round(0)
+ }
+ return z
+}
+
+func makeAcc(above bool) Accuracy {
+ if above {
+ return Above
+ }
+ return Below
+}
+
+// SetMode sets z's rounding mode to mode and returns an exact z.
+// z remains unchanged otherwise.
+// z.SetMode(z.Mode()) is a cheap way to set z's accuracy to Exact.
+func (z *Float) SetMode(mode RoundingMode) *Float {
+ z.mode = mode
+ z.acc = Exact
+ return z
+}
+
+// Prec returns the mantissa precision of x in bits.
+// The result may be 0 for |x| == 0 and |x| == Inf.
+func (x *Float) Prec() uint {
+ return uint(x.prec)
+}
+
+// MinPrec returns the minimum precision required to represent x exactly
+// (i.e., the smallest prec before x.SetPrec(prec) would start rounding x).
+// The result is 0 for |x| == 0 and |x| == Inf.
+func (x *Float) MinPrec() uint {
+ if x.form != finite {
+ return 0
+ }
+ return uint(len(x.mant))*_W - x.mant.trailingZeroBits()
+}
+
+// Mode returns the rounding mode of x.
+func (x *Float) Mode() RoundingMode {
+ return x.mode
+}
+
+// Acc returns the accuracy of x produced by the most recent operation.
+func (x *Float) Acc() Accuracy {
+ return x.acc
+}
+
+// Sign returns:
+//
+// -1 if x < 0
+// 0 if x is ±0
+// +1 if x > 0
+//
+func (x *Float) Sign() int {
+ if debugFloat {
+ x.validate()
+ }
+ if x.form == zero {
+ return 0
+ }
+ if x.neg {
+ return -1
+ }
+ return 1
+}
+
+// MantExp breaks x into its mantissa and exponent components
+// and returns the exponent. If a non-nil mant argument is
+// provided its value is set to the mantissa of x, with the
+// same precision and rounding mode as x. The components
+// satisfy x == mant × 2**exp, with 0.5 <= |mant| < 1.0.
+// Calling MantExp with a nil argument is an efficient way to
+// get the exponent of the receiver.
+//
+// Special cases are:
+//
+// ( ±0).MantExp(mant) = 0, with mant set to ±0
+// (±Inf).MantExp(mant) = 0, with mant set to ±Inf
+//
+// x and mant may be the same in which case x is set to its
+// mantissa value.
+func (x *Float) MantExp(mant *Float) (exp int) {
+ if debugFloat {
+ x.validate()
+ }
+ if x.form == finite {
+ exp = int(x.exp)
+ }
+ if mant != nil {
+ mant.Copy(x)
+ if mant.form == finite {
+ mant.exp = 0
+ }
+ }
+ return
+}
+
+func (z *Float) setExpAndRound(exp int64, sbit uint) {
+ if exp < MinExp {
+ // underflow
+ z.acc = makeAcc(z.neg)
+ z.form = zero
+ return
+ }
+
+ if exp > MaxExp {
+ // overflow
+ z.acc = makeAcc(!z.neg)
+ z.form = inf
+ return
+ }
+
+ z.form = finite
+ z.exp = int32(exp)
+ z.round(sbit)
+}
+
+// SetMantExp sets z to mant × 2**exp and and returns z.
+// The result z has the same precision and rounding mode
+// as mant. SetMantExp is an inverse of MantExp but does
+// not require 0.5 <= |mant| < 1.0. Specifically:
+//
+// mant := new(Float)
+// new(Float).SetMantExp(mant, x.SetMantExp(mant)).Cmp(x).Eql() is true
+//
+// Special cases are:
+//
+// z.SetMantExp( ±0, exp) = ±0
+// z.SetMantExp(±Inf, exp) = ±Inf
+//
+// z and mant may be the same in which case z's exponent
+// is set to exp.
+func (z *Float) SetMantExp(mant *Float, exp int) *Float {
+ if debugFloat {
+ z.validate()
+ mant.validate()
+ }
+ z.Copy(mant)
+ if z.form != finite {
+ return z
+ }
+ z.setExpAndRound(int64(z.exp)+int64(exp), 0)
+ return z
+}
+
+// Signbit returns true if x is negative or negative zero.
+func (x *Float) Signbit() bool {
+ return x.neg
+}
+
+// IsInf reports whether x is +Inf or -Inf.
+func (x *Float) IsInf() bool {
+ return x.form == inf
+}
+
+// IsInt reports whether x is an integer.
+// ±Inf values are not integers.
+func (x *Float) IsInt() bool {
+ if debugFloat {
+ x.validate()
+ }
+ // special cases
+ if x.form != finite {
+ return x.form == zero
+ }
+ // x.form == finite
+ if x.exp <= 0 {
+ return false
+ }
+ // x.exp > 0
+ return x.prec <= uint32(x.exp) || x.MinPrec() <= uint(x.exp) // not enough bits for fractional mantissa
+}
+
+// debugging support
+func (x *Float) validate() {
+ if !debugFloat {
+ // avoid performance bugs
+ panic("validate called but debugFloat is not set")
+ }
+ if x.form != finite {
+ return
+ }
+ m := len(x.mant)
+ if m == 0 {
+ panic("nonzero finite number with empty mantissa")
+ }
+ const msb = 1 << (_W - 1)
+ if x.mant[m-1]&msb == 0 {
+ panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Text('p', 0)))
+ }
+ if x.prec == 0 {
+ panic("zero precision finite number")
+ }
+}
+
+// round rounds z according to z.mode to z.prec bits and sets z.acc accordingly.
+// sbit must be 0 or 1 and summarizes any "sticky bit" information one might
+// have before calling round. z's mantissa must be normalized (with the msb set)
+// or empty.
+//
+// CAUTION: The rounding modes ToNegativeInf, ToPositiveInf are affected by the
+// sign of z. For correct rounding, the sign of z must be set correctly before
+// calling round.
+func (z *Float) round(sbit uint) {
+ if debugFloat {
+ z.validate()
+ }
+
+ z.acc = Exact
+ if z.form != finite {
+ // ±0 or ±Inf => nothing left to do
+ return
+ }
+ // z.form == finite && len(z.mant) > 0
+ // m > 0 implies z.prec > 0 (checked by validate)
+
+ m := uint32(len(z.mant)) // present mantissa length in words
+ bits := m * _W // present mantissa bits
+ if bits <= z.prec {
+ // mantissa fits => nothing to do
+ return
+ }
+ // bits > z.prec
+
+ n := (z.prec + (_W - 1)) / _W // mantissa length in words for desired precision
+
+ // Rounding is based on two bits: the rounding bit (rbit) and the
+ // sticky bit (sbit). The rbit is the bit immediately before the
+ // z.prec leading mantissa bits (the "0.5"). The sbit is set if any
+ // of the bits before the rbit are set (the "0.25", "0.125", etc.):
+ //
+ // rbit sbit => "fractional part"
+ //
+ // 0 0 == 0
+ // 0 1 > 0 , < 0.5
+ // 1 0 == 0.5
+ // 1 1 > 0.5, < 1.0
+
+ // bits > z.prec: mantissa too large => round
+ r := uint(bits - z.prec - 1) // rounding bit position; r >= 0
+ rbit := z.mant.bit(r) // rounding bit
+ if sbit == 0 {
+ sbit = z.mant.sticky(r)
+ }
+ if debugFloat && sbit&^1 != 0 {
+ panic(fmt.Sprintf("invalid sbit %#x", sbit))
+ }
+
+ // convert ToXInf rounding modes
+ mode := z.mode
+ switch mode {
+ case ToNegativeInf:
+ mode = ToZero
+ if z.neg {
+ mode = AwayFromZero
+ }
+ case ToPositiveInf:
+ mode = AwayFromZero
+ if z.neg {
+ mode = ToZero
+ }
+ }
+
+ // cut off extra words
+ if m > n {
+ copy(z.mant, z.mant[m-n:]) // move n last words to front
+ z.mant = z.mant[:n]
+ }
+
+ // determine number of trailing zero bits t
+ t := n*_W - z.prec // 0 <= t < _W
+ lsb := Word(1) << t
+
+ // make rounding decision
+ // TODO(gri) This can be simplified (see Bits.round in bits_test.go).
+ switch mode {
+ case ToZero:
+ // nothing to do
+ case ToNearestEven, ToNearestAway:
+ if rbit == 0 {
+ // rounding bits == 0b0x
+ mode = ToZero
+ } else if sbit == 1 {
+ // rounding bits == 0b11
+ mode = AwayFromZero
+ }
+ case AwayFromZero:
+ if rbit|sbit == 0 {
+ mode = ToZero
+ }
+ default:
+ // ToXInf modes have been converted to ToZero or AwayFromZero
+ panic("unreachable")
+ }
+
+ // round and determine accuracy
+ switch mode {
+ case ToZero:
+ if rbit|sbit != 0 {
+ z.acc = Below
+ }
+
+ case ToNearestEven, ToNearestAway:
+ if debugFloat && rbit != 1 {
+ panic("internal error in rounding")
+ }
+ if mode == ToNearestEven && sbit == 0 && z.mant[0]&lsb == 0 {
+ z.acc = Below
+ break
+ }
+ // mode == ToNearestAway || sbit == 1 || z.mant[0]&lsb != 0
+ fallthrough
+
+ case AwayFromZero:
+ // add 1 to mantissa
+ if addVW(z.mant, z.mant, lsb) != 0 {
+ // overflow => shift mantissa right by 1 and add msb
+ shrVU(z.mant, z.mant, 1)
+ z.mant[n-1] |= 1 << (_W - 1)
+ // adjust exponent
+ if z.exp < MaxExp {
+ z.exp++
+ } else {
+ // exponent overflow
+ z.acc = makeAcc(!z.neg)
+ z.form = inf
+ return
+ }
+ }
+ z.acc = Above
+ }
+
+ // zero out trailing bits in least-significant word
+ z.mant[0] &^= lsb - 1
+
+ // update accuracy
+ if z.acc != Exact && z.neg {
+ z.acc = -z.acc
+ }
+
+ if debugFloat {
+ z.validate()
+ }
+
+ return
+}
+
+func (z *Float) setBits64(neg bool, x uint64) *Float {
+ if z.prec == 0 {
+ z.prec = 64
+ }
+ z.acc = Exact
+ z.neg = neg
+ if x == 0 {
+ z.form = zero
+ return z
+ }
+ // x != 0
+ z.form = finite
+ s := nlz64(x)
+ z.mant = z.mant.setUint64(x << s)
+ z.exp = int32(64 - s) // always fits
+ if z.prec < 64 {
+ z.round(0)
+ }
+ return z
+}
+
+// SetUint64 sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to 64 (and rounding will have
+// no effect).
+func (z *Float) SetUint64(x uint64) *Float {
+ return z.setBits64(false, x)
+}
+
+// SetInt64 sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to 64 (and rounding will have
+// no effect).
+func (z *Float) SetInt64(x int64) *Float {
+ u := x
+ if u < 0 {
+ u = -u
+ }
+ // We cannot simply call z.SetUint64(uint64(u)) and change
+ // the sign afterwards because the sign affects rounding.
+ return z.setBits64(x < 0, uint64(u))
+}
+
+// SetFloat64 sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to 53 (and rounding will have
+// no effect). SetFloat64 panics with ErrNaN if x is a NaN.
+func (z *Float) SetFloat64(x float64) *Float {
+ if z.prec == 0 {
+ z.prec = 53
+ }
+ if math.IsNaN(x) {
+ panic(ErrNaN{"Float.SetFloat64(NaN)"})
+ }
+ z.acc = Exact
+ z.neg = math.Signbit(x) // handle -0, -Inf correctly
+ if x == 0 {
+ z.form = zero
+ return z
+ }
+ if math.IsInf(x, 0) {
+ z.form = inf
+ return z
+ }
+ // normalized x != 0
+ z.form = finite
+ fmant, exp := math.Frexp(x) // get normalized mantissa
+ z.mant = z.mant.setUint64(1<<63 | math.Float64bits(fmant)<<11)
+ z.exp = int32(exp) // always fits
+ if z.prec < 53 {
+ z.round(0)
+ }
+ return z
+}
+
+// fnorm normalizes mantissa m by shifting it to the left
+// such that the msb of the most-significant word (msw) is 1.
+// It returns the shift amount. It assumes that len(m) != 0.
+func fnorm(m nat) int64 {
+ if debugFloat && (len(m) == 0 || m[len(m)-1] == 0) {
+ panic("msw of mantissa is 0")
+ }
+ s := nlz(m[len(m)-1])
+ if s > 0 {
+ c := shlVU(m, m, s)
+ if debugFloat && c != 0 {
+ panic("nlz or shlVU incorrect")
+ }
+ }
+ return int64(s)
+}
+
+// SetInt sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to the larger of x.BitLen()
+// or 64 (and rounding will have no effect).
+func (z *Float) SetInt(x *Int) *Float {
+ // TODO(gri) can be more efficient if z.prec > 0
+ // but small compared to the size of x, or if there
+ // are many trailing 0's.
+ bits := uint32(x.BitLen())
+ if z.prec == 0 {
+ z.prec = umax32(bits, 64)
+ }
+ z.acc = Exact
+ z.neg = x.neg
+ if len(x.abs) == 0 {
+ z.form = zero
+ return z
+ }
+ // x != 0
+ z.mant = z.mant.set(x.abs)
+ fnorm(z.mant)
+ z.setExpAndRound(int64(bits), 0)
+ return z
+}
+
+// SetRat sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to the largest of a.BitLen(),
+// b.BitLen(), or 64; with x = a/b.
+func (z *Float) SetRat(x *Rat) *Float {
+ if x.IsInt() {
+ return z.SetInt(x.Num())
+ }
+ var a, b Float
+ a.SetInt(x.Num())
+ b.SetInt(x.Denom())
+ if z.prec == 0 {
+ z.prec = umax32(a.prec, b.prec)
+ }
+ return z.Quo(&a, &b)
+}
+
+// SetInf sets z to the infinite Float -Inf if signbit is
+// set, or +Inf if signbit is not set, and returns z. The
+// precision of z is unchanged and the result is always
+// Exact.
+func (z *Float) SetInf(signbit bool) *Float {
+ z.acc = Exact
+ z.form = inf
+ z.neg = signbit
+ return z
+}
+
+// Set sets z to the (possibly rounded) value of x and returns z.
+// If z's precision is 0, it is changed to the precision of x
+// before setting z (and rounding will have no effect).
+// Rounding is performed according to z's precision and rounding
+// mode; and z's accuracy reports the result error relative to the
+// exact (not rounded) result.
+func (z *Float) Set(x *Float) *Float {
+ if debugFloat {
+ x.validate()
+ }
+ z.acc = Exact
+ if z != x {
+ z.form = x.form
+ z.neg = x.neg
+ if x.form == finite {
+ z.exp = x.exp
+ z.mant = z.mant.set(x.mant)
+ }
+ if z.prec == 0 {
+ z.prec = x.prec
+ } else if z.prec < x.prec {
+ z.round(0)
+ }
+ }
+ return z
+}
+
+// Copy sets z to x, with the same precision, rounding mode, and
+// accuracy as x, and returns z. x is not changed even if z and
+// x are the same.
+func (z *Float) Copy(x *Float) *Float {
+ if debugFloat {
+ x.validate()
+ }
+ if z != x {
+ z.prec = x.prec
+ z.mode = x.mode
+ z.acc = x.acc
+ z.form = x.form
+ z.neg = x.neg
+ if z.form == finite {
+ z.mant = z.mant.set(x.mant)
+ z.exp = x.exp
+ }
+ }
+ return z
+}
+
+// msb32 returns the 32 most significant bits of x.
+func msb32(x nat) uint32 {
+ i := len(x) - 1
+ if i < 0 {
+ return 0
+ }
+ if debugFloat && x[i]&(1<<(_W-1)) == 0 {
+ panic("x not normalized")
+ }
+ switch _W {
+ case 32:
+ return uint32(x[i])
+ case 64:
+ return uint32(x[i] >> 32)
+ }
+ panic("unreachable")
+}
+
+// msb64 returns the 64 most significant bits of x.
+func msb64(x nat) uint64 {
+ i := len(x) - 1
+ if i < 0 {
+ return 0
+ }
+ if debugFloat && x[i]&(1<<(_W-1)) == 0 {
+ panic("x not normalized")
+ }
+ switch _W {
+ case 32:
+ v := uint64(x[i]) << 32
+ if i > 0 {
+ v |= uint64(x[i-1])
+ }
+ return v
+ case 64:
+ return uint64(x[i])
+ }
+ panic("unreachable")
+}
+
+// Uint64 returns the unsigned integer resulting from truncating x
+// towards zero. If 0 <= x <= math.MaxUint64, the result is Exact
+// if x is an integer and Below otherwise.
+// The result is (0, Above) for x < 0, and (math.MaxUint64, Below)
+// for x > math.MaxUint64.
+func (x *Float) Uint64() (uint64, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ switch x.form {
+ case finite:
+ if x.neg {
+ return 0, Above
+ }
+ // 0 < x < +Inf
+ if x.exp <= 0 {
+ // 0 < x < 1
+ return 0, Below
+ }
+ // 1 <= x < Inf
+ if x.exp <= 64 {
+ // u = trunc(x) fits into a uint64
+ u := msb64(x.mant) >> (64 - uint32(x.exp))
+ if x.MinPrec() <= 64 {
+ return u, Exact
+ }
+ return u, Below // x truncated
+ }
+ // x too large
+ return math.MaxUint64, Below
+
+ case zero:
+ return 0, Exact
+
+ case inf:
+ if x.neg {
+ return 0, Above
+ }
+ return math.MaxUint64, Below
+ }
+
+ panic("unreachable")
+}
+
+// Int64 returns the integer resulting from truncating x towards zero.
+// If math.MinInt64 <= x <= math.MaxInt64, the result is Exact if x is
+// an integer, and Above (x < 0) or Below (x > 0) otherwise.
+// The result is (math.MinInt64, Above) for x < math.MinInt64,
+// and (math.MaxInt64, Below) for x > math.MaxInt64.
+func (x *Float) Int64() (int64, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ switch x.form {
+ case finite:
+ // 0 < |x| < +Inf
+ acc := makeAcc(x.neg)
+ if x.exp <= 0 {
+ // 0 < |x| < 1
+ return 0, acc
+ }
+ // x.exp > 0
+
+ // 1 <= |x| < +Inf
+ if x.exp <= 63 {
+ // i = trunc(x) fits into an int64 (excluding math.MinInt64)
+ i := int64(msb64(x.mant) >> (64 - uint32(x.exp)))
+ if x.neg {
+ i = -i
+ }
+ if x.MinPrec() <= uint(x.exp) {
+ return i, Exact
+ }
+ return i, acc // x truncated
+ }
+ if x.neg {
+ // check for special case x == math.MinInt64 (i.e., x == -(0.5 << 64))
+ if x.exp == 64 && x.MinPrec() == 1 {
+ acc = Exact
+ }
+ return math.MinInt64, acc
+ }
+ // x too large
+ return math.MaxInt64, Below
+
+ case zero:
+ return 0, Exact
+
+ case inf:
+ if x.neg {
+ return math.MinInt64, Above
+ }
+ return math.MaxInt64, Below
+ }
+
+ panic("unreachable")
+}
+
+// Float32 returns the float32 value nearest to x. If x is too small to be
+// represented by a float32 (|x| < math.SmallestNonzeroFloat32), the result
+// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
+// If x is too large to be represented by a float32 (|x| > math.MaxFloat32),
+// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
+func (x *Float) Float32() (float32, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ switch x.form {
+ case finite:
+ // 0 < |x| < +Inf
+
+ const (
+ fbits = 32 // float size
+ mbits = 23 // mantissa size (excluding implicit msb)
+ ebits = fbits - mbits - 1 // 8 exponent size
+ bias = 1<<(ebits-1) - 1 // 127 exponent bias
+ dmin = 1 - bias - mbits // -149 smallest unbiased exponent (denormal)
+ emin = 1 - bias // -126 smallest unbiased exponent (normal)
+ emax = bias // 127 largest unbiased exponent (normal)
+ )
+
+ // Float mantissa m is 0.5 <= m < 1.0; compute exponent for floatxx mantissa.
+ e := x.exp - 1 // exponent for mantissa m with 1.0 <= m < 2.0
+ p := mbits + 1 // precision of normal float
+
+ // If the exponent is too small, we may have a denormal number
+ // in which case we have fewer mantissa bits available: reduce
+ // precision accordingly.
+ if e < emin {
+ p -= emin - int(e)
+ // Make sure we have at least 1 bit so that we don't
+ // lose numbers rounded up to the smallest denormal.
+ if p < 1 {
+ p = 1
+ }
+ }
+
+ // round
+ var r Float
+ r.prec = uint32(p)
+ r.Set(x)
+ e = r.exp - 1
+
+ // Rounding may have caused r to overflow to ±Inf
+ // (rounding never causes underflows to 0).
+ if r.form == inf {
+ e = emax + 1 // cause overflow below
+ }
+
+ // If the exponent is too large, overflow to ±Inf.
+ if e > emax {
+ // overflow
+ if x.neg {
+ return float32(math.Inf(-1)), Below
+ }
+ return float32(math.Inf(+1)), Above
+ }
+ // e <= emax
+
+ // Determine sign, biased exponent, and mantissa.
+ var sign, bexp, mant uint32
+ if x.neg {
+ sign = 1 << (fbits - 1)
+ }
+
+ // Rounding may have caused a denormal number to
+ // become normal. Check again.
+ if e < emin {
+ // denormal number
+ if e < dmin {
+ // underflow to ±0
+ if x.neg {
+ var z float32
+ return -z, Above
+ }
+ return 0.0, Below
+ }
+ // bexp = 0
+ mant = msb32(r.mant) >> (fbits - r.prec)
+ } else {
+ // normal number: emin <= e <= emax
+ bexp = uint32(e+bias) << mbits
+ mant = msb32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
+ }
+
+ return math.Float32frombits(sign | bexp | mant), r.acc
+
+ case zero:
+ if x.neg {
+ var z float32
+ return -z, Exact
+ }
+ return 0.0, Exact
+
+ case inf:
+ if x.neg {
+ return float32(math.Inf(-1)), Exact
+ }
+ return float32(math.Inf(+1)), Exact
+ }
+
+ panic("unreachable")
+}
+
+// Float64 returns the float64 value nearest to x. If x is too small to be
+// represented by a float64 (|x| < math.SmallestNonzeroFloat64), the result
+// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
+// If x is too large to be represented by a float64 (|x| > math.MaxFloat64),
+// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
+func (x *Float) Float64() (float64, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ switch x.form {
+ case finite:
+ // 0 < |x| < +Inf
+
+ const (
+ fbits = 64 // float size
+ mbits = 52 // mantissa size (excluding implicit msb)
+ ebits = fbits - mbits - 1 // 11 exponent size
+ bias = 1<<(ebits-1) - 1 // 1023 exponent bias
+ dmin = 1 - bias - mbits // -1074 smallest unbiased exponent (denormal)
+ emin = 1 - bias // -1022 smallest unbiased exponent (normal)
+ emax = bias // 1023 largest unbiased exponent (normal)
+ )
+
+ // Float mantissa m is 0.5 <= m < 1.0; compute exponent for floatxx mantissa.
+ e := x.exp - 1 // exponent for mantissa m with 1.0 <= m < 2.0
+ p := mbits + 1 // precision of normal float
+
+ // If the exponent is too small, we may have a denormal number
+ // in which case we have fewer mantissa bits available: reduce
+ // precision accordingly.
+ if e < emin {
+ p -= emin - int(e)
+ // Make sure we have at least 1 bit so that we don't
+ // lose numbers rounded up to the smallest denormal.
+ if p < 1 {
+ p = 1
+ }
+ }
+
+ // round
+ var r Float
+ r.prec = uint32(p)
+ r.Set(x)
+ e = r.exp - 1
+
+ // Rounding may have caused r to overflow to ±Inf
+ // (rounding never causes underflows to 0).
+ if r.form == inf {
+ e = emax + 1 // cause overflow below
+ }
+
+ // If the exponent is too large, overflow to ±Inf.
+ if e > emax {
+ // overflow
+ if x.neg {
+ return math.Inf(-1), Below
+ }
+ return math.Inf(+1), Above
+ }
+ // e <= emax
+
+ // Determine sign, biased exponent, and mantissa.
+ var sign, bexp, mant uint64
+ if x.neg {
+ sign = 1 << (fbits - 1)
+ }
+
+ // Rounding may have caused a denormal number to
+ // become normal. Check again.
+ if e < emin {
+ // denormal number
+ if e < dmin {
+ // underflow to ±0
+ if x.neg {
+ var z float64
+ return -z, Above
+ }
+ return 0.0, Below
+ }
+ // bexp = 0
+ mant = msb64(r.mant) >> (fbits - r.prec)
+ } else {
+ // normal number: emin <= e <= emax
+ bexp = uint64(e+bias) << mbits
+ mant = msb64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
+ }
+
+ return math.Float64frombits(sign | bexp | mant), r.acc
+
+ case zero:
+ if x.neg {
+ var z float64
+ return -z, Exact
+ }
+ return 0.0, Exact
+
+ case inf:
+ if x.neg {
+ return math.Inf(-1), Exact
+ }
+ return math.Inf(+1), Exact
+ }
+
+ panic("unreachable")
+}
+
+// Int returns the result of truncating x towards zero;
+// or nil if x is an infinity.
+// The result is Exact if x.IsInt(); otherwise it is Below
+// for x > 0, and Above for x < 0.
+// If a non-nil *Int argument z is provided, Int stores
+// the result in z instead of allocating a new Int.
+func (x *Float) Int(z *Int) (*Int, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ if z == nil && x.form <= finite {
+ z = new(Int)
+ }
+
+ switch x.form {
+ case finite:
+ // 0 < |x| < +Inf
+ acc := makeAcc(x.neg)
+ if x.exp <= 0 {
+ // 0 < |x| < 1
+ return z.SetInt64(0), acc
+ }
+ // x.exp > 0
+
+ // 1 <= |x| < +Inf
+ // determine minimum required precision for x
+ allBits := uint(len(x.mant)) * _W
+ exp := uint(x.exp)
+ if x.MinPrec() <= exp {
+ acc = Exact
+ }
+ // shift mantissa as needed
+ if z == nil {
+ z = new(Int)
+ }
+ z.neg = x.neg
+ switch {
+ case exp > allBits:
+ z.abs = z.abs.shl(x.mant, exp-allBits)
+ default:
+ z.abs = z.abs.set(x.mant)
+ case exp < allBits:
+ z.abs = z.abs.shr(x.mant, allBits-exp)
+ }
+ return z, acc
+
+ case zero:
+ return z.SetInt64(0), Exact
+
+ case inf:
+ return nil, makeAcc(x.neg)
+ }
+
+ panic("unreachable")
+}
+
+// Rat returns the rational number corresponding to x;
+// or nil if x is an infinity.
+// The result is Exact is x is not an Inf.
+// If a non-nil *Rat argument z is provided, Rat stores
+// the result in z instead of allocating a new Rat.
+func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
+ if debugFloat {
+ x.validate()
+ }
+
+ if z == nil && x.form <= finite {
+ z = new(Rat)
+ }
+
+ switch x.form {
+ case finite:
+ // 0 < |x| < +Inf
+ allBits := int32(len(x.mant)) * _W
+ // build up numerator and denominator
+ z.a.neg = x.neg
+ switch {
+ case x.exp > allBits:
+ z.a.abs = z.a.abs.shl(x.mant, uint(x.exp-allBits))
+ z.b.abs = z.b.abs[:0] // == 1 (see Rat)
+ // z already in normal form
+ default:
+ z.a.abs = z.a.abs.set(x.mant)
+ z.b.abs = z.b.abs[:0] // == 1 (see Rat)
+ // z already in normal form
+ case x.exp < allBits:
+ z.a.abs = z.a.abs.set(x.mant)
+ t := z.b.abs.setUint64(1)
+ z.b.abs = t.shl(t, uint(allBits-x.exp))
+ z.norm()
+ }
+ return z, Exact
+
+ case zero:
+ return z.SetInt64(0), Exact
+
+ case inf:
+ return nil, makeAcc(x.neg)
+ }
+
+ panic("unreachable")
+}
+
+// Abs sets z to the (possibly rounded) value |x| (the absolute value of x)
+// and returns z.
+func (z *Float) Abs(x *Float) *Float {
+ z.Set(x)
+ z.neg = false
+ return z
+}
+
+// Neg sets z to the (possibly rounded) value of x with its sign negated,
+// and returns z.
+func (z *Float) Neg(x *Float) *Float {
+ z.Set(x)
+ z.neg = !z.neg
+ return z
+}
+
+func validateBinaryOperands(x, y *Float) {
+ if !debugFloat {
+ // avoid performance bugs
+ panic("validateBinaryOperands called but debugFloat is not set")
+ }
+ if len(x.mant) == 0 {
+ panic("empty mantissa for x")
+ }
+ if len(y.mant) == 0 {
+ panic("empty mantissa for y")
+ }
+}
+
+// z = x + y, ignoring signs of x and y for the addition
+// but using the sign of z for rounding the result.
+// x and y must have a non-empty mantissa and valid exponent.
+func (z *Float) uadd(x, y *Float) {
+ // Note: This implementation requires 2 shifts most of the
+ // time. It is also inefficient if exponents or precisions
+ // differ by wide margins. The following article describes
+ // an efficient (but much more complicated) implementation
+ // compatible with the internal representation used here:
+ //
+ // Vincent Lefèvre: "The Generic Multiple-Precision Floating-
+ // Point Addition With Exact Rounding (as in the MPFR Library)"
+ // http://www.vinc17.net/research/papers/rnc6.pdf
+
+ if debugFloat {
+ validateBinaryOperands(x, y)
+ }
+
+ // compute exponents ex, ey for mantissa with "binary point"
+ // on the right (mantissa.0) - use int64 to avoid overflow
+ ex := int64(x.exp) - int64(len(x.mant))*_W
+ ey := int64(y.exp) - int64(len(y.mant))*_W
+
+ // TODO(gri) having a combined add-and-shift primitive
+ // could make this code significantly faster
+ switch {
+ case ex < ey:
+ // cannot re-use z.mant w/o testing for aliasing
+ t := nat(nil).shl(y.mant, uint(ey-ex))
+ z.mant = z.mant.add(x.mant, t)
+ default:
+ // ex == ey, no shift needed
+ z.mant = z.mant.add(x.mant, y.mant)
+ case ex > ey:
+ // cannot re-use z.mant w/o testing for aliasing
+ t := nat(nil).shl(x.mant, uint(ex-ey))
+ z.mant = z.mant.add(t, y.mant)
+ ex = ey
+ }
+ // len(z.mant) > 0
+
+ z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
+}
+
+// z = x - y for |x| > |y|, ignoring signs of x and y for the subtraction
+// but using the sign of z for rounding the result.
+// x and y must have a non-empty mantissa and valid exponent.
+func (z *Float) usub(x, y *Float) {
+ // This code is symmetric to uadd.
+ // We have not factored the common code out because
+ // eventually uadd (and usub) should be optimized
+ // by special-casing, and the code will diverge.
+
+ if debugFloat {
+ validateBinaryOperands(x, y)
+ }
+
+ ex := int64(x.exp) - int64(len(x.mant))*_W
+ ey := int64(y.exp) - int64(len(y.mant))*_W
+
+ switch {
+ case ex < ey:
+ // cannot re-use z.mant w/o testing for aliasing
+ t := nat(nil).shl(y.mant, uint(ey-ex))
+ z.mant = t.sub(x.mant, t)
+ default:
+ // ex == ey, no shift needed
+ z.mant = z.mant.sub(x.mant, y.mant)
+ case ex > ey:
+ // cannot re-use z.mant w/o testing for aliasing
+ t := nat(nil).shl(x.mant, uint(ex-ey))
+ z.mant = t.sub(t, y.mant)
+ ex = ey
+ }
+
+ // operands may have cancelled each other out
+ if len(z.mant) == 0 {
+ z.acc = Exact
+ z.form = zero
+ z.neg = false
+ return
+ }
+ // len(z.mant) > 0
+
+ z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
+}
+
+// z = x * y, ignoring signs of x and y for the multiplication
+// but using the sign of z for rounding the result.
+// x and y must have a non-empty mantissa and valid exponent.
+func (z *Float) umul(x, y *Float) {
+ if debugFloat {
+ validateBinaryOperands(x, y)
+ }
+
+ // Note: This is doing too much work if the precision
+ // of z is less than the sum of the precisions of x
+ // and y which is often the case (e.g., if all floats
+ // have the same precision).
+ // TODO(gri) Optimize this for the common case.
+
+ e := int64(x.exp) + int64(y.exp)
+ z.mant = z.mant.mul(x.mant, y.mant)
+
+ z.setExpAndRound(e-fnorm(z.mant), 0)
+}
+
+// z = x / y, ignoring signs of x and y for the division
+// but using the sign of z for rounding the result.
+// x and y must have a non-empty mantissa and valid exponent.
+func (z *Float) uquo(x, y *Float) {
+ if debugFloat {
+ validateBinaryOperands(x, y)
+ }
+
+ // mantissa length in words for desired result precision + 1
+ // (at least one extra bit so we get the rounding bit after
+ // the division)
+ n := int(z.prec/_W) + 1
+
+ // compute adjusted x.mant such that we get enough result precision
+ xadj := x.mant
+ if d := n - len(x.mant) + len(y.mant); d > 0 {
+ // d extra words needed => add d "0 digits" to x
+ xadj = make(nat, len(x.mant)+d)
+ copy(xadj[d:], x.mant)
+ }
+ // TODO(gri): If we have too many digits (d < 0), we should be able
+ // to shorten x for faster division. But we must be extra careful
+ // with rounding in that case.
+
+ // Compute d before division since there may be aliasing of x.mant
+ // (via xadj) or y.mant with z.mant.
+ d := len(xadj) - len(y.mant)
+
+ // divide
+ var r nat
+ z.mant, r = z.mant.div(nil, xadj, y.mant)
+ e := int64(x.exp) - int64(y.exp) - int64(d-len(z.mant))*_W
+
+ // The result is long enough to include (at least) the rounding bit.
+ // If there's a non-zero remainder, the corresponding fractional part
+ // (if it were computed), would have a non-zero sticky bit (if it were
+ // zero, it couldn't have a non-zero remainder).
+ var sbit uint
+ if len(r) > 0 {
+ sbit = 1
+ }
+
+ z.setExpAndRound(e-fnorm(z.mant), sbit)
+}
+
+// ucmp returns -1, 0, or +1, depending on whether
+// |x| < |y|, |x| == |y|, or |x| > |y|.
+// x and y must have a non-empty mantissa and valid exponent.
+func (x *Float) ucmp(y *Float) int {
+ if debugFloat {
+ validateBinaryOperands(x, y)
+ }
+
+ switch {
+ case x.exp < y.exp:
+ return -1
+ case x.exp > y.exp:
+ return +1
+ }
+ // x.exp == y.exp
+
+ // compare mantissas
+ i := len(x.mant)
+ j := len(y.mant)
+ for i > 0 || j > 0 {
+ var xm, ym Word
+ if i > 0 {
+ i--
+ xm = x.mant[i]
+ }
+ if j > 0 {
+ j--
+ ym = y.mant[j]
+ }
+ switch {
+ case xm < ym:
+ return -1
+ case xm > ym:
+ return +1
+ }
+ }
+
+ return 0
+}
+
+// Handling of sign bit as defined by IEEE 754-2008, section 6.3:
+//
+// When neither the inputs nor result are NaN, the sign of a product or
+// quotient is the exclusive OR of the operands’ signs; the sign of a sum,
+// or of a difference x−y regarded as a sum x+(−y), differs from at most
+// one of the addends’ signs; and the sign of the result of conversions,
+// the quantize operation, the roundToIntegral operations, and the
+// roundToIntegralExact (see 5.3.1) is the sign of the first or only operand.
+// These rules shall apply even when operands or results are zero or infinite.
+//
+// When the sum of two operands with opposite signs (or the difference of
+// two operands with like signs) is exactly zero, the sign of that sum (or
+// difference) shall be +0 in all rounding-direction attributes except
+// roundTowardNegative; under that attribute, the sign of an exact zero
+// sum (or difference) shall be −0. However, x+x = x−(−x) retains the same
+// sign as x even when x is zero.
+//
+// See also: https://play.golang.org/p/RtH3UCt5IH
+
+// Add sets z to the rounded sum x+y and returns z. If z's precision is 0,
+// it is changed to the larger of x's or y's precision before the operation.
+// Rounding is performed according to z's precision and rounding mode; and
+// z's accuracy reports the result error relative to the exact (not rounded)
+// result. Add panics with ErrNaN if x and y are infinities with opposite
+// signs. The value of z is undefined in that case.
+//
+// BUG(gri) When rounding ToNegativeInf, the sign of Float values rounded to 0 is incorrect.
+func (z *Float) Add(x, y *Float) *Float {
+ if debugFloat {
+ x.validate()
+ y.validate()
+ }
+
+ if z.prec == 0 {
+ z.prec = umax32(x.prec, y.prec)
+ }
+
+ if x.form == finite && y.form == finite {
+ // x + y (commom case)
+ z.neg = x.neg
+ if x.neg == y.neg {
+ // x + y == x + y
+ // (-x) + (-y) == -(x + y)
+ z.uadd(x, y)
+ } else {
+ // x + (-y) == x - y == -(y - x)
+ // (-x) + y == y - x == -(x - y)
+ if x.ucmp(y) > 0 {
+ z.usub(x, y)
+ } else {
+ z.neg = !z.neg
+ z.usub(y, x)
+ }
+ }
+ return z
+ }
+
+ if x.form == inf && y.form == inf && x.neg != y.neg {
+ // +Inf + -Inf
+ // -Inf + +Inf
+ // value of z is undefined but make sure it's valid
+ z.acc = Exact
+ z.form = zero
+ z.neg = false
+ panic(ErrNaN{"addition of infinities with opposite signs"})
+ }
+
+ if x.form == zero && y.form == zero {
+ // ±0 + ±0
+ z.acc = Exact
+ z.form = zero
+ z.neg = x.neg && y.neg // -0 + -0 == -0
+ return z
+ }
+
+ if x.form == inf || y.form == zero {
+ // ±Inf + y
+ // x + ±0
+ return z.Set(x)
+ }
+
+ // ±0 + y
+ // x + ±Inf
+ return z.Set(y)
+}
+
+// Sub sets z to the rounded difference x-y and returns z.
+// Precision, rounding, and accuracy reporting are as for Add.
+// Sub panics with ErrNaN if x and y are infinities with equal
+// signs. The value of z is undefined in that case.
+func (z *Float) Sub(x, y *Float) *Float {
+ if debugFloat {
+ x.validate()
+ y.validate()
+ }
+
+ if z.prec == 0 {
+ z.prec = umax32(x.prec, y.prec)
+ }
+
+ if x.form == finite && y.form == finite {
+ // x - y (common case)
+ z.neg = x.neg
+ if x.neg != y.neg {
+ // x - (-y) == x + y
+ // (-x) - y == -(x + y)
+ z.uadd(x, y)
+ } else {
+ // x - y == x - y == -(y - x)
+ // (-x) - (-y) == y - x == -(x - y)
+ if x.ucmp(y) > 0 {
+ z.usub(x, y)
+ } else {
+ z.neg = !z.neg
+ z.usub(y, x)
+ }
+ }
+ return z
+ }
+
+ if x.form == inf && y.form == inf && x.neg == y.neg {
+ // +Inf - +Inf
+ // -Inf - -Inf
+ // value of z is undefined but make sure it's valid
+ z.acc = Exact
+ z.form = zero
+ z.neg = false
+ panic(ErrNaN{"subtraction of infinities with equal signs"})
+ }
+
+ if x.form == zero && y.form == zero {
+ // ±0 - ±0
+ z.acc = Exact
+ z.form = zero
+ z.neg = x.neg && !y.neg // -0 - +0 == -0
+ return z
+ }
+
+ if x.form == inf || y.form == zero {
+ // ±Inf - y
+ // x - ±0
+ return z.Set(x)
+ }
+
+ // ±0 - y
+ // x - ±Inf
+ return z.Neg(y)
+}
+
+// Mul sets z to the rounded product x*y and returns z.
+// Precision, rounding, and accuracy reporting are as for Add.
+// Mul panics with ErrNaN if one operand is zero and the other
+// operand an infinity. The value of z is undefined in that case.
+func (z *Float) Mul(x, y *Float) *Float {
+ if debugFloat {
+ x.validate()
+ y.validate()
+ }
+
+ if z.prec == 0 {
+ z.prec = umax32(x.prec, y.prec)
+ }
+
+ z.neg = x.neg != y.neg
+
+ if x.form == finite && y.form == finite {
+ // x * y (common case)
+ z.umul(x, y)
+ return z
+ }
+
+ z.acc = Exact
+ if x.form == zero && y.form == inf || x.form == inf && y.form == zero {
+ // ±0 * ±Inf
+ // ±Inf * ±0
+ // value of z is undefined but make sure it's valid
+ z.form = zero
+ z.neg = false
+ panic(ErrNaN{"multiplication of zero with infinity"})
+ }
+
+ if x.form == inf || y.form == inf {
+ // ±Inf * y
+ // x * ±Inf
+ z.form = inf
+ return z
+ }
+
+ // ±0 * y
+ // x * ±0
+ z.form = zero
+ return z
+}
+
+// Quo sets z to the rounded quotient x/y and returns z.
+// Precision, rounding, and accuracy reporting are as for Add.
+// Quo panics with ErrNaN if both operands are zero or infinities.
+// The value of z is undefined in that case.
+func (z *Float) Quo(x, y *Float) *Float {
+ if debugFloat {
+ x.validate()
+ y.validate()
+ }
+
+ if z.prec == 0 {
+ z.prec = umax32(x.prec, y.prec)
+ }
+
+ z.neg = x.neg != y.neg
+
+ if x.form == finite && y.form == finite {
+ // x / y (common case)
+ z.uquo(x, y)
+ return z
+ }
+
+ z.acc = Exact
+ if x.form == zero && y.form == zero || x.form == inf && y.form == inf {
+ // ±0 / ±0
+ // ±Inf / ±Inf
+ // value of z is undefined but make sure it's valid
+ z.form = zero
+ z.neg = false
+ panic(ErrNaN{"division of zero by zero or infinity by infinity"})
+ }
+
+ if x.form == zero || y.form == inf {
+ // ±0 / y
+ // x / ±Inf
+ z.form = zero
+ return z
+ }
+
+ // x / ±0
+ // ±Inf / y
+ z.form = inf
+ return z
+}
+
+// Cmp compares x and y and returns:
+//
+// -1 if x < y
+// 0 if x == y (incl. -0 == 0, -Inf == -Inf, and +Inf == +Inf)
+// +1 if x > y
+//
+func (x *Float) Cmp(y *Float) int {
+ if debugFloat {
+ x.validate()
+ y.validate()
+ }
+
+ mx := x.ord()
+ my := y.ord()
+ switch {
+ case mx < my:
+ return -1
+ case mx > my:
+ return +1
+ }
+ // mx == my
+
+ // only if |mx| == 1 we have to compare the mantissae
+ switch mx {
+ case -1:
+ return y.ucmp(x)
+ case +1:
+ return x.ucmp(y)
+ }
+
+ return 0
+}
+
+// ord classifies x and returns:
+//
+// -2 if -Inf == x
+// -1 if -Inf < x < 0
+// 0 if x == 0 (signed or unsigned)
+// +1 if 0 < x < +Inf
+// +2 if x == +Inf
+//
+func (x *Float) ord() int {
+ var m int
+ switch x.form {
+ case finite:
+ m = 1
+ case zero:
+ return 0
+ case inf:
+ m = 2
+ }
+ if x.neg {
+ m = -m
+ }
+ return m
+}
+
+func umax32(x, y uint32) uint32 {
+ if x > y {
+ return x
+ }
+ return y
+}
diff --git a/libgo/go/math/big/float_test.go b/libgo/go/math/big/float_test.go
new file mode 100644
index 00000000000..d3b214b631d
--- /dev/null
+++ b/libgo/go/math/big/float_test.go
@@ -0,0 +1,1694 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+// Verify that ErrNaN implements the error interface.
+var _ error = ErrNaN{}
+
+func (x *Float) uint64() uint64 {
+ u, acc := x.Uint64()
+ if acc != Exact {
+ panic(fmt.Sprintf("%s is not a uint64", x.Text('g', 10)))
+ }
+ return u
+}
+
+func (x *Float) int64() int64 {
+ i, acc := x.Int64()
+ if acc != Exact {
+ panic(fmt.Sprintf("%s is not an int64", x.Text('g', 10)))
+ }
+ return i
+}
+
+func TestFloatZeroValue(t *testing.T) {
+ // zero (uninitialized) value is a ready-to-use 0.0
+ var x Float
+ if s := x.Text('f', 1); s != "0.0" {
+ t.Errorf("zero value = %s; want 0.0", s)
+ }
+
+ // zero value has precision 0
+ if prec := x.Prec(); prec != 0 {
+ t.Errorf("prec = %d; want 0", prec)
+ }
+
+ // zero value can be used in any and all positions of binary operations
+ make := func(x int) *Float {
+ var f Float
+ if x != 0 {
+ f.SetInt64(int64(x))
+ }
+ // x == 0 translates into the zero value
+ return &f
+ }
+ for _, test := range []struct {
+ z, x, y, want int
+ opname rune
+ op func(z, x, y *Float) *Float
+ }{
+ {0, 0, 0, 0, '+', (*Float).Add},
+ {0, 1, 2, 3, '+', (*Float).Add},
+ {1, 2, 0, 2, '+', (*Float).Add},
+ {2, 0, 1, 1, '+', (*Float).Add},
+
+ {0, 0, 0, 0, '-', (*Float).Sub},
+ {0, 1, 2, -1, '-', (*Float).Sub},
+ {1, 2, 0, 2, '-', (*Float).Sub},
+ {2, 0, 1, -1, '-', (*Float).Sub},
+
+ {0, 0, 0, 0, '*', (*Float).Mul},
+ {0, 1, 2, 2, '*', (*Float).Mul},
+ {1, 2, 0, 0, '*', (*Float).Mul},
+ {2, 0, 1, 0, '*', (*Float).Mul},
+
+ // {0, 0, 0, 0, '/', (*Float).Quo}, // panics
+ {0, 2, 1, 2, '/', (*Float).Quo},
+ {1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf
+ {2, 0, 1, 0, '/', (*Float).Quo},
+ } {
+ z := make(test.z)
+ test.op(z, make(test.x), make(test.y))
+ got := 0
+ if !z.IsInf() {
+ got = int(z.int64())
+ }
+ if got != test.want {
+ t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want)
+ }
+ }
+
+ // TODO(gri) test how precision is set for zero value results
+}
+
+func makeFloat(s string) *Float {
+ x, _, err := ParseFloat(s, 0, 1000, ToNearestEven)
+ if err != nil {
+ panic(err)
+ }
+ return x
+}
+
+func TestFloatSetPrec(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ prec uint
+ want string
+ acc Accuracy
+ }{
+ // prec 0
+ {"0", 0, "0", Exact},
+ {"-0", 0, "-0", Exact},
+ {"-Inf", 0, "-Inf", Exact},
+ {"+Inf", 0, "+Inf", Exact},
+ {"123", 0, "0", Below},
+ {"-123", 0, "-0", Above},
+
+ // prec at upper limit
+ {"0", MaxPrec, "0", Exact},
+ {"-0", MaxPrec, "-0", Exact},
+ {"-Inf", MaxPrec, "-Inf", Exact},
+ {"+Inf", MaxPrec, "+Inf", Exact},
+
+ // just a few regular cases - general rounding is tested elsewhere
+ {"1.5", 1, "2", Above},
+ {"-1.5", 1, "-2", Below},
+ {"123", 1e6, "123", Exact},
+ {"-123", 1e6, "-123", Exact},
+ } {
+ x := makeFloat(test.x).SetPrec(test.prec)
+ prec := test.prec
+ if prec > MaxPrec {
+ prec = MaxPrec
+ }
+ if got := x.Prec(); got != prec {
+ t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec)
+ }
+ if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc {
+ t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc)
+ }
+ }
+}
+
+func TestFloatMinPrec(t *testing.T) {
+ const max = 100
+ for _, test := range []struct {
+ x string
+ want uint
+ }{
+ {"0", 0},
+ {"-0", 0},
+ {"+Inf", 0},
+ {"-Inf", 0},
+ {"1", 1},
+ {"2", 1},
+ {"3", 2},
+ {"0x8001", 16},
+ {"0x8001p-1000", 16},
+ {"0x8001p+1000", 16},
+ {"0.1", max},
+ } {
+ x := makeFloat(test.x).SetPrec(max)
+ if got := x.MinPrec(); got != test.want {
+ t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want)
+ }
+ }
+}
+
+func TestFloatSign(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ s int
+ }{
+ {"-Inf", -1},
+ {"-1", -1},
+ {"-0", 0},
+ {"+0", 0},
+ {"+1", +1},
+ {"+Inf", +1},
+ } {
+ x := makeFloat(test.x)
+ s := x.Sign()
+ if s != test.s {
+ t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s)
+ }
+ }
+}
+
+// alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0).
+func alike(x, y *Float) bool {
+ return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
+}
+
+func alike32(x, y float32) bool {
+ // we can ignore NaNs
+ return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y))
+
+}
+
+func alike64(x, y float64) bool {
+ // we can ignore NaNs
+ return x == y && math.Signbit(x) == math.Signbit(y)
+
+}
+
+func TestFloatMantExp(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ mant string
+ exp int
+ }{
+ {"0", "0", 0},
+ {"+0", "0", 0},
+ {"-0", "-0", 0},
+ {"Inf", "+Inf", 0},
+ {"+Inf", "+Inf", 0},
+ {"-Inf", "-Inf", 0},
+ {"1.5", "0.75", 1},
+ {"1.024e3", "0.5", 11},
+ {"-0.125", "-0.5", -2},
+ } {
+ x := makeFloat(test.x)
+ mant := makeFloat(test.mant)
+ m := new(Float)
+ e := x.MantExp(m)
+ if !alike(m, mant) || e != test.exp {
+ t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Text('g', 10), e, test.mant, test.exp)
+ }
+ }
+}
+
+func TestFloatMantExpAliasing(t *testing.T) {
+ x := makeFloat("0.5p10")
+ if e := x.MantExp(x); e != 10 {
+ t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e)
+ }
+ if want := makeFloat("0.5"); !alike(x, want) {
+ t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Text('g', 10), want.Text('g', 10))
+ }
+}
+
+func TestFloatSetMantExp(t *testing.T) {
+ for _, test := range []struct {
+ frac string
+ exp int
+ z string
+ }{
+ {"0", 0, "0"},
+ {"+0", 0, "0"},
+ {"-0", 0, "-0"},
+ {"Inf", 1234, "+Inf"},
+ {"+Inf", -1234, "+Inf"},
+ {"-Inf", -1234, "-Inf"},
+ {"0", MinExp, "0"},
+ {"0.25", MinExp, "+0"}, // exponent underflow
+ {"-0.25", MinExp, "-0"}, // exponent underflow
+ {"1", MaxExp, "+Inf"}, // exponent overflow
+ {"2", MaxExp - 1, "+Inf"}, // exponent overflow
+ {"0.75", 1, "1.5"},
+ {"0.5", 11, "1024"},
+ {"-0.5", -2, "-0.125"},
+ {"32", 5, "1024"},
+ {"1024", -10, "1"},
+ } {
+ frac := makeFloat(test.frac)
+ want := makeFloat(test.z)
+ var z Float
+ z.SetMantExp(frac, test.exp)
+ if !alike(&z, want) {
+ t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Text('g', 10), test.z)
+ }
+ // test inverse property
+ mant := new(Float)
+ if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 {
+ t.Errorf("Inverse property not satisfied: got %s; want %s", z.Text('g', 10), test.z)
+ }
+ }
+}
+
+func TestFloatPredicates(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ sign int
+ signbit, inf bool
+ }{
+ {x: "-Inf", sign: -1, signbit: true, inf: true},
+ {x: "-1", sign: -1, signbit: true},
+ {x: "-0", signbit: true},
+ {x: "0"},
+ {x: "1", sign: 1},
+ {x: "+Inf", sign: 1, inf: true},
+ } {
+ x := makeFloat(test.x)
+ if got := x.Signbit(); got != test.signbit {
+ t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit)
+ }
+ if got := x.Sign(); got != test.sign {
+ t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign)
+ }
+ if got := x.IsInf(); got != test.inf {
+ t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf)
+ }
+ }
+}
+
+func TestFloatIsInt(t *testing.T) {
+ for _, test := range []string{
+ "0 int",
+ "-0 int",
+ "1 int",
+ "-1 int",
+ "0.5",
+ "1.23",
+ "1.23e1",
+ "1.23e2 int",
+ "0.000000001e+8",
+ "0.000000001e+9 int",
+ "1.2345e200 int",
+ "Inf",
+ "+Inf",
+ "-Inf",
+ } {
+ s := strings.TrimSuffix(test, " int")
+ want := s != test
+ if got := makeFloat(s).IsInt(); got != want {
+ t.Errorf("%s.IsInt() == %t", s, got)
+ }
+ }
+}
+
+func fromBinary(s string) int64 {
+ x, err := strconv.ParseInt(s, 2, 64)
+ if err != nil {
+ panic(err)
+ }
+ return x
+}
+
+func toBinary(x int64) string {
+ return strconv.FormatInt(x, 2)
+}
+
+func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
+ // verify test data
+ var ok bool
+ switch mode {
+ case ToNearestEven, ToNearestAway:
+ ok = true // nothing to do for now
+ case ToZero:
+ if x < 0 {
+ ok = r >= x
+ } else {
+ ok = r <= x
+ }
+ case AwayFromZero:
+ if x < 0 {
+ ok = r <= x
+ } else {
+ ok = r >= x
+ }
+ case ToNegativeInf:
+ ok = r <= x
+ case ToPositiveInf:
+ ok = r >= x
+ default:
+ panic("unreachable")
+ }
+ if !ok {
+ t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r))
+ }
+
+ // compute expected accuracy
+ a := Exact
+ switch {
+ case r < x:
+ a = Below
+ case r > x:
+ a = Above
+ }
+
+ // round
+ f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec)
+
+ // check result
+ r1 := f.int64()
+ p1 := f.Prec()
+ a1 := f.Acc()
+ if r1 != r || p1 != prec || a1 != a {
+ t.Errorf("round %s (%d bits, %s) incorrect: got %s (%d bits, %s); want %s (%d bits, %s)",
+ toBinary(x), prec, mode,
+ toBinary(r1), p1, a1,
+ toBinary(r), prec, a)
+ return
+ }
+
+ // g and f should be the same
+ // (rounding by SetPrec after SetInt64 using default precision
+ // should be the same as rounding by SetInt64 after setting the
+ // precision)
+ g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x)
+ if !alike(g, f) {
+ t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s",
+ toBinary(x), prec, mode,
+ toBinary(g.int64()),
+ toBinary(r1),
+ toBinary(r),
+ )
+ return
+ }
+
+ // h and f should be the same
+ // (repeated rounding should be idempotent)
+ h := new(Float).SetMode(mode).SetPrec(prec).Set(f)
+ if !alike(h, f) {
+ t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s",
+ toBinary(x), prec, mode,
+ toBinary(h.int64()),
+ toBinary(r1),
+ toBinary(r),
+ )
+ return
+ }
+}
+
+// TestFloatRound tests basic rounding.
+func TestFloatRound(t *testing.T) {
+ for _, test := range []struct {
+ prec uint
+ x, zero, neven, naway, away string // input, results rounded to prec bits
+ }{
+ {5, "1000", "1000", "1000", "1000", "1000"},
+ {5, "1001", "1001", "1001", "1001", "1001"},
+ {5, "1010", "1010", "1010", "1010", "1010"},
+ {5, "1011", "1011", "1011", "1011", "1011"},
+ {5, "1100", "1100", "1100", "1100", "1100"},
+ {5, "1101", "1101", "1101", "1101", "1101"},
+ {5, "1110", "1110", "1110", "1110", "1110"},
+ {5, "1111", "1111", "1111", "1111", "1111"},
+
+ {4, "1000", "1000", "1000", "1000", "1000"},
+ {4, "1001", "1001", "1001", "1001", "1001"},
+ {4, "1010", "1010", "1010", "1010", "1010"},
+ {4, "1011", "1011", "1011", "1011", "1011"},
+ {4, "1100", "1100", "1100", "1100", "1100"},
+ {4, "1101", "1101", "1101", "1101", "1101"},
+ {4, "1110", "1110", "1110", "1110", "1110"},
+ {4, "1111", "1111", "1111", "1111", "1111"},
+
+ {3, "1000", "1000", "1000", "1000", "1000"},
+ {3, "1001", "1000", "1000", "1010", "1010"},
+ {3, "1010", "1010", "1010", "1010", "1010"},
+ {3, "1011", "1010", "1100", "1100", "1100"},
+ {3, "1100", "1100", "1100", "1100", "1100"},
+ {3, "1101", "1100", "1100", "1110", "1110"},
+ {3, "1110", "1110", "1110", "1110", "1110"},
+ {3, "1111", "1110", "10000", "10000", "10000"},
+
+ {3, "1000001", "1000000", "1000000", "1000000", "1010000"},
+ {3, "1001001", "1000000", "1010000", "1010000", "1010000"},
+ {3, "1010001", "1010000", "1010000", "1010000", "1100000"},
+ {3, "1011001", "1010000", "1100000", "1100000", "1100000"},
+ {3, "1100001", "1100000", "1100000", "1100000", "1110000"},
+ {3, "1101001", "1100000", "1110000", "1110000", "1110000"},
+ {3, "1110001", "1110000", "1110000", "1110000", "10000000"},
+ {3, "1111001", "1110000", "10000000", "10000000", "10000000"},
+
+ {2, "1000", "1000", "1000", "1000", "1000"},
+ {2, "1001", "1000", "1000", "1000", "1100"},
+ {2, "1010", "1000", "1000", "1100", "1100"},
+ {2, "1011", "1000", "1100", "1100", "1100"},
+ {2, "1100", "1100", "1100", "1100", "1100"},
+ {2, "1101", "1100", "1100", "1100", "10000"},
+ {2, "1110", "1100", "10000", "10000", "10000"},
+ {2, "1111", "1100", "10000", "10000", "10000"},
+
+ {2, "1000001", "1000000", "1000000", "1000000", "1100000"},
+ {2, "1001001", "1000000", "1000000", "1000000", "1100000"},
+ {2, "1010001", "1000000", "1100000", "1100000", "1100000"},
+ {2, "1011001", "1000000", "1100000", "1100000", "1100000"},
+ {2, "1100001", "1100000", "1100000", "1100000", "10000000"},
+ {2, "1101001", "1100000", "1100000", "1100000", "10000000"},
+ {2, "1110001", "1100000", "10000000", "10000000", "10000000"},
+ {2, "1111001", "1100000", "10000000", "10000000", "10000000"},
+
+ {1, "1000", "1000", "1000", "1000", "1000"},
+ {1, "1001", "1000", "1000", "1000", "10000"},
+ {1, "1010", "1000", "1000", "1000", "10000"},
+ {1, "1011", "1000", "1000", "1000", "10000"},
+ {1, "1100", "1000", "10000", "10000", "10000"},
+ {1, "1101", "1000", "10000", "10000", "10000"},
+ {1, "1110", "1000", "10000", "10000", "10000"},
+ {1, "1111", "1000", "10000", "10000", "10000"},
+
+ {1, "1000001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1001001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1010001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1011001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1100001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1101001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1110001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1111001", "1000000", "10000000", "10000000", "10000000"},
+ } {
+ x := fromBinary(test.x)
+ z := fromBinary(test.zero)
+ e := fromBinary(test.neven)
+ n := fromBinary(test.naway)
+ a := fromBinary(test.away)
+ prec := test.prec
+
+ testFloatRound(t, x, z, prec, ToZero)
+ testFloatRound(t, x, e, prec, ToNearestEven)
+ testFloatRound(t, x, n, prec, ToNearestAway)
+ testFloatRound(t, x, a, prec, AwayFromZero)
+
+ testFloatRound(t, x, z, prec, ToNegativeInf)
+ testFloatRound(t, x, a, prec, ToPositiveInf)
+
+ testFloatRound(t, -x, -a, prec, ToNegativeInf)
+ testFloatRound(t, -x, -z, prec, ToPositiveInf)
+ }
+}
+
+// TestFloatRound24 tests that rounding a float64 to 24 bits
+// matches IEEE-754 rounding to nearest when converting a
+// float64 to a float32 (excluding denormal numbers).
+func TestFloatRound24(t *testing.T) {
+ const x0 = 1<<26 - 0x10 // 11...110000 (26 bits)
+ for d := 0; d <= 0x10; d++ {
+ x := float64(x0 + d)
+ f := new(Float).SetPrec(24).SetFloat64(x)
+ got, _ := f.Float32()
+ want := float32(x)
+ if got != want {
+ t.Errorf("Round(%g, 24) = %g; want %g", x, got, want)
+ }
+ }
+}
+
+func TestFloatSetUint64(t *testing.T) {
+ for _, want := range []uint64{
+ 0,
+ 1,
+ 2,
+ 10,
+ 100,
+ 1<<32 - 1,
+ 1 << 32,
+ 1<<64 - 1,
+ } {
+ var f Float
+ f.SetUint64(want)
+ if got := f.uint64(); got != want {
+ t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
+ }
+ }
+
+ // test basic rounding behavior (exhaustive rounding testing is done elsewhere)
+ const x uint64 = 0x8765432187654321 // 64 bits needed
+ for prec := uint(1); prec <= 64; prec++ {
+ f := new(Float).SetPrec(prec).SetMode(ToZero).SetUint64(x)
+ got := f.uint64()
+ want := x &^ (1<<(64-prec) - 1) // cut off (round to zero) low 64-prec bits
+ if got != want {
+ t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
+ }
+ }
+}
+
+func TestFloatSetInt64(t *testing.T) {
+ for _, want := range []int64{
+ 0,
+ 1,
+ 2,
+ 10,
+ 100,
+ 1<<32 - 1,
+ 1 << 32,
+ 1<<63 - 1,
+ } {
+ for i := range [2]int{} {
+ if i&1 != 0 {
+ want = -want
+ }
+ var f Float
+ f.SetInt64(want)
+ if got := f.int64(); got != want {
+ t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
+ }
+ }
+ }
+
+ // test basic rounding behavior (exhaustive rounding testing is done elsewhere)
+ const x int64 = 0x7654321076543210 // 63 bits needed
+ for prec := uint(1); prec <= 63; prec++ {
+ f := new(Float).SetPrec(prec).SetMode(ToZero).SetInt64(x)
+ got := f.int64()
+ want := x &^ (1<<(63-prec) - 1) // cut off (round to zero) low 63-prec bits
+ if got != want {
+ t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
+ }
+ }
+}
+
+func TestFloatSetFloat64(t *testing.T) {
+ for _, want := range []float64{
+ 0,
+ 1,
+ 2,
+ 12345,
+ 1e10,
+ 1e100,
+ 3.14159265e10,
+ 2.718281828e-123,
+ 1.0 / 3,
+ math.MaxFloat32,
+ math.MaxFloat64,
+ math.SmallestNonzeroFloat32,
+ math.SmallestNonzeroFloat64,
+ math.Inf(-1),
+ math.Inf(0),
+ -math.Inf(1),
+ } {
+ for i := range [2]int{} {
+ if i&1 != 0 {
+ want = -want
+ }
+ var f Float
+ f.SetFloat64(want)
+ if got, acc := f.Float64(); got != want || acc != Exact {
+ t.Errorf("got %g (%s, %s); want %g (Exact)", got, f.Text('p', 0), acc, want)
+ }
+ }
+ }
+
+ // test basic rounding behavior (exhaustive rounding testing is done elsewhere)
+ const x uint64 = 0x8765432143218 // 53 bits needed
+ for prec := uint(1); prec <= 52; prec++ {
+ f := new(Float).SetPrec(prec).SetMode(ToZero).SetFloat64(float64(x))
+ got, _ := f.Float64()
+ want := float64(x &^ (1<<(52-prec) - 1)) // cut off (round to zero) low 53-prec bits
+ if got != want {
+ t.Errorf("got %g (%s); want %g", got, f.Text('p', 0), want)
+ }
+ }
+
+ // test NaN
+ defer func() {
+ if p, ok := recover().(ErrNaN); !ok {
+ t.Errorf("got %v; want ErrNaN panic", p)
+ }
+ }()
+ var f Float
+ f.SetFloat64(math.NaN())
+ // should not reach here
+ t.Errorf("got %s; want ErrNaN panic", f.Text('p', 0))
+}
+
+func TestFloatSetInt(t *testing.T) {
+ for _, want := range []string{
+ "0",
+ "1",
+ "-1",
+ "1234567890",
+ "123456789012345678901234567890",
+ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ } {
+ var x Int
+ _, ok := x.SetString(want, 0)
+ if !ok {
+ t.Errorf("invalid integer %s", want)
+ continue
+ }
+ n := x.BitLen()
+
+ var f Float
+ f.SetInt(&x)
+
+ // check precision
+ if n < 64 {
+ n = 64
+ }
+ if prec := f.Prec(); prec != uint(n) {
+ t.Errorf("got prec = %d; want %d", prec, n)
+ }
+
+ // check value
+ got := f.Text('g', 100)
+ if got != want {
+ t.Errorf("got %s (%s); want %s", got, f.Text('p', 0), want)
+ }
+ }
+
+ // TODO(gri) test basic rounding behavior
+}
+
+func TestFloatSetRat(t *testing.T) {
+ for _, want := range []string{
+ "0",
+ "1",
+ "-1",
+ "1234567890",
+ "123456789012345678901234567890",
+ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "1.2",
+ "3.14159265",
+ // TODO(gri) expand
+ } {
+ var x Rat
+ _, ok := x.SetString(want)
+ if !ok {
+ t.Errorf("invalid fraction %s", want)
+ continue
+ }
+ n := max(x.Num().BitLen(), x.Denom().BitLen())
+
+ var f1, f2 Float
+ f2.SetPrec(1000)
+ f1.SetRat(&x)
+ f2.SetRat(&x)
+
+ // check precision when set automatically
+ if n < 64 {
+ n = 64
+ }
+ if prec := f1.Prec(); prec != uint(n) {
+ t.Errorf("got prec = %d; want %d", prec, n)
+ }
+
+ got := f2.Text('g', 100)
+ if got != want {
+ t.Errorf("got %s (%s); want %s", got, f2.Text('p', 0), want)
+ }
+ }
+}
+
+func TestFloatSetInf(t *testing.T) {
+ var f Float
+ for _, test := range []struct {
+ signbit bool
+ prec uint
+ want string
+ }{
+ {false, 0, "+Inf"},
+ {true, 0, "-Inf"},
+ {false, 10, "+Inf"},
+ {true, 30, "-Inf"},
+ } {
+ x := f.SetPrec(test.prec).SetInf(test.signbit)
+ if got := x.String(); got != test.want || x.Prec() != test.prec {
+ t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec)
+ }
+ }
+}
+
+func TestFloatUint64(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ out uint64
+ acc Accuracy
+ }{
+ {"-Inf", 0, Above},
+ {"-1", 0, Above},
+ {"-1e-1000", 0, Above},
+ {"-0", 0, Exact},
+ {"0", 0, Exact},
+ {"1e-1000", 0, Below},
+ {"1", 1, Exact},
+ {"1.000000000000000000001", 1, Below},
+ {"12345.0", 12345, Exact},
+ {"12345.000000000000000000001", 12345, Below},
+ {"18446744073709551615", 18446744073709551615, Exact},
+ {"18446744073709551615.000000000000000000001", math.MaxUint64, Below},
+ {"18446744073709551616", math.MaxUint64, Below},
+ {"1e10000", math.MaxUint64, Below},
+ {"+Inf", math.MaxUint64, Below},
+ } {
+ x := makeFloat(test.x)
+ out, acc := x.Uint64()
+ if out != test.out || acc != test.acc {
+ t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
+ }
+ }
+}
+
+func TestFloatInt64(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ out int64
+ acc Accuracy
+ }{
+ {"-Inf", math.MinInt64, Above},
+ {"-1e10000", math.MinInt64, Above},
+ {"-9223372036854775809", math.MinInt64, Above},
+ {"-9223372036854775808.000000000000000000001", math.MinInt64, Above},
+ {"-9223372036854775808", -9223372036854775808, Exact},
+ {"-9223372036854775807.000000000000000000001", -9223372036854775807, Above},
+ {"-9223372036854775807", -9223372036854775807, Exact},
+ {"-12345.000000000000000000001", -12345, Above},
+ {"-12345.0", -12345, Exact},
+ {"-1.000000000000000000001", -1, Above},
+ {"-1.5", -1, Above},
+ {"-1", -1, Exact},
+ {"-1e-1000", 0, Above},
+ {"0", 0, Exact},
+ {"1e-1000", 0, Below},
+ {"1", 1, Exact},
+ {"1.000000000000000000001", 1, Below},
+ {"1.5", 1, Below},
+ {"12345.0", 12345, Exact},
+ {"12345.000000000000000000001", 12345, Below},
+ {"9223372036854775807", 9223372036854775807, Exact},
+ {"9223372036854775807.000000000000000000001", math.MaxInt64, Below},
+ {"9223372036854775808", math.MaxInt64, Below},
+ {"1e10000", math.MaxInt64, Below},
+ {"+Inf", math.MaxInt64, Below},
+ } {
+ x := makeFloat(test.x)
+ out, acc := x.Int64()
+ if out != test.out || acc != test.acc {
+ t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
+ }
+ }
+}
+
+func TestFloatFloat32(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ out float32
+ acc Accuracy
+ }{
+ {"0", 0, Exact},
+
+ // underflow
+ {"1e-1000", 0, Below},
+ {"0x0.000002p-127", 0, Below},
+ {"0x.0000010p-126", 0, Below},
+
+ // denormals
+ {"1.401298464e-45", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.0000018p-126", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.0000020p-126", math.SmallestNonzeroFloat32, Exact},
+ {"0x.8p-148", math.SmallestNonzeroFloat32, Exact},
+ {"1p-149", math.SmallestNonzeroFloat32, Exact},
+ {"0x.fffffep-126", math.Float32frombits(0x7fffff), Exact}, // largest denormal
+
+ // normals
+ {"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal
+ {"1p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal
+ {"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact},
+ {"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up
+ {"1", 1, Exact},
+ {"1.000000000000000000001", 1, Below},
+ {"12345.0", 12345, Exact},
+ {"12345.000000000000000000001", 12345, Below},
+ {"0x1.fffffe0p127", math.MaxFloat32, Exact},
+ {"0x1.fffffe8p127", math.MaxFloat32, Below},
+
+ // overflow
+ {"0x1.ffffff0p127", float32(math.Inf(+1)), Above},
+ {"0x1p128", float32(math.Inf(+1)), Above},
+ {"1e10000", float32(math.Inf(+1)), Above},
+ {"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding
+
+ // inf
+ {"Inf", float32(math.Inf(+1)), Exact},
+ } {
+ for i := 0; i < 2; i++ {
+ // test both signs
+ tx, tout, tacc := test.x, test.out, test.acc
+ if i != 0 {
+ tx = "-" + tx
+ tout = -tout
+ tacc = -tacc
+ }
+
+ // conversion should match strconv where syntax is agreeable
+ if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) {
+ t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
+ }
+
+ x := makeFloat(tx)
+ out, acc := x.Float32()
+ if !alike32(out, tout) || acc != tacc {
+ t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc)
+ }
+
+ // test that x.SetFloat64(float64(f)).Float32() == f
+ var x2 Float
+ out2, acc2 := x2.SetFloat64(float64(out)).Float32()
+ if !alike32(out2, out) || acc2 != Exact {
+ t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ }
+ }
+ }
+}
+
+func TestFloatFloat64(t *testing.T) {
+ const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022
+ for _, test := range []struct {
+ x string
+ out float64
+ acc Accuracy
+ }{
+ {"0", 0, Exact},
+
+ // underflow
+ {"1e-1000", 0, Below},
+ {"0x0.0000000000001p-1023", 0, Below},
+ {"0x0.00000000000008p-1022", 0, Below},
+
+ // denormals
+ {"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal
+ {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal
+ {"0x.8p-1073", math.SmallestNonzeroFloat64, Exact},
+ {"1p-1074", math.SmallestNonzeroFloat64, Exact},
+ {"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal
+
+ // normals
+ {"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal
+ {"1p-1022", math.Float64frombits(0x0010000000000000), Exact}, // smallest normal
+ {"1", 1, Exact},
+ {"1.000000000000000000001", 1, Below},
+ {"12345.0", 12345, Exact},
+ {"12345.000000000000000000001", 12345, Below},
+ {"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact},
+ {"0x1.fffffffffffff4p1023", math.MaxFloat64, Below},
+
+ // overflow
+ {"0x1.fffffffffffff8p1023", math.Inf(+1), Above},
+ {"0x1p1024", math.Inf(+1), Above},
+ {"1e10000", math.Inf(+1), Above},
+ {"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding
+ {"Inf", math.Inf(+1), Exact},
+
+ // selected denormalized values that were handled incorrectly in the past
+ {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
+ {"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
+
+ // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+ {"2.2250738585072011e-308", 2.225073858507201e-308, Below},
+ // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+ {"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
+ } {
+ for i := 0; i < 2; i++ {
+ // test both signs
+ tx, tout, tacc := test.x, test.out, test.acc
+ if i != 0 {
+ tx = "-" + tx
+ tout = -tout
+ tacc = -tacc
+ }
+
+ // conversion should match strconv where syntax is agreeable
+ if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) {
+ t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
+ }
+
+ x := makeFloat(tx)
+ out, acc := x.Float64()
+ if !alike64(out, tout) || acc != tacc {
+ t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc)
+ }
+
+ // test that x.SetFloat64(f).Float64() == f
+ var x2 Float
+ out2, acc2 := x2.SetFloat64(out).Float64()
+ if !alike64(out2, out) || acc2 != Exact {
+ t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ }
+ }
+ }
+}
+
+func TestFloatInt(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ want string
+ acc Accuracy
+ }{
+ {"0", "0", Exact},
+ {"+0", "0", Exact},
+ {"-0", "0", Exact},
+ {"Inf", "nil", Below},
+ {"+Inf", "nil", Below},
+ {"-Inf", "nil", Above},
+ {"1", "1", Exact},
+ {"-1", "-1", Exact},
+ {"1.23", "1", Below},
+ {"-1.23", "-1", Above},
+ {"123e-2", "1", Below},
+ {"123e-3", "0", Below},
+ {"123e-4", "0", Below},
+ {"1e-1000", "0", Below},
+ {"-1e-1000", "0", Above},
+ {"1e+10", "10000000000", Exact},
+ {"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
+ } {
+ x := makeFloat(test.x)
+ res, acc := x.Int(nil)
+ got := "nil"
+ if res != nil {
+ got = res.String()
+ }
+ if got != test.want || acc != test.acc {
+ t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
+ }
+ }
+
+ // check that supplied *Int is used
+ for _, f := range []string{"0", "1", "-1", "1234"} {
+ x := makeFloat(f)
+ i := new(Int)
+ if res, _ := x.Int(i); res != i {
+ t.Errorf("(%s).Int is not using supplied *Int", f)
+ }
+ }
+}
+
+func TestFloatRat(t *testing.T) {
+ for _, test := range []struct {
+ x, want string
+ acc Accuracy
+ }{
+ {"0", "0/1", Exact},
+ {"+0", "0/1", Exact},
+ {"-0", "0/1", Exact},
+ {"Inf", "nil", Below},
+ {"+Inf", "nil", Below},
+ {"-Inf", "nil", Above},
+ {"1", "1/1", Exact},
+ {"-1", "-1/1", Exact},
+ {"1.25", "5/4", Exact},
+ {"-1.25", "-5/4", Exact},
+ {"1e10", "10000000000/1", Exact},
+ {"1p10", "1024/1", Exact},
+ {"-1p-10", "-1/1024", Exact},
+ {"3.14159265", "7244019449799623199/2305843009213693952", Exact},
+ } {
+ x := makeFloat(test.x).SetPrec(64)
+ res, acc := x.Rat(nil)
+ got := "nil"
+ if res != nil {
+ got = res.String()
+ }
+ if got != test.want {
+ t.Errorf("%s: got %s; want %s", test.x, got, test.want)
+ continue
+ }
+ if acc != test.acc {
+ t.Errorf("%s: got %s; want %s", test.x, acc, test.acc)
+ continue
+ }
+
+ // inverse conversion
+ if res != nil {
+ got := new(Float).SetPrec(64).SetRat(res)
+ if got.Cmp(x) != 0 {
+ t.Errorf("%s: got %s; want %s", test.x, got, x)
+ }
+ }
+ }
+
+ // check that supplied *Rat is used
+ for _, f := range []string{"0", "1", "-1", "1234"} {
+ x := makeFloat(f)
+ r := new(Rat)
+ if res, _ := x.Rat(r); res != r {
+ t.Errorf("(%s).Rat is not using supplied *Rat", f)
+ }
+ }
+}
+
+func TestFloatAbs(t *testing.T) {
+ for _, test := range []string{
+ "0",
+ "1",
+ "1234",
+ "1.23e-2",
+ "1e-1000",
+ "1e1000",
+ "Inf",
+ } {
+ p := makeFloat(test)
+ a := new(Float).Abs(p)
+ if !alike(a, p) {
+ t.Errorf("%s: got %s; want %s", test, a.Text('g', 10), test)
+ }
+
+ n := makeFloat("-" + test)
+ a.Abs(n)
+ if !alike(a, p) {
+ t.Errorf("-%s: got %s; want %s", test, a.Text('g', 10), test)
+ }
+ }
+}
+
+func TestFloatNeg(t *testing.T) {
+ for _, test := range []string{
+ "0",
+ "1",
+ "1234",
+ "1.23e-2",
+ "1e-1000",
+ "1e1000",
+ "Inf",
+ } {
+ p1 := makeFloat(test)
+ n1 := makeFloat("-" + test)
+ n2 := new(Float).Neg(p1)
+ p2 := new(Float).Neg(n2)
+ if !alike(n2, n1) {
+ t.Errorf("%s: got %s; want %s", test, n2.Text('g', 10), n1.Text('g', 10))
+ }
+ if !alike(p2, p1) {
+ t.Errorf("%s: got %s; want %s", test, p2.Text('g', 10), p1.Text('g', 10))
+ }
+ }
+}
+
+func TestFloatInc(t *testing.T) {
+ const n = 10
+ for _, prec := range precList {
+ if 1<<prec < n {
+ continue // prec must be large enough to hold all numbers from 0 to n
+ }
+ var x, one Float
+ x.SetPrec(prec)
+ one.SetInt64(1)
+ for i := 0; i < n; i++ {
+ x.Add(&x, &one)
+ }
+ if x.Cmp(new(Float).SetInt64(n)) != 0 {
+ t.Errorf("prec = %d: got %s; want %d", prec, &x, n)
+ }
+ }
+}
+
+// Selected precisions with which to run various tests.
+var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
+
+// Selected bits with which to run various tests.
+// Each entry is a list of bits representing a floating-point number (see fromBits).
+var bitsList = [...]Bits{
+ {}, // = 0
+ {0}, // = 1
+ {1}, // = 2
+ {-1}, // = 1/2
+ {10}, // = 2**10 == 1024
+ {-10}, // = 2**-10 == 1/1024
+ {100, 10, 1}, // = 2**100 + 2**10 + 2**1
+ {0, -1, -2, -10},
+ // TODO(gri) add more test cases
+}
+
+// TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual"
+// addition/subtraction of arguments represented by Bits values with the
+// respective Float addition/subtraction for a variety of precisions
+// and rounding modes.
+func TestFloatAdd(t *testing.T) {
+ for _, xbits := range bitsList {
+ for _, ybits := range bitsList {
+ // exact values
+ x := xbits.Float()
+ y := ybits.Float()
+ zbits := xbits.add(ybits)
+ z := zbits.Float()
+
+ for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
+ for _, prec := range precList {
+ got := new(Float).SetPrec(prec).SetMode(mode)
+ got.Add(x, y)
+ want := zbits.round(prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, x, xbits, y, ybits, got, want)
+ }
+
+ got.Sub(z, x)
+ want = ybits.round(prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, z, zbits, x, xbits, got, want)
+ }
+ }
+ }
+ }
+ }
+}
+
+// TestFloatAdd32 tests that Float.Add/Sub of numbers with
+// 24bit mantissa behaves like float32 addition/subtraction
+// (excluding denormal numbers).
+func TestFloatAdd32(t *testing.T) {
+ // chose base such that we cross the mantissa precision limit
+ const base = 1<<26 - 0x10 // 11...110000 (26 bits)
+ for d := 0; d <= 0x10; d++ {
+ for i := range [2]int{} {
+ x0, y0 := float64(base), float64(d)
+ if i&1 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := NewFloat(x0)
+ y := NewFloat(y0)
+ z := new(Float).SetPrec(24)
+
+ z.Add(x, y)
+ got, acc := z.Float32()
+ want := float32(y0) + float32(x0)
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
+ }
+
+ z.Sub(z, y)
+ got, acc = z.Float32()
+ want = float32(want) - float32(y0)
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
+ }
+ }
+ }
+}
+
+// TestFloatAdd64 tests that Float.Add/Sub of numbers with
+// 53bit mantissa behaves like float64 addition/subtraction.
+func TestFloatAdd64(t *testing.T) {
+ // chose base such that we cross the mantissa precision limit
+ const base = 1<<55 - 0x10 // 11...110000 (55 bits)
+ for d := 0; d <= 0x10; d++ {
+ for i := range [2]int{} {
+ x0, y0 := float64(base), float64(d)
+ if i&1 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := NewFloat(x0)
+ y := NewFloat(y0)
+ z := new(Float).SetPrec(53)
+
+ z.Add(x, y)
+ got, acc := z.Float64()
+ want := x0 + y0
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
+ }
+
+ z.Sub(z, y)
+ got, acc = z.Float64()
+ want -= y0
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
+ }
+ }
+ }
+}
+
+// TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual"
+// multiplication/division of arguments represented by Bits values with the
+// respective Float multiplication/division for a variety of precisions
+// and rounding modes.
+func TestFloatMul(t *testing.T) {
+ for _, xbits := range bitsList {
+ for _, ybits := range bitsList {
+ // exact values
+ x := xbits.Float()
+ y := ybits.Float()
+ zbits := xbits.mul(ybits)
+ z := zbits.Float()
+
+ for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
+ for _, prec := range precList {
+ got := new(Float).SetPrec(prec).SetMode(mode)
+ got.Mul(x, y)
+ want := zbits.round(prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, x, xbits, y, ybits, got, want)
+ }
+
+ if x.Sign() == 0 {
+ continue // ignore div-0 case (not invertable)
+ }
+ got.Quo(z, x)
+ want = ybits.round(prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, z, zbits, x, xbits, got, want)
+ }
+ }
+ }
+ }
+ }
+}
+
+// TestFloatMul64 tests that Float.Mul/Quo of numbers with
+// 53bit mantissa behaves like float64 multiplication/division.
+func TestFloatMul64(t *testing.T) {
+ for _, test := range []struct {
+ x, y float64
+ }{
+ {0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 1.5},
+ {1.234, 0.5678},
+ {2.718281828, 3.14159265358979},
+ {2.718281828e10, 3.14159265358979e-32},
+ {1.0 / 3, 1e200},
+ } {
+ for i := range [8]int{} {
+ x0, y0 := test.x, test.y
+ if i&1 != 0 {
+ x0 = -x0
+ }
+ if i&2 != 0 {
+ y0 = -y0
+ }
+ if i&4 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := NewFloat(x0)
+ y := NewFloat(y0)
+ z := new(Float).SetPrec(53)
+
+ z.Mul(x, y)
+ got, _ := z.Float64()
+ want := x0 * y0
+ if got != want {
+ t.Errorf("%g * %g = %g; want %g", x0, y0, got, want)
+ }
+
+ if y0 == 0 {
+ continue // avoid division-by-zero
+ }
+ z.Quo(z, y)
+ got, _ = z.Float64()
+ want /= y0
+ if got != want {
+ t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want)
+ }
+ }
+ }
+}
+
+func TestIssue6866(t *testing.T) {
+ for _, prec := range precList {
+ two := new(Float).SetPrec(prec).SetInt64(2)
+ one := new(Float).SetPrec(prec).SetInt64(1)
+ three := new(Float).SetPrec(prec).SetInt64(3)
+ msix := new(Float).SetPrec(prec).SetInt64(-6)
+ psix := new(Float).SetPrec(prec).SetInt64(+6)
+
+ p := new(Float).SetPrec(prec)
+ z1 := new(Float).SetPrec(prec)
+ z2 := new(Float).SetPrec(prec)
+
+ // z1 = 2 + 1.0/3*-6
+ p.Quo(one, three)
+ p.Mul(p, msix)
+ z1.Add(two, p)
+
+ // z2 = 2 - 1.0/3*+6
+ p.Quo(one, three)
+ p.Mul(p, psix)
+ z2.Sub(two, p)
+
+ if z1.Cmp(z2) != 0 {
+ t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2)
+ }
+ if z1.Sign() != 0 {
+ t.Errorf("prec %d: got z1 = %s; want 0", prec, z1)
+ }
+ if z2.Sign() != 0 {
+ t.Errorf("prec %d: got z2 = %s; want 0", prec, z2)
+ }
+ }
+}
+
+func TestFloatQuo(t *testing.T) {
+ // TODO(gri) make the test vary these precisions
+ preci := 200 // precision of integer part
+ precf := 20 // precision of fractional part
+
+ for i := 0; i < 8; i++ {
+ // compute accurate (not rounded) result z
+ bits := Bits{preci - 1}
+ if i&3 != 0 {
+ bits = append(bits, 0)
+ }
+ if i&2 != 0 {
+ bits = append(bits, -1)
+ }
+ if i&1 != 0 {
+ bits = append(bits, -precf)
+ }
+ z := bits.Float()
+
+ // compute accurate x as z*y
+ y := NewFloat(3.14159265358979323e123)
+
+ x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero)
+ x.Mul(z, y)
+
+ // leave for debugging
+ // fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z)
+
+ if got := x.Acc(); got != Exact {
+ t.Errorf("got acc = %s; want exact", got)
+ }
+
+ // round accurate z for a variety of precisions and
+ // modes and compare against result of x / y.
+ for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
+ for d := -5; d < 5; d++ {
+ prec := uint(preci + d)
+ got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y)
+ want := bits.round(prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s",
+ i, prec, mode, x, y, got, want)
+ }
+ }
+ }
+ }
+}
+
+// TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
+// it serves as a smoke test for basic correctness of division.
+func TestFloatQuoSmoke(t *testing.T) {
+ n := 1000
+ if testing.Short() {
+ n = 10
+ }
+
+ const dprec = 3 // max. precision variation
+ const prec = 10 + dprec // enough bits to hold n precisely
+ for x := -n; x <= n; x++ {
+ for y := -n; y < n; y++ {
+ if y == 0 {
+ continue
+ }
+
+ a := float64(x)
+ b := float64(y)
+ c := a / b
+
+ // vary operand precision (only ok as long as a, b can be represented correctly)
+ for ad := -dprec; ad <= dprec; ad++ {
+ for bd := -dprec; bd <= dprec; bd++ {
+ A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a)
+ B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b)
+ C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width
+
+ cc, acc := C.Float64()
+ if cc != c {
+ t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Text('g', 5), c)
+ continue
+ }
+ if acc != Exact {
+ t.Errorf("%g/%g got %s result; want exact result", a, b, acc)
+ }
+ }
+ }
+ }
+ }
+}
+
+// TestFloatArithmeticSpecialValues tests that Float operations produce the
+// correct results for combinations of zero (±0), finite (±1 and ±2.71828),
+// and infinite (±Inf) operands.
+func TestFloatArithmeticSpecialValues(t *testing.T) {
+ zero := 0.0
+ args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
+ xx := new(Float)
+ yy := new(Float)
+ got := new(Float)
+ want := new(Float)
+ for i := 0; i < 4; i++ {
+ for _, x := range args {
+ xx.SetFloat64(x)
+ // check conversion is correct
+ // (no need to do this for y, since we see exactly the
+ // same values there)
+ if got, acc := xx.Float64(); got != x || acc != Exact {
+ t.Errorf("Float(%g) == %g (%s)", x, got, acc)
+ }
+ for _, y := range args {
+ yy.SetFloat64(y)
+ var (
+ op string
+ z float64
+ f func(z, x, y *Float) *Float
+ )
+ switch i {
+ case 0:
+ op = "+"
+ z = x + y
+ f = (*Float).Add
+ case 1:
+ op = "-"
+ z = x - y
+ f = (*Float).Sub
+ case 2:
+ op = "*"
+ z = x * y
+ f = (*Float).Mul
+ case 3:
+ op = "/"
+ z = x / y
+ f = (*Float).Quo
+ default:
+ panic("unreachable")
+ }
+ var errnan bool // set if execution of f panicked with ErrNaN
+ // protect execution of f
+ func() {
+ defer func() {
+ if p := recover(); p != nil {
+ _ = p.(ErrNaN) // re-panic if not ErrNaN
+ errnan = true
+ }
+ }()
+ f(got, xx, yy)
+ }()
+ if math.IsNaN(z) {
+ if !errnan {
+ t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got)
+ }
+ continue
+ }
+ if errnan {
+ t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want)
+ continue
+ }
+ want.SetFloat64(z)
+ if !alike(got, want) {
+ t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
+ }
+ }
+ }
+ }
+}
+
+func TestFloatArithmeticOverflow(t *testing.T) {
+ for _, test := range []struct {
+ prec uint
+ mode RoundingMode
+ op byte
+ x, y, want string
+ acc Accuracy
+ }{
+ {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test
+ {4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact}, // smoke test
+
+ {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact},
+ {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below}, // rounded to zero
+ {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in +
+ {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in +
+ {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in -
+
+ {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below}, // rounded to zero
+ {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding
+ {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding
+
+ {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding
+ {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding
+ {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above}, // rounded to zero
+
+ {4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact},
+ {4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact},
+
+ {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p+2147483647", Exact},
+ {4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in *
+ {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in *
+
+ {4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact},
+ {4, ToNearestEven, '/', "0x.8p+0", "0x.8p2147483647", "0x.8p-2147483646", Exact},
+ {4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact},
+ {4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact},
+ {4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in /
+ } {
+ x := makeFloat(test.x)
+ y := makeFloat(test.y)
+ z := new(Float).SetPrec(test.prec).SetMode(test.mode)
+ switch test.op {
+ case '+':
+ z.Add(x, y)
+ case '-':
+ z.Sub(x, y)
+ case '*':
+ z.Mul(x, y)
+ case '/':
+ z.Quo(x, y)
+ default:
+ panic("unreachable")
+ }
+ if got := z.Text('p', 0); got != test.want || z.Acc() != test.acc {
+ t.Errorf(
+ "prec = %d (%s): %s %c %s = %s (%s); want %s (%s)",
+ test.prec, test.mode, x.Text('p', 0), test.op, y.Text('p', 0), got, z.Acc(), test.want, test.acc,
+ )
+ }
+ }
+}
+
+// TODO(gri) Add tests that check correctness in the presence of aliasing.
+
+// For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected
+// by the sign of the value to be rounded. Test that rounding happens after
+// the sign of a result has been set.
+// This test uses specific values that are known to fail if rounding is
+// "factored" out before setting the result sign.
+func TestFloatArithmeticRounding(t *testing.T) {
+ for _, test := range []struct {
+ mode RoundingMode
+ prec uint
+ x, y, want int64
+ op byte
+ }{
+ {ToZero, 3, -0x8, -0x1, -0x8, '+'},
+ {AwayFromZero, 3, -0x8, -0x1, -0xa, '+'},
+ {ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'},
+
+ {ToZero, 3, -0x8, 0x1, -0x8, '-'},
+ {AwayFromZero, 3, -0x8, 0x1, -0xa, '-'},
+ {ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'},
+
+ {ToZero, 3, -0x9, 0x1, -0x8, '*'},
+ {AwayFromZero, 3, -0x9, 0x1, -0xa, '*'},
+ {ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'},
+
+ {ToZero, 3, -0x9, 0x1, -0x8, '/'},
+ {AwayFromZero, 3, -0x9, 0x1, -0xa, '/'},
+ {ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'},
+ } {
+ var x, y, z Float
+ x.SetInt64(test.x)
+ y.SetInt64(test.y)
+ z.SetPrec(test.prec).SetMode(test.mode)
+ switch test.op {
+ case '+':
+ z.Add(&x, &y)
+ case '-':
+ z.Sub(&x, &y)
+ case '*':
+ z.Mul(&x, &y)
+ case '/':
+ z.Quo(&x, &y)
+ default:
+ panic("unreachable")
+ }
+ if got, acc := z.Int64(); got != test.want || acc != Exact {
+ t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)",
+ test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want,
+ )
+ }
+ }
+}
+
+// TestFloatCmpSpecialValues tests that Cmp produces the correct results for
+// combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf)
+// operands.
+func TestFloatCmpSpecialValues(t *testing.T) {
+ zero := 0.0
+ args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
+ xx := new(Float)
+ yy := new(Float)
+ for i := 0; i < 4; i++ {
+ for _, x := range args {
+ xx.SetFloat64(x)
+ // check conversion is correct
+ // (no need to do this for y, since we see exactly the
+ // same values there)
+ if got, acc := xx.Float64(); got != x || acc != Exact {
+ t.Errorf("Float(%g) == %g (%s)", x, got, acc)
+ }
+ for _, y := range args {
+ yy.SetFloat64(y)
+ got := xx.Cmp(yy)
+ want := 0
+ switch {
+ case x < y:
+ want = -1
+ case x > y:
+ want = +1
+ }
+ if got != want {
+ t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want)
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/math/big/floatconv.go b/libgo/go/math/big/floatconv.go
new file mode 100644
index 00000000000..4a070ca64d4
--- /dev/null
+++ b/libgo/go/math/big/floatconv.go
@@ -0,0 +1,239 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements string-to-Float conversion functions.
+
+package big
+
+import (
+ "fmt"
+ "io"
+ "strings"
+)
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s must be a floating-point number of the same format as accepted
+// by Parse, with base argument 0.
+func (z *Float) SetString(s string) (*Float, bool) {
+ if f, _, err := z.Parse(s, 0); err == nil {
+ return f, true
+ }
+ return nil, false
+}
+
+// scan is like Parse but reads the longest possible prefix representing a valid
+// floating point number from an io.ByteScanner rather than a string. It serves
+// as the implementation of Parse. It does not recognize ±Inf and does not expect
+// EOF at the end.
+func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
+ prec := z.prec
+ if prec == 0 {
+ prec = 64
+ }
+
+ // A reasonable value in case of an error.
+ z.form = zero
+
+ // sign
+ z.neg, err = scanSign(r)
+ if err != nil {
+ return
+ }
+
+ // mantissa
+ var fcount int // fractional digit count; valid if <= 0
+ z.mant, b, fcount, err = z.mant.scan(r, base, true)
+ if err != nil {
+ return
+ }
+
+ // exponent
+ var exp int64
+ var ebase int
+ exp, ebase, err = scanExponent(r, true)
+ if err != nil {
+ return
+ }
+
+ // special-case 0
+ if len(z.mant) == 0 {
+ z.prec = prec
+ z.acc = Exact
+ z.form = zero
+ f = z
+ return
+ }
+ // len(z.mant) > 0
+
+ // The mantissa may have a decimal point (fcount <= 0) and there
+ // may be a nonzero exponent exp. The decimal point amounts to a
+ // division by b**(-fcount). An exponent means multiplication by
+ // ebase**exp. Finally, mantissa normalization (shift left) requires
+ // a correcting multiplication by 2**(-shiftcount). Multiplications
+ // are commutative, so we can apply them in any order as long as there
+ // is no loss of precision. We only have powers of 2 and 10; keep
+ // track via separate exponents exp2 and exp10.
+
+ // normalize mantissa and get initial binary exponent
+ var exp2 = int64(len(z.mant))*_W - fnorm(z.mant)
+
+ // determine binary or decimal exponent contribution of decimal point
+ var exp10 int64
+ if fcount < 0 {
+ // The mantissa has a "decimal" point ddd.dddd; and
+ // -fcount is the number of digits to the right of '.'.
+ // Adjust relevant exponent accodingly.
+ switch b {
+ case 16:
+ fcount *= 4 // hexadecimal digits are 4 bits each
+ fallthrough
+ case 2:
+ exp2 += int64(fcount)
+ default: // b == 10
+ exp10 = int64(fcount)
+ }
+ // we don't need fcount anymore
+ }
+
+ // take actual exponent into account
+ if ebase == 2 {
+ exp2 += exp
+ } else { // ebase == 10
+ exp10 += exp
+ }
+ // we don't need exp anymore
+
+ // apply 2**exp2
+ if MinExp <= exp2 && exp2 <= MaxExp {
+ z.prec = prec
+ z.form = finite
+ z.exp = int32(exp2)
+ f = z
+ } else {
+ err = fmt.Errorf("exponent overflow")
+ return
+ }
+
+ if exp10 == 0 {
+ // no decimal exponent to consider
+ z.round(0)
+ return
+ }
+ // exp10 != 0
+
+ // apply 10**exp10
+ p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
+ if exp10 < 0 {
+ z.uquo(z, p.pow10(-exp10))
+ } else {
+ z.umul(z, p.pow10(exp10))
+ }
+
+ return
+}
+
+// These powers of 10 can be represented exactly as a float64.
+var pow10tab = [...]float64{
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+}
+
+// pow10 sets z to 10**n and returns z.
+// n must not be negative.
+func (z *Float) pow10(n int64) *Float {
+ if n < 0 {
+ panic("pow10 called with negative argument")
+ }
+
+ const m = int64(len(pow10tab) - 1)
+ if n <= m {
+ return z.SetFloat64(pow10tab[n])
+ }
+ // n > m
+
+ z.SetFloat64(pow10tab[m])
+ n -= m
+
+ // use more bits for f than for z
+ // TODO(gri) what is the right number?
+ f := new(Float).SetPrec(z.Prec() + 64).SetInt64(10)
+
+ for n > 0 {
+ if n&1 != 0 {
+ z.Mul(z, f)
+ }
+ f.Mul(f, f)
+ n >>= 1
+ }
+
+ return z
+}
+
+// Parse parses s which must contain a text representation of a floating-
+// point number with a mantissa in the given conversion base (the exponent
+// is always a decimal number), or a string representing an infinite value.
+//
+// It sets z to the (possibly rounded) value of the corresponding floating-
+// point value, and returns z, the actual base b, and an error err, if any.
+// If z's precision is 0, it is changed to 64 before rounding takes effect.
+// The number must be of the form:
+//
+// number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
+// sign = "+" | "-" .
+// prefix = "0" ( "x" | "X" | "b" | "B" ) .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
+// digits = digit { digit } .
+// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+// infinity = [ sign ] ( "inf" | "Inf" ) .
+//
+// The base argument must be 0, 2, 10, or 16. Providing an invalid base
+// argument will lead to a run-time panic.
+//
+// For base 0, the number prefix determines the actual base: A prefix of
+// "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
+// base 2; otherwise, the actual base is 10 and no prefix is accepted.
+// The octal prefix "0" is not supported (a leading "0" is simply
+// considered a "0").
+//
+// A "p" exponent indicates a binary (rather then decimal) exponent;
+// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
+// maximum float64 value. For hexadecimal mantissae, the exponent must
+// be binary, if present (an "e" or "E" exponent indicator cannot be
+// distinguished from a mantissa digit).
+//
+// The returned *Float f is nil and the value of z is valid but not
+// defined if an error is reported.
+//
+func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
+ // scan doesn't handle ±Inf
+ if len(s) == 3 && (s == "Inf" || s == "inf") {
+ f = z.SetInf(false)
+ return
+ }
+ if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
+ f = z.SetInf(s[0] == '-')
+ return
+ }
+
+ r := strings.NewReader(s)
+ if f, b, err = z.scan(r, base); err != nil {
+ return
+ }
+
+ // entire string must have been consumed
+ if ch, err2 := r.ReadByte(); err2 == nil {
+ err = fmt.Errorf("expected end of string, found %q", ch)
+ } else if err2 != io.EOF {
+ err = err2
+ }
+
+ return
+}
+
+// ParseFloat is like f.Parse(s, base) with f set to the given precision
+// and rounding mode.
+func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
+ return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
+}
diff --git a/libgo/go/math/big/floatconv_test.go b/libgo/go/math/big/floatconv_test.go
new file mode 100644
index 00000000000..4f239534a14
--- /dev/null
+++ b/libgo/go/math/big/floatconv_test.go
@@ -0,0 +1,573 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "fmt"
+ "math"
+ "strconv"
+ "testing"
+)
+
+func TestFloatSetFloat64String(t *testing.T) {
+ inf := math.Inf(0)
+ nan := math.NaN()
+
+ for _, test := range []struct {
+ s string
+ x float64 // NaNs represent invalid inputs
+ }{
+ // basics
+ {"0", 0},
+ {"-0", -0},
+ {"+0", 0},
+ {"1", 1},
+ {"-1", -1},
+ {"+1", 1},
+ {"1.234", 1.234},
+ {"-1.234", -1.234},
+ {"+1.234", 1.234},
+ {".1", 0.1},
+ {"1.", 1},
+ {"+1.", 1},
+
+ // various zeros
+ {"0e100", 0},
+ {"-0e+100", 0},
+ {"+0e-100", 0},
+ {"0E100", 0},
+ {"-0E+100", 0},
+ {"+0E-100", 0},
+
+ // various decimal exponent formats
+ {"1.e10", 1e10},
+ {"1e+10", 1e10},
+ {"+1e-10", 1e-10},
+ {"1E10", 1e10},
+ {"1.E+10", 1e10},
+ {"+1E-10", 1e-10},
+
+ // infinities
+ {"Inf", inf},
+ {"+Inf", inf},
+ {"-Inf", -inf},
+ {"inf", inf},
+ {"+inf", inf},
+ {"-inf", -inf},
+
+ // invalid numbers
+ {"", nan},
+ {"-", nan},
+ {"0x", nan},
+ {"0e", nan},
+ {"1.2ef", nan},
+ {"2..3", nan},
+ {"123..", nan},
+ {"infinity", nan},
+ {"foobar", nan},
+
+ // misc decimal values
+ {"3.14159265", 3.14159265},
+ {"-687436.79457e-245", -687436.79457e-245},
+ {"-687436.79457E245", -687436.79457e245},
+ {".0000000000000000000000000000000000000001", 1e-40},
+ {"+10000000000000000000000000000000000000000e-0", 1e40},
+
+ // decimal mantissa, binary exponent
+ {"0p0", 0},
+ {"-0p0", -0},
+ {"1p10", 1 << 10},
+ {"1p+10", 1 << 10},
+ {"+1p-10", 1.0 / (1 << 10)},
+ {"1024p-12", 0.25},
+ {"-1p10", -1024},
+ {"1.5p1", 3},
+
+ // binary mantissa, decimal exponent
+ {"0b0", 0},
+ {"-0b0", -0},
+ {"0b0e+10", 0},
+ {"-0b0e-10", -0},
+ {"0b1010", 10},
+ {"0B1010E2", 1000},
+ {"0b.1", 0.5},
+ {"0b.001", 0.125},
+ {"0b.001e3", 125},
+
+ // binary mantissa, binary exponent
+ {"0b0p+10", 0},
+ {"-0b0p-10", -0},
+ {"0b.1010p4", 10},
+ {"0b1p-1", 0.5},
+ {"0b001p-3", 0.125},
+ {"0b.001p3", 1},
+ {"0b0.01p2", 1},
+
+ // hexadecimal mantissa and exponent
+ {"0x0", 0},
+ {"-0x0", -0},
+ {"0x0p+10", 0},
+ {"-0x0p-10", -0},
+ {"0xff", 255},
+ {"0X.8p1", 1},
+ {"-0X0.00008p16", -0.5},
+ {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
+ {"0x1.fffffffffffffp1023", math.MaxFloat64},
+ } {
+ var x Float
+ x.SetPrec(53)
+ _, ok := x.SetString(test.s)
+ if math.IsNaN(test.x) {
+ // test.s is invalid
+ if ok {
+ t.Errorf("%s: want parse error", test.s)
+ }
+ continue
+ }
+ // test.s is valid
+ if !ok {
+ t.Errorf("%s: got parse error", test.s)
+ continue
+ }
+ f, _ := x.Float64()
+ want := new(Float).SetFloat64(test.x)
+ if x.Cmp(want) != 0 {
+ t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
+ }
+ }
+}
+
+const (
+ below1e23 = 99999999999999974834176
+ above1e23 = 100000000000000008388608
+)
+
+func TestFloat64Text(t *testing.T) {
+ for _, test := range []struct {
+ x float64
+ format byte
+ prec int
+ want string
+ }{
+ {0, 'f', 0, "0"},
+ {math.Copysign(0, -1), 'f', 0, "-0"},
+ {1, 'f', 0, "1"},
+ {-1, 'f', 0, "-1"},
+
+ {0.001, 'e', 0, "1e-03"},
+ {0.459, 'e', 0, "5e-01"},
+ {1.459, 'e', 0, "1e+00"},
+ {2.459, 'e', 1, "2.5e+00"},
+ {3.459, 'e', 2, "3.46e+00"},
+ {4.459, 'e', 3, "4.459e+00"},
+ {5.459, 'e', 4, "5.4590e+00"},
+
+ {0.001, 'f', 0, "0"},
+ {0.459, 'f', 0, "0"},
+ {1.459, 'f', 0, "1"},
+ {2.459, 'f', 1, "2.5"},
+ {3.459, 'f', 2, "3.46"},
+ {4.459, 'f', 3, "4.459"},
+ {5.459, 'f', 4, "5.4590"},
+
+ {0, 'b', 0, "0"},
+ {math.Copysign(0, -1), 'b', 0, "-0"},
+ {1.0, 'b', 0, "4503599627370496p-52"},
+ {-1.0, 'b', 0, "-4503599627370496p-52"},
+ {4503599627370496, 'b', 0, "4503599627370496p+0"},
+
+ {0, 'p', 0, "0"},
+ {math.Copysign(0, -1), 'p', 0, "-0"},
+ {1024.0, 'p', 0, "0x.8p+11"},
+ {-1024.0, 'p', 0, "-0x.8p+11"},
+
+ // all test cases below from strconv/ftoa_test.go
+ {1, 'e', 5, "1.00000e+00"},
+ {1, 'f', 5, "1.00000"},
+ {1, 'g', 5, "1"},
+ // {1, 'g', -1, "1"},
+ // {20, 'g', -1, "20"},
+ // {1234567.8, 'g', -1, "1.2345678e+06"},
+ // {200000, 'g', -1, "200000"},
+ // {2000000, 'g', -1, "2e+06"},
+
+ // g conversion and zero suppression
+ {400, 'g', 2, "4e+02"},
+ {40, 'g', 2, "40"},
+ {4, 'g', 2, "4"},
+ {.4, 'g', 2, "0.4"},
+ {.04, 'g', 2, "0.04"},
+ {.004, 'g', 2, "0.004"},
+ {.0004, 'g', 2, "0.0004"},
+ {.00004, 'g', 2, "4e-05"},
+ {.000004, 'g', 2, "4e-06"},
+
+ {0, 'e', 5, "0.00000e+00"},
+ {0, 'f', 5, "0.00000"},
+ {0, 'g', 5, "0"},
+ // {0, 'g', -1, "0"},
+
+ {-1, 'e', 5, "-1.00000e+00"},
+ {-1, 'f', 5, "-1.00000"},
+ {-1, 'g', 5, "-1"},
+ // {-1, 'g', -1, "-1"},
+
+ {12, 'e', 5, "1.20000e+01"},
+ {12, 'f', 5, "12.00000"},
+ {12, 'g', 5, "12"},
+ // {12, 'g', -1, "12"},
+
+ {123456700, 'e', 5, "1.23457e+08"},
+ {123456700, 'f', 5, "123456700.00000"},
+ {123456700, 'g', 5, "1.2346e+08"},
+ // {123456700, 'g', -1, "1.234567e+08"},
+
+ {1.2345e6, 'e', 5, "1.23450e+06"},
+ {1.2345e6, 'f', 5, "1234500.00000"},
+ {1.2345e6, 'g', 5, "1.2345e+06"},
+
+ {1e23, 'e', 17, "9.99999999999999916e+22"},
+ {1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
+ {1e23, 'g', 17, "9.9999999999999992e+22"},
+
+ // {1e23, 'e', -1, "1e+23"},
+ // {1e23, 'f', -1, "100000000000000000000000"},
+ // {1e23, 'g', -1, "1e+23"},
+
+ {below1e23, 'e', 17, "9.99999999999999748e+22"},
+ {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
+ {below1e23, 'g', 17, "9.9999999999999975e+22"},
+
+ // {below1e23, 'e', -1, "9.999999999999997e+22"},
+ // {below1e23, 'f', -1, "99999999999999970000000"},
+ // {below1e23, 'g', -1, "9.999999999999997e+22"},
+
+ {above1e23, 'e', 17, "1.00000000000000008e+23"},
+ {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
+ // {above1e23, 'g', 17, "1.0000000000000001e+23"},
+
+ // {above1e23, 'e', -1, "1.0000000000000001e+23"},
+ // {above1e23, 'f', -1, "100000000000000010000000"},
+ // {above1e23, 'g', -1, "1.0000000000000001e+23"},
+
+ // {fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
+ // {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+
+ // {32, 'g', -1, "32"},
+ // {32, 'g', 0, "3e+01"},
+
+ // {100, 'x', -1, "%x"},
+
+ // {math.NaN(), 'g', -1, "NaN"},
+ // {-math.NaN(), 'g', -1, "NaN"},
+ {math.Inf(0), 'g', -1, "+Inf"},
+ {math.Inf(-1), 'g', -1, "-Inf"},
+ {-math.Inf(0), 'g', -1, "-Inf"},
+
+ {-1, 'b', -1, "-4503599627370496p-52"},
+
+ // fixed bugs
+ {0.9, 'f', 1, "0.9"},
+ {0.09, 'f', 1, "0.1"},
+ {0.0999, 'f', 1, "0.1"},
+ {0.05, 'f', 1, "0.1"},
+ {0.05, 'f', 0, "0"},
+ {0.5, 'f', 1, "0.5"},
+ {0.5, 'f', 0, "0"},
+ {1.5, 'f', 0, "2"},
+
+ // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+ // {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
+ // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+ // {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
+
+ // Issue 2625.
+ {383260575764816448, 'f', 0, "383260575764816448"},
+ // {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
+ } {
+ f := new(Float).SetFloat64(test.x)
+ got := f.Text(test.format, test.prec)
+ if got != test.want {
+ t.Errorf("%v: got %s; want %s", test, got, test.want)
+ }
+
+ if test.format == 'b' && test.x == 0 {
+ continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
+ }
+ if test.format == 'p' {
+ continue // 'p' format not supported in strconv.Format
+ }
+
+ // verify that Float format matches strconv format
+ want := strconv.FormatFloat(test.x, test.format, test.prec, 64)
+ if got != want {
+ t.Errorf("%v: got %s; want %s (strconv)", test, got, want)
+ }
+ }
+}
+
+func TestFloatText(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ prec uint
+ format byte
+ digits int
+ want string
+ }{
+ {"0", 10, 'f', 0, "0"},
+ {"-0", 10, 'f', 0, "-0"},
+ {"1", 10, 'f', 0, "1"},
+ {"-1", 10, 'f', 0, "-1"},
+
+ {"1.459", 100, 'e', 0, "1e+00"},
+ {"2.459", 100, 'e', 1, "2.5e+00"},
+ {"3.459", 100, 'e', 2, "3.46e+00"},
+ {"4.459", 100, 'e', 3, "4.459e+00"},
+ {"5.459", 100, 'e', 4, "5.4590e+00"},
+
+ {"1.459", 100, 'E', 0, "1E+00"},
+ {"2.459", 100, 'E', 1, "2.5E+00"},
+ {"3.459", 100, 'E', 2, "3.46E+00"},
+ {"4.459", 100, 'E', 3, "4.459E+00"},
+ {"5.459", 100, 'E', 4, "5.4590E+00"},
+
+ {"1.459", 100, 'f', 0, "1"},
+ {"2.459", 100, 'f', 1, "2.5"},
+ {"3.459", 100, 'f', 2, "3.46"},
+ {"4.459", 100, 'f', 3, "4.459"},
+ {"5.459", 100, 'f', 4, "5.4590"},
+
+ {"1.459", 100, 'g', 0, "1"},
+ {"2.459", 100, 'g', 1, "2"},
+ {"3.459", 100, 'g', 2, "3.5"},
+ {"4.459", 100, 'g', 3, "4.46"},
+ {"5.459", 100, 'g', 4, "5.459"},
+
+ {"1459", 53, 'g', 0, "1e+03"},
+ {"2459", 53, 'g', 1, "2e+03"},
+ {"3459", 53, 'g', 2, "3.5e+03"},
+ {"4459", 53, 'g', 3, "4.46e+03"},
+ {"5459", 53, 'g', 4, "5459"},
+
+ {"1459", 53, 'G', 0, "1E+03"},
+ {"2459", 53, 'G', 1, "2E+03"},
+ {"3459", 53, 'G', 2, "3.5E+03"},
+ {"4459", 53, 'G', 3, "4.46E+03"},
+ {"5459", 53, 'G', 4, "5459"},
+
+ {"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
+ {"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
+ {"3", 10, 'g', 40, "3"},
+
+ {"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
+ {"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
+ {"3e40", 100, 'g', 40, "3e+40"},
+
+ // make sure "stupid" exponents don't stall the machine
+ {"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
+ {"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p+1538481529"},
+ {"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
+ {"1e-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"},
+
+ // TODO(gri) need tests for actual large Floats
+
+ {"0", 53, 'b', 0, "0"},
+ {"-0", 53, 'b', 0, "-0"},
+ {"1.0", 53, 'b', 0, "4503599627370496p-52"},
+ {"-1.0", 53, 'b', 0, "-4503599627370496p-52"},
+ {"4503599627370496", 53, 'b', 0, "4503599627370496p+0"},
+
+ // issue 9939
+ {"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+ {"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+ {"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+ {"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+ {"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+ {"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
+
+ {"3", 350, 'p', 0, "0x.cp+2"},
+ {"03", 350, 'p', 0, "0x.cp+2"},
+ {"3.", 350, 'p', 0, "0x.cp+2"},
+ {"3.0", 350, 'p', 0, "0x.cp+2"},
+ {"3.00", 350, 'p', 0, "0x.cp+2"},
+ {"3.000", 350, 'p', 0, "0x.cp+2"},
+
+ {"0", 64, 'p', 0, "0"},
+ {"-0", 64, 'p', 0, "-0"},
+ {"1024.0", 64, 'p', 0, "0x.8p+11"},
+ {"-1024.0", 64, 'p', 0, "-0x.8p+11"},
+
+ // unsupported format
+ {"3.14", 64, 'x', 0, "%x"},
+ {"-3.14", 64, 'x', 0, "%x"},
+ } {
+ f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
+ if err != nil {
+ t.Errorf("%v: %s", test, err)
+ continue
+ }
+
+ got := f.Text(test.format, test.digits)
+ if got != test.want {
+ t.Errorf("%v: got %s; want %s", test, got, test.want)
+ }
+
+ // compare with strconv.FormatFloat output if possible
+ // ('p' format is not supported by strconv.FormatFloat,
+ // and its output for 0.0 prints a biased exponent value
+ // as in 0p-1074 which makes no sense to emulate here)
+ if test.prec == 53 && test.format != 'p' && f.Sign() != 0 {
+ f64, acc := f.Float64()
+ if acc != Exact {
+ t.Errorf("%v: expected exact conversion to float64", test)
+ continue
+ }
+ got := strconv.FormatFloat(f64, test.format, test.digits, 64)
+ if got != test.want {
+ t.Errorf("%v: got %s; want %s", test, got, test.want)
+ }
+ }
+ }
+}
+
+func TestFloatFormat(t *testing.T) {
+ for _, test := range []struct {
+ format string
+ value interface{} // float32, float64, or string (== 512bit *Float)
+ want string
+ }{
+ // TODO(gri) uncomment the disabled 'g'/'G' formats
+ // below once (*Float).Text supports prec < 0
+
+ // from fmt/fmt_test.go
+ {"%+.3e", 0.0, "+0.000e+00"},
+ {"%+.3e", 1.0, "+1.000e+00"},
+ {"%+.3f", -1.0, "-1.000"},
+ {"%+.3F", -1.0, "-1.000"},
+ {"%+.3F", float32(-1.0), "-1.000"},
+ {"%+07.2f", 1.0, "+001.00"},
+ {"%+07.2f", -1.0, "-001.00"},
+ {"%+10.2f", +1.0, " +1.00"},
+ {"%+10.2f", -1.0, " -1.00"},
+ {"% .3E", -1.0, "-1.000E+00"},
+ {"% .3e", 1.0, " 1.000e+00"},
+ {"%+.3g", 0.0, "+0"},
+ {"%+.3g", 1.0, "+1"},
+ {"%+.3g", -1.0, "-1"},
+ {"% .3g", -1.0, "-1"},
+ {"% .3g", 1.0, " 1"},
+ {"%b", float32(1.0), "8388608p-23"},
+ {"%b", 1.0, "4503599627370496p-52"},
+
+ // from fmt/fmt_test.go: old test/fmt_test.go
+ {"%e", 1.0, "1.000000e+00"},
+ {"%e", 1234.5678e3, "1.234568e+06"},
+ {"%e", 1234.5678e-8, "1.234568e-05"},
+ {"%e", -7.0, "-7.000000e+00"},
+ {"%e", -1e-9, "-1.000000e-09"},
+ {"%f", 1234.5678e3, "1234567.800000"},
+ {"%f", 1234.5678e-8, "0.000012"},
+ {"%f", -7.0, "-7.000000"},
+ {"%f", -1e-9, "-0.000000"},
+ // {"%g", 1234.5678e3, "1.2345678e+06"},
+ // {"%g", float32(1234.5678e3), "1.2345678e+06"},
+ // {"%g", 1234.5678e-8, "1.2345678e-05"},
+ {"%g", -7.0, "-7"},
+ {"%g", -1e-9, "-1e-09"},
+ {"%g", float32(-1e-9), "-1e-09"},
+ {"%E", 1.0, "1.000000E+00"},
+ {"%E", 1234.5678e3, "1.234568E+06"},
+ {"%E", 1234.5678e-8, "1.234568E-05"},
+ {"%E", -7.0, "-7.000000E+00"},
+ {"%E", -1e-9, "-1.000000E-09"},
+ // {"%G", 1234.5678e3, "1.2345678E+06"},
+ // {"%G", float32(1234.5678e3), "1.2345678E+06"},
+ // {"%G", 1234.5678e-8, "1.2345678E-05"},
+ {"%G", -7.0, "-7"},
+ {"%G", -1e-9, "-1E-09"},
+ {"%G", float32(-1e-9), "-1E-09"},
+
+ {"%20.6e", 1.2345e3, " 1.234500e+03"},
+ {"%20.6e", 1.2345e-3, " 1.234500e-03"},
+ {"%20e", 1.2345e3, " 1.234500e+03"},
+ {"%20e", 1.2345e-3, " 1.234500e-03"},
+ {"%20.8e", 1.2345e3, " 1.23450000e+03"},
+ {"%20f", 1.23456789e3, " 1234.567890"},
+ {"%20f", 1.23456789e-3, " 0.001235"},
+ {"%20f", 12345678901.23456789, " 12345678901.234568"},
+ {"%-20f", 1.23456789e3, "1234.567890 "},
+ {"%20.8f", 1.23456789e3, " 1234.56789000"},
+ {"%20.8f", 1.23456789e-3, " 0.00123457"},
+ // {"%g", 1.23456789e3, "1234.56789"},
+ // {"%g", 1.23456789e-3, "0.00123456789"},
+ // {"%g", 1.23456789e20, "1.23456789e+20"},
+ {"%20e", math.Inf(1), " +Inf"},
+ {"%-20f", math.Inf(-1), "-Inf "},
+
+ // from fmt/fmt_test.go: comparison of padding rules with C printf
+ {"%.2f", 1.0, "1.00"},
+ {"%.2f", -1.0, "-1.00"},
+ {"% .2f", 1.0, " 1.00"},
+ {"% .2f", -1.0, "-1.00"},
+ {"%+.2f", 1.0, "+1.00"},
+ {"%+.2f", -1.0, "-1.00"},
+ {"%7.2f", 1.0, " 1.00"},
+ {"%7.2f", -1.0, " -1.00"},
+ {"% 7.2f", 1.0, " 1.00"},
+ {"% 7.2f", -1.0, " -1.00"},
+ {"%+7.2f", 1.0, " +1.00"},
+ {"%+7.2f", -1.0, " -1.00"},
+ {"%07.2f", 1.0, "0001.00"},
+ {"%07.2f", -1.0, "-001.00"},
+ {"% 07.2f", 1.0, " 001.00"},
+ {"% 07.2f", -1.0, "-001.00"},
+ {"%+07.2f", 1.0, "+001.00"},
+ {"%+07.2f", -1.0, "-001.00"},
+
+ // from fmt/fmt_test.go: zero padding does not apply to infinities
+ {"%020f", math.Inf(-1), " -Inf"},
+ {"%020f", math.Inf(+1), " +Inf"},
+ {"% 020f", math.Inf(-1), " -Inf"},
+ {"% 020f", math.Inf(+1), " Inf"},
+ {"%+020f", math.Inf(-1), " -Inf"},
+ {"%+020f", math.Inf(+1), " +Inf"},
+ {"%20f", -1.0, " -1.000000"},
+
+ // handle %v like %g
+ {"%v", 0.0, "0"},
+ {"%v", -7.0, "-7"},
+ {"%v", -1e-9, "-1e-09"},
+ {"%v", float32(-1e-9), "-1e-09"},
+ {"%010v", 0.0, "0000000000"},
+ {"%010v", 0.0, "0000000000"},
+
+ // *Float cases
+ {"%.20f", "1e-20", "0.00000000000000000001"},
+ {"%.20f", "-1e-20", "-0.00000000000000000001"},
+ {"%30.20f", "-1e-20", " -0.00000000000000000001"},
+ {"%030.20f", "-1e-20", "-00000000.00000000000000000001"},
+ {"%030.20f", "+1e-20", "000000000.00000000000000000001"},
+ {"% 030.20f", "+1e-20", " 00000000.00000000000000000001"},
+
+ // erroneous formats
+ {"%s", 1.0, "%!s(*big.Float=1)"},
+ } {
+ value := new(Float)
+ switch v := test.value.(type) {
+ case float32:
+ value.SetPrec(24).SetFloat64(float64(v))
+ case float64:
+ value.SetPrec(53).SetFloat64(v)
+ case string:
+ value.SetPrec(512).Parse(v, 0)
+ default:
+ t.Fatalf("unsupported test value: %v (%T)", v, v)
+ }
+
+ if got := fmt.Sprintf(test.format, value); got != test.want {
+ t.Errorf("%v: got %q; want %q", test, got, test.want)
+ }
+ }
+}
diff --git a/libgo/go/math/big/floatexample_test.go b/libgo/go/math/big/floatexample_test.go
new file mode 100644
index 00000000000..69686b7d16b
--- /dev/null
+++ b/libgo/go/math/big/floatexample_test.go
@@ -0,0 +1,113 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package big_test
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+)
+
+func ExampleFloat_Add() {
+ // Operating on numbers of different precision.
+ var x, y, z big.Float
+ x.SetInt64(1000) // x is automatically set to 64bit precision
+ y.SetFloat64(2.718281828) // y is automatically set to 53bit precision
+ z.SetPrec(32)
+ z.Add(&x, &y)
+ fmt.Printf("x = %.10g (%s, prec = %d, acc = %s)\n", &x, x.Text('p', 0), x.Prec(), x.Acc())
+ fmt.Printf("y = %.10g (%s, prec = %d, acc = %s)\n", &y, y.Text('p', 0), y.Prec(), y.Acc())
+ fmt.Printf("z = %.10g (%s, prec = %d, acc = %s)\n", &z, z.Text('p', 0), z.Prec(), z.Acc())
+ // Output:
+ // x = 1000 (0x.fap+10, prec = 64, acc = Exact)
+ // y = 2.718281828 (0x.adf85458248cd8p+2, prec = 53, acc = Exact)
+ // z = 1002.718282 (0x.faadf854p+10, prec = 32, acc = Below)
+}
+
+func Example_Shift() {
+ // Implementing Float "shift" by modifying the (binary) exponents directly.
+ for s := -5; s <= 5; s++ {
+ x := big.NewFloat(0.5)
+ x.SetMantExp(x, x.MantExp(nil)+s) // shift x by s
+ fmt.Println(x)
+ }
+ // Output:
+ // 0.015625
+ // 0.03125
+ // 0.0625
+ // 0.125
+ // 0.25
+ // 0.5
+ // 1
+ // 2
+ // 4
+ // 8
+ // 16
+}
+
+func ExampleFloat_Cmp() {
+ inf := math.Inf(1)
+ zero := 0.0
+
+ operands := []float64{-inf, -1.2, -zero, 0, +1.2, +inf}
+
+ fmt.Println(" x y cmp")
+ fmt.Println("---------------")
+ for _, x64 := range operands {
+ x := big.NewFloat(x64)
+ for _, y64 := range operands {
+ y := big.NewFloat(y64)
+ fmt.Printf("%4g %4g %3d\n", x, y, x.Cmp(y))
+ }
+ fmt.Println()
+ }
+
+ // Output:
+ // x y cmp
+ // ---------------
+ // -Inf -Inf 0
+ // -Inf -1.2 -1
+ // -Inf -0 -1
+ // -Inf 0 -1
+ // -Inf 1.2 -1
+ // -Inf +Inf -1
+ //
+ // -1.2 -Inf 1
+ // -1.2 -1.2 0
+ // -1.2 -0 -1
+ // -1.2 0 -1
+ // -1.2 1.2 -1
+ // -1.2 +Inf -1
+ //
+ // -0 -Inf 1
+ // -0 -1.2 1
+ // -0 -0 0
+ // -0 0 0
+ // -0 1.2 -1
+ // -0 +Inf -1
+ //
+ // 0 -Inf 1
+ // 0 -1.2 1
+ // 0 -0 0
+ // 0 0 0
+ // 0 1.2 -1
+ // 0 +Inf -1
+ //
+ // 1.2 -Inf 1
+ // 1.2 -1.2 1
+ // 1.2 -0 1
+ // 1.2 0 1
+ // 1.2 1.2 0
+ // 1.2 +Inf -1
+ //
+ // +Inf -Inf 1
+ // +Inf -1.2 1
+ // +Inf -0 1
+ // +Inf 0 1
+ // +Inf 1.2 1
+ // +Inf +Inf 0
+}
diff --git a/libgo/go/math/big/ftoa.go b/libgo/go/math/big/ftoa.go
new file mode 100644
index 00000000000..5c5f2cea460
--- /dev/null
+++ b/libgo/go/math/big/ftoa.go
@@ -0,0 +1,393 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements Float-to-string conversion functions.
+// It is closely following the corresponding implementation
+// in strconv/ftoa.go, but modified and simplified for Float.
+
+package big
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// Text converts the floating-point number x to a string according
+// to the given format and precision prec. The format is one of:
+//
+// 'e' -d.dddde±dd, decimal exponent, at least two (possibly 0) exponent digits
+// 'E' -d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
+// 'f' -ddddd.dddd, no exponent
+// 'g' like 'e' for large exponents, like 'f' otherwise
+// 'G' like 'E' for large exponents, like 'f' otherwise
+// 'b' -ddddddp±dd, binary exponent
+// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
+//
+// For the binary exponent formats, the mantissa is printed in normalized form:
+//
+// 'b' decimal integer mantissa using x.Prec() bits, or -0
+// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
+//
+// If format is a different character, Text returns a "%" followed by the
+// unrecognized format character.
+//
+// The precision prec controls the number of digits (excluding the exponent)
+// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
+// it is the number of digits after the decimal point. For 'g' and 'G' it is
+// the total number of digits. A negative precision selects the smallest
+// number of digits necessary to identify the value x uniquely.
+// The prec value is ignored for the 'b' or 'p' format.
+//
+// BUG(gri) Float.Text does not accept negative precisions (issue #10991).
+func (x *Float) Text(format byte, prec int) string {
+ const extra = 10 // TODO(gri) determine a good/better value here
+ return string(x.Append(make([]byte, 0, prec+extra), format, prec))
+}
+
+// String formats x like x.Text('g', 10).
+func (x *Float) String() string {
+ return x.Text('g', 10)
+}
+
+// Append appends to buf the string form of the floating-point number x,
+// as generated by x.Text, and returns the extended buffer.
+func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
+ // sign
+ if x.neg {
+ buf = append(buf, '-')
+ }
+
+ // Inf
+ if x.form == inf {
+ if !x.neg {
+ buf = append(buf, '+')
+ }
+ return append(buf, "Inf"...)
+ }
+
+ // pick off easy formats
+ switch fmt {
+ case 'b':
+ return x.fmtB(buf)
+ case 'p':
+ return x.fmtP(buf)
+ }
+
+ // Algorithm:
+ // 1) convert Float to multiprecision decimal
+ // 2) round to desired precision
+ // 3) read digits out and format
+
+ // 1) convert Float to multiprecision decimal
+ var d decimal // == 0.0
+ if x.form == finite {
+ d.init(x.mant, int(x.exp)-x.mant.bitLen())
+ }
+
+ // 2) round to desired precision
+ shortest := false
+ if prec < 0 {
+ shortest = true
+ panic("unimplemented")
+ // TODO(gri) complete this
+ // roundShortest(&d, f.mant, int(f.exp))
+ // Precision for shortest representation mode.
+ switch fmt {
+ case 'e', 'E':
+ prec = len(d.mant) - 1
+ case 'f':
+ prec = max(len(d.mant)-d.exp, 0)
+ case 'g', 'G':
+ prec = len(d.mant)
+ }
+ } else {
+ // round appropriately
+ switch fmt {
+ case 'e', 'E':
+ // one digit before and number of digits after decimal point
+ d.round(1 + prec)
+ case 'f':
+ // number of digits before and after decimal point
+ d.round(d.exp + prec)
+ case 'g', 'G':
+ if prec == 0 {
+ prec = 1
+ }
+ d.round(prec)
+ }
+ }
+
+ // 3) read digits out and format
+ switch fmt {
+ case 'e', 'E':
+ return fmtE(buf, fmt, prec, d)
+ case 'f':
+ return fmtF(buf, prec, d)
+ case 'g', 'G':
+ // trim trailing fractional zeros in %e format
+ eprec := prec
+ if eprec > len(d.mant) && len(d.mant) >= d.exp {
+ eprec = len(d.mant)
+ }
+ // %e is used if the exponent from the conversion
+ // is less than -4 or greater than or equal to the precision.
+ // If precision was the shortest possible, use eprec = 6 for
+ // this decision.
+ if shortest {
+ eprec = 6
+ }
+ exp := d.exp - 1
+ if exp < -4 || exp >= eprec {
+ if prec > len(d.mant) {
+ prec = len(d.mant)
+ }
+ return fmtE(buf, fmt+'e'-'g', prec-1, d)
+ }
+ if prec > d.exp {
+ prec = len(d.mant)
+ }
+ return fmtF(buf, max(prec-d.exp, 0), d)
+ }
+
+ // unknown format
+ if x.neg {
+ buf = buf[:len(buf)-1] // sign was added prematurely - remove it again
+ }
+ return append(buf, '%', fmt)
+}
+
+// %e: d.ddddde±dd
+func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
+ // first digit
+ ch := byte('0')
+ if len(d.mant) > 0 {
+ ch = d.mant[0]
+ }
+ buf = append(buf, ch)
+
+ // .moredigits
+ if prec > 0 {
+ buf = append(buf, '.')
+ i := 1
+ m := min(len(d.mant), prec+1)
+ if i < m {
+ buf = append(buf, d.mant[i:m]...)
+ i = m
+ }
+ for ; i <= prec; i++ {
+ buf = append(buf, '0')
+ }
+ }
+
+ // e±
+ buf = append(buf, fmt)
+ var exp int64
+ if len(d.mant) > 0 {
+ exp = int64(d.exp) - 1 // -1 because first digit was printed before '.'
+ }
+ if exp < 0 {
+ ch = '-'
+ exp = -exp
+ } else {
+ ch = '+'
+ }
+ buf = append(buf, ch)
+
+ // dd...d
+ if exp < 10 {
+ buf = append(buf, '0') // at least 2 exponent digits
+ }
+ return strconv.AppendInt(buf, exp, 10)
+}
+
+// %f: ddddddd.ddddd
+func fmtF(buf []byte, prec int, d decimal) []byte {
+ // integer, padded with zeros as needed
+ if d.exp > 0 {
+ m := min(len(d.mant), d.exp)
+ buf = append(buf, d.mant[:m]...)
+ for ; m < d.exp; m++ {
+ buf = append(buf, '0')
+ }
+ } else {
+ buf = append(buf, '0')
+ }
+
+ // fraction
+ if prec > 0 {
+ buf = append(buf, '.')
+ for i := 0; i < prec; i++ {
+ ch := byte('0')
+ if j := d.exp + i; 0 <= j && j < len(d.mant) {
+ ch = d.mant[j]
+ }
+ buf = append(buf, ch)
+ }
+ }
+
+ return buf
+}
+
+// fmtB appends the string of x in the format mantissa "p" exponent
+// with a decimal mantissa and a binary exponent, or 0" if x is zero,
+// and returns the extended buffer.
+// The mantissa is normalized such that is uses x.Prec() bits in binary
+// representation.
+// The sign of x is ignored, and x must not be an Inf.
+func (x *Float) fmtB(buf []byte) []byte {
+ if x.form == zero {
+ return append(buf, '0')
+ }
+
+ if debugFloat && x.form != finite {
+ panic("non-finite float")
+ }
+ // x != 0
+
+ // adjust mantissa to use exactly x.prec bits
+ m := x.mant
+ switch w := uint32(len(x.mant)) * _W; {
+ case w < x.prec:
+ m = nat(nil).shl(m, uint(x.prec-w))
+ case w > x.prec:
+ m = nat(nil).shr(m, uint(w-x.prec))
+ }
+
+ buf = append(buf, m.decimalString()...)
+ buf = append(buf, 'p')
+ e := int64(x.exp) - int64(x.prec)
+ if e >= 0 {
+ buf = append(buf, '+')
+ }
+ return strconv.AppendInt(buf, e, 10)
+}
+
+// fmtP appends the string of x in the format 0x." mantissa "p" exponent
+// with a hexadecimal mantissa and a binary exponent, or 0" if x is zero,
+// ad returns the extended buffer.
+// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
+// The sign of x is ignored, and x must not be an Inf.
+func (x *Float) fmtP(buf []byte) []byte {
+ if x.form == zero {
+ return append(buf, '0')
+ }
+
+ if debugFloat && x.form != finite {
+ panic("non-finite float")
+ }
+ // x != 0
+
+ // remove trailing 0 words early
+ // (no need to convert to hex 0's and trim later)
+ m := x.mant
+ i := 0
+ for i < len(m) && m[i] == 0 {
+ i++
+ }
+ m = m[i:]
+
+ buf = append(buf, "0x."...)
+ buf = append(buf, strings.TrimRight(m.hexString(), "0")...)
+ buf = append(buf, 'p')
+ if x.exp >= 0 {
+ buf = append(buf, '+')
+ }
+ return strconv.AppendInt(buf, int64(x.exp), 10)
+}
+
+func min(x, y int) int {
+ if x < y {
+ return x
+ }
+ return y
+}
+
+// Format implements fmt.Formatter. It accepts all the regular
+// formats for floating-point numbers ('e', 'E', 'f', 'F', 'g',
+// 'G') as well as 'b', 'p', and 'v'. See (*Float).Text for the
+// interpretation of 'b' and 'p'. The 'v' format is handled like
+// 'g'.
+// Format also supports specification of the minimum precision
+// in digits, the output field width, as well as the format verbs
+// '+' and ' ' for sign control, '0' for space or zero padding,
+// and '-' for left or right justification. See the fmt package
+// for details.
+//
+// BUG(gri) A missing precision for the 'g' format, or a negative
+// (via '*') precision is not yet supported. Instead the
+// default precision (6) is used in that case (issue #10991).
+func (x *Float) Format(s fmt.State, format rune) {
+ prec, hasPrec := s.Precision()
+ if !hasPrec {
+ prec = 6 // default precision for 'e', 'f'
+ }
+
+ switch format {
+ case 'e', 'E', 'f', 'b', 'p':
+ // nothing to do
+ case 'F':
+ // (*Float).Text doesn't support 'F'; handle like 'f'
+ format = 'f'
+ case 'v':
+ // handle like 'g'
+ format = 'g'
+ fallthrough
+ case 'g', 'G':
+ if !hasPrec {
+ // TODO(gri) uncomment once (*Float).Text handles prec < 0
+ // prec = -1 // default precision for 'g', 'G'
+ }
+ default:
+ fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
+ return
+ }
+ var buf []byte
+ buf = x.Append(buf, byte(format), prec)
+ if len(buf) == 0 {
+ buf = []byte("?") // should never happen, but don't crash
+ }
+ // len(buf) > 0
+
+ var sign string
+ switch {
+ case buf[0] == '-':
+ sign = "-"
+ buf = buf[1:]
+ case buf[0] == '+':
+ // +Inf
+ sign = "+"
+ if s.Flag(' ') {
+ sign = " "
+ }
+ buf = buf[1:]
+ case s.Flag('+'):
+ sign = "+"
+ case s.Flag(' '):
+ sign = " "
+ }
+
+ var padding int
+ if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
+ padding = width - len(sign) - len(buf)
+ }
+
+ switch {
+ case s.Flag('0') && !x.IsInf():
+ // 0-padding on left
+ writeMultiple(s, sign, 1)
+ writeMultiple(s, "0", padding)
+ s.Write(buf)
+ case s.Flag('-'):
+ // padding on right
+ writeMultiple(s, sign, 1)
+ s.Write(buf)
+ writeMultiple(s, " ", padding)
+ default:
+ // padding on left
+ writeMultiple(s, " ", padding)
+ writeMultiple(s, sign, 1)
+ s.Write(buf)
+ }
+}
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index ade5c2fc8cd..65334e0ef55 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -7,7 +7,6 @@
package big
import (
- "errors"
"fmt"
"io"
"math/rand"
@@ -184,6 +183,10 @@ func (z *Int) MulRange(a, b int64) *Int {
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
func (z *Int) Binomial(n, k int64) *Int {
+ // reduce the number of multiplications by reducing k
+ if n/2 < k && k <= n {
+ k = n - k // Binomial(n, k) == Binomial(n, n-k)
+ }
var a, b Int
a.MulRange(n-k+1, n)
b.MulRange(1, k)
@@ -321,195 +324,6 @@ func (x *Int) Cmp(y *Int) (r int) {
return
}
-func (x *Int) String() string {
- switch {
- case x == nil:
- return "<nil>"
- case x.neg:
- return "-" + x.abs.decimalString()
- }
- return x.abs.decimalString()
-}
-
-func charset(ch rune) string {
- switch ch {
- case 'b':
- return lowercaseDigits[0:2]
- case 'o':
- return lowercaseDigits[0:8]
- case 'd', 's', 'v':
- return lowercaseDigits[0:10]
- case 'x':
- return lowercaseDigits[0:16]
- case 'X':
- return uppercaseDigits[0:16]
- }
- return "" // unknown format
-}
-
-// write count copies of text to s
-func writeMultiple(s fmt.State, text string, count int) {
- if len(text) > 0 {
- b := []byte(text)
- for ; count > 0; count-- {
- s.Write(b)
- }
- }
-}
-
-// Format is a support routine for fmt.Formatter. It accepts
-// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
-// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-// Also supported are the full suite of package fmt's format
-// verbs for integral types, including '+', '-', and ' '
-// for sign control, '#' for leading zero in octal and for
-// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
-// respectively, specification of minimum digits precision,
-// output field width, space or zero padding, and left or
-// right justification.
-//
-func (x *Int) Format(s fmt.State, ch rune) {
- cs := charset(ch)
-
- // special cases
- switch {
- case cs == "":
- // unknown format
- fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
- return
- case x == nil:
- fmt.Fprint(s, "<nil>")
- return
- }
-
- // determine sign character
- sign := ""
- switch {
- case x.neg:
- sign = "-"
- case s.Flag('+'): // supersedes ' ' when both specified
- sign = "+"
- case s.Flag(' '):
- sign = " "
- }
-
- // determine prefix characters for indicating output base
- prefix := ""
- if s.Flag('#') {
- switch ch {
- case 'o': // octal
- prefix = "0"
- case 'x': // hexadecimal
- prefix = "0x"
- case 'X':
- prefix = "0X"
- }
- }
-
- // determine digits with base set by len(cs) and digit characters from cs
- digits := x.abs.string(cs)
-
- // number of characters for the three classes of number padding
- var left int // space characters to left of digits for right justification ("%8d")
- var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
- var right int // space characters to right of digits for left justification ("%-8d")
-
- // determine number padding from precision: the least number of digits to output
- precision, precisionSet := s.Precision()
- if precisionSet {
- switch {
- case len(digits) < precision:
- zeroes = precision - len(digits) // count of zero padding
- case digits == "0" && precision == 0:
- return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
- }
- }
-
- // determine field pad from width: the least number of characters to output
- length := len(sign) + len(prefix) + zeroes + len(digits)
- if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
- switch d := width - length; {
- case s.Flag('-'):
- // pad on the right with spaces; supersedes '0' when both specified
- right = d
- case s.Flag('0') && !precisionSet:
- // pad with zeroes unless precision also specified
- zeroes = d
- default:
- // pad on the left with spaces
- left = d
- }
- }
-
- // print number as [left pad][sign][prefix][zero pad][digits][right pad]
- writeMultiple(s, " ", left)
- writeMultiple(s, sign, 1)
- writeMultiple(s, prefix, 1)
- writeMultiple(s, "0", zeroes)
- writeMultiple(s, digits, 1)
- writeMultiple(s, " ", right)
-}
-
-// scan sets z to the integer value corresponding to the longest possible prefix
-// read from r representing a signed integer number in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined but the returned value is nil. The
-// syntax follows the syntax of integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) {
- // determine sign
- ch, _, err := r.ReadRune()
- if err != nil {
- return nil, 0, err
- }
- neg := false
- switch ch {
- case '-':
- neg = true
- case '+': // nothing to do
- default:
- r.UnreadRune()
- }
-
- // determine mantissa
- z.abs, base, err = z.abs.scan(r, base)
- if err != nil {
- return nil, base, err
- }
- z.neg = len(z.abs) > 0 && neg // 0 has no sign
-
- return z, base, nil
-}
-
-// Scan is a support routine for fmt.Scanner; it sets z to the value of
-// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
-// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-func (z *Int) Scan(s fmt.ScanState, ch rune) error {
- s.SkipSpace() // skip leading space characters
- base := 0
- switch ch {
- case 'b':
- base = 2
- case 'o':
- base = 8
- case 'd':
- base = 10
- case 'x', 'X':
- base = 16
- case 's', 'v':
- // let scan determine the base
- default:
- return errors.New("Int.Scan: invalid verb")
- }
- _, _, err := z.scan(s, base)
- return err
-}
-
// low32 returns the least significant 32 bits of z.
func low32(z nat) uint32 {
if len(z) == 0 {
@@ -550,7 +364,7 @@ func (x *Int) Uint64() uint64 {
// and returns z and a boolean indicating success. If SetString fails,
// the value of z is undefined but the returned value is nil.
//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// The base argument must be 0 or a value between 2 and MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
@@ -561,7 +375,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) {
if err != nil {
return nil, false
}
- _, _, err = r.ReadRune()
+ _, err = r.ReadByte()
if err != io.EOF {
return nil, false
}
@@ -686,15 +500,17 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
// use one Euclidean iteration to ensure that u and v are approx. the same size
switch {
case len(a.abs) > len(b.abs):
- u.Set(b)
+ // must set v before u since u may be alias for a or b (was issue #11284)
v.Rem(a, b)
+ u.Set(b)
case len(a.abs) < len(b.abs):
- u.Set(a)
v.Rem(b, a)
- default:
u.Set(a)
+ default:
v.Set(b)
+ u.Set(a)
}
+ // a, b must not be used anymore (may be aliases with u)
// v might be 0 now
if len(v.abs) == 0 {
@@ -736,8 +552,11 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
// If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime.
+// If it returns false, x is not prime. n must be > 0.
func (x *Int) ProbablyPrime(n int) bool {
+ if n <= 0 {
+ panic("non-positive n for ProbablyPrime")
+ }
return !x.neg && x.abs.probablyPrime(n)
}
@@ -766,6 +585,124 @@ func (z *Int) ModInverse(g, n *Int) *Int {
return z
}
+// Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0.
+// The y argument must be an odd integer.
+func Jacobi(x, y *Int) int {
+ if len(y.abs) == 0 || y.abs[0]&1 == 0 {
+ panic(fmt.Sprintf("big: invalid 2nd argument to Int.Jacobi: need odd integer but got %s", y))
+ }
+
+ // We use the formulation described in chapter 2, section 2.4,
+ // "The Yacas Book of Algorithms":
+ // http://yacas.sourceforge.net/Algo.book.pdf
+
+ var a, b, c Int
+ a.Set(x)
+ b.Set(y)
+ j := 1
+
+ if b.neg {
+ if a.neg {
+ j = -1
+ }
+ b.neg = false
+ }
+
+ for {
+ if b.Cmp(intOne) == 0 {
+ return j
+ }
+ if len(a.abs) == 0 {
+ return 0
+ }
+ a.Mod(&a, &b)
+ if len(a.abs) == 0 {
+ return 0
+ }
+ // a > 0
+
+ // handle factors of 2 in 'a'
+ s := a.abs.trailingZeroBits()
+ if s&1 != 0 {
+ bmod8 := b.abs[0] & 7
+ if bmod8 == 3 || bmod8 == 5 {
+ j = -j
+ }
+ }
+ c.Rsh(&a, s) // a = 2^s*c
+
+ // swap numerator and denominator
+ if b.abs[0]&3 == 3 && c.abs[0]&3 == 3 {
+ j = -j
+ }
+ a.Set(&b)
+ b.Set(&c)
+ }
+}
+
+// ModSqrt sets z to a square root of x mod p if such a square root exists, and
+// returns z. The modulus p must be an odd prime. If x is not a square mod p,
+// ModSqrt leaves z unchanged and returns nil. This function panics if p is
+// not an odd integer.
+func (z *Int) ModSqrt(x, p *Int) *Int {
+ switch Jacobi(x, p) {
+ case -1:
+ return nil // x is not a square mod p
+ case 0:
+ return z.SetInt64(0) // sqrt(0) mod p = 0
+ case 1:
+ break
+ }
+ if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
+ x = new(Int).Mod(x, p)
+ }
+
+ // Break p-1 into s*2^e such that s is odd.
+ var s Int
+ s.Sub(p, intOne)
+ e := s.abs.trailingZeroBits()
+ s.Rsh(&s, e)
+
+ // find some non-square n
+ var n Int
+ n.SetInt64(2)
+ for Jacobi(&n, p) != -1 {
+ n.Add(&n, intOne)
+ }
+
+ // Core of the Tonelli-Shanks algorithm. Follows the description in
+ // section 6 of "Square roots from 1; 24, 51, 10 to Dan Shanks" by Ezra
+ // Brown:
+ // https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf
+ var y, b, g, t Int
+ y.Add(&s, intOne)
+ y.Rsh(&y, 1)
+ y.Exp(x, &y, p) // y = x^((s+1)/2)
+ b.Exp(x, &s, p) // b = x^s
+ g.Exp(&n, &s, p) // g = n^s
+ r := e
+ for {
+ // find the least m such that ord_p(b) = 2^m
+ var m uint
+ t.Set(&b)
+ for t.Cmp(intOne) != 0 {
+ t.Mul(&t, &t).Mod(&t, p)
+ m++
+ }
+
+ if m == 0 {
+ return z.Set(&y)
+ }
+
+ t.SetInt64(0).SetBit(&t, int(r-m-1), 1).Exp(&g, &t, p)
+ // t = g^(2^(r-m-1)) mod p
+ g.Mul(&t, &t).Mod(&g, p) // g = g^(2^(r-m)) mod p
+ y.Mul(&y, &t).Mod(&y, p)
+ b.Mul(&b, &g).Mod(&b, p)
+ r = m
+ }
+}
+
// Lsh sets z = x << n and returns z.
func (z *Int) Lsh(x *Int, n uint) *Int {
z.abs = z.abs.shl(x.abs, n)
@@ -995,7 +932,7 @@ func (z *Int) GobDecode(buf []byte) error {
}
b := buf[0]
if b>>1 != intGobVersion {
- return errors.New(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
+ return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
}
z.neg = b&1 != 0
z.abs = z.abs.setBytes(buf[1:])
diff --git a/libgo/go/math/big/int_test.go b/libgo/go/math/big/int_test.go
index 2d762dbc89f..88c8c2bb641 100644
--- a/libgo/go/math/big/int_test.go
+++ b/libgo/go/math/big/int_test.go
@@ -219,334 +219,42 @@ func TestMulRangeZ(t *testing.T) {
}
}
-var stringTests = []struct {
- in string
- out string
- base int
- val int64
- ok bool
-}{
- {in: "", ok: false},
- {in: "a", ok: false},
- {in: "z", ok: false},
- {in: "+", ok: false},
- {in: "-", ok: false},
- {in: "0b", ok: false},
- {in: "0x", ok: false},
- {in: "2", base: 2, ok: false},
- {in: "0b2", base: 0, ok: false},
- {in: "08", ok: false},
- {in: "8", base: 8, ok: false},
- {in: "0xg", base: 0, ok: false},
- {in: "g", base: 16, ok: false},
- {"0", "0", 0, 0, true},
- {"0", "0", 10, 0, true},
- {"0", "0", 16, 0, true},
- {"+0", "0", 0, 0, true},
- {"-0", "0", 0, 0, true},
- {"10", "10", 0, 10, true},
- {"10", "10", 10, 10, true},
- {"10", "10", 16, 16, true},
- {"-10", "-10", 16, -16, true},
- {"+10", "10", 16, 16, true},
- {"0x10", "16", 0, 16, true},
- {in: "0x10", base: 16, ok: false},
- {"-0x10", "-16", 0, -16, true},
- {"+0x10", "16", 0, 16, true},
- {"00", "0", 0, 0, true},
- {"0", "0", 8, 0, true},
- {"07", "7", 0, 7, true},
- {"7", "7", 8, 7, true},
- {"023", "19", 0, 19, true},
- {"23", "23", 8, 19, true},
- {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
- {"0b0", "0", 0, 0, true},
- {"-111", "-111", 2, -7, true},
- {"-0b111", "-7", 0, -7, true},
- {"0b1001010111", "599", 0, 0x257, true},
- {"1001010111", "1001010111", 2, 0x257, true},
-}
-
-func format(base int) string {
- switch base {
- case 2:
- return "%b"
- case 8:
- return "%o"
- case 16:
- return "%x"
- }
- return "%d"
-}
-
-func TestGetString(t *testing.T) {
- z := new(Int)
- for i, test := range stringTests {
- if !test.ok {
- continue
- }
- z.SetInt64(test.val)
-
- if test.base == 10 {
- s := z.String()
- if s != test.out {
- t.Errorf("#%da got %s; want %s", i, s, test.out)
- }
- }
-
- s := fmt.Sprintf(format(test.base), z)
- if s != test.out {
- t.Errorf("#%db got %s; want %s", i, s, test.out)
- }
- }
-}
-
-func TestSetString(t *testing.T) {
- tmp := new(Int)
- for i, test := range stringTests {
- // initialize to a non-zero value so that issues with parsing
- // 0 are detected
- tmp.SetInt64(1234567890)
- n1, ok1 := new(Int).SetString(test.in, test.base)
- n2, ok2 := tmp.SetString(test.in, test.base)
- expected := NewInt(test.val)
- if ok1 != test.ok || ok2 != test.ok {
- t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
- continue
- }
- if !ok1 {
- if n1 != nil {
- t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
- }
- continue
- }
- if !ok2 {
- if n2 != nil {
- t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
- }
- continue
- }
-
- if ok1 && !isNormalized(n1) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
- }
- if ok2 && !isNormalized(n2) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
- }
-
- if n1.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
- }
- if n2.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
- }
- }
-}
-
-var formatTests = []struct {
- input string
- format string
- output string
-}{
- {"<nil>", "%x", "<nil>"},
- {"<nil>", "%#x", "<nil>"},
- {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
-
- {"10", "%b", "1010"},
- {"10", "%o", "12"},
- {"10", "%d", "10"},
- {"10", "%v", "10"},
- {"10", "%x", "a"},
- {"10", "%X", "A"},
- {"-10", "%X", "-A"},
- {"10", "%y", "%!y(big.Int=10)"},
- {"-10", "%y", "%!y(big.Int=-10)"},
-
- {"10", "%#b", "1010"},
- {"10", "%#o", "012"},
- {"10", "%#d", "10"},
- {"10", "%#v", "10"},
- {"10", "%#x", "0xa"},
- {"10", "%#X", "0XA"},
- {"-10", "%#X", "-0XA"},
- {"10", "%#y", "%!y(big.Int=10)"},
- {"-10", "%#y", "%!y(big.Int=-10)"},
-
- {"1234", "%d", "1234"},
- {"1234", "%3d", "1234"},
- {"1234", "%4d", "1234"},
- {"-1234", "%d", "-1234"},
- {"1234", "% 5d", " 1234"},
- {"1234", "%+5d", "+1234"},
- {"1234", "%-5d", "1234 "},
- {"1234", "%x", "4d2"},
- {"1234", "%X", "4D2"},
- {"-1234", "%3x", "-4d2"},
- {"-1234", "%4x", "-4d2"},
- {"-1234", "%5x", " -4d2"},
- {"-1234", "%-5x", "-4d2 "},
- {"1234", "%03d", "1234"},
- {"1234", "%04d", "1234"},
- {"1234", "%05d", "01234"},
- {"1234", "%06d", "001234"},
- {"-1234", "%06d", "-01234"},
- {"1234", "%+06d", "+01234"},
- {"1234", "% 06d", " 01234"},
- {"1234", "%-6d", "1234 "},
- {"1234", "%-06d", "1234 "},
- {"-1234", "%-06d", "-1234 "},
-
- {"1234", "%.3d", "1234"},
- {"1234", "%.4d", "1234"},
- {"1234", "%.5d", "01234"},
- {"1234", "%.6d", "001234"},
- {"-1234", "%.3d", "-1234"},
- {"-1234", "%.4d", "-1234"},
- {"-1234", "%.5d", "-01234"},
- {"-1234", "%.6d", "-001234"},
-
- {"1234", "%8.3d", " 1234"},
- {"1234", "%8.4d", " 1234"},
- {"1234", "%8.5d", " 01234"},
- {"1234", "%8.6d", " 001234"},
- {"-1234", "%8.3d", " -1234"},
- {"-1234", "%8.4d", " -1234"},
- {"-1234", "%8.5d", " -01234"},
- {"-1234", "%8.6d", " -001234"},
-
- {"1234", "%+8.3d", " +1234"},
- {"1234", "%+8.4d", " +1234"},
- {"1234", "%+8.5d", " +01234"},
- {"1234", "%+8.6d", " +001234"},
- {"-1234", "%+8.3d", " -1234"},
- {"-1234", "%+8.4d", " -1234"},
- {"-1234", "%+8.5d", " -01234"},
- {"-1234", "%+8.6d", " -001234"},
-
- {"1234", "% 8.3d", " 1234"},
- {"1234", "% 8.4d", " 1234"},
- {"1234", "% 8.5d", " 01234"},
- {"1234", "% 8.6d", " 001234"},
- {"-1234", "% 8.3d", " -1234"},
- {"-1234", "% 8.4d", " -1234"},
- {"-1234", "% 8.5d", " -01234"},
- {"-1234", "% 8.6d", " -001234"},
-
- {"1234", "%.3x", "4d2"},
- {"1234", "%.4x", "04d2"},
- {"1234", "%.5x", "004d2"},
- {"1234", "%.6x", "0004d2"},
- {"-1234", "%.3x", "-4d2"},
- {"-1234", "%.4x", "-04d2"},
- {"-1234", "%.5x", "-004d2"},
- {"-1234", "%.6x", "-0004d2"},
-
- {"1234", "%8.3x", " 4d2"},
- {"1234", "%8.4x", " 04d2"},
- {"1234", "%8.5x", " 004d2"},
- {"1234", "%8.6x", " 0004d2"},
- {"-1234", "%8.3x", " -4d2"},
- {"-1234", "%8.4x", " -04d2"},
- {"-1234", "%8.5x", " -004d2"},
- {"-1234", "%8.6x", " -0004d2"},
-
- {"1234", "%+8.3x", " +4d2"},
- {"1234", "%+8.4x", " +04d2"},
- {"1234", "%+8.5x", " +004d2"},
- {"1234", "%+8.6x", " +0004d2"},
- {"-1234", "%+8.3x", " -4d2"},
- {"-1234", "%+8.4x", " -04d2"},
- {"-1234", "%+8.5x", " -004d2"},
- {"-1234", "%+8.6x", " -0004d2"},
-
- {"1234", "% 8.3x", " 4d2"},
- {"1234", "% 8.4x", " 04d2"},
- {"1234", "% 8.5x", " 004d2"},
- {"1234", "% 8.6x", " 0004d2"},
- {"1234", "% 8.7x", " 00004d2"},
- {"1234", "% 8.8x", " 000004d2"},
- {"-1234", "% 8.3x", " -4d2"},
- {"-1234", "% 8.4x", " -04d2"},
- {"-1234", "% 8.5x", " -004d2"},
- {"-1234", "% 8.6x", " -0004d2"},
- {"-1234", "% 8.7x", "-00004d2"},
- {"-1234", "% 8.8x", "-000004d2"},
-
- {"1234", "%-8.3d", "1234 "},
- {"1234", "%-8.4d", "1234 "},
- {"1234", "%-8.5d", "01234 "},
- {"1234", "%-8.6d", "001234 "},
- {"1234", "%-8.7d", "0001234 "},
- {"1234", "%-8.8d", "00001234"},
- {"-1234", "%-8.3d", "-1234 "},
- {"-1234", "%-8.4d", "-1234 "},
- {"-1234", "%-8.5d", "-01234 "},
- {"-1234", "%-8.6d", "-001234 "},
- {"-1234", "%-8.7d", "-0001234"},
- {"-1234", "%-8.8d", "-00001234"},
-
- {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
-
- {"0", "%.d", ""},
- {"0", "%.0d", ""},
- {"0", "%3.d", ""},
-}
-
-func TestFormat(t *testing.T) {
- for i, test := range formatTests {
- var x *Int
- if test.input != "<nil>" {
- var ok bool
- x, ok = new(Int).SetString(test.input, 0)
- if !ok {
- t.Errorf("#%d failed reading input %s", i, test.input)
- }
- }
- output := fmt.Sprintf(test.format, x)
- if output != test.output {
- t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
- }
- }
-}
-
-var scanTests = []struct {
- input string
- format string
- output string
- remaining int
-}{
- {"1010", "%b", "10", 0},
- {"0b1010", "%v", "10", 0},
- {"12", "%o", "10", 0},
- {"012", "%v", "10", 0},
- {"10", "%d", "10", 0},
- {"10", "%v", "10", 0},
- {"a", "%x", "10", 0},
- {"0xa", "%v", "10", 0},
- {"A", "%X", "10", 0},
- {"-A", "%X", "-10", 0},
- {"+0b1011001", "%v", "89", 0},
- {"0xA", "%v", "10", 0},
- {"0 ", "%v", "0", 1},
- {"2+3", "%v", "2", 2},
- {"0XABC 12", "%v", "2748", 3},
-}
-
-func TestScan(t *testing.T) {
- var buf bytes.Buffer
- for i, test := range scanTests {
- x := new(Int)
- buf.Reset()
- buf.WriteString(test.input)
- if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
- t.Errorf("#%d error: %s", i, err)
- }
- if x.String() != test.output {
- t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
- }
- if buf.Len() != test.remaining {
- t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
- }
+func TestBinomial(t *testing.T) {
+ var z Int
+ for _, test := range []struct {
+ n, k int64
+ want string
+ }{
+ {0, 0, "1"},
+ {0, 1, "0"},
+ {1, 0, "1"},
+ {1, 1, "1"},
+ {1, 10, "0"},
+ {4, 0, "1"},
+ {4, 1, "4"},
+ {4, 2, "6"},
+ {4, 3, "4"},
+ {4, 4, "1"},
+ {10, 1, "10"},
+ {10, 9, "10"},
+ {10, 5, "252"},
+ {11, 5, "462"},
+ {11, 6, "462"},
+ {100, 10, "17310309456440"},
+ {100, 90, "17310309456440"},
+ {1000, 10, "263409560461970212832400"},
+ {1000, 990, "263409560461970212832400"},
+ } {
+ if got := z.Binomial(test.n, test.k).String(); got != test.want {
+ t.Errorf("Binomial(%d, %d) = %s; want %s", test.n, test.k, got, test.want)
+ }
+ }
+}
+
+func BenchmarkBinomial(b *testing.B) {
+ var z Int
+ for i := b.N - 1; i >= 0; i-- {
+ z.Binomial(1000, 990)
}
}
@@ -621,6 +329,42 @@ func TestDivisionSigns(t *testing.T) {
}
}
+func norm(x nat) nat {
+ i := len(x)
+ for i > 0 && x[i-1] == 0 {
+ i--
+ }
+ return x[:i]
+}
+
+func TestBits(t *testing.T) {
+ for _, test := range []nat{
+ nil,
+ {0},
+ {1},
+ {0, 1, 2, 3, 4},
+ {4, 3, 2, 1, 0},
+ {4, 3, 2, 1, 0, 0, 0, 0},
+ } {
+ var z Int
+ z.neg = true
+ got := z.SetBits(test)
+ want := norm(test)
+ if got.abs.cmp(want) != 0 {
+ t.Errorf("SetBits(%v) = %v; want %v", test, got.abs, want)
+ }
+
+ if got.neg {
+ t.Errorf("SetBits(%v): got negative result", test)
+ }
+
+ bits := nat(z.Bits())
+ if bits.cmp(want) != 0 {
+ t.Errorf("%v.Bits() = %v; want %v", z.abs, bits, want)
+ }
+ }
+}
+
func checkSetBytes(b []byte) bool {
hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
hex2 := hex.EncodeToString(b)
@@ -648,7 +392,7 @@ func checkBytes(b []byte) bool {
}
func TestBytes(t *testing.T) {
- if err := quick.Check(checkSetBytes, nil); err != nil {
+ if err := quick.Check(checkBytes, nil); err != nil {
t.Error(err)
}
}
@@ -781,6 +525,7 @@ var expTests = []struct {
{"1234", "-1", "1", "0"},
// misc
+ {"5", "1", "3", "2"},
{"5", "-7", "", "1"},
{"-5", "-7", "", "1"},
{"5", "0", "", "1"},
@@ -917,6 +662,21 @@ func testGcd(t *testing.T, d, x, y, a, b *Int) {
if D.Cmp(d) != 0 {
t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
}
+
+ // check results in presence of aliasing (issue #11284)
+ a2 := new(Int).Set(a)
+ b2 := new(Int).Set(b)
+ a2.binaryGCD(a2, b2) // result is same as 1st argument
+ if a2.Cmp(d) != 0 {
+ t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, a2, d)
+ }
+
+ a2 = new(Int).Set(a)
+ b2 = new(Int).Set(b)
+ b2.binaryGCD(a2, b2) // result is same as 2nd argument
+ if b2.Cmp(d) != 0 {
+ t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, b2, d)
+ }
}
func TestGcd(t *testing.T) {
@@ -948,7 +708,7 @@ var primes = []string{
"10953742525620032441",
"17908251027575790097",
- // http://code.google.com/p/go/issues/detail?id=638
+ // https://golang.org/issue/638
"18699199384836356663",
"98920366548084643601728869055592650835572950932266967461790948584315647051443",
@@ -959,9 +719,18 @@ var primes = []string{
"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
+
+ // ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02
+ "3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9
+ "57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19
+ "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105
+ "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17
+ "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1
}
var composites = []string{
+ "0",
+ "1",
"21284175091214687912771199898307297748211672914763848041968395774954376176754",
"6084766654921918907427900243509372380954290099172559290432744450051395395951",
"84594350493221918389213352992032324280367711247940675652888030554255915464401",
@@ -989,6 +758,21 @@ func TestProbablyPrime(t *testing.T) {
break
}
}
+
+ // check that ProbablyPrime panics if n <= 0
+ c := NewInt(11) // a prime
+ for _, n := range []int{-1, 0, 1} {
+ func() {
+ defer func() {
+ if n <= 0 && recover() == nil {
+ t.Fatalf("expected panic from ProbablyPrime(%d)", n)
+ }
+ }()
+ if !c.ProbablyPrime(n) {
+ t.Fatalf("%v should be a prime", c)
+ }
+ }()
+ }
}
type intShiftTest struct {
@@ -1487,6 +1271,136 @@ func TestModInverse(t *testing.T) {
}
}
+// testModSqrt is a helper for TestModSqrt,
+// which checks that ModSqrt can compute a square-root of elt^2.
+func testModSqrt(t *testing.T, elt, mod, sq, sqrt *Int) bool {
+ var sqChk, sqrtChk, sqrtsq Int
+ sq.Mul(elt, elt)
+ sq.Mod(sq, mod)
+ z := sqrt.ModSqrt(sq, mod)
+ if z != sqrt {
+ t.Errorf("ModSqrt returned wrong value %s", z)
+ }
+
+ // test ModSqrt arguments outside the range [0,mod)
+ sqChk.Add(sq, mod)
+ z = sqrtChk.ModSqrt(&sqChk, mod)
+ if z != &sqrtChk || z.Cmp(sqrt) != 0 {
+ t.Errorf("ModSqrt returned inconsistent value %s", z)
+ }
+ sqChk.Sub(sq, mod)
+ z = sqrtChk.ModSqrt(&sqChk, mod)
+ if z != &sqrtChk || z.Cmp(sqrt) != 0 {
+ t.Errorf("ModSqrt returned inconsistent value %s", z)
+ }
+
+ // make sure we actually got a square root
+ if sqrt.Cmp(elt) == 0 {
+ return true // we found the "desired" square root
+ }
+ sqrtsq.Mul(sqrt, sqrt) // make sure we found the "other" one
+ sqrtsq.Mod(&sqrtsq, mod)
+ return sq.Cmp(&sqrtsq) == 0
+}
+
+func TestModSqrt(t *testing.T) {
+ var elt, mod, modx4, sq, sqrt Int
+ r := rand.New(rand.NewSource(9))
+ for i, s := range primes[1:] { // skip 2, use only odd primes
+ mod.SetString(s, 10)
+ modx4.Lsh(&mod, 2)
+
+ // test a few random elements per prime
+ for x := 1; x < 5; x++ {
+ elt.Rand(r, &modx4)
+ elt.Sub(&elt, &mod) // test range [-mod, 3*mod)
+ if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
+ t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
+ }
+ }
+ }
+
+ // exhaustive test for small values
+ for n := 3; n < 100; n++ {
+ mod.SetInt64(int64(n))
+ if !mod.ProbablyPrime(10) {
+ continue
+ }
+ isSquare := make([]bool, n)
+
+ // test all the squares
+ for x := 1; x < n; x++ {
+ elt.SetInt64(int64(x))
+ if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
+ t.Errorf("#%d: failed (sqrt(%d,%d) = %s)", x, &elt, &mod, &sqrt)
+ }
+ isSquare[sq.Uint64()] = true
+ }
+
+ // test all non-squares
+ for x := 1; x < n; x++ {
+ sq.SetInt64(int64(x))
+ z := sqrt.ModSqrt(&sq, &mod)
+ if !isSquare[x] && z != nil {
+ t.Errorf("#%d: failed (sqrt(%d,%d) = nil)", x, &sqrt, &mod)
+ }
+ }
+ }
+}
+
+func TestJacobi(t *testing.T) {
+ testCases := []struct {
+ x, y int64
+ result int
+ }{
+ {0, 1, 1},
+ {0, -1, 1},
+ {1, 1, 1},
+ {1, -1, 1},
+ {0, 5, 0},
+ {1, 5, 1},
+ {2, 5, -1},
+ {-2, 5, -1},
+ {2, -5, -1},
+ {-2, -5, 1},
+ {3, 5, -1},
+ {5, 5, 0},
+ {-5, 5, 0},
+ {6, 5, 1},
+ {6, -5, 1},
+ {-6, 5, 1},
+ {-6, -5, -1},
+ }
+
+ var x, y Int
+
+ for i, test := range testCases {
+ x.SetInt64(test.x)
+ y.SetInt64(test.y)
+ expected := test.result
+ actual := Jacobi(&x, &y)
+ if actual != expected {
+ t.Errorf("#%d: Jacobi(%d, %d) = %d, but expected %d", i, test.x, test.y, actual, expected)
+ }
+ }
+}
+
+func TestJacobiPanic(t *testing.T) {
+ const failureMsg = "test failure"
+ defer func() {
+ msg := recover()
+ if msg == nil || msg == failureMsg {
+ panic(msg)
+ }
+ t.Log(msg)
+ }()
+ x := NewInt(1)
+ y := NewInt(2)
+ // Jacobi should panic when the second argument is even.
+ Jacobi(x, y)
+ panic(failureMsg)
+}
+
var encodingTests = []string{
"-539345864568634858364538753846587364875430589374589",
"-678645873",
diff --git a/libgo/go/math/big/intconv.go b/libgo/go/math/big/intconv.go
new file mode 100644
index 00000000000..9c68a22bed8
--- /dev/null
+++ b/libgo/go/math/big/intconv.go
@@ -0,0 +1,228 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements int-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+)
+
+func (x *Int) String() string {
+ switch {
+ case x == nil:
+ return "<nil>"
+ case x.neg:
+ return "-" + x.abs.decimalString()
+ }
+ return x.abs.decimalString()
+}
+
+func charset(ch rune) string {
+ switch ch {
+ case 'b':
+ return lowercaseDigits[0:2]
+ case 'o':
+ return lowercaseDigits[0:8]
+ case 'd', 's', 'v':
+ return lowercaseDigits[0:10]
+ case 'x':
+ return lowercaseDigits[0:16]
+ case 'X':
+ return uppercaseDigits[0:16]
+ }
+ return "" // unknown format
+}
+
+// write count copies of text to s
+func writeMultiple(s fmt.State, text string, count int) {
+ if len(text) > 0 {
+ b := []byte(text)
+ for ; count > 0; count-- {
+ s.Write(b)
+ }
+ }
+}
+
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
+// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+// Also supported are the full suite of package fmt's format
+// verbs for integral types, including '+', '-', and ' '
+// for sign control, '#' for leading zero in octal and for
+// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
+// respectively, specification of minimum digits precision,
+// output field width, space or zero padding, and left or
+// right justification.
+//
+func (x *Int) Format(s fmt.State, ch rune) {
+ cs := charset(ch)
+
+ // special cases
+ switch {
+ case cs == "":
+ // unknown format
+ fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
+ return
+ case x == nil:
+ fmt.Fprint(s, "<nil>")
+ return
+ }
+
+ // determine sign character
+ sign := ""
+ switch {
+ case x.neg:
+ sign = "-"
+ case s.Flag('+'): // supersedes ' ' when both specified
+ sign = "+"
+ case s.Flag(' '):
+ sign = " "
+ }
+
+ // determine prefix characters for indicating output base
+ prefix := ""
+ if s.Flag('#') {
+ switch ch {
+ case 'o': // octal
+ prefix = "0"
+ case 'x': // hexadecimal
+ prefix = "0x"
+ case 'X':
+ prefix = "0X"
+ }
+ }
+
+ // determine digits with base set by len(cs) and digit characters from cs
+ digits := x.abs.string(cs)
+
+ // number of characters for the three classes of number padding
+ var left int // space characters to left of digits for right justification ("%8d")
+ var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+ var right int // space characters to right of digits for left justification ("%-8d")
+
+ // determine number padding from precision: the least number of digits to output
+ precision, precisionSet := s.Precision()
+ if precisionSet {
+ switch {
+ case len(digits) < precision:
+ zeroes = precision - len(digits) // count of zero padding
+ case digits == "0" && precision == 0:
+ return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
+ }
+ }
+
+ // determine field pad from width: the least number of characters to output
+ length := len(sign) + len(prefix) + zeroes + len(digits)
+ if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
+ switch d := width - length; {
+ case s.Flag('-'):
+ // pad on the right with spaces; supersedes '0' when both specified
+ right = d
+ case s.Flag('0') && !precisionSet:
+ // pad with zeroes unless precision also specified
+ zeroes = d
+ default:
+ // pad on the left with spaces
+ left = d
+ }
+ }
+
+ // print number as [left pad][sign][prefix][zero pad][digits][right pad]
+ writeMultiple(s, " ", left)
+ writeMultiple(s, sign, 1)
+ writeMultiple(s, prefix, 1)
+ writeMultiple(s, "0", zeroes)
+ writeMultiple(s, digits, 1)
+ writeMultiple(s, " ", right)
+}
+
+// scan sets z to the integer value corresponding to the longest possible prefix
+// read from r representing a signed integer number in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined but the returned value is nil. The
+// syntax follows the syntax of integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
+ // determine sign
+ neg, err := scanSign(r)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // determine mantissa
+ z.abs, base, _, err = z.abs.scan(r, base, false)
+ if err != nil {
+ return nil, base, err
+ }
+ z.neg = len(z.abs) > 0 && neg // 0 has no sign
+
+ return z, base, nil
+}
+
+func scanSign(r io.ByteScanner) (neg bool, err error) {
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
+ return false, err
+ }
+ switch ch {
+ case '-':
+ neg = true
+ case '+':
+ // nothing to do
+ default:
+ r.UnreadByte()
+ }
+ return
+}
+
+// byteReader is a local wrapper around fmt.ScanState;
+// it implements the ByteReader interface.
+type byteReader struct {
+ fmt.ScanState
+}
+
+func (r byteReader) ReadByte() (byte, error) {
+ ch, size, err := r.ReadRune()
+ if size != 1 && err == nil {
+ err = fmt.Errorf("invalid rune %#U", ch)
+ }
+ return byte(ch), err
+}
+
+func (r byteReader) UnreadByte() error {
+ return r.UnreadRune()
+}
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
+// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+func (z *Int) Scan(s fmt.ScanState, ch rune) error {
+ s.SkipSpace() // skip leading space characters
+ base := 0
+ switch ch {
+ case 'b':
+ base = 2
+ case 'o':
+ base = 8
+ case 'd':
+ base = 10
+ case 'x', 'X':
+ base = 16
+ case 's', 'v':
+ // let scan determine the base
+ default:
+ return errors.New("Int.Scan: invalid verb")
+ }
+ _, _, err := z.scan(byteReader{s}, base)
+ return err
+}
diff --git a/libgo/go/math/big/intconv_test.go b/libgo/go/math/big/intconv_test.go
new file mode 100644
index 00000000000..2deb84b48f6
--- /dev/null
+++ b/libgo/go/math/big/intconv_test.go
@@ -0,0 +1,342 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+var stringTests = []struct {
+ in string
+ out string
+ base int
+ val int64
+ ok bool
+}{
+ {in: "", ok: false},
+ {in: "a", ok: false},
+ {in: "z", ok: false},
+ {in: "+", ok: false},
+ {in: "-", ok: false},
+ {in: "0b", ok: false},
+ {in: "0x", ok: false},
+ {in: "2", base: 2, ok: false},
+ {in: "0b2", base: 0, ok: false},
+ {in: "08", ok: false},
+ {in: "8", base: 8, ok: false},
+ {in: "0xg", base: 0, ok: false},
+ {in: "g", base: 16, ok: false},
+ {"0", "0", 0, 0, true},
+ {"0", "0", 10, 0, true},
+ {"0", "0", 16, 0, true},
+ {"+0", "0", 0, 0, true},
+ {"-0", "0", 0, 0, true},
+ {"10", "10", 0, 10, true},
+ {"10", "10", 10, 10, true},
+ {"10", "10", 16, 16, true},
+ {"-10", "-10", 16, -16, true},
+ {"+10", "10", 16, 16, true},
+ {"0x10", "16", 0, 16, true},
+ {in: "0x10", base: 16, ok: false},
+ {"-0x10", "-16", 0, -16, true},
+ {"+0x10", "16", 0, 16, true},
+ {"00", "0", 0, 0, true},
+ {"0", "0", 8, 0, true},
+ {"07", "7", 0, 7, true},
+ {"7", "7", 8, 7, true},
+ {"023", "19", 0, 19, true},
+ {"23", "23", 8, 19, true},
+ {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
+ {"0b0", "0", 0, 0, true},
+ {"-111", "-111", 2, -7, true},
+ {"-0b111", "-7", 0, -7, true},
+ {"0b1001010111", "599", 0, 0x257, true},
+ {"1001010111", "1001010111", 2, 0x257, true},
+}
+
+func format(base int) string {
+ switch base {
+ case 2:
+ return "%b"
+ case 8:
+ return "%o"
+ case 16:
+ return "%x"
+ }
+ return "%d"
+}
+
+func TestGetString(t *testing.T) {
+ z := new(Int)
+ for i, test := range stringTests {
+ if !test.ok {
+ continue
+ }
+ z.SetInt64(test.val)
+
+ if test.base == 10 {
+ s := z.String()
+ if s != test.out {
+ t.Errorf("#%da got %s; want %s", i, s, test.out)
+ }
+ }
+
+ s := fmt.Sprintf(format(test.base), z)
+ if s != test.out {
+ t.Errorf("#%db got %s; want %s", i, s, test.out)
+ }
+ }
+}
+
+func TestSetString(t *testing.T) {
+ tmp := new(Int)
+ for i, test := range stringTests {
+ // initialize to a non-zero value so that issues with parsing
+ // 0 are detected
+ tmp.SetInt64(1234567890)
+ n1, ok1 := new(Int).SetString(test.in, test.base)
+ n2, ok2 := tmp.SetString(test.in, test.base)
+ expected := NewInt(test.val)
+ if ok1 != test.ok || ok2 != test.ok {
+ t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
+ continue
+ }
+ if !ok1 {
+ if n1 != nil {
+ t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
+ }
+ continue
+ }
+ if !ok2 {
+ if n2 != nil {
+ t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
+ }
+ continue
+ }
+
+ if ok1 && !isNormalized(n1) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
+ }
+ if ok2 && !isNormalized(n2) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
+ }
+
+ if n1.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
+ }
+ if n2.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
+ }
+ }
+}
+
+var formatTests = []struct {
+ input string
+ format string
+ output string
+}{
+ {"<nil>", "%x", "<nil>"},
+ {"<nil>", "%#x", "<nil>"},
+ {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
+
+ {"10", "%b", "1010"},
+ {"10", "%o", "12"},
+ {"10", "%d", "10"},
+ {"10", "%v", "10"},
+ {"10", "%x", "a"},
+ {"10", "%X", "A"},
+ {"-10", "%X", "-A"},
+ {"10", "%y", "%!y(big.Int=10)"},
+ {"-10", "%y", "%!y(big.Int=-10)"},
+
+ {"10", "%#b", "1010"},
+ {"10", "%#o", "012"},
+ {"10", "%#d", "10"},
+ {"10", "%#v", "10"},
+ {"10", "%#x", "0xa"},
+ {"10", "%#X", "0XA"},
+ {"-10", "%#X", "-0XA"},
+ {"10", "%#y", "%!y(big.Int=10)"},
+ {"-10", "%#y", "%!y(big.Int=-10)"},
+
+ {"1234", "%d", "1234"},
+ {"1234", "%3d", "1234"},
+ {"1234", "%4d", "1234"},
+ {"-1234", "%d", "-1234"},
+ {"1234", "% 5d", " 1234"},
+ {"1234", "%+5d", "+1234"},
+ {"1234", "%-5d", "1234 "},
+ {"1234", "%x", "4d2"},
+ {"1234", "%X", "4D2"},
+ {"-1234", "%3x", "-4d2"},
+ {"-1234", "%4x", "-4d2"},
+ {"-1234", "%5x", " -4d2"},
+ {"-1234", "%-5x", "-4d2 "},
+ {"1234", "%03d", "1234"},
+ {"1234", "%04d", "1234"},
+ {"1234", "%05d", "01234"},
+ {"1234", "%06d", "001234"},
+ {"-1234", "%06d", "-01234"},
+ {"1234", "%+06d", "+01234"},
+ {"1234", "% 06d", " 01234"},
+ {"1234", "%-6d", "1234 "},
+ {"1234", "%-06d", "1234 "},
+ {"-1234", "%-06d", "-1234 "},
+
+ {"1234", "%.3d", "1234"},
+ {"1234", "%.4d", "1234"},
+ {"1234", "%.5d", "01234"},
+ {"1234", "%.6d", "001234"},
+ {"-1234", "%.3d", "-1234"},
+ {"-1234", "%.4d", "-1234"},
+ {"-1234", "%.5d", "-01234"},
+ {"-1234", "%.6d", "-001234"},
+
+ {"1234", "%8.3d", " 1234"},
+ {"1234", "%8.4d", " 1234"},
+ {"1234", "%8.5d", " 01234"},
+ {"1234", "%8.6d", " 001234"},
+ {"-1234", "%8.3d", " -1234"},
+ {"-1234", "%8.4d", " -1234"},
+ {"-1234", "%8.5d", " -01234"},
+ {"-1234", "%8.6d", " -001234"},
+
+ {"1234", "%+8.3d", " +1234"},
+ {"1234", "%+8.4d", " +1234"},
+ {"1234", "%+8.5d", " +01234"},
+ {"1234", "%+8.6d", " +001234"},
+ {"-1234", "%+8.3d", " -1234"},
+ {"-1234", "%+8.4d", " -1234"},
+ {"-1234", "%+8.5d", " -01234"},
+ {"-1234", "%+8.6d", " -001234"},
+
+ {"1234", "% 8.3d", " 1234"},
+ {"1234", "% 8.4d", " 1234"},
+ {"1234", "% 8.5d", " 01234"},
+ {"1234", "% 8.6d", " 001234"},
+ {"-1234", "% 8.3d", " -1234"},
+ {"-1234", "% 8.4d", " -1234"},
+ {"-1234", "% 8.5d", " -01234"},
+ {"-1234", "% 8.6d", " -001234"},
+
+ {"1234", "%.3x", "4d2"},
+ {"1234", "%.4x", "04d2"},
+ {"1234", "%.5x", "004d2"},
+ {"1234", "%.6x", "0004d2"},
+ {"-1234", "%.3x", "-4d2"},
+ {"-1234", "%.4x", "-04d2"},
+ {"-1234", "%.5x", "-004d2"},
+ {"-1234", "%.6x", "-0004d2"},
+
+ {"1234", "%8.3x", " 4d2"},
+ {"1234", "%8.4x", " 04d2"},
+ {"1234", "%8.5x", " 004d2"},
+ {"1234", "%8.6x", " 0004d2"},
+ {"-1234", "%8.3x", " -4d2"},
+ {"-1234", "%8.4x", " -04d2"},
+ {"-1234", "%8.5x", " -004d2"},
+ {"-1234", "%8.6x", " -0004d2"},
+
+ {"1234", "%+8.3x", " +4d2"},
+ {"1234", "%+8.4x", " +04d2"},
+ {"1234", "%+8.5x", " +004d2"},
+ {"1234", "%+8.6x", " +0004d2"},
+ {"-1234", "%+8.3x", " -4d2"},
+ {"-1234", "%+8.4x", " -04d2"},
+ {"-1234", "%+8.5x", " -004d2"},
+ {"-1234", "%+8.6x", " -0004d2"},
+
+ {"1234", "% 8.3x", " 4d2"},
+ {"1234", "% 8.4x", " 04d2"},
+ {"1234", "% 8.5x", " 004d2"},
+ {"1234", "% 8.6x", " 0004d2"},
+ {"1234", "% 8.7x", " 00004d2"},
+ {"1234", "% 8.8x", " 000004d2"},
+ {"-1234", "% 8.3x", " -4d2"},
+ {"-1234", "% 8.4x", " -04d2"},
+ {"-1234", "% 8.5x", " -004d2"},
+ {"-1234", "% 8.6x", " -0004d2"},
+ {"-1234", "% 8.7x", "-00004d2"},
+ {"-1234", "% 8.8x", "-000004d2"},
+
+ {"1234", "%-8.3d", "1234 "},
+ {"1234", "%-8.4d", "1234 "},
+ {"1234", "%-8.5d", "01234 "},
+ {"1234", "%-8.6d", "001234 "},
+ {"1234", "%-8.7d", "0001234 "},
+ {"1234", "%-8.8d", "00001234"},
+ {"-1234", "%-8.3d", "-1234 "},
+ {"-1234", "%-8.4d", "-1234 "},
+ {"-1234", "%-8.5d", "-01234 "},
+ {"-1234", "%-8.6d", "-001234 "},
+ {"-1234", "%-8.7d", "-0001234"},
+ {"-1234", "%-8.8d", "-00001234"},
+
+ {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
+
+ {"0", "%.d", ""},
+ {"0", "%.0d", ""},
+ {"0", "%3.d", ""},
+}
+
+func TestFormat(t *testing.T) {
+ for i, test := range formatTests {
+ var x *Int
+ if test.input != "<nil>" {
+ var ok bool
+ x, ok = new(Int).SetString(test.input, 0)
+ if !ok {
+ t.Errorf("#%d failed reading input %s", i, test.input)
+ }
+ }
+ output := fmt.Sprintf(test.format, x)
+ if output != test.output {
+ t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
+ }
+ }
+}
+
+var scanTests = []struct {
+ input string
+ format string
+ output string
+ remaining int
+}{
+ {"1010", "%b", "10", 0},
+ {"0b1010", "%v", "10", 0},
+ {"12", "%o", "10", 0},
+ {"012", "%v", "10", 0},
+ {"10", "%d", "10", 0},
+ {"10", "%v", "10", 0},
+ {"a", "%x", "10", 0},
+ {"0xa", "%v", "10", 0},
+ {"A", "%X", "10", 0},
+ {"-A", "%X", "-10", 0},
+ {"+0b1011001", "%v", "89", 0},
+ {"0xA", "%v", "10", 0},
+ {"0 ", "%v", "0", 1},
+ {"2+3", "%v", "2", 2},
+ {"0XABC 12", "%v", "2748", 3},
+}
+
+func TestScan(t *testing.T) {
+ var buf bytes.Buffer
+ for i, test := range scanTests {
+ x := new(Int)
+ buf.Reset()
+ buf.WriteString(test.input)
+ if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
+ t.Errorf("#%d error: %s", i, err)
+ }
+ if x.String() != test.output {
+ t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+ }
+ if buf.Len() != test.remaining {
+ t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+ }
+ }
+}
diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go
index 16a87f5c537..6545bc17ed3 100644
--- a/libgo/go/math/big/nat.go
+++ b/libgo/go/math/big/nat.go
@@ -5,18 +5,22 @@
// Package big implements multi-precision arithmetic (big numbers).
// The following numeric types are supported:
//
-// - Int signed integers
-// - Rat rational numbers
+// Int signed integers
+// Rat rational numbers
+// Float floating-point numbers
//
// Methods are typically of the form:
//
-// func (z *Int) Op(x, y *Int) *Int (similar for *Rat)
+// func (z *T) Unary(x *T) *T // z = op x
+// func (z *T) Binary(x, y *T) *T // z = x op y
+// func (x *T) M() T1 // v = x.M()
//
-// and implement operations z = x Op y with the result as receiver; if it
-// is one of the operands it may be overwritten (and its memory reused).
+// with T one of Int, Rat, or Float. For unary and binary operations, the
+// result is the receiver (usually named z in that case); if it is one of
+// the operands x or y it may be overwritten (and its memory reused).
// To enable chaining of operations, the result is also returned. Methods
-// returning a result other than *Int or *Rat take one of the operands as
-// the receiver.
+// returning a result other than *Int, *Rat, or *Float take an operand as
+// the receiver (usually named x in that case).
//
package big
@@ -24,13 +28,7 @@ package big
// These are the building blocks for the operations on signed integers
// and rationals.
-import (
- "errors"
- "io"
- "math"
- "math/rand"
- "sync"
-)
+import "math/rand"
// An unsigned integer x of the form
//
@@ -68,7 +66,7 @@ func (z nat) norm() nat {
func (z nat) make(n int) nat {
if n <= cap(z) {
- return z[0:n] // reuse z
+ return z[:n] // reuse z
}
// Choosing a good value for e has significant performance impact
// because it increases the chance that a value can be reused.
@@ -78,7 +76,7 @@ func (z nat) make(n int) nat {
func (z nat) setWord(x Word) nat {
if x == 0 {
- return z.make(0)
+ return z[:0]
}
z = z.make(1)
z[0] = x
@@ -122,7 +120,7 @@ func (z nat) add(x, y nat) nat {
return z.add(y, x)
case m == 0:
// n == 0 because m >= n; result is 0
- return z.make(0)
+ return z[:0]
case n == 0:
// result is x
return z.set(x)
@@ -148,7 +146,7 @@ func (z nat) sub(x, y nat) nat {
panic("underflow")
case m == 0:
// n == 0 because m >= n; result is 0
- return z.make(0)
+ return z[:0]
case n == 0:
// result is x
return z.set(x)
@@ -218,6 +216,34 @@ func basicMul(z, x, y nat) {
}
}
+// montgomery computes x*y*2^(-n*_W) mod m,
+// assuming k = -1/m mod 2^_W.
+// z is used for storing the result which is returned;
+// z must not alias x, y or m.
+func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
+ var c1, c2 Word
+ z = z.make(n)
+ z.clear()
+ for i := 0; i < n; i++ {
+ d := y[i]
+ c1 += addMulVVW(z, x, d)
+ t := z[0] * k
+ c2 = addMulVVW(z, m, t)
+
+ copy(z, z[1:])
+ z[n-1] = c1 + c2
+ if z[n-1] < c1 {
+ c1 = 1
+ } else {
+ c1 = 0
+ }
+ }
+ if c1 != 0 {
+ subVV(z, z, m)
+ }
+ return z
+}
+
// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
// Factored out for readability - do not use outside karatsuba.
func karatsubaAdd(z, x nat, n int) {
@@ -337,7 +363,7 @@ func karatsuba(z, x, y nat) {
}
}
-// alias returns true if x and y share the same base array.
+// alias reports whether x and y share the same base array.
func alias(x, y nat) bool {
return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
}
@@ -384,7 +410,7 @@ func (z nat) mul(x, y nat) nat {
case m < n:
return z.mul(y, x)
case m == 0 || n == 0:
- return z.make(0)
+ return z[:0]
case n == 1:
return z.mulAddWW(x, y[0], 0)
}
@@ -488,7 +514,7 @@ func (z nat) divW(x nat, y Word) (q nat, r Word) {
q = z.set(x) // result is x
return
case m == 0:
- q = z.make(0) // result is 0
+ q = z[:0] // result is 0
return
}
// m > 0
@@ -504,7 +530,7 @@ func (z nat) div(z2, u, v nat) (q, r nat) {
}
if u.cmp(v) < 0 {
- q = z.make(0)
+ q = z[:0]
r = z2.set(u)
return
}
@@ -543,10 +569,10 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
u = nil // u is an alias for uIn or v - cannot reuse
}
u = u.make(len(uIn) + 1)
- u.clear()
+ u.clear() // TODO(gri) no need to clear if we allocated a new u
// D1.
- shift := leadingZeros(v[n-1])
+ shift := nlz(v[n-1])
if shift > 0 {
// do not modify v, it may be used by another goroutine simultaneously
v1 := make(nat, n)
@@ -606,385 +632,6 @@ func (x nat) bitLen() int {
return 0
}
-// MaxBase is the largest number base accepted for string conversions.
-const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
-
-func hexValue(ch rune) Word {
- d := int(MaxBase + 1) // illegal base
- switch {
- case '0' <= ch && ch <= '9':
- d = int(ch - '0')
- case 'a' <= ch && ch <= 'z':
- d = int(ch - 'a' + 10)
- case 'A' <= ch && ch <= 'Z':
- d = int(ch - 'A' + 10)
- }
- return Word(d)
-}
-
-// scan sets z to the natural number corresponding to the longest possible prefix
-// read from r representing an unsigned integer in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined. The syntax follows the syntax of
-// unsigned integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) {
- // reject illegal bases
- if base < 0 || base == 1 || MaxBase < base {
- return z, 0, errors.New("illegal number base")
- }
-
- // one char look-ahead
- ch, _, err := r.ReadRune()
- if err != nil {
- return z, 0, err
- }
-
- // determine base if necessary
- b := Word(base)
- if base == 0 {
- b = 10
- if ch == '0' {
- switch ch, _, err = r.ReadRune(); err {
- case nil:
- b = 8
- switch ch {
- case 'x', 'X':
- b = 16
- case 'b', 'B':
- b = 2
- }
- if b == 2 || b == 16 {
- if ch, _, err = r.ReadRune(); err != nil {
- return z, 0, err
- }
- }
- case io.EOF:
- return z.make(0), 10, nil
- default:
- return z, 10, err
- }
- }
- }
-
- // convert string
- // - group as many digits d as possible together into a "super-digit" dd with "super-base" bb
- // - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd
- z = z.make(0)
- bb := Word(1)
- dd := Word(0)
- for max := _M / b; ; {
- d := hexValue(ch)
- if d >= b {
- r.UnreadRune() // ch does not belong to number anymore
- break
- }
-
- if bb <= max {
- bb *= b
- dd = dd*b + d
- } else {
- // bb * b would overflow
- z = z.mulAddWW(z, bb, dd)
- bb = b
- dd = d
- }
-
- if ch, _, err = r.ReadRune(); err != nil {
- if err != io.EOF {
- return z, int(b), err
- }
- break
- }
- }
-
- switch {
- case bb > 1:
- // there was at least one mantissa digit
- z = z.mulAddWW(z, bb, dd)
- case base == 0 && b == 8:
- // there was only the octal prefix 0 (possibly followed by digits > 7);
- // return base 10, not 8
- return z, 10, nil
- case base != 0 || b != 8:
- // there was neither a mantissa digit nor the octal prefix 0
- return z, int(b), errors.New("syntax error scanning number")
- }
-
- return z.norm(), int(b), nil
-}
-
-// Character sets for string conversion.
-const (
- lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
- uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
- return x.string(lowercaseDigits[0:10])
-}
-
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2 and <= 256.
-func (x nat) string(charset string) string {
- b := Word(len(charset))
-
- // special cases
- switch {
- case b < 2 || MaxBase > 256:
- panic("illegal base")
- case len(x) == 0:
- return string(charset[0])
- }
-
- // allocate buffer for conversion
- i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
- s := make([]byte, i)
-
- // convert power of two and non power of two bases separately
- if b == b&-b {
- // shift is base-b digit size in bits
- shift := trailingZeroBits(b) // shift > 0 because b >= 2
- mask := Word(1)<<shift - 1
- w := x[0]
- nbits := uint(_W) // number of unprocessed bits in w
-
- // convert less-significant words
- for k := 1; k < len(x); k++ {
- // convert full digits
- for nbits >= shift {
- i--
- s[i] = charset[w&mask]
- w >>= shift
- nbits -= shift
- }
-
- // convert any partial leading digit and advance to next word
- if nbits == 0 {
- // no partial digit remaining, just advance
- w = x[k]
- nbits = _W
- } else {
- // partial digit in current (k-1) and next (k) word
- w |= x[k] << nbits
- i--
- s[i] = charset[w&mask]
-
- // advance
- w = x[k] >> (shift - nbits)
- nbits = _W - (shift - nbits)
- }
- }
-
- // convert digits of most-significant word (omit leading zeros)
- for nbits >= 0 && w != 0 {
- i--
- s[i] = charset[w&mask]
- w >>= shift
- nbits -= shift
- }
-
- } else {
- // determine "big base"; i.e., the largest possible value bb
- // that is a power of base b and still fits into a Word
- // (as in 10^19 for 19 decimal digits in a 64bit Word)
- bb := b // big base is b**ndigits
- ndigits := 1 // number of base b digits
- for max := Word(_M / b); bb <= max; bb *= b {
- ndigits++ // maximize ndigits where bb = b**ndigits, bb <= _M
- }
-
- // construct table of successive squares of bb*leafSize to use in subdivisions
- // result (table != nil) <=> (len(x) > leafSize > 0)
- table := divisors(len(x), b, ndigits, bb)
-
- // preserve x, create local copy for use by convertWords
- q := nat(nil).set(x)
-
- // convert q to string s in base b
- q.convertWords(s, charset, b, ndigits, bb, table)
-
- // strip leading zeros
- // (x != 0; thus s must contain at least one non-zero digit
- // and the loop will terminate)
- i = 0
- for zero := charset[0]; s[i] == zero; {
- i++
- }
- }
-
- return string(s[i:])
-}
-
-// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
-// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
-// repeated nat/Word division.
-//
-// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
-// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
-// Recursive conversion divides q by its approximate square root, yielding two parts, each half
-// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
-// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
-// is made better by splitting the subblocks recursively. Best is to split blocks until one more
-// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
-// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
-// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
-// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
-// specific hardware.
-//
-func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
- // split larger blocks recursively
- if table != nil {
- // len(q) > leafSize > 0
- var r nat
- index := len(table) - 1
- for len(q) > leafSize {
- // find divisor close to sqrt(q) if possible, but in any case < q
- maxLength := q.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
- minLength := maxLength >> 1 // ~= log2 sqrt(q)
- for index > 0 && table[index-1].nbits > minLength {
- index-- // desired
- }
- if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
- index--
- if index < 0 {
- panic("internal inconsistency")
- }
- }
-
- // split q into the two digit number (q'*bbb + r) to form independent subblocks
- q, r = q.div(r, q, table[index].bbb)
-
- // convert subblocks and collect results in s[:h] and s[h:]
- h := len(s) - table[index].ndigits
- r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
- s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
- }
- }
-
- // having split any large blocks now process the remaining (small) block iteratively
- i := len(s)
- var r Word
- if b == 10 {
- // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
- for len(q) > 0 {
- // extract least significant, base bb "digit"
- q, r = q.divW(q, bb)
- for j := 0; j < ndigits && i > 0; j++ {
- i--
- // avoid % computation since r%10 == r - int(r/10)*10;
- // this appears to be faster for BenchmarkString10000Base10
- // and smaller strings (but a bit slower for larger ones)
- t := r / 10
- s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
- r = t
- }
- }
- } else {
- for len(q) > 0 {
- // extract least significant, base bb "digit"
- q, r = q.divW(q, bb)
- for j := 0; j < ndigits && i > 0; j++ {
- i--
- s[i] = charset[r%b]
- r /= b
- }
- }
- }
-
- // prepend high-order zeroes
- zero := charset[0]
- for i > 0 { // while need more leading zeroes
- i--
- s[i] = zero
- }
-}
-
-// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
-// Benchmark and configure leafSize using: go test -bench="Leaf"
-// 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
-// 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
-var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
-
-type divisor struct {
- bbb nat // divisor
- nbits int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
- ndigits int // digit length of divisor in terms of output base digits
-}
-
-var cacheBase10 struct {
- sync.Mutex
- table [64]divisor // cached divisors for base 10
-}
-
-// expWW computes x**y
-func (z nat) expWW(x, y Word) nat {
- return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
-}
-
-// construct table of powers of bb*leafSize to use in subdivisions
-func divisors(m int, b Word, ndigits int, bb Word) []divisor {
- // only compute table when recursive conversion is enabled and x is large
- if leafSize == 0 || m <= leafSize {
- return nil
- }
-
- // determine k where (bb**leafSize)**(2**k) >= sqrt(x)
- k := 1
- for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
- k++
- }
-
- // reuse and extend existing table of divisors or create new table as appropriate
- var table []divisor // for b == 10, table overlaps with cacheBase10.table
- if b == 10 {
- cacheBase10.Lock()
- table = cacheBase10.table[0:k] // reuse old table for this conversion
- } else {
- table = make([]divisor, k) // create new table for this conversion
- }
-
- // extend table
- if table[k-1].ndigits == 0 {
- // add new entries as needed
- var larger nat
- for i := 0; i < k; i++ {
- if table[i].ndigits == 0 {
- if i == 0 {
- table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
- table[0].ndigits = ndigits * leafSize
- } else {
- table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
- table[i].ndigits = 2 * table[i-1].ndigits
- }
-
- // optimization: exploit aggregated extra bits in macro blocks
- larger = nat(nil).set(table[i].bbb)
- for mulAddVWW(larger, larger, b, 0) == 0 {
- table[i].bbb = table[i].bbb.set(larger)
- table[i].ndigits++
- }
-
- table[i].nbits = table[i].bbb.bitLen()
- }
- }
- }
-
- if b == 10 {
- cacheBase10.Unlock()
- }
-
- return table
-}
-
const deBruijn32 = 0x077CB531
var deBruijn32Lookup = []byte{
@@ -1041,7 +688,7 @@ func (x nat) trailingZeroBits() uint {
func (z nat) shl(x nat, s uint) nat {
m := len(x)
if m == 0 {
- return z.make(0)
+ return z[:0]
}
// m > 0
@@ -1058,7 +705,7 @@ func (z nat) shr(x nat, s uint) nat {
m := len(x)
n := m - int(s/_W)
if n <= 0 {
- return z.make(0)
+ return z[:0]
}
// n > 0
@@ -1097,12 +744,36 @@ func (z nat) setBit(x nat, i uint, b uint) nat {
panic("set bit is not 0 or 1")
}
-func (z nat) bit(i uint) uint {
- j := int(i / _W)
- if j >= len(z) {
+// bit returns the value of the i'th bit, with lsb == bit 0.
+func (x nat) bit(i uint) uint {
+ j := i / _W
+ if j >= uint(len(x)) {
return 0
}
- return uint(z[j] >> (i % _W) & 1)
+ // 0 <= j < len(x)
+ return uint(x[j] >> (i % _W) & 1)
+}
+
+// sticky returns 1 if there's a 1 bit within the
+// i least significant bits, otherwise it returns 0.
+func (x nat) sticky(i uint) uint {
+ j := i / _W
+ if j >= uint(len(x)) {
+ if len(x) == 0 {
+ return 0
+ }
+ return 1
+ }
+ // 0 <= j < len(x)
+ for _, x := range x[:j] {
+ if x != 0 {
+ return 1
+ }
+ }
+ if x[j]<<(_W-i%_W) != 0 {
+ return 1
+ }
+ return 0
}
func (z nat) and(x, y nat) nat {
@@ -1176,7 +847,7 @@ func (z nat) xor(x, y nat) nat {
return z.norm()
}
-// greaterThan returns true iff (x1<<_W + x2) > (y1<<_W + y2)
+// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2)
func greaterThan(x1, x2, y1, y2 Word) bool {
return x1 > y1 || x1 == y1 && x2 > y2
}
@@ -1245,6 +916,13 @@ func (z nat) expNN(x, y, m nat) nat {
}
// y > 0
+ // x**1 mod m == x mod m
+ if len(y) == 1 && y[0] == 1 && len(m) != 0 {
+ _, z = z.div(z, x, m)
+ return z
+ }
+ // y > 1
+
if len(m) != 0 {
// We likely end up being as long as the modulus.
z = z.make(len(m))
@@ -1255,13 +933,16 @@ func (z nat) expNN(x, y, m nat) nat {
// 4-bit, windowed exponentiation. This involves precomputing 14 values
// (x^2...x^15) but then reduces the number of multiply-reduces by a
// third. Even for a 32-bit exponent, this reduces the number of
- // operations.
+ // operations. Uses Montgomery method for odd moduli.
if len(x) > 1 && len(y) > 1 && len(m) > 0 {
+ if m[0]&1 == 1 {
+ return z.expNNMontgomery(x, y, m)
+ }
return z.expNNWindowed(x, y, m)
}
v := y[len(y)-1] // v > 0 because y is normalized and y > 0
- shift := leadingZeros(v) + 1
+ shift := nlz(v) + 1
v <<= shift
var q nat
@@ -1379,6 +1060,87 @@ func (z nat) expNNWindowed(x, y, m nat) nat {
return z.norm()
}
+// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
+// Uses Montgomery representation.
+func (z nat) expNNMontgomery(x, y, m nat) nat {
+ var zz, one, rr, RR nat
+
+ numWords := len(m)
+
+ // We want the lengths of x and m to be equal.
+ if len(x) > numWords {
+ _, rr = rr.div(rr, x, m)
+ } else if len(x) < numWords {
+ rr = rr.make(numWords)
+ rr.clear()
+ for i := range x {
+ rr[i] = x[i]
+ }
+ } else {
+ rr = x
+ }
+ x = rr
+
+ // Ideally the precomputations would be performed outside, and reused
+ // k0 = -mˆ-1 mod 2ˆ_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
+ // Iteration for Multiplicative Inverses Modulo Prime Powers".
+ k0 := 2 - m[0]
+ t := m[0] - 1
+ for i := 1; i < _W; i <<= 1 {
+ t *= t
+ k0 *= (t + 1)
+ }
+ k0 = -k0
+
+ // RR = 2ˆ(2*_W*len(m)) mod m
+ RR = RR.setWord(1)
+ zz = zz.shl(RR, uint(2*numWords*_W))
+ _, RR = RR.div(RR, zz, m)
+ if len(RR) < numWords {
+ zz = zz.make(numWords)
+ copy(zz, RR)
+ RR = zz
+ }
+ // one = 1, with equal length to that of m
+ one = one.make(numWords)
+ one.clear()
+ one[0] = 1
+
+ const n = 4
+ // powers[i] contains x^i
+ var powers [1 << n]nat
+ powers[0] = powers[0].montgomery(one, RR, m, k0, numWords)
+ powers[1] = powers[1].montgomery(x, RR, m, k0, numWords)
+ for i := 2; i < 1<<n; i++ {
+ powers[i] = powers[i].montgomery(powers[i-1], powers[1], m, k0, numWords)
+ }
+
+ // initialize z = 1 (Montgomery 1)
+ z = z.make(numWords)
+ copy(z, powers[0])
+
+ zz = zz.make(numWords)
+
+ // same windowed exponent, but with Montgomery multiplications
+ for i := len(y) - 1; i >= 0; i-- {
+ yi := y[i]
+ for j := 0; j < _W; j += n {
+ if i != len(y)-1 || j != 0 {
+ zz = zz.montgomery(z, z, m, k0, numWords)
+ z = z.montgomery(zz, zz, m, k0, numWords)
+ zz = zz.montgomery(z, z, m, k0, numWords)
+ z = z.montgomery(zz, zz, m, k0, numWords)
+ }
+ zz = zz.montgomery(z, powers[yi>>(_W-n)], m, k0, numWords)
+ z, zz = zz, z
+ yi <<= n
+ }
+ }
+ // convert to regular number
+ zz = zz.montgomery(z, one, m, k0, numWords)
+ return zz.norm()
+}
+
// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
// If it returns true, n is prime with probability 1 - 1/4^reps.
// If it returns false, n is not prime.
@@ -1404,6 +1166,10 @@ func (n nat) probablyPrime(reps int) bool {
}
}
+ if n[0]&1 == 0 {
+ return false // n is even
+ }
+
const primesProduct32 = 0xC0CFD797 // Π {p ∈ primes, 2 < p <= 29}
const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
diff --git a/libgo/go/math/big/nat_test.go b/libgo/go/math/big/nat_test.go
index a2ae53385c9..7ac3cb8a846 100644
--- a/libgo/go/math/big/nat_test.go
+++ b/libgo/go/math/big/nat_test.go
@@ -5,7 +5,6 @@
package big
import (
- "io"
"runtime"
"strings"
"testing"
@@ -88,7 +87,7 @@ var prodNN = []argNN{
}
func natFromString(s string) nat {
- x, _, err := nat(nil).scan(strings.NewReader(s), 0)
+ x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false)
if err != nil {
panic(err)
}
@@ -206,398 +205,11 @@ func BenchmarkMul(b *testing.B) {
}
}
-func toString(x nat, charset string) string {
- base := len(charset)
-
- // special cases
- switch {
- case base < 2:
- panic("illegal base")
- case len(x) == 0:
- return string(charset[0])
- }
-
- // allocate buffer for conversion
- i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
- s := make([]byte, i)
-
- // don't destroy x
- q := nat(nil).set(x)
-
- // convert
- for len(q) > 0 {
- i--
- var r Word
- q, r = q.divW(q, Word(base))
- s[i] = charset[r]
- }
-
- return string(s[i:])
-}
-
-var strTests = []struct {
- x nat // nat value to be converted
- c string // conversion charset
- s string // expected result
-}{
- {nil, "01", "0"},
- {nat{1}, "01", "1"},
- {nat{0xc5}, "01", "11000101"},
- {nat{03271}, lowercaseDigits[0:8], "3271"},
- {nat{10}, lowercaseDigits[0:10], "10"},
- {nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
- {nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
- {nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
- {nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
- {nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
-}
-
-func TestString(t *testing.T) {
- for _, a := range strTests {
- s := a.x.string(a.c)
- if s != a.s {
- t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
- }
-
- x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c))
- if x.cmp(a.x) != 0 {
- t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
- }
- if b != len(a.c) {
- t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
- }
- if err != nil {
- t.Errorf("scan%+v\n\tgot error = %s", a, err)
- }
- }
-}
-
-var natScanTests = []struct {
- s string // string to be scanned
- base int // input base
- x nat // expected nat
- b int // expected base
- ok bool // expected success
- next rune // next character (or 0, if at EOF)
-}{
- // error: illegal base
- {base: -1},
- {base: 1},
- {base: 37},
-
- // error: no mantissa
- {},
- {s: "?"},
- {base: 10},
- {base: 36},
- {s: "?", base: 10},
- {s: "0x"},
- {s: "345", base: 2},
-
- // no errors
- {"0", 0, nil, 10, true, 0},
- {"0", 10, nil, 10, true, 0},
- {"0", 36, nil, 36, true, 0},
- {"1", 0, nat{1}, 10, true, 0},
- {"1", 10, nat{1}, 10, true, 0},
- {"0 ", 0, nil, 10, true, ' '},
- {"08", 0, nil, 10, true, '8'},
- {"018", 0, nat{1}, 8, true, '8'},
- {"0b1", 0, nat{1}, 2, true, 0},
- {"0b11000101", 0, nat{0xc5}, 2, true, 0},
- {"03271", 0, nat{03271}, 8, true, 0},
- {"10ab", 0, nat{10}, 10, true, 'a'},
- {"1234567890", 0, nat{1234567890}, 10, true, 0},
- {"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0},
- {"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'},
- {"0x", 16, nil, 16, true, 'x'},
- {"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0},
- {"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0},
-}
-
-func TestScanBase(t *testing.T) {
- for _, a := range natScanTests {
- r := strings.NewReader(a.s)
- x, b, err := nat(nil).scan(r, a.base)
- if err == nil && !a.ok {
- t.Errorf("scan%+v\n\texpected error", a)
- }
- if err != nil {
- if a.ok {
- t.Errorf("scan%+v\n\tgot error = %s", a, err)
- }
- continue
- }
- if x.cmp(a.x) != 0 {
- t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
- }
- if b != a.b {
- t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
- }
- next, _, err := r.ReadRune()
- if err == io.EOF {
- next = 0
- err = nil
- }
- if err == nil && next != a.next {
- t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
- }
- }
-}
-
-var pi = "3" +
- "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
- "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
- "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
- "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
- "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
- "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
- "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
- "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
- "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
- "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
- "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
- "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
- "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
- "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
- "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
- "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
- "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
- "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
- "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
- "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
- "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
- "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
- "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
- "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
- "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
- "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
- "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
- "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
- "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
- "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
- "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
- "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
- "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
- "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
- "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
- "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
- "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
- "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
- "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
- "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
- "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
- "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
- "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
- "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
- "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
- "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
- "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
- "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
- "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
- "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
- "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
-
-// Test case for BenchmarkScanPi.
-func TestScanPi(t *testing.T) {
- var x nat
- z, _, err := x.scan(strings.NewReader(pi), 10)
- if err != nil {
- t.Errorf("scanning pi: %s", err)
- }
- if s := z.decimalString(); s != pi {
- t.Errorf("scanning pi: got %s", s)
- }
-}
-
-func TestScanPiParallel(t *testing.T) {
- const n = 2
- c := make(chan int)
- for i := 0; i < n; i++ {
- go func() {
- TestScanPi(t)
- c <- 0
- }()
- }
- for i := 0; i < n; i++ {
- <-c
- }
-}
-
-func BenchmarkScanPi(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var x nat
- x.scan(strings.NewReader(pi), 10)
- }
-}
-
-func BenchmarkStringPiParallel(b *testing.B) {
- var x nat
- x, _, _ = x.scan(strings.NewReader(pi), 0)
- if x.decimalString() != pi {
- panic("benchmark incorrect: conversion failed")
- }
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- x.decimalString()
- }
- })
-}
-
-func BenchmarkScan10Base2(b *testing.B) { ScanHelper(b, 2, 10, 10) }
-func BenchmarkScan100Base2(b *testing.B) { ScanHelper(b, 2, 10, 100) }
-func BenchmarkScan1000Base2(b *testing.B) { ScanHelper(b, 2, 10, 1000) }
-func BenchmarkScan10000Base2(b *testing.B) { ScanHelper(b, 2, 10, 10000) }
-func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
-
-func BenchmarkScan10Base8(b *testing.B) { ScanHelper(b, 8, 10, 10) }
-func BenchmarkScan100Base8(b *testing.B) { ScanHelper(b, 8, 10, 100) }
-func BenchmarkScan1000Base8(b *testing.B) { ScanHelper(b, 8, 10, 1000) }
-func BenchmarkScan10000Base8(b *testing.B) { ScanHelper(b, 8, 10, 10000) }
-func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
-
-func BenchmarkScan10Base10(b *testing.B) { ScanHelper(b, 10, 10, 10) }
-func BenchmarkScan100Base10(b *testing.B) { ScanHelper(b, 10, 10, 100) }
-func BenchmarkScan1000Base10(b *testing.B) { ScanHelper(b, 10, 10, 1000) }
-func BenchmarkScan10000Base10(b *testing.B) { ScanHelper(b, 10, 10, 10000) }
-func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
-
-func BenchmarkScan10Base16(b *testing.B) { ScanHelper(b, 16, 10, 10) }
-func BenchmarkScan100Base16(b *testing.B) { ScanHelper(b, 16, 10, 100) }
-func BenchmarkScan1000Base16(b *testing.B) { ScanHelper(b, 16, 10, 1000) }
-func BenchmarkScan10000Base16(b *testing.B) { ScanHelper(b, 16, 10, 10000) }
-func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
-
-func ScanHelper(b *testing.B, base int, x, y Word) {
- b.StopTimer()
- var z nat
- z = z.expWW(x, y)
-
- var s string
- s = z.string(lowercaseDigits[0:base])
- if t := toString(z, lowercaseDigits[0:base]); t != s {
- b.Fatalf("scanning: got %s; want %s", s, t)
- }
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- z.scan(strings.NewReader(s), base)
- }
-}
-
-func BenchmarkString10Base2(b *testing.B) { StringHelper(b, 2, 10, 10) }
-func BenchmarkString100Base2(b *testing.B) { StringHelper(b, 2, 10, 100) }
-func BenchmarkString1000Base2(b *testing.B) { StringHelper(b, 2, 10, 1000) }
-func BenchmarkString10000Base2(b *testing.B) { StringHelper(b, 2, 10, 10000) }
-func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
-
-func BenchmarkString10Base8(b *testing.B) { StringHelper(b, 8, 10, 10) }
-func BenchmarkString100Base8(b *testing.B) { StringHelper(b, 8, 10, 100) }
-func BenchmarkString1000Base8(b *testing.B) { StringHelper(b, 8, 10, 1000) }
-func BenchmarkString10000Base8(b *testing.B) { StringHelper(b, 8, 10, 10000) }
-func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
-
-func BenchmarkString10Base10(b *testing.B) { StringHelper(b, 10, 10, 10) }
-func BenchmarkString100Base10(b *testing.B) { StringHelper(b, 10, 10, 100) }
-func BenchmarkString1000Base10(b *testing.B) { StringHelper(b, 10, 10, 1000) }
-func BenchmarkString10000Base10(b *testing.B) { StringHelper(b, 10, 10, 10000) }
-func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
-
-func BenchmarkString10Base16(b *testing.B) { StringHelper(b, 16, 10, 10) }
-func BenchmarkString100Base16(b *testing.B) { StringHelper(b, 16, 10, 100) }
-func BenchmarkString1000Base16(b *testing.B) { StringHelper(b, 16, 10, 1000) }
-func BenchmarkString10000Base16(b *testing.B) { StringHelper(b, 16, 10, 10000) }
-func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
-
-func StringHelper(b *testing.B, base int, x, y Word) {
- b.StopTimer()
- var z nat
- z = z.expWW(x, y)
- z.string(lowercaseDigits[0:base]) // warm divisor cache
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- _ = z.string(lowercaseDigits[0:base])
- }
-}
-
-func BenchmarkLeafSize0(b *testing.B) { LeafSizeHelper(b, 10, 0) } // test without splitting
-func BenchmarkLeafSize1(b *testing.B) { LeafSizeHelper(b, 10, 1) }
-func BenchmarkLeafSize2(b *testing.B) { LeafSizeHelper(b, 10, 2) }
-func BenchmarkLeafSize3(b *testing.B) { LeafSizeHelper(b, 10, 3) }
-func BenchmarkLeafSize4(b *testing.B) { LeafSizeHelper(b, 10, 4) }
-func BenchmarkLeafSize5(b *testing.B) { LeafSizeHelper(b, 10, 5) }
-func BenchmarkLeafSize6(b *testing.B) { LeafSizeHelper(b, 10, 6) }
-func BenchmarkLeafSize7(b *testing.B) { LeafSizeHelper(b, 10, 7) }
-func BenchmarkLeafSize8(b *testing.B) { LeafSizeHelper(b, 10, 8) }
-func BenchmarkLeafSize9(b *testing.B) { LeafSizeHelper(b, 10, 9) }
-func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
-func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
-func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
-func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
-func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
-func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
-func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
-func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
-func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
-
-func LeafSizeHelper(b *testing.B, base Word, size int) {
- b.StopTimer()
- originalLeafSize := leafSize
- resetTable(cacheBase10.table[:])
- leafSize = size
- b.StartTimer()
-
- for d := 1; d <= 10000; d *= 10 {
- b.StopTimer()
- var z nat
- z = z.expWW(base, Word(d)) // build target number
- _ = z.string(lowercaseDigits[0:base]) // warm divisor cache
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- _ = z.string(lowercaseDigits[0:base])
- }
- }
-
- b.StopTimer()
- resetTable(cacheBase10.table[:])
- leafSize = originalLeafSize
- b.StartTimer()
-}
-
-func resetTable(table []divisor) {
- if table != nil && table[0].bbb != nil {
- for i := 0; i < len(table); i++ {
- table[i].bbb = nil
- table[i].nbits = 0
- table[i].ndigits = 0
- }
- }
-}
-
-func TestStringPowers(t *testing.T) {
- var b, p Word
- for b = 2; b <= 16; b++ {
- for p = 0; p <= 512; p++ {
- x := nat(nil).expWW(b, p)
- xs := x.string(lowercaseDigits[0:b])
- xs2 := toString(x, lowercaseDigits[0:b])
- if xs != xs2 {
- t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
- }
- }
- if b >= 3 && testing.Short() {
- break
- }
- }
-}
-
-func TestLeadingZeros(t *testing.T) {
+func TestNLZ(t *testing.T) {
var x Word = _B >> 1
for i := 0; i <= _W; i++ {
- if int(leadingZeros(x)) != i {
- t.Errorf("failed at %x: got %d want %d", x, leadingZeros(x), i)
+ if int(nlz(x)) != i {
+ t.Errorf("failed at %x: got %d want %d", x, nlz(x), i)
}
x >>= 1
}
@@ -691,25 +303,96 @@ func TestModW(t *testing.T) {
}
func TestTrailingZeroBits(t *testing.T) {
+ // test 0 case explicitly
+ if n := trailingZeroBits(0); n != 0 {
+ t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
+ }
+
x := Word(1)
- for i := uint(0); i <= _W; i++ {
+ for i := uint(0); i < _W; i++ {
n := trailingZeroBits(x)
- if n != i%_W {
+ if n != i {
t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
}
x <<= 1
}
+ // test 0 case explicitly
+ if n := nat(nil).trailingZeroBits(); n != 0 {
+ t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
+ }
+
y := nat(nil).set(natOne)
for i := uint(0); i <= 3*_W; i++ {
n := y.trailingZeroBits()
if n != i {
- t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.string(lowercaseDigits[0:16]), n, i)
+ t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
}
y = y.shl(y, 1)
}
}
+var montgomeryTests = []struct {
+ x, y, m string
+ k0 uint64
+ out32, out64 string
+}{
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffff",
+ 0x0000000000000000,
+ "0xffffffffffffffffffffffffffffffffffffffffff",
+ "0xffffffffffffffffffffffffffffffffff",
+ },
+ {
+ "0x0000000080000000",
+ "0x00000000ffffffff",
+ "0x0000000010000001",
+ 0xff0000000fffffff,
+ "0x0000000088000000",
+ "0x0000000007800001",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
+ "0xffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+ "0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
+ 0xdecc8f1249812adf,
+ "0x22bb05b6d95eaaeca2bb7c05e51f807bce9064b5fbad177161695e4558f9474e91cd79",
+ "0x14beb58d230f85b6d95eaaeca2bb7c05e51f807bce9064b5fb45669afa695f228e48cd",
+ },
+ {
+ "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
+ "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
+ 0xdecc8f1249812adf,
+ "0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715",
+ "0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6",
+ },
+}
+
+func TestMontgomery(t *testing.T) {
+ for i, test := range montgomeryTests {
+ x := natFromString(test.x)
+ y := natFromString(test.y)
+ m := natFromString(test.m)
+
+ var out nat
+ if _W == 32 {
+ out = natFromString(test.out32)
+ } else {
+ out = natFromString(test.out64)
+ }
+
+ k0 := Word(test.k0 & _M) // mask k0 to ensure that it fits for 32-bit systems.
+ z := nat(nil).montgomery(x, y, m, k0, len(m))
+ z = z.norm()
+ if z.cmp(out) != 0 {
+ t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+ }
+ }
+}
+
var expNNTests = []struct {
x, y, m string
out string
@@ -735,14 +418,13 @@ var expNNTests = []struct {
func TestExpNN(t *testing.T) {
for i, test := range expNNTests {
- x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0)
- y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0)
- out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0)
+ x := natFromString(test.x)
+ y := natFromString(test.y)
+ out := natFromString(test.out)
var m nat
-
if len(test.m) > 0 {
- m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
+ m = natFromString(test.m)
}
z := nat(nil).expNN(x, y, m)
@@ -769,3 +451,129 @@ func BenchmarkExp3Power0x10000(b *testing.B) { ExpHelper(b, 3, 0x10000) }
func BenchmarkExp3Power0x40000(b *testing.B) { ExpHelper(b, 3, 0x40000) }
func BenchmarkExp3Power0x100000(b *testing.B) { ExpHelper(b, 3, 0x100000) }
func BenchmarkExp3Power0x400000(b *testing.B) { ExpHelper(b, 3, 0x400000) }
+
+func fibo(n int) nat {
+ switch n {
+ case 0:
+ return nil
+ case 1:
+ return nat{1}
+ }
+ f0 := fibo(0)
+ f1 := fibo(1)
+ var f2 nat
+ for i := 1; i < n; i++ {
+ f2 = f2.add(f0, f1)
+ f0, f1, f2 = f1, f2, f0
+ }
+ return f1
+}
+
+var fiboNums = []string{
+ "0",
+ "55",
+ "6765",
+ "832040",
+ "102334155",
+ "12586269025",
+ "1548008755920",
+ "190392490709135",
+ "23416728348467685",
+ "2880067194370816120",
+ "354224848179261915075",
+}
+
+func TestFibo(t *testing.T) {
+ for i, want := range fiboNums {
+ n := i * 10
+ got := fibo(n).decimalString()
+ if got != want {
+ t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
+ }
+ }
+}
+
+func BenchmarkFibo(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ fibo(1e0)
+ fibo(1e1)
+ fibo(1e2)
+ fibo(1e3)
+ fibo(1e4)
+ fibo(1e5)
+ }
+}
+
+var bitTests = []struct {
+ x string
+ i uint
+ want uint
+}{
+ {"0", 0, 0},
+ {"0", 1, 0},
+ {"0", 1000, 0},
+
+ {"0x1", 0, 1},
+ {"0x10", 0, 0},
+ {"0x10", 3, 0},
+ {"0x10", 4, 1},
+ {"0x10", 5, 0},
+
+ {"0x8000000000000000", 62, 0},
+ {"0x8000000000000000", 63, 1},
+ {"0x8000000000000000", 64, 0},
+
+ {"0x3" + strings.Repeat("0", 32), 127, 0},
+ {"0x3" + strings.Repeat("0", 32), 128, 1},
+ {"0x3" + strings.Repeat("0", 32), 129, 1},
+ {"0x3" + strings.Repeat("0", 32), 130, 0},
+}
+
+func TestBit(t *testing.T) {
+ for i, test := range bitTests {
+ x := natFromString(test.x)
+ if got := x.bit(test.i); got != test.want {
+ t.Errorf("#%d: %s.bit(%d) = %v; want %v", i, test.x, test.i, got, test.want)
+ }
+ }
+}
+
+var stickyTests = []struct {
+ x string
+ i uint
+ want uint
+}{
+ {"0", 0, 0},
+ {"0", 1, 0},
+ {"0", 1000, 0},
+
+ {"0x1", 0, 0},
+ {"0x1", 1, 1},
+
+ {"0x1350", 0, 0},
+ {"0x1350", 4, 0},
+ {"0x1350", 5, 1},
+
+ {"0x8000000000000000", 63, 0},
+ {"0x8000000000000000", 64, 1},
+
+ {"0x1" + strings.Repeat("0", 100), 400, 0},
+ {"0x1" + strings.Repeat("0", 100), 401, 1},
+}
+
+func TestSticky(t *testing.T) {
+ for i, test := range stickyTests {
+ x := natFromString(test.x)
+ if got := x.sticky(test.i); got != test.want {
+ t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i, got, test.want)
+ }
+ if test.want == 1 {
+ // all subsequent i's should also return 1
+ for d := uint(1); d <= 3; d++ {
+ if got := x.sticky(test.i + d); got != 1 {
+ t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i+d, got, 1)
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/math/big/natconv.go b/libgo/go/math/big/natconv.go
new file mode 100644
index 00000000000..022dcfe38c8
--- /dev/null
+++ b/libgo/go/math/big/natconv.go
@@ -0,0 +1,495 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements nat-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "sync"
+)
+
+// MaxBase is the largest number base accepted for string conversions.
+const MaxBase = 'z' - 'a' + 10 + 1
+
+// maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
+// For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
+// In other words, at most n digits in base b fit into a Word.
+// TODO(gri) replace this with a table, generated at build time.
+func maxPow(b Word) (p Word, n int) {
+ p, n = b, 1 // assuming b <= _M
+ for max := _M / b; p <= max; {
+ // p == b**n && p <= max
+ p *= b
+ n++
+ }
+ // p == b**n && p <= _M
+ return
+}
+
+// pow returns x**n for n > 0, and 1 otherwise.
+func pow(x Word, n int) (p Word) {
+ // n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
+ // thus x**n == product of x**(2**i) for all i where bi == 1
+ // (Russian Peasant Method for exponentiation)
+ p = 1
+ for n > 0 {
+ if n&1 != 0 {
+ p *= x
+ }
+ x *= x
+ n >>= 1
+ }
+ return
+}
+
+// scan scans the number corresponding to the longest possible prefix
+// from r representing an unsigned number in a given conversion base.
+// It returns the corresponding natural number res, the actual base b,
+// a digit count, and a read or syntax error err, if any.
+//
+// number = [ prefix ] mantissa .
+// prefix = "0" [ "x" | "X" | "b" | "B" ] .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// digits = digit { digit } .
+// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+//
+// Unless fracOk is set, the base argument must be 0 or a value between
+// 2 and MaxBase. If fracOk is set, the base argument must be one of
+// 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
+// time panic.
+//
+// For base 0, the number prefix determines the actual base: A prefix of
+// ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
+// selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
+// the selected base is 10 and no prefix is accepted.
+//
+// If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
+// stands for a zero digit), and a period followed by a fractional part
+// is permitted. The result value is computed as if there were no period
+// present; and the count value is used to determine the fractional part.
+//
+// A result digit count > 0 corresponds to the number of (non-prefix) digits
+// parsed. A digit count <= 0 indicates the presence of a period (if fracOk
+// is set, only), and -count is the number of fractional digits found.
+// In this case, the actual value of the scanned number is res * b**count.
+//
+func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count int, err error) {
+ // reject illegal bases
+ baseOk := base == 0 ||
+ !fracOk && 2 <= base && base <= MaxBase ||
+ fracOk && (base == 2 || base == 10 || base == 16)
+ if !baseOk {
+ panic(fmt.Sprintf("illegal number base %d", base))
+ }
+
+ // one char look-ahead
+ ch, err := r.ReadByte()
+ if err != nil {
+ return
+ }
+
+ // determine actual base
+ b = base
+ if base == 0 {
+ // actual base is 10 unless there's a base prefix
+ b = 10
+ if ch == '0' {
+ count = 1
+ switch ch, err = r.ReadByte(); err {
+ case nil:
+ // possibly one of 0x, 0X, 0b, 0B
+ if !fracOk {
+ b = 8
+ }
+ switch ch {
+ case 'x', 'X':
+ b = 16
+ case 'b', 'B':
+ b = 2
+ }
+ switch b {
+ case 16, 2:
+ count = 0 // prefix is not counted
+ if ch, err = r.ReadByte(); err != nil {
+ // io.EOF is also an error in this case
+ return
+ }
+ case 8:
+ count = 0 // prefix is not counted
+ }
+ case io.EOF:
+ // input is "0"
+ res = z[:0]
+ err = nil
+ return
+ default:
+ // read error
+ return
+ }
+ }
+ }
+
+ // convert string
+ // Algorithm: Collect digits in groups of at most n digits in di
+ // and then use mulAddWW for every such group to add them to the
+ // result.
+ z = z[:0]
+ b1 := Word(b)
+ bn, n := maxPow(b1) // at most n digits in base b1 fit into Word
+ di := Word(0) // 0 <= di < b1**i < bn
+ i := 0 // 0 <= i < n
+ dp := -1 // position of decimal point
+ for {
+ if fracOk && ch == '.' {
+ fracOk = false
+ dp = count
+ // advance
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil
+ break
+ }
+ return
+ }
+ }
+
+ // convert rune into digit value d1
+ var d1 Word
+ switch {
+ case '0' <= ch && ch <= '9':
+ d1 = Word(ch - '0')
+ case 'a' <= ch && ch <= 'z':
+ d1 = Word(ch - 'a' + 10)
+ case 'A' <= ch && ch <= 'Z':
+ d1 = Word(ch - 'A' + 10)
+ default:
+ d1 = MaxBase + 1
+ }
+ if d1 >= b1 {
+ r.UnreadByte() // ch does not belong to number anymore
+ break
+ }
+ count++
+
+ // collect d1 in di
+ di = di*b1 + d1
+ i++
+
+ // if di is "full", add it to the result
+ if i == n {
+ z = z.mulAddWW(z, bn, di)
+ di = 0
+ i = 0
+ }
+
+ // advance
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil
+ break
+ }
+ return
+ }
+ }
+
+ if count == 0 {
+ // no digits found
+ switch {
+ case base == 0 && b == 8:
+ // there was only the octal prefix 0 (possibly followed by digits > 7);
+ // count as one digit and return base 10, not 8
+ count = 1
+ b = 10
+ case base != 0 || b != 8:
+ // there was neither a mantissa digit nor the octal prefix 0
+ err = errors.New("syntax error scanning number")
+ }
+ return
+ }
+ // count > 0
+
+ // add remaining digits to result
+ if i > 0 {
+ z = z.mulAddWW(z, pow(b1, i), di)
+ }
+ res = z.norm()
+
+ // adjust for fraction, if any
+ if dp >= 0 {
+ // 0 <= dp <= count > 0
+ count = dp - count
+ }
+
+ return
+}
+
+// Character sets for string conversion.
+const (
+ lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
+ uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+)
+
+// decimalString returns a decimal representation of x.
+// It calls x.string with the charset "0123456789".
+func (x nat) decimalString() string {
+ return x.string(lowercaseDigits[:10])
+}
+
+// hexString returns a hexadecimal representation of x.
+// It calls x.string with the charset "0123456789abcdef".
+func (x nat) hexString() string {
+ return x.string(lowercaseDigits[:16])
+}
+
+// string converts x to a string using digits from a charset; a digit with
+// value d is represented by charset[d]. The conversion base is determined
+// by len(charset), which must be >= 2 and <= 256.
+func (x nat) string(charset string) string {
+ b := Word(len(charset))
+
+ // special cases
+ switch {
+ case b < 2 || b > 256:
+ panic("invalid character set length")
+ case len(x) == 0:
+ return string(charset[0])
+ }
+
+ // allocate buffer for conversion
+ i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+ s := make([]byte, i)
+
+ // convert power of two and non power of two bases separately
+ if b == b&-b {
+ // shift is base-b digit size in bits
+ shift := trailingZeroBits(b) // shift > 0 because b >= 2
+ mask := Word(1)<<shift - 1
+ w := x[0]
+ nbits := uint(_W) // number of unprocessed bits in w
+
+ // convert less-significant words
+ for k := 1; k < len(x); k++ {
+ // convert full digits
+ for nbits >= shift {
+ i--
+ s[i] = charset[w&mask]
+ w >>= shift
+ nbits -= shift
+ }
+
+ // convert any partial leading digit and advance to next word
+ if nbits == 0 {
+ // no partial digit remaining, just advance
+ w = x[k]
+ nbits = _W
+ } else {
+ // partial digit in current (k-1) and next (k) word
+ w |= x[k] << nbits
+ i--
+ s[i] = charset[w&mask]
+
+ // advance
+ w = x[k] >> (shift - nbits)
+ nbits = _W - (shift - nbits)
+ }
+ }
+
+ // convert digits of most-significant word (omit leading zeros)
+ for nbits >= 0 && w != 0 {
+ i--
+ s[i] = charset[w&mask]
+ w >>= shift
+ nbits -= shift
+ }
+
+ } else {
+ bb, ndigits := maxPow(Word(b))
+
+ // construct table of successive squares of bb*leafSize to use in subdivisions
+ // result (table != nil) <=> (len(x) > leafSize > 0)
+ table := divisors(len(x), b, ndigits, bb)
+
+ // preserve x, create local copy for use by convertWords
+ q := nat(nil).set(x)
+
+ // convert q to string s in base b
+ q.convertWords(s, charset, b, ndigits, bb, table)
+
+ // strip leading zeros
+ // (x != 0; thus s must contain at least one non-zero digit
+ // and the loop will terminate)
+ i = 0
+ for zero := charset[0]; s[i] == zero; {
+ i++
+ }
+ }
+
+ return string(s[i:])
+}
+
+// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
+// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
+// repeated nat/Word division.
+//
+// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
+// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
+// Recursive conversion divides q by its approximate square root, yielding two parts, each half
+// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
+// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
+// is made better by splitting the subblocks recursively. Best is to split blocks until one more
+// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
+// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
+// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
+// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
+// specific hardware.
+//
+func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+ // split larger blocks recursively
+ if table != nil {
+ // len(q) > leafSize > 0
+ var r nat
+ index := len(table) - 1
+ for len(q) > leafSize {
+ // find divisor close to sqrt(q) if possible, but in any case < q
+ maxLength := q.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
+ minLength := maxLength >> 1 // ~= log2 sqrt(q)
+ for index > 0 && table[index-1].nbits > minLength {
+ index-- // desired
+ }
+ if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
+ index--
+ if index < 0 {
+ panic("internal inconsistency")
+ }
+ }
+
+ // split q into the two digit number (q'*bbb + r) to form independent subblocks
+ q, r = q.div(r, q, table[index].bbb)
+
+ // convert subblocks and collect results in s[:h] and s[h:]
+ h := len(s) - table[index].ndigits
+ r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
+ s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+ }
+ }
+
+ // having split any large blocks now process the remaining (small) block iteratively
+ i := len(s)
+ var r Word
+ if b == 10 {
+ // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
+ for len(q) > 0 {
+ // extract least significant, base bb "digit"
+ q, r = q.divW(q, bb)
+ for j := 0; j < ndigits && i > 0; j++ {
+ i--
+ // avoid % computation since r%10 == r - int(r/10)*10;
+ // this appears to be faster for BenchmarkString10000Base10
+ // and smaller strings (but a bit slower for larger ones)
+ t := r / 10
+ s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+ r = t
+ }
+ }
+ } else {
+ for len(q) > 0 {
+ // extract least significant, base bb "digit"
+ q, r = q.divW(q, bb)
+ for j := 0; j < ndigits && i > 0; j++ {
+ i--
+ s[i] = charset[r%b]
+ r /= b
+ }
+ }
+ }
+
+ // prepend high-order zeroes
+ zero := charset[0]
+ for i > 0 { // while need more leading zeroes
+ i--
+ s[i] = zero
+ }
+}
+
+// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
+// Benchmark and configure leafSize using: go test -bench="Leaf"
+// 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
+// 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
+var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
+
+type divisor struct {
+ bbb nat // divisor
+ nbits int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+ ndigits int // digit length of divisor in terms of output base digits
+}
+
+var cacheBase10 struct {
+ sync.Mutex
+ table [64]divisor // cached divisors for base 10
+}
+
+// expWW computes x**y
+func (z nat) expWW(x, y Word) nat {
+ return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
+}
+
+// construct table of powers of bb*leafSize to use in subdivisions
+func divisors(m int, b Word, ndigits int, bb Word) []divisor {
+ // only compute table when recursive conversion is enabled and x is large
+ if leafSize == 0 || m <= leafSize {
+ return nil
+ }
+
+ // determine k where (bb**leafSize)**(2**k) >= sqrt(x)
+ k := 1
+ for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
+ k++
+ }
+
+ // reuse and extend existing table of divisors or create new table as appropriate
+ var table []divisor // for b == 10, table overlaps with cacheBase10.table
+ if b == 10 {
+ cacheBase10.Lock()
+ table = cacheBase10.table[0:k] // reuse old table for this conversion
+ } else {
+ table = make([]divisor, k) // create new table for this conversion
+ }
+
+ // extend table
+ if table[k-1].ndigits == 0 {
+ // add new entries as needed
+ var larger nat
+ for i := 0; i < k; i++ {
+ if table[i].ndigits == 0 {
+ if i == 0 {
+ table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
+ table[0].ndigits = ndigits * leafSize
+ } else {
+ table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
+ table[i].ndigits = 2 * table[i-1].ndigits
+ }
+
+ // optimization: exploit aggregated extra bits in macro blocks
+ larger = nat(nil).set(table[i].bbb)
+ for mulAddVWW(larger, larger, b, 0) == 0 {
+ table[i].bbb = table[i].bbb.set(larger)
+ table[i].ndigits++
+ }
+
+ table[i].nbits = table[i].bbb.bitLen()
+ }
+ }
+ }
+
+ if b == 10 {
+ cacheBase10.Unlock()
+ }
+
+ return table
+}
diff --git a/libgo/go/math/big/natconv_test.go b/libgo/go/math/big/natconv_test.go
new file mode 100644
index 00000000000..f321fbc2df0
--- /dev/null
+++ b/libgo/go/math/big/natconv_test.go
@@ -0,0 +1,425 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "io"
+ "strings"
+ "testing"
+)
+
+func toString(x nat, charset string) string {
+ base := len(charset)
+
+ // special cases
+ switch {
+ case base < 2:
+ panic("illegal base")
+ case len(x) == 0:
+ return string(charset[0])
+ }
+
+ // allocate buffer for conversion
+ i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
+ s := make([]byte, i)
+
+ // don't destroy x
+ q := nat(nil).set(x)
+
+ // convert
+ for len(q) > 0 {
+ i--
+ var r Word
+ q, r = q.divW(q, Word(base))
+ s[i] = charset[r]
+ }
+
+ return string(s[i:])
+}
+
+var strTests = []struct {
+ x nat // nat value to be converted
+ c string // conversion charset
+ s string // expected result
+}{
+ {nil, "01", "0"},
+ {nat{1}, "01", "1"},
+ {nat{0xc5}, "01", "11000101"},
+ {nat{03271}, lowercaseDigits[:8], "3271"},
+ {nat{10}, lowercaseDigits[:10], "10"},
+ {nat{1234567890}, uppercaseDigits[:10], "1234567890"},
+ {nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
+ {nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
+ {nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
+ {nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
+}
+
+func TestString(t *testing.T) {
+ // test invalid character set explicitly
+ var panicStr string
+ func() {
+ defer func() {
+ panicStr = recover().(string)
+ }()
+ natOne.string("0")
+ }()
+ if panicStr != "invalid character set length" {
+ t.Errorf("expected panic for invalid character set")
+ }
+
+ for _, a := range strTests {
+ s := a.x.string(a.c)
+ if s != a.s {
+ t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
+ }
+
+ x, b, _, err := nat(nil).scan(strings.NewReader(a.s), len(a.c), false)
+ if x.cmp(a.x) != 0 {
+ t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+ }
+ if b != len(a.c) {
+ t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+ }
+ if err != nil {
+ t.Errorf("scan%+v\n\tgot error = %s", a, err)
+ }
+ }
+}
+
+var natScanTests = []struct {
+ s string // string to be scanned
+ base int // input base
+ frac bool // fraction ok
+ x nat // expected nat
+ b int // expected base
+ count int // expected digit count
+ ok bool // expected success
+ next rune // next character (or 0, if at EOF)
+}{
+ // error: no mantissa
+ {},
+ {s: "?"},
+ {base: 10},
+ {base: 36},
+ {s: "?", base: 10},
+ {s: "0x"},
+ {s: "345", base: 2},
+
+ // error: incorrect use of decimal point
+ {s: ".0"},
+ {s: ".0", base: 10},
+ {s: ".", base: 0},
+ {s: "0x.0"},
+
+ // no errors
+ {"0", 0, false, nil, 10, 1, true, 0},
+ {"0", 10, false, nil, 10, 1, true, 0},
+ {"0", 36, false, nil, 36, 1, true, 0},
+ {"1", 0, false, nat{1}, 10, 1, true, 0},
+ {"1", 10, false, nat{1}, 10, 1, true, 0},
+ {"0 ", 0, false, nil, 10, 1, true, ' '},
+ {"08", 0, false, nil, 10, 1, true, '8'},
+ {"08", 10, false, nat{8}, 10, 2, true, 0},
+ {"018", 0, false, nat{1}, 8, 1, true, '8'},
+ {"0b1", 0, false, nat{1}, 2, 1, true, 0},
+ {"0b11000101", 0, false, nat{0xc5}, 2, 8, true, 0},
+ {"03271", 0, false, nat{03271}, 8, 4, true, 0},
+ {"10ab", 0, false, nat{10}, 10, 2, true, 'a'},
+ {"1234567890", 0, false, nat{1234567890}, 10, 10, true, 0},
+ {"xyz", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, 0},
+ {"xyz?", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, '?'},
+ {"0x", 16, false, nil, 16, 1, true, 'x'},
+ {"0xdeadbeef", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
+ {"0XDEADBEEF", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
+
+ // no errors, decimal point
+ {"0.", 0, false, nil, 10, 1, true, '.'},
+ {"0.", 10, true, nil, 10, 0, true, 0},
+ {"0.1.2", 10, true, nat{1}, 10, -1, true, '.'},
+ {".000", 10, true, nil, 10, -3, true, 0},
+ {"12.3", 10, true, nat{123}, 10, -1, true, 0},
+ {"012.345", 10, true, nat{12345}, 10, -3, true, 0},
+}
+
+func TestScanBase(t *testing.T) {
+ for _, a := range natScanTests {
+ r := strings.NewReader(a.s)
+ x, b, count, err := nat(nil).scan(r, a.base, a.frac)
+ if err == nil && !a.ok {
+ t.Errorf("scan%+v\n\texpected error", a)
+ }
+ if err != nil {
+ if a.ok {
+ t.Errorf("scan%+v\n\tgot error = %s", a, err)
+ }
+ continue
+ }
+ if x.cmp(a.x) != 0 {
+ t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+ }
+ if b != a.b {
+ t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
+ }
+ if count != a.count {
+ t.Errorf("scan%+v\n\tgot count = %d; want %d", a, count, a.count)
+ }
+ next, _, err := r.ReadRune()
+ if err == io.EOF {
+ next = 0
+ err = nil
+ }
+ if err == nil && next != a.next {
+ t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
+ }
+ }
+}
+
+var pi = "3" +
+ "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
+ "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
+ "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
+ "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
+ "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
+ "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
+ "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
+ "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
+ "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
+ "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
+ "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
+ "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
+ "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
+ "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
+ "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
+ "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
+ "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
+ "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
+ "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
+ "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
+ "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
+ "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
+ "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
+ "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
+ "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
+ "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
+ "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
+ "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
+ "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
+ "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
+ "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
+ "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
+ "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
+ "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
+ "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
+ "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
+ "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
+ "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
+ "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
+ "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
+ "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
+ "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
+ "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
+ "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
+ "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
+ "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
+ "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
+ "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
+ "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
+ "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
+ "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
+
+// Test case for BenchmarkScanPi.
+func TestScanPi(t *testing.T) {
+ var x nat
+ z, _, _, err := x.scan(strings.NewReader(pi), 10, false)
+ if err != nil {
+ t.Errorf("scanning pi: %s", err)
+ }
+ if s := z.decimalString(); s != pi {
+ t.Errorf("scanning pi: got %s", s)
+ }
+}
+
+func TestScanPiParallel(t *testing.T) {
+ const n = 2
+ c := make(chan int)
+ for i := 0; i < n; i++ {
+ go func() {
+ TestScanPi(t)
+ c <- 0
+ }()
+ }
+ for i := 0; i < n; i++ {
+ <-c
+ }
+}
+
+func BenchmarkScanPi(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x nat
+ x.scan(strings.NewReader(pi), 10, false)
+ }
+}
+
+func BenchmarkStringPiParallel(b *testing.B) {
+ var x nat
+ x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
+ if x.decimalString() != pi {
+ panic("benchmark incorrect: conversion failed")
+ }
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ x.decimalString()
+ }
+ })
+}
+
+func BenchmarkScan10Base2(b *testing.B) { ScanHelper(b, 2, 10, 10) }
+func BenchmarkScan100Base2(b *testing.B) { ScanHelper(b, 2, 10, 100) }
+func BenchmarkScan1000Base2(b *testing.B) { ScanHelper(b, 2, 10, 1000) }
+func BenchmarkScan10000Base2(b *testing.B) { ScanHelper(b, 2, 10, 10000) }
+func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
+
+func BenchmarkScan10Base8(b *testing.B) { ScanHelper(b, 8, 10, 10) }
+func BenchmarkScan100Base8(b *testing.B) { ScanHelper(b, 8, 10, 100) }
+func BenchmarkScan1000Base8(b *testing.B) { ScanHelper(b, 8, 10, 1000) }
+func BenchmarkScan10000Base8(b *testing.B) { ScanHelper(b, 8, 10, 10000) }
+func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
+
+func BenchmarkScan10Base10(b *testing.B) { ScanHelper(b, 10, 10, 10) }
+func BenchmarkScan100Base10(b *testing.B) { ScanHelper(b, 10, 10, 100) }
+func BenchmarkScan1000Base10(b *testing.B) { ScanHelper(b, 10, 10, 1000) }
+func BenchmarkScan10000Base10(b *testing.B) { ScanHelper(b, 10, 10, 10000) }
+func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
+
+func BenchmarkScan10Base16(b *testing.B) { ScanHelper(b, 16, 10, 10) }
+func BenchmarkScan100Base16(b *testing.B) { ScanHelper(b, 16, 10, 100) }
+func BenchmarkScan1000Base16(b *testing.B) { ScanHelper(b, 16, 10, 1000) }
+func BenchmarkScan10000Base16(b *testing.B) { ScanHelper(b, 16, 10, 10000) }
+func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
+
+func ScanHelper(b *testing.B, base int, x, y Word) {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(x, y)
+
+ var s string
+ s = z.string(lowercaseDigits[:base])
+ if t := toString(z, lowercaseDigits[:base]); t != s {
+ b.Fatalf("scanning: got %s; want %s", s, t)
+ }
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ z.scan(strings.NewReader(s), base, false)
+ }
+}
+
+func BenchmarkString10Base2(b *testing.B) { StringHelper(b, 2, 10, 10) }
+func BenchmarkString100Base2(b *testing.B) { StringHelper(b, 2, 10, 100) }
+func BenchmarkString1000Base2(b *testing.B) { StringHelper(b, 2, 10, 1000) }
+func BenchmarkString10000Base2(b *testing.B) { StringHelper(b, 2, 10, 10000) }
+func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
+
+func BenchmarkString10Base8(b *testing.B) { StringHelper(b, 8, 10, 10) }
+func BenchmarkString100Base8(b *testing.B) { StringHelper(b, 8, 10, 100) }
+func BenchmarkString1000Base8(b *testing.B) { StringHelper(b, 8, 10, 1000) }
+func BenchmarkString10000Base8(b *testing.B) { StringHelper(b, 8, 10, 10000) }
+func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
+
+func BenchmarkString10Base10(b *testing.B) { StringHelper(b, 10, 10, 10) }
+func BenchmarkString100Base10(b *testing.B) { StringHelper(b, 10, 10, 100) }
+func BenchmarkString1000Base10(b *testing.B) { StringHelper(b, 10, 10, 1000) }
+func BenchmarkString10000Base10(b *testing.B) { StringHelper(b, 10, 10, 10000) }
+func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
+
+func BenchmarkString10Base16(b *testing.B) { StringHelper(b, 16, 10, 10) }
+func BenchmarkString100Base16(b *testing.B) { StringHelper(b, 16, 10, 100) }
+func BenchmarkString1000Base16(b *testing.B) { StringHelper(b, 16, 10, 1000) }
+func BenchmarkString10000Base16(b *testing.B) { StringHelper(b, 16, 10, 10000) }
+func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
+
+func StringHelper(b *testing.B, base int, x, y Word) {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(x, y)
+ z.string(lowercaseDigits[:base]) // warm divisor cache
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ _ = z.string(lowercaseDigits[:base])
+ }
+}
+
+func BenchmarkLeafSize0(b *testing.B) { LeafSizeHelper(b, 10, 0) } // test without splitting
+func BenchmarkLeafSize1(b *testing.B) { LeafSizeHelper(b, 10, 1) }
+func BenchmarkLeafSize2(b *testing.B) { LeafSizeHelper(b, 10, 2) }
+func BenchmarkLeafSize3(b *testing.B) { LeafSizeHelper(b, 10, 3) }
+func BenchmarkLeafSize4(b *testing.B) { LeafSizeHelper(b, 10, 4) }
+func BenchmarkLeafSize5(b *testing.B) { LeafSizeHelper(b, 10, 5) }
+func BenchmarkLeafSize6(b *testing.B) { LeafSizeHelper(b, 10, 6) }
+func BenchmarkLeafSize7(b *testing.B) { LeafSizeHelper(b, 10, 7) }
+func BenchmarkLeafSize8(b *testing.B) { LeafSizeHelper(b, 10, 8) }
+func BenchmarkLeafSize9(b *testing.B) { LeafSizeHelper(b, 10, 9) }
+func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
+func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
+func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
+func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
+func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
+func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
+func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
+func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
+func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
+
+func LeafSizeHelper(b *testing.B, base Word, size int) {
+ b.StopTimer()
+ originalLeafSize := leafSize
+ resetTable(cacheBase10.table[:])
+ leafSize = size
+ b.StartTimer()
+
+ for d := 1; d <= 10000; d *= 10 {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(base, Word(d)) // build target number
+ _ = z.string(lowercaseDigits[:base]) // warm divisor cache
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ _ = z.string(lowercaseDigits[:base])
+ }
+ }
+
+ b.StopTimer()
+ resetTable(cacheBase10.table[:])
+ leafSize = originalLeafSize
+ b.StartTimer()
+}
+
+func resetTable(table []divisor) {
+ if table != nil && table[0].bbb != nil {
+ for i := 0; i < len(table); i++ {
+ table[i].bbb = nil
+ table[i].nbits = 0
+ table[i].ndigits = 0
+ }
+ }
+}
+
+func TestStringPowers(t *testing.T) {
+ var b, p Word
+ for b = 2; b <= 16; b++ {
+ for p = 0; p <= 512; p++ {
+ x := nat(nil).expWW(b, p)
+ xs := x.string(lowercaseDigits[:b])
+ xs2 := toString(x, lowercaseDigits[:b])
+ if xs != xs2 {
+ t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
+ }
+ }
+ if b >= 3 && testing.Short() {
+ break
+ }
+ }
+}
diff --git a/libgo/go/math/big/rat.go b/libgo/go/math/big/rat.go
index c5339fe4431..fb16f18a964 100644
--- a/libgo/go/math/big/rat.go
+++ b/libgo/go/math/big/rat.go
@@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"math"
- "strings"
)
// A Rat represents a quotient a/b of arbitrary precision.
@@ -324,14 +323,14 @@ func (z *Rat) SetFrac64(a, b int64) *Rat {
// SetInt sets z to x (by making a copy of x) and returns z.
func (z *Rat) SetInt(x *Int) *Rat {
z.a.Set(x)
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
return z
}
// SetInt64 sets z to x and returns z.
func (z *Rat) SetInt64(x int64) *Rat {
z.a.SetInt64(x)
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
return z
}
@@ -370,7 +369,7 @@ func (z *Rat) Inv(x *Rat) *Rat {
}
b := z.a.abs
if b.cmp(natOne) == 0 {
- b = b.make(0) // normalize denominator
+ b = b[:0] // normalize denominator
}
z.a.abs, z.b.abs = a, b // sign doesn't change
return z
@@ -386,7 +385,7 @@ func (x *Rat) Sign() int {
return x.a.Sign()
}
-// IsInt returns true if the denominator of x is 1.
+// IsInt reports whether the denominator of x is 1.
func (x *Rat) IsInt() bool {
return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
}
@@ -415,12 +414,12 @@ func (z *Rat) norm() *Rat {
case len(z.a.abs) == 0:
// z == 0 - normalize sign and denominator
z.a.neg = false
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
case len(z.b.abs) == 0:
// z is normalized int - nothing to do
case z.b.abs.cmp(natOne) == 0:
// z is int - normalize denominator
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
default:
neg := z.a.neg
z.a.neg = false
@@ -430,7 +429,7 @@ func (z *Rat) norm() *Rat {
z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
if z.b.abs.cmp(natOne) == 0 {
// z is int - normalize denominator
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
}
}
z.a.neg = neg
@@ -512,151 +511,6 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
return z.norm()
}
-func ratTok(ch rune) bool {
- return strings.IndexRune("+-/0123456789.eE", ch) >= 0
-}
-
-// Scan is a support routine for fmt.Scanner. It accepts the formats
-// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
-func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
- tok, err := s.Token(true, ratTok)
- if err != nil {
- return err
- }
- if strings.IndexRune("efgEFGv", ch) < 0 {
- return errors.New("Rat.Scan: invalid verb")
- }
- if _, ok := z.SetString(string(tok)); !ok {
- return errors.New("Rat.Scan: invalid syntax")
- }
- return nil
-}
-
-// SetString sets z to the value of s and returns z and a boolean indicating
-// success. s can be given as a fraction "a/b" or as a floating-point number
-// optionally followed by an exponent. If the operation failed, the value of
-// z is undefined but the returned value is nil.
-func (z *Rat) SetString(s string) (*Rat, bool) {
- if len(s) == 0 {
- return nil, false
- }
-
- // check for a quotient
- sep := strings.Index(s, "/")
- if sep >= 0 {
- if _, ok := z.a.SetString(s[0:sep], 10); !ok {
- return nil, false
- }
- s = s[sep+1:]
- var err error
- if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
- return nil, false
- }
- if len(z.b.abs) == 0 {
- return nil, false
- }
- return z.norm(), true
- }
-
- // check for a decimal point
- sep = strings.Index(s, ".")
- // check for an exponent
- e := strings.IndexAny(s, "eE")
- var exp Int
- if e >= 0 {
- if e < sep {
- // The E must come after the decimal point.
- return nil, false
- }
- if _, ok := exp.SetString(s[e+1:], 10); !ok {
- return nil, false
- }
- s = s[0:e]
- }
- if sep >= 0 {
- s = s[0:sep] + s[sep+1:]
- exp.Sub(&exp, NewInt(int64(len(s)-sep)))
- }
-
- if _, ok := z.a.SetString(s, 10); !ok {
- return nil, false
- }
- powTen := nat(nil).expNN(natTen, exp.abs, nil)
- if exp.neg {
- z.b.abs = powTen
- z.norm()
- } else {
- z.a.abs = z.a.abs.mul(z.a.abs, powTen)
- z.b.abs = z.b.abs.make(0)
- }
-
- return z, true
-}
-
-// String returns a string representation of x in the form "a/b" (even if b == 1).
-func (x *Rat) String() string {
- s := "/1"
- if len(x.b.abs) != 0 {
- s = "/" + x.b.abs.decimalString()
- }
- return x.a.String() + s
-}
-
-// RatString returns a string representation of x in the form "a/b" if b != 1,
-// and in the form "a" if b == 1.
-func (x *Rat) RatString() string {
- if x.IsInt() {
- return x.a.String()
- }
- return x.String()
-}
-
-// FloatString returns a string representation of x in decimal form with prec
-// digits of precision after the decimal point and the last digit rounded.
-func (x *Rat) FloatString(prec int) string {
- if x.IsInt() {
- s := x.a.String()
- if prec > 0 {
- s += "." + strings.Repeat("0", prec)
- }
- return s
- }
- // x.b.abs != 0
-
- q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
-
- p := natOne
- if prec > 0 {
- p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
- }
-
- r = r.mul(r, p)
- r, r2 := r.div(nat(nil), r, x.b.abs)
-
- // see if we need to round up
- r2 = r2.add(r2, r2)
- if x.b.abs.cmp(r2) <= 0 {
- r = r.add(r, natOne)
- if r.cmp(p) >= 0 {
- q = nat(nil).add(q, natOne)
- r = nat(nil).sub(r, p)
- }
- }
-
- s := q.decimalString()
- if x.a.neg {
- s = "-" + s
- }
-
- if prec > 0 {
- rs := r.decimalString()
- leadingZeros := prec - len(rs)
- s += "." + strings.Repeat("0", leadingZeros) + rs
- }
-
- return s
-}
-
// Gob codec version. Permits backward-compatible changes to the encoding.
const ratGobVersion byte = 1
@@ -667,7 +521,7 @@ func (x *Rat) GobEncode() ([]byte, error) {
}
buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
i := x.b.abs.bytes(buf)
- j := x.a.abs.bytes(buf[0:i])
+ j := x.a.abs.bytes(buf[:i])
n := i - j
if int(uint32(n)) != n {
// this should never happen
@@ -692,7 +546,7 @@ func (z *Rat) GobDecode(buf []byte) error {
}
b := buf[0]
if b>>1 != ratGobVersion {
- return errors.New(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
+ return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
}
const j = 1 + 4
i := j + binary.BigEndian.Uint32(buf[j-4:j])
diff --git a/libgo/go/math/big/rat_test.go b/libgo/go/math/big/rat_test.go
index 5dbbb3510f0..012d0c47ec4 100644
--- a/libgo/go/math/big/rat_test.go
+++ b/libgo/go/math/big/rat_test.go
@@ -9,10 +9,7 @@ import (
"encoding/gob"
"encoding/json"
"encoding/xml"
- "fmt"
"math"
- "strconv"
- "strings"
"testing"
)
@@ -56,112 +53,6 @@ func TestZeroRat(t *testing.T) {
z.Quo(&x, &y)
}
-var setStringTests = []struct {
- in, out string
- ok bool
-}{
- {"0", "0", true},
- {"-0", "0", true},
- {"1", "1", true},
- {"-1", "-1", true},
- {"1.", "1", true},
- {"1e0", "1", true},
- {"1.e1", "10", true},
- {in: "1e", ok: false},
- {in: "1.e", ok: false},
- {in: "1e+14e-5", ok: false},
- {in: "1e4.5", ok: false},
- {in: "r", ok: false},
- {in: "a/b", ok: false},
- {in: "a.b", ok: false},
- {"-0.1", "-1/10", true},
- {"-.1", "-1/10", true},
- {"2/4", "1/2", true},
- {".25", "1/4", true},
- {"-1/5", "-1/5", true},
- {"8129567.7690E14", "812956776900000000000", true},
- {"78189e+4", "781890000", true},
- {"553019.8935e+8", "55301989350000", true},
- {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
- {"9877861857500000E-7", "3951144743/4", true},
- {"2169378.417e-3", "2169378417/1000000", true},
- {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
- {"53/70893980658822810696", "53/70893980658822810696", true},
- {"106/141787961317645621392", "53/70893980658822810696", true},
- {"204211327800791583.81095", "4084226556015831676219/20000", true},
- {in: "1/0", ok: false},
-}
-
-func TestRatSetString(t *testing.T) {
- for i, test := range setStringTests {
- x, ok := new(Rat).SetString(test.in)
-
- if ok {
- if !test.ok {
- t.Errorf("#%d SetString(%q) expected failure", i, test.in)
- } else if x.RatString() != test.out {
- t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
- }
- } else if x != nil {
- t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
- }
- }
-}
-
-func TestRatScan(t *testing.T) {
- var buf bytes.Buffer
- for i, test := range setStringTests {
- x := new(Rat)
- buf.Reset()
- buf.WriteString(test.in)
-
- _, err := fmt.Fscanf(&buf, "%v", x)
- if err == nil != test.ok {
- if test.ok {
- t.Errorf("#%d error: %s", i, err)
- } else {
- t.Errorf("#%d expected error", i)
- }
- continue
- }
- if err == nil && x.RatString() != test.out {
- t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
- }
- }
-}
-
-var floatStringTests = []struct {
- in string
- prec int
- out string
-}{
- {"0", 0, "0"},
- {"0", 4, "0.0000"},
- {"1", 0, "1"},
- {"1", 2, "1.00"},
- {"-1", 0, "-1"},
- {".25", 2, "0.25"},
- {".25", 1, "0.3"},
- {".25", 3, "0.250"},
- {"-1/3", 3, "-0.333"},
- {"-2/3", 4, "-0.6667"},
- {"0.96", 1, "1.0"},
- {"0.999", 2, "1.00"},
- {"0.9", 0, "1"},
- {".25", -1, "0"},
- {".55", -1, "1"},
-}
-
-func TestFloatString(t *testing.T) {
- for i, test := range floatStringTests {
- x, _ := new(Rat).SetString(test.in)
-
- if x.FloatString(test.prec) != test.out {
- t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
- }
- }
-}
-
func TestRatSign(t *testing.T) {
zero := NewRat(0, 1)
for _, a := range setStringTests {
@@ -592,321 +483,6 @@ func TestIssue3521(t *testing.T) {
}
}
-// Test inputs to Rat.SetString. The prefix "long:" causes the test
-// to be skipped in --test.short mode. (The threshold is about 500us.)
-var float64inputs = []string{
- // Constants plundered from strconv/testfp.txt.
-
- // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
- "5e+125",
- "69e+267",
- "999e-026",
- "7861e-034",
- "75569e-254",
- "928609e-261",
- "9210917e+080",
- "84863171e+114",
- "653777767e+273",
- "5232604057e-298",
- "27235667517e-109",
- "653532977297e-123",
- "3142213164987e-294",
- "46202199371337e-072",
- "231010996856685e-073",
- "9324754620109615e+212",
- "78459735791271921e+049",
- "272104041512242479e+200",
- "6802601037806061975e+198",
- "20505426358836677347e-221",
- "836168422905420598437e-234",
- "4891559871276714924261e+222",
-
- // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
- "9e-265",
- "85e-037",
- "623e+100",
- "3571e+263",
- "81661e+153",
- "920657e-023",
- "4603285e-024",
- "87575437e-309",
- "245540327e+122",
- "6138508175e+120",
- "83356057653e+193",
- "619534293513e+124",
- "2335141086879e+218",
- "36167929443327e-159",
- "609610927149051e-255",
- "3743626360493413e-165",
- "94080055902682397e-242",
- "899810892172646163e+283",
- "7120190517612959703e+120",
- "25188282901709339043e-252",
- "308984926168550152811e-052",
- "6372891218502368041059e+064",
-
- // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
- "5e-20",
- "67e+14",
- "985e+15",
- "7693e-42",
- "55895e-16",
- "996622e-44",
- "7038531e-32",
- "60419369e-46",
- "702990899e-20",
- "6930161142e-48",
- "25933168707e+13",
- "596428896559e+20",
-
- // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
- "3e-23",
- "57e+18",
- "789e-35",
- "2539e-18",
- "76173e+28",
- "887745e-11",
- "5382571e-37",
- "82381273e-35",
- "750486563e-38",
- "3752432815e-39",
- "75224575729e-45",
- "459926601011e+15",
-
- // Constants plundered from strconv/atof_test.go.
-
- "0",
- "1",
- "+1",
- "1e23",
- "1E23",
- "100000000000000000000000",
- "1e-100",
- "123456700",
- "99999999999999974834176",
- "100000000000000000000001",
- "100000000000000008388608",
- "100000000000000016777215",
- "100000000000000016777216",
- "-1",
- "-0.1",
- "-0", // NB: exception made for this input
- "1e-20",
- "625e-3",
-
- // largest float64
- "1.7976931348623157e308",
- "-1.7976931348623157e308",
- // next float64 - too large
- "1.7976931348623159e308",
- "-1.7976931348623159e308",
- // the border is ...158079
- // borderline - okay
- "1.7976931348623158e308",
- "-1.7976931348623158e308",
- // borderline - too large
- "1.797693134862315808e308",
- "-1.797693134862315808e308",
-
- // a little too large
- "1e308",
- "2e308",
- "1e309",
-
- // way too large
- "1e310",
- "-1e310",
- "1e400",
- "-1e400",
- "long:1e400000",
- "long:-1e400000",
-
- // denormalized
- "1e-305",
- "1e-306",
- "1e-307",
- "1e-308",
- "1e-309",
- "1e-310",
- "1e-322",
- // smallest denormal
- "5e-324",
- "4e-324",
- "3e-324",
- // too small
- "2e-324",
- // way too small
- "1e-350",
- "long:1e-400000",
- // way too small, negative
- "-1e-350",
- "long:-1e-400000",
-
- // try to overflow exponent
- // [Disabled: too slow and memory-hungry with rationals.]
- // "1e-4294967296",
- // "1e+4294967296",
- // "1e-18446744073709551616",
- // "1e+18446744073709551616",
-
- // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
- "2.2250738585072012e-308",
- // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
- "2.2250738585072011e-308",
-
- // A very large number (initially wrongly parsed by the fast algorithm).
- "4.630813248087435e+307",
-
- // A different kind of very large number.
- "22.222222222222222",
- "long:2." + strings.Repeat("2", 4000) + "e+1",
-
- // Exactly halfway between 1 and math.Nextafter(1, 2).
- // Round to even (down).
- "1.00000000000000011102230246251565404236316680908203125",
- // Slightly lower; still round down.
- "1.00000000000000011102230246251565404236316680908203124",
- // Slightly higher; round up.
- "1.00000000000000011102230246251565404236316680908203126",
- // Slightly higher, but you have to read all the way to the end.
- "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
-
- // Smallest denormal, 2^(-1022-52)
- "4.940656458412465441765687928682213723651e-324",
- // Half of smallest denormal, 2^(-1022-53)
- "2.470328229206232720882843964341106861825e-324",
- // A little more than the exact half of smallest denormal
- // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
- "2.470328302827751011111470718709768633275e-324",
- // The exact halfway between smallest normal and largest denormal:
- // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
- "2.225073858507201136057409796709131975935e-308",
-
- "1152921504606846975", // 1<<60 - 1
- "-1152921504606846975", // -(1<<60 - 1)
- "1152921504606846977", // 1<<60 + 1
- "-1152921504606846977", // -(1<<60 + 1)
-
- "1/3",
-}
-
-// isFinite reports whether f represents a finite rational value.
-// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
-func isFinite(f float64) bool {
- return math.Abs(f) <= math.MaxFloat64
-}
-
-func TestFloat32SpecialCases(t *testing.T) {
- for _, input := range float64inputs {
- if strings.HasPrefix(input, "long:") {
- if testing.Short() {
- continue
- }
- input = input[len("long:"):]
- }
-
- r, ok := new(Rat).SetString(input)
- if !ok {
- t.Errorf("Rat.SetString(%q) failed", input)
- continue
- }
- f, exact := r.Float32()
-
- // 1. Check string -> Rat -> float32 conversions are
- // consistent with strconv.ParseFloat.
- // Skip this check if the input uses "a/b" rational syntax.
- if !strings.Contains(input, "/") {
- e64, _ := strconv.ParseFloat(input, 32)
- e := float32(e64)
-
- // Careful: negative Rats too small for
- // float64 become -0, but Rat obviously cannot
- // preserve the sign from SetString("-0").
- switch {
- case math.Float32bits(e) == math.Float32bits(f):
- // Ok: bitwise equal.
- case f == 0 && r.Num().BitLen() == 0:
- // Ok: Rat(0) is equivalent to both +/- float64(0).
- default:
- t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
- }
- }
-
- if !isFinite(float64(f)) {
- continue
- }
-
- // 2. Check f is best approximation to r.
- if !checkIsBestApprox32(t, f, r) {
- // Append context information.
- t.Errorf("(input was %q)", input)
- }
-
- // 3. Check f->R->f roundtrip is non-lossy.
- checkNonLossyRoundtrip32(t, f)
-
- // 4. Check exactness using slow algorithm.
- if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
- t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
- }
- }
-}
-
-func TestFloat64SpecialCases(t *testing.T) {
- for _, input := range float64inputs {
- if strings.HasPrefix(input, "long:") {
- if testing.Short() {
- continue
- }
- input = input[len("long:"):]
- }
-
- r, ok := new(Rat).SetString(input)
- if !ok {
- t.Errorf("Rat.SetString(%q) failed", input)
- continue
- }
- f, exact := r.Float64()
-
- // 1. Check string -> Rat -> float64 conversions are
- // consistent with strconv.ParseFloat.
- // Skip this check if the input uses "a/b" rational syntax.
- if !strings.Contains(input, "/") {
- e, _ := strconv.ParseFloat(input, 64)
-
- // Careful: negative Rats too small for
- // float64 become -0, but Rat obviously cannot
- // preserve the sign from SetString("-0").
- switch {
- case math.Float64bits(e) == math.Float64bits(f):
- // Ok: bitwise equal.
- case f == 0 && r.Num().BitLen() == 0:
- // Ok: Rat(0) is equivalent to both +/- float64(0).
- default:
- t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
- }
- }
-
- if !isFinite(f) {
- continue
- }
-
- // 2. Check f is best approximation to r.
- if !checkIsBestApprox64(t, f, r) {
- // Append context information.
- t.Errorf("(input was %q)", input)
- }
-
- // 3. Check f->R->f roundtrip is non-lossy.
- checkNonLossyRoundtrip64(t, f)
-
- // 4. Check exactness using slow algorithm.
- if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
- t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
- }
- }
-}
-
func TestFloat32Distribution(t *testing.T) {
// Generate a distribution of (sign, mantissa, exp) values
// broader than the float32 range, and check Rat.Float32()
diff --git a/libgo/go/math/big/ratconv.go b/libgo/go/math/big/ratconv.go
new file mode 100644
index 00000000000..961ff649a50
--- /dev/null
+++ b/libgo/go/math/big/ratconv.go
@@ -0,0 +1,252 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements rat-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+)
+
+func ratTok(ch rune) bool {
+ return strings.IndexRune("+-/0123456789.eE", ch) >= 0
+}
+
+// Scan is a support routine for fmt.Scanner. It accepts the formats
+// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
+func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+ tok, err := s.Token(true, ratTok)
+ if err != nil {
+ return err
+ }
+ if strings.IndexRune("efgEFGv", ch) < 0 {
+ return errors.New("Rat.Scan: invalid verb")
+ }
+ if _, ok := z.SetString(string(tok)); !ok {
+ return errors.New("Rat.Scan: invalid syntax")
+ }
+ return nil
+}
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s can be given as a fraction "a/b" or as a floating-point number
+// optionally followed by an exponent. If the operation failed, the value of
+// z is undefined but the returned value is nil.
+func (z *Rat) SetString(s string) (*Rat, bool) {
+ if len(s) == 0 {
+ return nil, false
+ }
+ // len(s) > 0
+
+ // parse fraction a/b, if any
+ if sep := strings.Index(s, "/"); sep >= 0 {
+ if _, ok := z.a.SetString(s[:sep], 0); !ok {
+ return nil, false
+ }
+ s = s[sep+1:]
+ var err error
+ if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
+ return nil, false
+ }
+ if len(z.b.abs) == 0 {
+ return nil, false
+ }
+ return z.norm(), true
+ }
+
+ // parse floating-point number
+ r := strings.NewReader(s)
+
+ // sign
+ neg, err := scanSign(r)
+ if err != nil {
+ return nil, false
+ }
+
+ // mantissa
+ var ecorr int
+ z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
+ if err != nil {
+ return nil, false
+ }
+
+ // exponent
+ var exp int64
+ exp, _, err = scanExponent(r, false)
+ if err != nil {
+ return nil, false
+ }
+
+ // there should be no unread characters left
+ if _, err = r.ReadByte(); err != io.EOF {
+ return nil, false
+ }
+
+ // correct exponent
+ if ecorr < 0 {
+ exp += int64(ecorr)
+ }
+
+ // compute exponent power
+ expabs := exp
+ if expabs < 0 {
+ expabs = -expabs
+ }
+ powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
+
+ // complete fraction
+ if exp < 0 {
+ z.b.abs = powTen
+ z.norm()
+ } else {
+ z.a.abs = z.a.abs.mul(z.a.abs, powTen)
+ z.b.abs = z.b.abs[:0]
+ }
+
+ z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
+
+ return z, true
+}
+
+// scanExponent scans the longest possible prefix of r representing a decimal
+// ('e', 'E') or binary ('p') exponent, if any. It returns the exponent, the
+// exponent base (10 or 2), or a read or syntax error, if any.
+//
+// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
+// sign = "+" | "-" .
+// digits = digit { digit } .
+// digit = "0" ... "9" .
+//
+// A binary exponent is only permitted if binExpOk is set.
+func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err error) {
+ base = 10
+
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil // no exponent; same as e0
+ }
+ return
+ }
+
+ switch ch {
+ case 'e', 'E':
+ // ok
+ case 'p':
+ if binExpOk {
+ base = 2
+ break // ok
+ }
+ fallthrough // binary exponent not permitted
+ default:
+ r.UnreadByte()
+ return // no exponent; same as e0
+ }
+
+ var neg bool
+ if neg, err = scanSign(r); err != nil {
+ return
+ }
+
+ var digits []byte
+ if neg {
+ digits = append(digits, '-')
+ }
+
+ // no need to use nat.scan for exponent digits
+ // since we only care about int64 values - the
+ // from-scratch scan is easy enough and faster
+ for i := 0; ; i++ {
+ if ch, err = r.ReadByte(); err != nil {
+ if err != io.EOF || i == 0 {
+ return
+ }
+ err = nil
+ break // i > 0
+ }
+ if ch < '0' || '9' < ch {
+ if i == 0 {
+ r.UnreadByte()
+ err = fmt.Errorf("invalid exponent (missing digits)")
+ return
+ }
+ break // i > 0
+ }
+ digits = append(digits, byte(ch))
+ }
+ // i > 0 => we have at least one digit
+
+ exp, err = strconv.ParseInt(string(digits), 10, 64)
+ return
+}
+
+// String returns a string representation of x in the form "a/b" (even if b == 1).
+func (x *Rat) String() string {
+ s := "/1"
+ if len(x.b.abs) != 0 {
+ s = "/" + x.b.abs.decimalString()
+ }
+ return x.a.String() + s
+}
+
+// RatString returns a string representation of x in the form "a/b" if b != 1,
+// and in the form "a" if b == 1.
+func (x *Rat) RatString() string {
+ if x.IsInt() {
+ return x.a.String()
+ }
+ return x.String()
+}
+
+// FloatString returns a string representation of x in decimal form with prec
+// digits of precision after the decimal point. The last digit is rounded to
+// nearest, with halves rounded away from zero.
+func (x *Rat) FloatString(prec int) string {
+ if x.IsInt() {
+ s := x.a.String()
+ if prec > 0 {
+ s += "." + strings.Repeat("0", prec)
+ }
+ return s
+ }
+ // x.b.abs != 0
+
+ q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
+
+ p := natOne
+ if prec > 0 {
+ p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
+ }
+
+ r = r.mul(r, p)
+ r, r2 := r.div(nat(nil), r, x.b.abs)
+
+ // see if we need to round up
+ r2 = r2.add(r2, r2)
+ if x.b.abs.cmp(r2) <= 0 {
+ r = r.add(r, natOne)
+ if r.cmp(p) >= 0 {
+ q = nat(nil).add(q, natOne)
+ r = nat(nil).sub(r, p)
+ }
+ }
+
+ s := q.decimalString()
+ if x.a.neg {
+ s = "-" + s
+ }
+
+ if prec > 0 {
+ rs := r.decimalString()
+ leadingZeros := prec - len(rs)
+ s += "." + strings.Repeat("0", leadingZeros) + rs
+ }
+
+ return s
+}
diff --git a/libgo/go/math/big/ratconv_test.go b/libgo/go/math/big/ratconv_test.go
new file mode 100644
index 00000000000..da2fdab4cab
--- /dev/null
+++ b/libgo/go/math/big/ratconv_test.go
@@ -0,0 +1,453 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+type StringTest struct {
+ in, out string
+ ok bool
+}
+
+var setStringTests = []StringTest{
+ {"0", "0", true},
+ {"-0", "0", true},
+ {"1", "1", true},
+ {"-1", "-1", true},
+ {"1.", "1", true},
+ {"1e0", "1", true},
+ {"1.e1", "10", true},
+ {in: "1e"},
+ {in: "1.e"},
+ {in: "1e+14e-5"},
+ {in: "1e4.5"},
+ {in: "r"},
+ {in: "a/b"},
+ {in: "a.b"},
+ {"-0.1", "-1/10", true},
+ {"-.1", "-1/10", true},
+ {"2/4", "1/2", true},
+ {".25", "1/4", true},
+ {"-1/5", "-1/5", true},
+ {"8129567.7690E14", "812956776900000000000", true},
+ {"78189e+4", "781890000", true},
+ {"553019.8935e+8", "55301989350000", true},
+ {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
+ {"9877861857500000E-7", "3951144743/4", true},
+ {"2169378.417e-3", "2169378417/1000000", true},
+ {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
+ {"53/70893980658822810696", "53/70893980658822810696", true},
+ {"106/141787961317645621392", "53/70893980658822810696", true},
+ {"204211327800791583.81095", "4084226556015831676219/20000", true},
+ {in: "1/0"},
+}
+
+// These are not supported by fmt.Fscanf.
+var setStringTests2 = []StringTest{
+ {"0x10", "16", true},
+ {"-010/1", "-8", true}, // TODO(gri) should we even permit octal here?
+ {"-010.", "-10", true},
+ {"0x10/0x20", "1/2", true},
+ {"0b1000/3", "8/3", true},
+ // TODO(gri) add more tests
+}
+
+func TestRatSetString(t *testing.T) {
+ var tests []StringTest
+ tests = append(tests, setStringTests...)
+ tests = append(tests, setStringTests2...)
+
+ for i, test := range tests {
+ x, ok := new(Rat).SetString(test.in)
+
+ if ok {
+ if !test.ok {
+ t.Errorf("#%d SetString(%q) expected failure", i, test.in)
+ } else if x.RatString() != test.out {
+ t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
+ }
+ } else if x != nil {
+ t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
+ }
+ }
+}
+
+func TestRatScan(t *testing.T) {
+ var buf bytes.Buffer
+ for i, test := range setStringTests {
+ x := new(Rat)
+ buf.Reset()
+ buf.WriteString(test.in)
+
+ _, err := fmt.Fscanf(&buf, "%v", x)
+ if err == nil != test.ok {
+ if test.ok {
+ t.Errorf("#%d (%s) error: %s", i, test.in, err)
+ } else {
+ t.Errorf("#%d (%s) expected error", i, test.in)
+ }
+ continue
+ }
+ if err == nil && x.RatString() != test.out {
+ t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+ }
+ }
+}
+
+var floatStringTests = []struct {
+ in string
+ prec int
+ out string
+}{
+ {"0", 0, "0"},
+ {"0", 4, "0.0000"},
+ {"1", 0, "1"},
+ {"1", 2, "1.00"},
+ {"-1", 0, "-1"},
+ {"0.05", 1, "0.1"},
+ {"-0.05", 1, "-0.1"},
+ {".25", 2, "0.25"},
+ {".25", 1, "0.3"},
+ {".25", 3, "0.250"},
+ {"-1/3", 3, "-0.333"},
+ {"-2/3", 4, "-0.6667"},
+ {"0.96", 1, "1.0"},
+ {"0.999", 2, "1.00"},
+ {"0.9", 0, "1"},
+ {".25", -1, "0"},
+ {".55", -1, "1"},
+}
+
+func TestFloatString(t *testing.T) {
+ for i, test := range floatStringTests {
+ x, _ := new(Rat).SetString(test.in)
+
+ if x.FloatString(test.prec) != test.out {
+ t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
+ }
+ }
+}
+
+// Test inputs to Rat.SetString. The prefix "long:" causes the test
+// to be skipped in --test.short mode. (The threshold is about 500us.)
+var float64inputs = []string{
+ // Constants plundered from strconv/testfp.txt.
+
+ // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+ "5e+125",
+ "69e+267",
+ "999e-026",
+ "7861e-034",
+ "75569e-254",
+ "928609e-261",
+ "9210917e+080",
+ "84863171e+114",
+ "653777767e+273",
+ "5232604057e-298",
+ "27235667517e-109",
+ "653532977297e-123",
+ "3142213164987e-294",
+ "46202199371337e-072",
+ "231010996856685e-073",
+ "9324754620109615e+212",
+ "78459735791271921e+049",
+ "272104041512242479e+200",
+ "6802601037806061975e+198",
+ "20505426358836677347e-221",
+ "836168422905420598437e-234",
+ "4891559871276714924261e+222",
+
+ // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+ "9e-265",
+ "85e-037",
+ "623e+100",
+ "3571e+263",
+ "81661e+153",
+ "920657e-023",
+ "4603285e-024",
+ "87575437e-309",
+ "245540327e+122",
+ "6138508175e+120",
+ "83356057653e+193",
+ "619534293513e+124",
+ "2335141086879e+218",
+ "36167929443327e-159",
+ "609610927149051e-255",
+ "3743626360493413e-165",
+ "94080055902682397e-242",
+ "899810892172646163e+283",
+ "7120190517612959703e+120",
+ "25188282901709339043e-252",
+ "308984926168550152811e-052",
+ "6372891218502368041059e+064",
+
+ // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+ "5e-20",
+ "67e+14",
+ "985e+15",
+ "7693e-42",
+ "55895e-16",
+ "996622e-44",
+ "7038531e-32",
+ "60419369e-46",
+ "702990899e-20",
+ "6930161142e-48",
+ "25933168707e+13",
+ "596428896559e+20",
+
+ // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+ "3e-23",
+ "57e+18",
+ "789e-35",
+ "2539e-18",
+ "76173e+28",
+ "887745e-11",
+ "5382571e-37",
+ "82381273e-35",
+ "750486563e-38",
+ "3752432815e-39",
+ "75224575729e-45",
+ "459926601011e+15",
+
+ // Constants plundered from strconv/atof_test.go.
+
+ "0",
+ "1",
+ "+1",
+ "1e23",
+ "1E23",
+ "100000000000000000000000",
+ "1e-100",
+ "123456700",
+ "99999999999999974834176",
+ "100000000000000000000001",
+ "100000000000000008388608",
+ "100000000000000016777215",
+ "100000000000000016777216",
+ "-1",
+ "-0.1",
+ "-0", // NB: exception made for this input
+ "1e-20",
+ "625e-3",
+
+ // largest float64
+ "1.7976931348623157e308",
+ "-1.7976931348623157e308",
+ // next float64 - too large
+ "1.7976931348623159e308",
+ "-1.7976931348623159e308",
+ // the border is ...158079
+ // borderline - okay
+ "1.7976931348623158e308",
+ "-1.7976931348623158e308",
+ // borderline - too large
+ "1.797693134862315808e308",
+ "-1.797693134862315808e308",
+
+ // a little too large
+ "1e308",
+ "2e308",
+ "1e309",
+
+ // way too large
+ "1e310",
+ "-1e310",
+ "1e400",
+ "-1e400",
+ "long:1e400000",
+ "long:-1e400000",
+
+ // denormalized
+ "1e-305",
+ "1e-306",
+ "1e-307",
+ "1e-308",
+ "1e-309",
+ "1e-310",
+ "1e-322",
+ // smallest denormal
+ "5e-324",
+ "4e-324",
+ "3e-324",
+ // too small
+ "2e-324",
+ // way too small
+ "1e-350",
+ "long:1e-400000",
+ // way too small, negative
+ "-1e-350",
+ "long:-1e-400000",
+
+ // try to overflow exponent
+ // [Disabled: too slow and memory-hungry with rationals.]
+ // "1e-4294967296",
+ // "1e+4294967296",
+ // "1e-18446744073709551616",
+ // "1e+18446744073709551616",
+
+ // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+ "2.2250738585072012e-308",
+ // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+ "2.2250738585072011e-308",
+
+ // A very large number (initially wrongly parsed by the fast algorithm).
+ "4.630813248087435e+307",
+
+ // A different kind of very large number.
+ "22.222222222222222",
+ "long:2." + strings.Repeat("2", 4000) + "e+1",
+
+ // Exactly halfway between 1 and math.Nextafter(1, 2).
+ // Round to even (down).
+ "1.00000000000000011102230246251565404236316680908203125",
+ // Slightly lower; still round down.
+ "1.00000000000000011102230246251565404236316680908203124",
+ // Slightly higher; round up.
+ "1.00000000000000011102230246251565404236316680908203126",
+ // Slightly higher, but you have to read all the way to the end.
+ "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
+
+ // Smallest denormal, 2^(-1022-52)
+ "4.940656458412465441765687928682213723651e-324",
+ // Half of smallest denormal, 2^(-1022-53)
+ "2.470328229206232720882843964341106861825e-324",
+ // A little more than the exact half of smallest denormal
+ // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
+ "2.470328302827751011111470718709768633275e-324",
+ // The exact halfway between smallest normal and largest denormal:
+ // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
+ "2.225073858507201136057409796709131975935e-308",
+
+ "1152921504606846975", // 1<<60 - 1
+ "-1152921504606846975", // -(1<<60 - 1)
+ "1152921504606846977", // 1<<60 + 1
+ "-1152921504606846977", // -(1<<60 + 1)
+
+ "1/3",
+}
+
+// isFinite reports whether f represents a finite rational value.
+// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
+func isFinite(f float64) bool {
+ return math.Abs(f) <= math.MaxFloat64
+}
+
+func TestFloat32SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+ if testing.Short() {
+ continue
+ }
+ input = input[len("long:"):]
+ }
+
+ r, ok := new(Rat).SetString(input)
+ if !ok {
+ t.Errorf("Rat.SetString(%q) failed", input)
+ continue
+ }
+ f, exact := r.Float32()
+
+ // 1. Check string -> Rat -> float32 conversions are
+ // consistent with strconv.ParseFloat.
+ // Skip this check if the input uses "a/b" rational syntax.
+ if !strings.Contains(input, "/") {
+ e64, _ := strconv.ParseFloat(input, 32)
+ e := float32(e64)
+
+ // Careful: negative Rats too small for
+ // float64 become -0, but Rat obviously cannot
+ // preserve the sign from SetString("-0").
+ switch {
+ case math.Float32bits(e) == math.Float32bits(f):
+ // Ok: bitwise equal.
+ case f == 0 && r.Num().BitLen() == 0:
+ // Ok: Rat(0) is equivalent to both +/- float64(0).
+ default:
+ t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+ }
+ }
+
+ if !isFinite(float64(f)) {
+ continue
+ }
+
+ // 2. Check f is best approximation to r.
+ if !checkIsBestApprox32(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was %q)", input)
+ }
+
+ // 3. Check f->R->f roundtrip is non-lossy.
+ checkNonLossyRoundtrip32(t, f)
+
+ // 4. Check exactness using slow algorithm.
+ if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
+ t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
+ }
+ }
+}
+
+func TestFloat64SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+ if testing.Short() {
+ continue
+ }
+ input = input[len("long:"):]
+ }
+
+ r, ok := new(Rat).SetString(input)
+ if !ok {
+ t.Errorf("Rat.SetString(%q) failed", input)
+ continue
+ }
+ f, exact := r.Float64()
+
+ // 1. Check string -> Rat -> float64 conversions are
+ // consistent with strconv.ParseFloat.
+ // Skip this check if the input uses "a/b" rational syntax.
+ if !strings.Contains(input, "/") {
+ e, _ := strconv.ParseFloat(input, 64)
+
+ // Careful: negative Rats too small for
+ // float64 become -0, but Rat obviously cannot
+ // preserve the sign from SetString("-0").
+ switch {
+ case math.Float64bits(e) == math.Float64bits(f):
+ // Ok: bitwise equal.
+ case f == 0 && r.Num().BitLen() == 0:
+ // Ok: Rat(0) is equivalent to both +/- float64(0).
+ default:
+ t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+ }
+ }
+
+ if !isFinite(f) {
+ continue
+ }
+
+ // 2. Check f is best approximation to r.
+ if !checkIsBestApprox64(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was %q)", input)
+ }
+
+ // 3. Check f->R->f roundtrip is non-lossy.
+ checkNonLossyRoundtrip64(t, f)
+
+ // 4. Check exactness using slow algorithm.
+ if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
+ t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
+ }
+ }
+}
diff --git a/libgo/go/math/big/roundingmode_string.go b/libgo/go/math/big/roundingmode_string.go
new file mode 100644
index 00000000000..05024b80656
--- /dev/null
+++ b/libgo/go/math/big/roundingmode_string.go
@@ -0,0 +1,16 @@
+// generated by stringer -type=RoundingMode; DO NOT EDIT
+
+package big
+
+import "fmt"
+
+const _RoundingMode_name = "ToNearestEvenToNearestAwayToZeroAwayFromZeroToNegativeInfToPositiveInf"
+
+var _RoundingMode_index = [...]uint8{0, 13, 26, 32, 44, 57, 70}
+
+func (i RoundingMode) String() string {
+ if i+1 >= RoundingMode(len(_RoundingMode_index)) {
+ return fmt.Sprintf("RoundingMode(%d)", i)
+ }
+ return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
+}
diff --git a/libgo/go/math/cbrt.go b/libgo/go/math/cbrt.go
index 272e3092310..f009fafd7d8 100644
--- a/libgo/go/math/cbrt.go
+++ b/libgo/go/math/cbrt.go
@@ -4,13 +4,17 @@
package math
-/*
- The algorithm is based in part on "Optimal Partitioning of
- Newton's Method for Calculating Roots", by Gunter Meinardus
- and G. D. Taylor, Mathematics of Computation © 1980 American
- Mathematical Society.
- (http://www.jstor.org/stable/2006387?seq=9, accessed 11-Feb-2010)
-*/
+// The go code is a modified version of the original C code from
+// http://www.netlib.org/fdlibm/s_cbrt.c and came with this notice.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
// Cbrt returns the cube root of x.
//
@@ -20,57 +24,54 @@ package math
// Cbrt(NaN) = NaN
func Cbrt(x float64) float64 {
const (
- A1 = 1.662848358e-01
- A2 = 1.096040958e+00
- A3 = 4.105032829e-01
- A4 = 5.649335816e-01
- B1 = 2.639607233e-01
- B2 = 8.699282849e-01
- B3 = 1.629083358e-01
- B4 = 2.824667908e-01
- C1 = 4.190115298e-01
- C2 = 6.904625373e-01
- C3 = 6.46502159e-02
- C4 = 1.412333954e-01
+ B1 = 715094163 // (682-0.03306235651)*2**20
+ B2 = 696219795 // (664-0.03306235651)*2**20
+ C = 5.42857142857142815906e-01 // 19/35 = 0x3FE15F15F15F15F1
+ D = -7.05306122448979611050e-01 // -864/1225 = 0xBFE691DE2532C834
+ E = 1.41428571428571436819e+00 // 99/70 = 0x3FF6A0EA0EA0EA0F
+ F = 1.60714285714285720630e+00 // 45/28 = 0x3FF9B6DB6DB6DB6E
+ G = 3.57142857142857150787e-01 // 5/14 = 0x3FD6DB6DB6DB6DB7
+ SmallestNormal = 2.22507385850720138309e-308 // 2**-1022 = 0x0010000000000000
)
// special cases
switch {
case x == 0 || IsNaN(x) || IsInf(x, 0):
return x
}
+
sign := false
if x < 0 {
x = -x
sign = true
}
- // Reduce argument and estimate cube root
- f, e := Frexp(x) // 0.5 <= f < 1.0
- m := e % 3
- if m > 0 {
- m -= 3
- e -= m // e is multiple of 3
- }
- switch m {
- case 0: // 0.5 <= f < 1.0
- f = A1*f + A2 - A3/(A4+f)
- case -1:
- f *= 0.5 // 0.25 <= f < 0.5
- f = B1*f + B2 - B3/(B4+f)
- default: // m == -2
- f *= 0.25 // 0.125 <= f < 0.25
- f = C1*f + C2 - C3/(C4+f)
+
+ // rough cbrt to 5 bits
+ t := Float64frombits(Float64bits(x)/3 + B1<<32)
+ if x < SmallestNormal {
+ // subnormal number
+ t = float64(1 << 54) // set t= 2**54
+ t *= x
+ t = Float64frombits(Float64bits(t)/3 + B2<<32)
}
- y := Ldexp(f, e/3) // e/3 = exponent of cube root
- // Iterate
- s := y * y * y
- t := s + x
- y *= (t + x) / (s + t)
- // Reiterate
- s = (y*y*y - x) / x
- y -= y * (((14.0/81.0)*s-(2.0/9.0))*s + (1.0 / 3.0)) * s
+ // new cbrt to 23 bits
+ r := t * t / x
+ s := C + r*t
+ t *= G + F/(s+E+D/s)
+
+ // chop to 22 bits, make larger than cbrt(x)
+ t = Float64frombits(Float64bits(t)&(0xFFFFFFFFC<<28) + 1<<30)
+
+ // one step newton iteration to 53 bits with error less than 0.667ulps
+ s = t * t // t*t is exact
+ r = x / s
+ w := t + t
+ r = (r - t) / (w + r) // r-s is exact
+ t = t + t*r
+
+ // restore the sign bit
if sign {
- y = -y
+ t = -t
}
- return y
+ return t
}
diff --git a/libgo/go/math/const.go b/libgo/go/math/const.go
index f1247c383fd..b4405383c8e 100644
--- a/libgo/go/math/const.go
+++ b/libgo/go/math/const.go
@@ -6,20 +6,19 @@
package math
// Mathematical constants.
-// Reference: http://oeis.org/Axxxxxx
const (
- E = 2.71828182845904523536028747135266249775724709369995957496696763 // A001113
- Pi = 3.14159265358979323846264338327950288419716939937510582097494459 // A000796
- Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // A001622
+ E = 2.71828182845904523536028747135266249775724709369995957496696763 // http://oeis.org/A001113
+ Pi = 3.14159265358979323846264338327950288419716939937510582097494459 // http://oeis.org/A000796
+ Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // http://oeis.org/A001622
- Sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 // A002193
- SqrtE = 1.64872127070012814684865078781416357165377610071014801157507931 // A019774
- SqrtPi = 1.77245385090551602729816748334114518279754945612238712821380779 // A002161
- SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // A139339
+ Sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 // http://oeis.org/A002193
+ SqrtE = 1.64872127070012814684865078781416357165377610071014801157507931 // http://oeis.org/A019774
+ SqrtPi = 1.77245385090551602729816748334114518279754945612238712821380779 // http://oeis.org/A002161
+ SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // http://oeis.org/A139339
- Ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 // A002162
+ Ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 // http://oeis.org/A002162
Log2E = 1 / Ln2
- Ln10 = 2.30258509299404568401799145468436420760110148862877297603332790 // A002392
+ Ln10 = 2.30258509299404568401799145468436420760110148862877297603332790 // http://oeis.org/A002392
Log10E = 1 / Ln10
)
diff --git a/libgo/go/math/expm1.go b/libgo/go/math/expm1.go
index f7e15dbbc9d..8d7b3d365a6 100644
--- a/libgo/go/math/expm1.go
+++ b/libgo/go/math/expm1.go
@@ -164,11 +164,11 @@ func expm1(x float64) float64 {
// filter out huge argument
if absx >= Ln2X56 { // if |x| >= 56 * ln2
- if absx >= Othreshold { // if |x| >= 709.78...
- return Inf(1) // overflow
- }
if sign {
- return -1 // x < -56*ln2, return -1.0
+ return -1 // x < -56*ln2, return -1
+ }
+ if absx >= Othreshold { // if |x| >= 709.78...
+ return Inf(1)
}
}
diff --git a/libgo/go/math/log10.go b/libgo/go/math/log10.go
index d880ec2040d..2c09d88f2a1 100644
--- a/libgo/go/math/log10.go
+++ b/libgo/go/math/log10.go
@@ -27,5 +27,10 @@ func Log2(x float64) float64 {
func log2(x float64) float64 {
frac, exp := Frexp(x)
+ // Make sure exact powers of two give an exact answer.
+ // Don't depend on Log(0.5)*(1/Ln2)+exp being exactly exp-1.
+ if frac == 0.5 {
+ return float64(exp - 1)
+ }
return Log(frac)*(1/Ln2) + float64(exp)
}
diff --git a/libgo/go/math/nextafter.go b/libgo/go/math/nextafter.go
index bbb139986aa..9088e4d248a 100644
--- a/libgo/go/math/nextafter.go
+++ b/libgo/go/math/nextafter.go
@@ -5,10 +5,11 @@
package math
// Nextafter32 returns the next representable float32 value after x towards y.
-// Special cases:
+//
+// Special cases are:
// Nextafter32(x, x) = x
-// Nextafter32(NaN, y) = NaN
-// Nextafter32(x, NaN) = NaN
+// Nextafter32(NaN, y) = NaN
+// Nextafter32(x, NaN) = NaN
func Nextafter32(x, y float32) (r float32) {
switch {
case IsNaN(float64(x)) || IsNaN(float64(y)): // special case
@@ -26,10 +27,11 @@ func Nextafter32(x, y float32) (r float32) {
}
// Nextafter returns the next representable float64 value after x towards y.
-// Special cases:
-// Nextafter64(x, x) = x
-// Nextafter64(NaN, y) = NaN
-// Nextafter64(x, NaN) = NaN
+//
+// Special cases are:
+// Nextafter(x, x) = x
+// Nextafter(NaN, y) = NaN
+// Nextafter(x, NaN) = NaN
func Nextafter(x, y float64) (r float64) {
switch {
case IsNaN(x) || IsNaN(y): // special case
diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go
index 3ffb5c4e5c6..6360128e391 100644
--- a/libgo/go/math/rand/rand.go
+++ b/libgo/go/math/rand/rand.go
@@ -9,6 +9,9 @@
// sequence of values each time a program is run. Use the Seed function to
// initialize the default Source if different behavior is required for each run.
// The default Source is safe for concurrent use by multiple goroutines.
+//
+// For random numbers suitable for security-sensitive work, see the crypto/rand
+// package.
package rand
import "sync"
diff --git a/libgo/go/math/rand/rand_test.go b/libgo/go/math/rand/rand_test.go
index ab0dc49b411..c61494f8eb8 100644
--- a/libgo/go/math/rand/rand_test.go
+++ b/libgo/go/math/rand/rand_test.go
@@ -8,6 +8,8 @@ import (
"errors"
"fmt"
"math"
+ "os"
+ "runtime"
"testing"
)
@@ -322,10 +324,17 @@ func TestExpTables(t *testing.T) {
}
}
-// For issue 6721, the problem came after 7533753 calls, so check 10e6.
func TestFloat32(t *testing.T) {
+ // For issue 6721, the problem came after 7533753 calls, so check 10e6.
+ num := int(10e6)
+ // But ARM5 floating point emulation is slow (Issue 10749), so
+ // do less for that builder:
+ if testing.Short() && runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" {
+ num /= 100 // 1.72 seconds instead of 172 seconds
+ }
+
r := New(NewSource(1))
- for ct := 0; ct < 10e6; ct++ {
+ for ct := 0; ct < num; ct++ {
f := r.Float32()
if f >= 1 {
t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f)
diff --git a/libgo/go/math/rand/zipf.go b/libgo/go/math/rand/zipf.go
index 8db2c6f5bff..f04c814eb75 100644
--- a/libgo/go/math/rand/zipf.go
+++ b/libgo/go/math/rand/zipf.go
@@ -32,8 +32,10 @@ func (z *Zipf) hinv(x float64) float64 {
return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v
}
-// NewZipf returns a Zipf generating variates p(k) on [0, imax]
-// proportional to (v+k)**(-s) where s>1 and k>=0, and v>=1.
+// NewZipf returns a Zipf variate generator.
+// The generator generates values k ∈ [0, imax]
+// such that P(k) is proportional to (v + k) ** (-s).
+// Requirements: s > 1 and v >= 1.
func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
z := new(Zipf)
if s <= 1.0 || v < 1 {
diff --git a/libgo/go/math/sqrt.go b/libgo/go/math/sqrt.go
index 56122b59814..215d6485442 100644
--- a/libgo/go/math/sqrt.go
+++ b/libgo/go/math/sqrt.go
@@ -96,6 +96,12 @@ func Sqrt(x float64) float64 {
// Sqrt(±0) = ±0
// Sqrt(x < 0) = NaN
// Sqrt(NaN) = NaN
+
+// Note: Sqrt is implemented in assembly on some systems.
+// Others have assembly stubs that jump to func sqrt below.
+// On systems where Sqrt is a single instruction, the compiler
+// may turn a direct call into a direct use of that instruction instead.
+
func sqrt(x float64) float64 {
// special cases
switch {