From 15040c11b9b8f2e33b2833feb99a48ea9a2dba6c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 13 Oct 2016 15:13:41 -0400 Subject: [PATCH] cmd/dist: copy needed packages from standard library during bootstrap This allows use of newer math/big (and later debug/pe) without maintaining a vendored copy somewhere in cmd. Use for math/big, deleting cmd/compile/internal/big. Change-Id: I2bffa7a9ef115015be29fafdb02acc3e7a665d11 Reviewed-on: https://go-review.googlesource.com/31010 Reviewed-by: Minux Ma Reviewed-by: Ian Lance Taylor --- src/cmd/compile/fmt_test.go | 6 +- .../compile/internal/big/accuracy_string.go | 17 - src/cmd/compile/internal/big/arith.go | 305 --- src/cmd/compile/internal/big/arith_decl.go | 53 - src/cmd/compile/internal/big/arith_test.go | 413 ---- src/cmd/compile/internal/big/bits_test.go | 224 --- .../compile/internal/big/calibrate_test.go | 88 - src/cmd/compile/internal/big/decimal.go | 266 --- src/cmd/compile/internal/big/decimal_test.go | 118 -- src/cmd/compile/internal/big/doc.go | 99 - .../compile/internal/big/example_rat_test.go | 65 - src/cmd/compile/internal/big/example_test.go | 128 -- src/cmd/compile/internal/big/float.go | 1683 ---------------- src/cmd/compile/internal/big/float_test.go | 1764 ----------------- src/cmd/compile/internal/big/floatconv.go | 275 --- .../compile/internal/big/floatconv_test.go | 667 ------- .../compile/internal/big/floatexample_test.go | 141 -- src/cmd/compile/internal/big/floatmarsh.go | 120 -- .../compile/internal/big/floatmarsh_test.go | 136 -- src/cmd/compile/internal/big/ftoa.go | 459 ----- src/cmd/compile/internal/big/gcd_test.go | 61 - src/cmd/compile/internal/big/hilbert_test.go | 160 -- src/cmd/compile/internal/big/int.go | 934 --------- src/cmd/compile/internal/big/int_test.go | 1482 -------------- src/cmd/compile/internal/big/intconv.go | 248 --- src/cmd/compile/internal/big/intconv_test.go | 391 ---- src/cmd/compile/internal/big/intmarsh.go | 78 - src/cmd/compile/internal/big/intmarsh_test.go | 121 -- src/cmd/compile/internal/big/nat.go | 1305 ------------ src/cmd/compile/internal/big/nat_test.go | 651 ------ src/cmd/compile/internal/big/natconv.go | 492 ----- src/cmd/compile/internal/big/natconv_test.go | 379 ---- src/cmd/compile/internal/big/rat.go | 510 ----- src/cmd/compile/internal/big/rat_test.go | 622 ------ src/cmd/compile/internal/big/ratconv.go | 270 --- src/cmd/compile/internal/big/ratconv_test.go | 454 ----- src/cmd/compile/internal/big/ratmarsh.go | 73 - src/cmd/compile/internal/big/ratmarsh_test.go | 125 -- .../internal/big/roundingmode_string.go | 16 - src/cmd/compile/internal/big/vendor.bash | 31 - src/cmd/compile/internal/gc/bexport.go | 2 +- src/cmd/compile/internal/gc/bimport.go | 2 +- src/cmd/compile/internal/gc/mpfloat.go | 2 +- src/cmd/compile/internal/gc/mpint.go | 2 +- src/cmd/compile/internal/gc/swt_test.go | 2 +- src/cmd/dist/buildtool.go | 118 +- 46 files changed, 80 insertions(+), 15478 deletions(-) delete mode 100644 src/cmd/compile/internal/big/accuracy_string.go delete mode 100644 src/cmd/compile/internal/big/arith.go delete mode 100644 src/cmd/compile/internal/big/arith_decl.go delete mode 100644 src/cmd/compile/internal/big/arith_test.go delete mode 100644 src/cmd/compile/internal/big/bits_test.go delete mode 100644 src/cmd/compile/internal/big/calibrate_test.go delete mode 100644 src/cmd/compile/internal/big/decimal.go delete mode 100644 src/cmd/compile/internal/big/decimal_test.go delete mode 100644 src/cmd/compile/internal/big/doc.go delete mode 100644 src/cmd/compile/internal/big/example_rat_test.go delete mode 100644 src/cmd/compile/internal/big/example_test.go delete mode 100644 src/cmd/compile/internal/big/float.go delete mode 100644 src/cmd/compile/internal/big/float_test.go delete mode 100644 src/cmd/compile/internal/big/floatconv.go delete mode 100644 src/cmd/compile/internal/big/floatconv_test.go delete mode 100644 src/cmd/compile/internal/big/floatexample_test.go delete mode 100644 src/cmd/compile/internal/big/floatmarsh.go delete mode 100644 src/cmd/compile/internal/big/floatmarsh_test.go delete mode 100644 src/cmd/compile/internal/big/ftoa.go delete mode 100644 src/cmd/compile/internal/big/gcd_test.go delete mode 100644 src/cmd/compile/internal/big/hilbert_test.go delete mode 100644 src/cmd/compile/internal/big/int.go delete mode 100644 src/cmd/compile/internal/big/int_test.go delete mode 100644 src/cmd/compile/internal/big/intconv.go delete mode 100644 src/cmd/compile/internal/big/intconv_test.go delete mode 100644 src/cmd/compile/internal/big/intmarsh.go delete mode 100644 src/cmd/compile/internal/big/intmarsh_test.go delete mode 100644 src/cmd/compile/internal/big/nat.go delete mode 100644 src/cmd/compile/internal/big/nat_test.go delete mode 100644 src/cmd/compile/internal/big/natconv.go delete mode 100644 src/cmd/compile/internal/big/natconv_test.go delete mode 100644 src/cmd/compile/internal/big/rat.go delete mode 100644 src/cmd/compile/internal/big/rat_test.go delete mode 100644 src/cmd/compile/internal/big/ratconv.go delete mode 100644 src/cmd/compile/internal/big/ratconv_test.go delete mode 100644 src/cmd/compile/internal/big/ratmarsh.go delete mode 100644 src/cmd/compile/internal/big/ratmarsh_test.go delete mode 100644 src/cmd/compile/internal/big/roundingmode_string.go delete mode 100755 src/cmd/compile/internal/big/vendor.bash diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index 48999aec15..424131d765 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -506,9 +506,7 @@ func formatReplace(in string, f func(i int, s string) string) string { // blacklistedPackages is the set of packages which can // be ignored. -var blacklistedPackages = map[string]bool{ - "cmd/compile/internal/big": true, -} +var blacklistedPackages = map[string]bool{} // blacklistedFunctions is the set of functions which may have // format-like arguments but which don't do any formatting and @@ -537,7 +535,7 @@ func init() { // To print out a new table, run: go test -run Formats -v. var knownFormats = map[string]string{ "*bytes.Buffer %s": "", - "*cmd/compile/internal/big.Int %#x": "", + "*math/big.Int %#x": "", "*cmd/compile/internal/gc.Bits %v": "", "*cmd/compile/internal/gc.Field %p": "", "*cmd/compile/internal/gc.Field %v": "", diff --git a/src/cmd/compile/internal/big/accuracy_string.go b/src/cmd/compile/internal/big/accuracy_string.go deleted file mode 100644 index 24ef7f1077..0000000000 --- a/src/cmd/compile/internal/big/accuracy_string.go +++ /dev/null @@ -1,17 +0,0 @@ -// 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/src/cmd/compile/internal/big/arith.go b/src/cmd/compile/internal/big/arith.go deleted file mode 100644 index d7ea8381e7..0000000000 --- a/src/cmd/compile/internal/big/arith.go +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2009 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 provides Go implementations of elementary multi-precision -// arithmetic operations on word vectors. Needed for platforms without -// assembly implementations of these routines. - -package big - -// A Word represents a single digit of a multi-precision unsigned integer. -type Word uintptr - -const ( - // Compute the size _S of a Word in bytes. - _m = ^Word(0) - _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 - _S = 1 << _logS - - _W = _S << 3 // word size in bits - _B = 1 << _W // digit base - _M = _B - 1 // digit mask - - _W2 = _W / 2 // half word size in bits - _B2 = 1 << _W2 // half digit base - _M2 = _B2 - 1 // half digit mask -) - -// ---------------------------------------------------------------------------- -// Elementary operations on words -// -// These operations are used by the vector operations below. - -// z1<<_W + z0 = x+y+c, with c == 0 or 1 -func addWW_g(x, y, c Word) (z1, z0 Word) { - yc := y + c - z0 = x + yc - if z0 < x || yc < y { - z1 = 1 - } - return -} - -// z1<<_W + z0 = x-y-c, with c == 0 or 1 -func subWW_g(x, y, c Word) (z1, z0 Word) { - yc := y + c - z0 = x - yc - if z0 > x || yc < y { - z1 = 1 - } - return -} - -// z1<<_W + z0 = x*y -// Adapted from Warren, Hacker's Delight, p. 132. -func mulWW_g(x, y Word) (z1, z0 Word) { - x0 := x & _M2 - x1 := x >> _W2 - y0 := y & _M2 - y1 := y >> _W2 - w0 := x0 * y0 - t := x1*y0 + w0>>_W2 - w1 := t & _M2 - w2 := t >> _W2 - w1 += x0 * y1 - z1 = x1*y1 + w2 + w1>>_W2 - z0 = x * y - return -} - -// z1<<_W + z0 = x*y + c -func mulAddWWW_g(x, y, c Word) (z1, z0 Word) { - z1, zz0 := mulWW_g(x, y) - if z0 = zz0 + c; z0 < zz0 { - z1++ - } - return -} - -// Length of x in bits. -func bitLen_g(x Word) (n int) { - for ; x >= 0x8000; x >>= 16 { - n += 16 - } - if x >= 0x80 { - x >>= 8 - n += 8 - } - if x >= 0x8 { - x >>= 4 - n += 4 - } - if x >= 0x2 { - x >>= 2 - n += 2 - } - if x >= 0x1 { - n++ - } - return -} - -// log2 computes the integer binary logarithm of x. -// The result is the integer n for which 2^n <= x < 2^(n+1). -// If x == 0, the result is -1. -func log2(x Word) int { - return bitLen(x) - 1 -} - -// nlz returns the number of leading zeros in x. -func nlz(x Word) uint { - return uint(_W - bitLen(x)) -} - -// 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 := nlz(v) - v <<= s - - vn1 := v >> _W2 - vn0 := v & _M2 - un32 := u1<>(_W-s) - un10 := u0 << s - un1 := un10 >> _W2 - un0 := un10 & _M2 - q1 := un32 / vn1 - rhat := un32 - q1*vn1 - - for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 { - q1-- - rhat += vn1 - if rhat >= _B2 { - break - } - } - - un21 := un32*_B2 + un1 - q1*v - q0 := un21 / vn1 - rhat = un21 - q0*vn1 - - for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 { - q0-- - rhat += vn1 - if rhat >= _B2 { - break - } - } - - return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s -} - -// 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) { - 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 -} - -// The resulting carry c is either 0 or 1. -func subVV_g(z, x, y []Word) (c Word) { - 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 -} - -// 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, xi := range x[:len(z)] { - zi := xi + c - z[i] = zi - c = xi &^ zi >> (_W - 1) - } - return -} - -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, xi := range x[:len(z)] { - zi := xi - c - z[i] = zi - c = (zi &^ xi) >> (_W - 1) - } - return -} - -func shlVU_g(z, x []Word, s uint) (c Word) { - if n := len(z); n > 0 { - ŝ := _W - s - w1 := x[n-1] - c = w1 >> ŝ - for i := n - 1; i > 0; i-- { - w := w1 - w1 = x[i-1] - z[i] = w<>ŝ - } - z[0] = w1 << s - } - return -} - -func shrVU_g(z, x []Word, s uint) (c Word) { - if n := len(z); n > 0 { - ŝ := _W - s - w1 := x[0] - c = w1 << ŝ - for i := 0; i < n-1; i++ { - w := w1 - w1 = x[i+1] - z[i] = w>>s | w1<<ŝ - } - z[n-1] = w1 >> s - } - return -} - -func mulAddVWW_g(z, x []Word, y, r Word) (c Word) { - c = r - for i := range z { - c, z[i] = mulAddWWW_g(x[i], y, c) - } - return -} - -// 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]) - c, z[i] = addWW_g(z0, c, 0) - c += z1 - } - return -} - -func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) { - r = xn - for i := len(z) - 1; i >= 0; i-- { - z[i], r = divWW_g(r, x[i], y) - } - return -} diff --git a/src/cmd/compile/internal/big/arith_decl.go b/src/cmd/compile/internal/big/arith_decl.go deleted file mode 100644 index d60b7f95fc..0000000000 --- a/src/cmd/compile/internal/big/arith_decl.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 - -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/src/cmd/compile/internal/big/arith_test.go b/src/cmd/compile/internal/big/arith_test.go deleted file mode 100644 index 75862b4951..0000000000 --- a/src/cmd/compile/internal/big/arith_test.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2009 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/rand" - "testing" -) - -type funWW func(x, y, c Word) (z1, z0 Word) -type argWW struct { - x, y, c, z1, z0 Word -} - -var sumWW = []argWW{ - {0, 0, 0, 0, 0}, - {0, 1, 0, 0, 1}, - {0, 0, 1, 0, 1}, - {0, 1, 1, 0, 2}, - {12345, 67890, 0, 0, 80235}, - {12345, 67890, 1, 0, 80236}, - {_M, 1, 0, 1, 0}, - {_M, 0, 1, 1, 0}, - {_M, 1, 1, 1, 1}, - {_M, _M, 0, 1, _M - 1}, - {_M, _M, 1, 1, _M}, -} - -func testFunWW(t *testing.T, msg string, f funWW, a argWW) { - z1, z0 := f(a.x, a.y, a.c) - if z1 != a.z1 || z0 != a.z0 { - t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0) - } -} - -func TestFunWW(t *testing.T) { - for _, a := range sumWW { - arg := a - testFunWW(t, "addWW_g", addWW_g, arg) - - arg = argWW{a.y, a.x, a.c, a.z1, a.z0} - testFunWW(t, "addWW_g symmetric", addWW_g, arg) - - arg = argWW{a.z0, a.x, a.c, a.z1, a.y} - testFunWW(t, "subWW_g", subWW_g, arg) - - arg = argWW{a.z0, a.y, a.c, a.z1, a.x} - testFunWW(t, "subWW_g symmetric", subWW_g, arg) - } -} - -type funVV func(z, x, y []Word) (c Word) -type argVV struct { - z, x, y nat - c Word -} - -var sumVV = []argVV{ - {}, - {nat{0}, nat{0}, nat{0}, 0}, - {nat{1}, nat{1}, nat{0}, 0}, - {nat{0}, nat{_M}, nat{1}, 1}, - {nat{80235}, nat{12345}, nat{67890}, 0}, - {nat{_M - 1}, nat{_M}, nat{_M}, 1}, - {nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1}, - {nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0}, - {nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1}, -} - -func testFunVV(t *testing.T, msg string, f funVV, a argVV) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -func TestFunVV(t *testing.T) { - for _, a := range sumVV { - arg := a - testFunVV(t, "addVV_g", addVV_g, arg) - testFunVV(t, "addVV", addVV, arg) - - arg = argVV{a.z, a.y, a.x, a.c} - testFunVV(t, "addVV_g symmetric", addVV_g, arg) - testFunVV(t, "addVV symmetric", addVV, arg) - - arg = argVV{a.x, a.z, a.y, a.c} - testFunVV(t, "subVV_g", subVV_g, arg) - testFunVV(t, "subVV", subVV, arg) - - arg = argVV{a.y, a.z, a.x, a.c} - testFunVV(t, "subVV_g symmetric", subVV_g, arg) - testFunVV(t, "subVV symmetric", subVV, arg) - } -} - -// Always the same seed for reproducible results. -var rnd = rand.New(rand.NewSource(0)) - -func rndW() Word { - return Word(rnd.Int63()<<1 | rnd.Int63n(2)) -} - -func rndV(n int) []Word { - v := make([]Word, n) - for i := range v { - v[i] = rndW() - } - return v -} - -var benchSizes = []int{1, 2, 3, 4, 5, 1e1, 1e2, 1e3, 1e4, 1e5} - -func BenchmarkAddVV(b *testing.B) { - for _, n := range benchSizes { - x := rndV(n) - y := rndV(n) - z := make([]Word, n) - b.Run(fmt.Sprint(n), func(b *testing.B) { - b.SetBytes(int64(n * _W)) - for i := 0; i < b.N; i++ { - addVV(z, x, y) - } - }) - } -} - -type funVW func(z, x []Word, y Word) (c Word) -type argVW struct { - z, x nat - y Word - c Word -} - -var sumVW = []argVW{ - {}, - {nil, nil, 2, 2}, - {nat{0}, nat{0}, 0, 0}, - {nat{1}, nat{0}, 1, 0}, - {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 lshVW = []argVW{ - {}, - {nat{0}, nat{0}, 0, 0}, - {nat{0}, nat{0}, 1, 0}, - {nat{0}, nat{0}, 20, 0}, - - {nat{_M}, nat{_M}, 0, 0}, - {nat{_M << 1 & _M}, nat{_M}, 1, 1}, - {nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)}, - - {nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0}, - {nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1}, - {nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)}, -} - -var rshVW = []argVW{ - {}, - {nat{0}, nat{0}, 0, 0}, - {nat{0}, nat{0}, 1, 0}, - {nat{0}, nat{0}, 20, 0}, - - {nat{_M}, nat{_M}, 0, 0}, - {nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M}, - {nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M}, - - {nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0}, - {nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M}, - {nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M}, -} - -func testFunVW(t *testing.T, msg string, f funVW, a argVW) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW { - return func(z, x []Word, s Word) (c Word) { - return f(z, x, uint(s)) - } -} - -func TestFunVW(t *testing.T) { - for _, a := range sumVW { - arg := a - testFunVW(t, "addVW_g", addVW_g, arg) - testFunVW(t, "addVW", addVW, arg) - - arg = argVW{a.x, a.z, a.y, a.c} - testFunVW(t, "subVW_g", subVW_g, arg) - testFunVW(t, "subVW", subVW, arg) - } - - shlVW_g := makeFunVW(shlVU_g) - shlVW := makeFunVW(shlVU) - for _, a := range lshVW { - arg := a - testFunVW(t, "shlVU_g", shlVW_g, arg) - testFunVW(t, "shlVU", shlVW, arg) - } - - shrVW_g := makeFunVW(shrVU_g) - shrVW := makeFunVW(shrVU) - for _, a := range rshVW { - arg := a - testFunVW(t, "shrVU_g", shrVW_g, arg) - testFunVW(t, "shrVU", shrVW, arg) - } -} - -func BenchmarkAddVW(b *testing.B) { - for _, n := range benchSizes { - x := rndV(n) - y := rndW() - z := make([]Word, n) - b.Run(fmt.Sprint(n), func(b *testing.B) { - b.SetBytes(int64(n * _S)) - for i := 0; i < b.N; i++ { - addVW(z, x, y) - } - }) - } -} - -type funVWW func(z, x []Word, y, r Word) (c Word) -type argVWW struct { - z, x nat - y, r Word - c Word -} - -var prodVWW = []argVWW{ - {}, - {nat{0}, nat{0}, 0, 0, 0}, - {nat{991}, nat{0}, 0, 991, 0}, - {nat{0}, nat{_M}, 0, 0, 0}, - {nat{991}, nat{_M}, 0, 991, 0}, - {nat{0}, nat{0}, _M, 0, 0}, - {nat{991}, nat{0}, _M, 991, 0}, - {nat{1}, nat{1}, 1, 0, 0}, - {nat{992}, nat{1}, 1, 991, 0}, - {nat{22793}, nat{991}, 23, 0, 0}, - {nat{22800}, nat{991}, 23, 7, 0}, - {nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0}, - {nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0}, - {nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0}, - {nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0}, - {nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0}, - {nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0}, - {nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)}, - {nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)}, - {nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)}, - {nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, - {nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)}, - {nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, -} - -func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y, a.r) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -// TODO(gri) mulAddVWW and divWVW are symmetric operations but -// their signature is not symmetric. Try to unify. - -type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word) -type argWVW struct { - z nat - xn Word - x nat - y Word - r Word -} - -func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) { - z := make(nat, len(a.z)) - r := f(z, a.xn, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if r != a.r { - t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r) - } -} - -func TestFunVWW(t *testing.T) { - for _, a := range prodVWW { - arg := a - testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg) - testFunVWW(t, "mulAddVWW", mulAddVWW, arg) - - if a.y != 0 && a.r < a.y { - arg := argWVW{a.x, a.c, a.z, a.y, a.r} - testFunWVW(t, "divWVW_g", divWVW_g, arg) - testFunWVW(t, "divWVW", divWVW, arg) - } - } -} - -var mulWWTests = []struct { - x, y Word - q, r Word -}{ - {_M, _M, _M - 1, 1}, - // 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4}, -} - -func TestMulWW(t *testing.T) { - for i, test := range mulWWTests { - q, r := mulWW_g(test.x, test.y) - if q != test.q || r != test.r { - t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r) - } - } -} - -var mulAddWWWTests = []struct { - x, y, c Word - q, r Word -}{ - // TODO(agl): These will only work on 64-bit platforms. - // {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781}, - // {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382}, - {_M, _M, 0, _M - 1, 1}, - {_M, _M, _M, _M, 0}, -} - -func TestMulAddWWW(t *testing.T) { - for i, test := range mulAddWWWTests { - q, r := mulAddWWW_g(test.x, test.y, test.c) - if q != test.q || r != test.r { - t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r) - } - } -} - -func BenchmarkAddMulVVW(b *testing.B) { - for _, n := range benchSizes { - x := rndV(n) - y := rndW() - z := make([]Word, n) - b.Run(fmt.Sprint(n), func(b *testing.B) { - b.SetBytes(int64(n * _W)) - for i := 0; i < b.N; i++ { - addMulVVW(z, x, y) - } - }) - } -} - -func testWordBitLen(t *testing.T, fname string, f func(Word) int) { - for i := 0; i <= _W; i++ { - x := Word(1) << uint(i-1) // i == 0 => x == 0 - n := f(x) - if n != i { - t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x) - } - } -} - -func TestWordBitLen(t *testing.T) { - testWordBitLen(t, "bitLen", bitLen) - testWordBitLen(t, "bitLen_g", bitLen_g) -} - -// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1. -func BenchmarkBitLen(b *testing.B) { - // Individual bitLen tests. Numbers chosen to examine both sides - // of powers-of-two boundaries. - for _, nbits := range []uint{0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 31} { - testword := Word((uint64(1) << nbits) - 1) - b.Run(fmt.Sprint(nbits), func(b *testing.B) { - for i := 0; i < b.N; i++ { - bitLen(testword) - } - }) - } -} diff --git a/src/cmd/compile/internal/big/bits_test.go b/src/cmd/compile/internal/big/bits_test.go deleted file mode 100644 index 985b60bd4b..0000000000 --- a/src/cmd/compile/internal/big/bits_test.go +++ /dev/null @@ -1,224 +0,0 @@ -// 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/src/cmd/compile/internal/big/calibrate_test.go b/src/cmd/compile/internal/big/calibrate_test.go deleted file mode 100644 index f69ffbf5cf..0000000000 --- a/src/cmd/compile/internal/big/calibrate_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2009 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 prints execution times for the Mul benchmark -// given different Karatsuba thresholds. The result may be -// used to manually fine-tune the threshold constant. The -// results are somewhat fragile; use repeated runs to get -// a clear picture. - -// Usage: go test -run=TestCalibrate -calibrate - -package big - -import ( - "flag" - "fmt" - "testing" - "time" -) - -var calibrate = flag.Bool("calibrate", false, "run calibration test") - -func karatsubaLoad(b *testing.B) { - BenchmarkMul(b) -} - -// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark -// given Karatsuba threshold th. -func measureKaratsuba(th int) time.Duration { - th, karatsubaThreshold = karatsubaThreshold, th - res := testing.Benchmark(karatsubaLoad) - karatsubaThreshold = th - return time.Duration(res.NsPerOp()) -} - -func computeThresholds() { - fmt.Printf("Multiplication times for varying Karatsuba thresholds\n") - fmt.Printf("(run repeatedly for good results)\n") - - // determine Tk, the work load execution time using basic multiplication - Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled - fmt.Printf("Tb = %10s\n", Tb) - - // thresholds - th := 4 - th1 := -1 - th2 := -1 - - var deltaOld time.Duration - for count := -1; count != 0 && th < 128; count-- { - // determine Tk, the work load execution time using Karatsuba multiplication - Tk := measureKaratsuba(th) - - // improvement over Tb - delta := (Tb - Tk) * 100 / Tb - - fmt.Printf("th = %3d Tk = %10s %4d%%", th, Tk, delta) - - // determine break-even point - if Tk < Tb && th1 < 0 { - th1 = th - fmt.Print(" break-even point") - } - - // determine diminishing return - if 0 < delta && delta < deltaOld && th2 < 0 { - th2 = th - fmt.Print(" diminishing return") - } - deltaOld = delta - - fmt.Println() - - // trigger counter - if th1 >= 0 && th2 >= 0 && count < 0 { - count = 10 // this many extra measurements after we got both thresholds - } - - th++ - } -} - -func TestCalibrate(t *testing.T) { - if *calibrate { - computeThresholds() - } -} diff --git a/src/cmd/compile/internal/big/decimal.go b/src/cmd/compile/internal/big/decimal.go deleted file mode 100644 index 2c0c9daebc..0000000000 --- a/src/cmd/compile/internal/big/decimal.go +++ /dev/null @@ -1,266 +0,0 @@ -// 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 d is d.mant * 10**d.exp with 0.5 <= d.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 -} - -// at returns the i'th mantissa digit, starting with the most significant digit at 0. -func (d *decimal) at(i int) byte { - if 0 <= i && i < len(d.mant) { - return d.mant[i] - } - return '0' -} - -// Maximum shift amount that can be done in one pass without overflow. -// A Word has _W bits and (1<= 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.utoa(10) - 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)) - } -} - -// shr implements x >> s, for s <= maxShift. -func shr(x *decimal, s uint) { - // Division by 1<>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/src/cmd/compile/internal/big/decimal_test.go b/src/cmd/compile/internal/big/decimal_test.go deleted file mode 100644 index 13452f8343..0000000000 --- a/src/cmd/compile/internal/big/decimal_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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) - } - } -} - -var sink string - -func BenchmarkDecimalConversion(b *testing.B) { - for i := 0; i < b.N; i++ { - for shift := -100; shift <= +100; shift++ { - var d decimal - d.init(natOne, shift) - sink = d.String() - } - } -} diff --git a/src/cmd/compile/internal/big/doc.go b/src/cmd/compile/internal/big/doc.go deleted file mode 100644 index a3c23751ba..0000000000 --- a/src/cmd/compile/internal/big/doc.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2009 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 implements arbitrary-precision arithmetic (big numbers). -The following numeric types are supported: - - Int signed integers - Rat rational numbers - Float floating-point numbers - -The zero value for an Int, Rat, or Float correspond to 0. Thus, new -values can be declared in the usual ways and denote 0 without further -initialization: - - var x Int // &x is an *Int of value 0 - var r = &Rat{} // r is a *Rat of value 0 - y := new(Float) // y is a *Float of value 0 - -Alternatively, new values can be allocated and initialized with factory -functions of the form: - - func NewT(v V) *T - -For instance, NewInt(x) returns an *Int set to the value of the int64 -argument x, NewRat(a, b) returns a *Rat set to the fraction a/b where -a and b are int64 values, and NewFloat(f) returns a *Float initialized -to the float64 argument f. More flexibility is provided with explicit -setters, for instance: - - var z1 Int - z1.SetUint64(123) // z1 := 123 - z2 := new(Rat).SetFloat64(1.2) // z2 := 6/5 - z3 := new(Float).SetInt(z1) // z3 := 123.0 - -Setters, numeric operations and predicates are represented as methods of -the form: - - func (z *T) SetV(v V) *T // z = v - func (z *T) Unary(x *T) *T // z = unary x - func (z *T) Binary(x, y *T) *T // z = x binary y - func (x *T) Pred() P // p = pred(x) - -with T one of Int, Rat, or Float. For unary and binary operations, the -result is the receiver (usually named z in that case; see below); if it -is one of the operands x or y it may be safely overwritten (and its memory -reused). - -Arithmetic expressions are typically written as a sequence of individual -method calls, with each call corresponding to an operation. The receiver -denotes the result and the method arguments are the operation's operands. -For instance, given three *Int values a, b and c, the invocation - - c.Add(a, b) - -computes the sum a + b and stores the result in c, overwriting whatever -value was held in c before. Unless specified otherwise, operations permit -aliasing of parameters, so it is perfectly ok to write - - sum.Add(sum, x) - -to accumulate values x in a sum. - -(By always passing in a result value via the receiver, memory use can be -much better controlled. Instead of having to allocate new memory for each -result, an operation can reuse the space allocated for the result value, -and overwrite that value with the new result in the process.) - -Notational convention: Incoming method parameters (including the receiver) -are named consistently in the API to clarify their use. Incoming operands -are usually named x, y, a, b, and so on, but never z. A parameter specifying -the result is named z (typically the receiver). - -For instance, the arguments for (*Int).Add are named x and y, and because -the receiver specifies the result destination, it is called z: - - func (z *Int) Add(x, y *Int) *Int - -Methods of this form typically return the incoming receiver as well, to -enable simple call chaining. - -Methods which don't require a result value to be passed in (for instance, -Int.Sign), simply return the result. In this case, the receiver is typically -the first operand, named x: - - func (x *Int) Sign() int - -Various methods support conversions between strings and corresponding -numeric values, and vice versa: *Int, *Rat, and *Float values implement -the Stringer interface for a (default) string representation of the value, -but also provide SetString methods to initialize a value from a string in -a variety of supported formats (see the respective SetString documentation). - -Finally, *Int, *Rat, and *Float satisfy the fmt package's Scanner interface -for scanning and (except for *Rat) the Formatter interface for formatted -printing. -*/ -package big diff --git a/src/cmd/compile/internal/big/example_rat_test.go b/src/cmd/compile/internal/big/example_rat_test.go deleted file mode 100644 index ef0649785a..0000000000 --- a/src/cmd/compile/internal/big/example_rat_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// 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_test - -import ( - "cmd/compile/internal/big" - "fmt" -) - -// Use the classic continued fraction for e -// e = [1; 0, 1, 1, 2, 1, 1, ... 2n, 1, 1, ...] -// i.e., for the nth term, use -// 1 if n mod 3 != 1 -// (n-1)/3 * 2 if n mod 3 == 1 -func recur(n, lim int64) *big.Rat { - term := new(big.Rat) - if n%3 != 1 { - term.SetInt64(1) - } else { - term.SetInt64((n - 1) / 3 * 2) - } - - if n > lim { - return term - } - - // Directly initialize frac as the fractional - // inverse of the result of recur. - frac := new(big.Rat).Inv(recur(n+1, lim)) - - return term.Add(term, frac) -} - -// This example demonstrates how to use big.Rat to compute the -// first 15 terms in the sequence of rational convergents for -// the constant e (base of natural logarithm). -func Example_eConvergents() { - for i := 1; i <= 15; i++ { - r := recur(0, int64(i)) - - // Print r both as a fraction and as a floating-point number. - // Since big.Rat implements fmt.Formatter, we can use %-13s to - // get a left-aligned string representation of the fraction. - fmt.Printf("%-13s = %s\n", r, r.FloatString(8)) - } - - // Output: - // 2/1 = 2.00000000 - // 3/1 = 3.00000000 - // 8/3 = 2.66666667 - // 11/4 = 2.75000000 - // 19/7 = 2.71428571 - // 87/32 = 2.71875000 - // 106/39 = 2.71794872 - // 193/71 = 2.71830986 - // 1264/465 = 2.71827957 - // 1457/536 = 2.71828358 - // 2721/1001 = 2.71828172 - // 23225/8544 = 2.71828184 - // 25946/9545 = 2.71828182 - // 49171/18089 = 2.71828183 - // 517656/190435 = 2.71828183 -} diff --git a/src/cmd/compile/internal/big/example_test.go b/src/cmd/compile/internal/big/example_test.go deleted file mode 100644 index 8a71a08627..0000000000 --- a/src/cmd/compile/internal/big/example_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2012 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_test - -import ( - "cmd/compile/internal/big" - "fmt" - "log" - "math" -) - -func ExampleRat_SetString() { - r := new(big.Rat) - r.SetString("355/113") - fmt.Println(r.FloatString(3)) - // Output: 3.142 -} - -func ExampleInt_SetString() { - i := new(big.Int) - i.SetString("644", 8) // octal - fmt.Println(i) - // Output: 420 -} - -func ExampleRat_Scan() { - // The Scan function is rarely used directly; - // the fmt package recognizes it as an implementation of fmt.Scanner. - r := new(big.Rat) - _, err := fmt.Sscan("1.5000", r) - if err != nil { - log.Println("error scanning value:", err) - } else { - fmt.Println(r) - } - // Output: 3/2 -} - -func ExampleInt_Scan() { - // The Scan function is rarely used directly; - // the fmt package recognizes it as an implementation of fmt.Scanner. - i := new(big.Int) - _, err := fmt.Sscan("18446744073709551617", i) - if err != nil { - log.Println("error scanning value:", err) - } else { - fmt.Println(i) - } - // Output: 18446744073709551617 -} - -// This example demonstrates how to use big.Int to compute the smallest -// Fibonacci number with 100 decimal digits and to test whether it is prime. -func Example_fibonacci() { - // Initialize two big ints with the first two numbers in the sequence. - a := big.NewInt(0) - b := big.NewInt(1) - - // Initialize limit as 10^99, the smallest integer with 100 digits. - var limit big.Int - limit.Exp(big.NewInt(10), big.NewInt(99), nil) - - // Loop while a is smaller than 1e100. - for a.Cmp(&limit) < 0 { - // Compute the next Fibonacci number, storing it in a. - a.Add(a, b) - // Swap a and b so that b is the next number in the sequence. - a, b = b, a - } - fmt.Println(a) // 100-digit Fibonacci number - - // Test a for primality. - // (ProbablyPrimes' argument sets the number of Miller-Rabin - // rounds to be performed. 20 is a good value.) - fmt.Println(a.ProbablyPrime(20)) - - // Output: - // 1344719667586153181419716641724567886890850696275767987106294472017884974410332069524504824747437757 - // false -} - -// This example shows how to use big.Float to compute the square root of 2 with -// a precision of 200 bits, and how to print the result as a decimal number. -func Example_sqrt2() { - // We'll do computations with 200 bits of precision in the mantissa. - const prec = 200 - - // Compute the square root of 2 using Newton's Method. We start with - // an initial estimate for sqrt(2), and then iterate: - // x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) ) - - // Since Newton's Method doubles the number of correct digits at each - // iteration, we need at least log_2(prec) steps. - steps := int(math.Log2(prec)) - - // Initialize values we need for the computation. - two := new(big.Float).SetPrec(prec).SetInt64(2) - half := new(big.Float).SetPrec(prec).SetFloat64(0.5) - - // Use 1 as the initial estimate. - x := new(big.Float).SetPrec(prec).SetInt64(1) - - // We use t as a temporary variable. There's no need to set its precision - // since big.Float values with unset (== 0) precision automatically assume - // the largest precision of the arguments when used as the result (receiver) - // of a big.Float operation. - t := new(big.Float) - - // Iterate. - for i := 0; i <= steps; i++ { - t.Quo(two, x) // t = 2.0 / x_n - t.Add(x, t) // t = x_n + (2.0 / x_n) - x.Mul(half, t) // x_{n+1} = 0.5 * t - } - - // We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter - fmt.Printf("sqrt(2) = %.50f\n", x) - - // Print the error between 2 and x*x. - t.Mul(x, x) // t = x*x - fmt.Printf("error = %e\n", t.Sub(two, t)) - - // Output: - // sqrt(2) = 1.41421356237309504880168872420969807856967187537695 - // error = 0.000000e+00 -} diff --git a/src/cmd/compile/internal/big/float.go b/src/cmd/compile/internal/big/float.go deleted file mode 100644 index 7a9c2b3dfb..0000000000 --- a/src/cmd/compile/internal/big/float.go +++ /dev/null @@ -1,1683 +0,0 @@ -// 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 - -// These constants define supported rounding modes. -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.MantExp(mant)).Cmp(x) == 0 -// -// 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; bits > 0 - if bits <= z.prec { - // mantissa fits => nothing to do - return - } - // bits > z.prec - - // 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) & 1 // rounding bit; be safe and ensure it's a single bit - if sbit == 0 { - // TODO(gri) if rbit != 0 we don't need to compute sbit for some rounding modes (optimization) - sbit = z.mant.sticky(r) - } - sbit &= 1 // be safe and ensure it's a single bit - - // cut off extra words - n := (z.prec + (_W - 1)) / _W // mantissa length in words for desired precision - 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 (ntz) and compute lsb mask of mantissa's least-significant word - ntz := n*_W - z.prec // 0 <= ntz < _W - lsb := Word(1) << ntz - - // round if result is inexact - if rbit|sbit != 0 { - // Make rounding decision: The result mantissa is truncated ("rounded down") - // by default. Decide if we need to increment, or "round up", the (unsigned) - // mantissa. - inc := false - switch z.mode { - case ToNegativeInf: - inc = z.neg - case ToZero: - // nothing to do - case ToNearestEven: - inc = rbit != 0 && (sbit != 0 || z.mant[0]&lsb != 0) - case ToNearestAway: - inc = rbit != 0 - case AwayFromZero: - inc = true - case ToPositiveInf: - inc = !z.neg - default: - panic("unreachable") - } - - // A positive result (!z.neg) is Above the exact result if we increment, - // and it's Below if we truncate (Exact results require no rounding). - // For a negative result (z.neg) it is exactly the opposite. - z.acc = makeAcc(inc != z.neg) - - if inc { - // add 1 to mantissa - if addVW(z.mant, z.mant, lsb) != 0 { - // mantissa overflow => adjust exponent - if z.exp >= MaxExp { - // exponent overflow - z.form = inf - return - } - z.exp++ - // adjust mantissa: divide by 2 to compensate for exponent adjustment - shrVU(z.mant, z.mant, 1) - // set msb == carry == 1 from the mantissa overflow above - const msb = 1 << (_W - 1) - z.mant[n-1] |= msb - } - } - } - - // zero out trailing bits in least-significant word - z.mant[0] &^= lsb - 1 - - if debugFloat { - z.validate() - } -} - -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 e for float32 mantissa. - e := x.exp - 1 // exponent for normal mantissa m with 1.0 <= m < 2.0 - - // Compute precision p for float32 mantissa. - // If the exponent is too small, we have a denormal number before - // rounding and fewer than p mantissa bits of precision available - // (the exponent remains fixed but the mantissa gets shifted right). - p := mbits + 1 // precision of normal float - if e < emin { - // recompute precision - p = mbits + 1 - emin + int(e) - // If p == 0, the mantissa of x is shifted so much to the right - // that its msb falls immediately to the right of the float32 - // mantissa space. In other words, if the smallest denormal is - // considered "1.0", for p == 0, the mantissa value m is >= 0.5. - // If m > 0.5, it is rounded up to 1.0; i.e., the smallest denormal. - // If m == 0.5, it is rounded down to even, i.e., 0.0. - // If p < 0, the mantissa value m is <= "0.25" which is never rounded up. - if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ { - // underflow to ±0 - if x.neg { - var z float32 - return -z, Above - } - return 0.0, Below - } - // otherwise, round up - // We handle p == 0 explicitly because it's easy and because - // Float.round doesn't support rounding to 0 bits of precision. - if p == 0 { - if x.neg { - return -math.SmallestNonzeroFloat32, Below - } - return math.SmallestNonzeroFloat32, Above - } - } - // p > 0 - - // 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 the exponent is too large, also overflow to ±Inf. - if r.form == inf || 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: recompute precision - // Since rounding may have at best increased precision - // and we have eliminated p <= 0 early, we know p > 0. - // bexp == 0 for denormals - p = mbits + 1 - emin + int(e) - mant = msb32(r.mant) >> uint(fbits-p) - } else { - // normal number: emin <= e <= emax - bexp = uint32(e+bias) << mbits - mant = msb32(r.mant) >> ebits & (1< 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 e for float64 mantissa. - e := x.exp - 1 // exponent for normal mantissa m with 1.0 <= m < 2.0 - - // Compute precision p for float64 mantissa. - // If the exponent is too small, we have a denormal number before - // rounding and fewer than p mantissa bits of precision available - // (the exponent remains fixed but the mantissa gets shifted right). - p := mbits + 1 // precision of normal float - if e < emin { - // recompute precision - p = mbits + 1 - emin + int(e) - // If p == 0, the mantissa of x is shifted so much to the right - // that its msb falls immediately to the right of the float64 - // mantissa space. In other words, if the smallest denormal is - // considered "1.0", for p == 0, the mantissa value m is >= 0.5. - // If m > 0.5, it is rounded up to 1.0; i.e., the smallest denormal. - // If m == 0.5, it is rounded down to even, i.e., 0.0. - // If p < 0, the mantissa value m is <= "0.25" which is never rounded up. - if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ { - // underflow to ±0 - if x.neg { - var z float64 - return -z, Above - } - return 0.0, Below - } - // otherwise, round up - // We handle p == 0 explicitly because it's easy and because - // Float.round doesn't support rounding to 0 bits of precision. - if p == 0 { - if x.neg { - return -math.SmallestNonzeroFloat64, Below - } - return math.SmallestNonzeroFloat64, Above - } - } - // p > 0 - - // 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 the exponent is too large, also overflow to ±Inf. - if r.form == inf || 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: recompute precision - // Since rounding may have at best increased precision - // and we have eliminated p <= 0 early, we know p > 0. - // bexp == 0 for denormals - p = mbits + 1 - emin + int(e) - mant = msb64(r.mant) >> uint(fbits-p) - } else { - // normal number: emin <= e <= emax - bexp = uint64(e+bias) << mbits - mant = msb64(r.mant) >> ebits & (1< 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 if 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 canceled 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 (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{"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/src/cmd/compile/internal/big/float_test.go b/src/cmd/compile/internal/big/float_test.go deleted file mode 100644 index 464619b338..0000000000 --- a/src/cmd/compile/internal/big/float_test.go +++ /dev/null @@ -1,1764 +0,0 @@ -// 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 to zero - {"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 - - // special denormal cases (see issues 14553, 14651) - {"0x0.0000001p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero - {"0x0.0000008p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero - {"0x0.0000010p-126", math.Float32frombits(0x00000000), Below}, // rounded down to even - {"0x0.0000011p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal - {"0x0.0000018p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal - - {"0x1.0000000p-149", math.Float32frombits(0x00000001), Exact}, // smallest denormal - {"0x0.0000020p-126", math.Float32frombits(0x00000001), Exact}, // smallest denormal - {"0x0.fffffe0p-126", math.Float32frombits(0x007fffff), Exact}, // largest denormal - {"0x1.0000000p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal - - {"0x0.8p-149", math.Float32frombits(0x000000000), Below}, // rounded down to even - {"0x0.9p-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal - {"0x0.ap-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal - {"0x0.bp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal - {"0x0.cp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal - - {"0x1.0p-149", math.Float32frombits(0x000000001), Exact}, // smallest denormal - {"0x1.7p-149", math.Float32frombits(0x000000001), Below}, - {"0x1.8p-149", math.Float32frombits(0x000000002), Above}, - {"0x1.9p-149", math.Float32frombits(0x000000002), Above}, - - {"0x2.0p-149", math.Float32frombits(0x000000002), Exact}, - {"0x2.8p-149", math.Float32frombits(0x000000002), Below}, // rounded down to even - {"0x2.9p-149", math.Float32frombits(0x000000003), Above}, - - {"0x3.0p-149", math.Float32frombits(0x000000003), Exact}, - {"0x3.7p-149", math.Float32frombits(0x000000003), Below}, - {"0x3.8p-149", math.Float32frombits(0x000000004), Above}, // rounded up to even - - {"0x4.0p-149", math.Float32frombits(0x000000004), Exact}, - {"0x4.8p-149", math.Float32frombits(0x000000004), Below}, // rounded down to even - {"0x4.9p-149", math.Float32frombits(0x000000005), Above}, - - // specific case from issue 14553 - {"0x7.7p-149", math.Float32frombits(0x000000007), Below}, - {"0x7.8p-149", math.Float32frombits(0x000000008), Above}, - {"0x7.9p-149", math.Float32frombits(0x000000008), Above}, - - // 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 (%#08x, %s); want %g (%#08x, %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 to zero - {"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.00000000000010p-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 - - // special denormal cases (see issues 14553, 14651) - {"0x0.00000000000001p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero - {"0x0.00000000000004p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero - {"0x0.00000000000008p-1022", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even - {"0x0.00000000000009p-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - {"0x0.0000000000000ap-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - - {"0x0.8p-1074", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even - {"0x0.9p-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - {"0x0.ap-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - {"0x0.bp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - {"0x0.cp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal - - {"0x1.0p-1074", math.Float64frombits(0x00000000000000001), Exact}, - {"0x1.7p-1074", math.Float64frombits(0x00000000000000001), Below}, - {"0x1.8p-1074", math.Float64frombits(0x00000000000000002), Above}, - {"0x1.9p-1074", math.Float64frombits(0x00000000000000002), Above}, - - {"0x2.0p-1074", math.Float64frombits(0x00000000000000002), Exact}, - {"0x2.8p-1074", math.Float64frombits(0x00000000000000002), Below}, // rounded down to even - {"0x2.9p-1074", math.Float64frombits(0x00000000000000003), Above}, - - {"0x3.0p-1074", math.Float64frombits(0x00000000000000003), Exact}, - {"0x3.7p-1074", math.Float64frombits(0x00000000000000003), Below}, - {"0x3.8p-1074", math.Float64frombits(0x00000000000000004), Above}, // rounded up to even - - {"0x4.0p-1074", math.Float64frombits(0x00000000000000004), Exact}, - {"0x4.8p-1074", math.Float64frombits(0x00000000000000004), Below}, // rounded down to even - {"0x4.9p-1074", math.Float64frombits(0x00000000000000005), Above}, - - // 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 (%#016x, %s); want %g (%#016x, %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< y: - want = +1 - } - if got != want { - t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want) - } - } - } - } -} diff --git a/src/cmd/compile/internal/big/floatconv.go b/src/cmd/compile/internal/big/floatconv.go deleted file mode 100644 index a884df6fe1..0000000000 --- a/src/cmd/compile/internal/big/floatconv.go +++ /dev/null @@ -1,275 +0,0 @@ -// 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, and - // we split powers of 10 into the product of the same powers of - // 2 and 5. This reduces the size of the multiplication factor - // needed for base-10 exponents. - - // normalize mantissa and determine initial exponent contributions - exp2 := int64(len(z.mant))*_W - fnorm(z.mant) - exp5 := int64(0) - - // determine binary or decimal exponent contribution of decimal point - 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 accordingly. - d := int64(fcount) - switch b { - case 10: - exp5 = d - fallthrough // 10**e == 5**e * 2**e - case 2: - exp2 += d - case 16: - exp2 += d * 4 // hexadecimal digits are 4 bits each - default: - panic("unexpected mantissa base") - } - // fcount consumed - not needed anymore - } - - // take actual exponent into account - switch ebase { - case 10: - exp5 += exp - fallthrough - case 2: - exp2 += exp - default: - panic("unexpected exponent base") - } - // exp consumed - not needed 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 exp5 == 0 { - // no decimal exponent contribution - z.round(0) - return - } - // exp5 != 0 - - // apply 5**exp5 - p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number? - if exp5 < 0 { - z.Quo(z, p.pow5(uint64(-exp5))) - } else { - z.Mul(z, p.pow5(uint64(exp5))) - } - - return -} - -// These powers of 5 fit into a uint64. -// -// for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 { -// fmt.Println(q) -// } -// -var pow5tab = [...]uint64{ - 1, - 5, - 25, - 125, - 625, - 3125, - 15625, - 78125, - 390625, - 1953125, - 9765625, - 48828125, - 244140625, - 1220703125, - 6103515625, - 30517578125, - 152587890625, - 762939453125, - 3814697265625, - 19073486328125, - 95367431640625, - 476837158203125, - 2384185791015625, - 11920928955078125, - 59604644775390625, - 298023223876953125, - 1490116119384765625, - 7450580596923828125, -} - -// pow5 sets z to 5**n and returns z. -// n must not be negative. -func (z *Float) pow5(n uint64) *Float { - const m = uint64(len(pow5tab) - 1) - if n <= m { - return z.SetUint64(pow5tab[n]) - } - // n > m - - z.SetUint64(pow5tab[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).SetUint64(5) - - 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/src/cmd/compile/internal/big/floatconv_test.go b/src/cmd/compile/internal/big/floatconv_test.go deleted file mode 100644 index b2a1ab05fc..0000000000 --- a/src/cmd/compile/internal/big/floatconv_test.go +++ /dev/null @@ -1,667 +0,0 @@ -// 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) - } - } -} - -func fdiv(a, b float64) float64 { return a / b } - -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"}, - - {5e-304 / 1e20, 'g', -1, "5e-324"}, - {-5e-304 / 1e20, 'g', -1, "-5e-324"}, - {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic - {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic - - {32, 'g', -1, "32"}, - {32, 'g', 0, "3e+01"}, - - {100, 'x', -1, "%x"}, - - // {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs - // {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs - {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"}, - - // Issue 15918. - {1, 'f', -10, "1"}, - {1, 'f', -11, "1"}, - {1, 'f', -12, "1"}, - } { - // The test cases are from the strconv package which tests float64 values. - // When formatting values with prec = -1 (shortest representation), - // the actually available mantissa precision matters. - // For denormalized values, that precision is < 53 (SetFloat64 default). - // Compute and set the actual precision explicitly. - f := new(Float).SetPrec(actualPrec(test.x)).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) - continue - } - - 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) - } - } -} - -// actualPrec returns the number of actually used mantissa bits. -func actualPrec(x float64) uint { - if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 { - // x is denormalized - return 64 - nlz64(bits&(1<<52-1)) - } - return 53 -} - -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"}, - {"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"}, - {"1e646456993", 64, 'p', 0, "+Inf"}, - {"1e1000000000", 64, 'p', 0, "+Inf"}, - {"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"}, - {"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"}, - {"1e-646456994", 64, 'p', 0, "0"}, - {"1e-1000000000", 64, 'p', 0, "0"}, - - // minimum and maximum values - {"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"}, - {"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"}, - {"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"}, - {"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"}, - - // 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 - }{ - // 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"}, - - // *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) - } - } -} - -func BenchmarkParseFloatSmallExp(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, s := range []string{ - "1e0", - "1e-1", - "1e-2", - "1e-3", - "1e-4", - "1e-5", - "1e-10", - "1e-20", - "1e-50", - "1e1", - "1e2", - "1e3", - "1e4", - "1e5", - "1e10", - "1e20", - "1e50", - } { - var x Float - _, _, err := x.Parse(s, 0) - if err != nil { - b.Fatalf("%s: %v", s, err) - } - } - } -} - -func BenchmarkParseFloatLargeExp(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, s := range []string{ - "1e0", - "1e-10", - "1e-20", - "1e-30", - "1e-40", - "1e-50", - "1e-100", - "1e-500", - "1e-1000", - "1e-5000", - "1e-10000", - "1e10", - "1e20", - "1e30", - "1e40", - "1e50", - "1e100", - "1e500", - "1e1000", - "1e5000", - "1e10000", - } { - var x Float - _, _, err := x.Parse(s, 0) - if err != nil { - b.Fatalf("%s: %v", s, err) - } - } - } -} diff --git a/src/cmd/compile/internal/big/floatexample_test.go b/src/cmd/compile/internal/big/floatexample_test.go deleted file mode 100644 index beb9052ebd..0000000000 --- a/src/cmd/compile/internal/big/floatexample_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// 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_test - -import ( - "cmd/compile/internal/big" - "fmt" - "math" -) - -func ExampleFloat_Add() { - // Operate 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 ExampleFloat_shift() { - // Implement 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 -} - -func ExampleRoundingMode() { - operands := []float64{2.6, 2.5, 2.1, -2.1, -2.5, -2.6} - - fmt.Print(" x") - for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ { - fmt.Printf(" %s", mode) - } - fmt.Println() - - for _, f64 := range operands { - fmt.Printf("%4g", f64) - for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ { - // sample operands above require 2 bits to represent mantissa - // set binary precision to 2 to round them to integer values - f := new(big.Float).SetPrec(2).SetMode(mode).SetFloat64(f64) - fmt.Printf(" %*g", len(mode.String()), f) - } - fmt.Println() - } - - // Output: - // x ToNearestEven ToNearestAway ToZero AwayFromZero ToNegativeInf ToPositiveInf - // 2.6 3 3 2 3 2 3 - // 2.5 2 3 2 3 2 3 - // 2.1 2 2 2 3 2 3 - // -2.1 -2 -2 -2 -3 -3 -2 - // -2.5 -2 -3 -2 -3 -3 -2 - // -2.6 -3 -3 -2 -3 -3 -2 -} diff --git a/src/cmd/compile/internal/big/floatmarsh.go b/src/cmd/compile/internal/big/floatmarsh.go deleted file mode 100644 index 3725d4b834..0000000000 --- a/src/cmd/compile/internal/big/floatmarsh.go +++ /dev/null @@ -1,120 +0,0 @@ -// 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 encoding/decoding of Floats. - -package big - -import ( - "encoding/binary" - "fmt" -) - -// Gob codec version. Permits backward-compatible changes to the encoding. -const floatGobVersion byte = 1 - -// GobEncode implements the gob.GobEncoder interface. -// The Float value and all its attributes (precision, -// rounding mode, accuracy) are marshalled. -func (x *Float) GobEncode() ([]byte, error) { - if x == nil { - return nil, nil - } - - // determine max. space (bytes) required for encoding - sz := 1 + 1 + 4 // version + mode|acc|form|neg (3+2+2+1bit) + prec - n := 0 // number of mantissa words - if x.form == finite { - // add space for mantissa and exponent - n = int((x.prec + (_W - 1)) / _W) // required mantissa length in words for given precision - // actual mantissa slice could be shorter (trailing 0's) or longer (unused bits): - // - if shorter, only encode the words present - // - if longer, cut off unused words when encoding in bytes - // (in practice, this should never happen since rounding - // takes care of it, but be safe and do it always) - if len(x.mant) < n { - n = len(x.mant) - } - // len(x.mant) >= n - sz += 4 + n*_S // exp + mant - } - buf := make([]byte, sz) - - buf[0] = floatGobVersion - b := byte(x.mode&7)<<5 | byte((x.acc+1)&3)<<3 | byte(x.form&3)<<1 - if x.neg { - b |= 1 - } - buf[1] = b - binary.BigEndian.PutUint32(buf[2:], x.prec) - - if x.form == finite { - binary.BigEndian.PutUint32(buf[6:], uint32(x.exp)) - x.mant[len(x.mant)-n:].bytes(buf[10:]) // cut off unused trailing words - } - - return buf, nil -} - -// GobDecode implements the gob.GobDecoder interface. -// The result is rounded per the precision and rounding mode of -// z unless z's precision is 0, in which case z is set exactly -// to the decoded value. -func (z *Float) GobDecode(buf []byte) error { - if len(buf) == 0 { - // Other side sent a nil or default value. - *z = Float{} - return nil - } - - if buf[0] != floatGobVersion { - return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0]) - } - - oldPrec := z.prec - oldMode := z.mode - - b := buf[1] - z.mode = RoundingMode((b >> 5) & 7) - z.acc = Accuracy((b>>3)&3) - 1 - z.form = form((b >> 1) & 3) - z.neg = b&1 != 0 - z.prec = binary.BigEndian.Uint32(buf[2:]) - - if z.form == finite { - z.exp = int32(binary.BigEndian.Uint32(buf[6:])) - z.mant = z.mant.setBytes(buf[10:]) - } - - if oldPrec != 0 { - z.mode = oldMode - z.SetPrec(uint(oldPrec)) - } - - return nil -} - -// MarshalText implements the encoding.TextMarshaler interface. -// Only the Float value is marshaled (in full precision), other -// attributes such as precision or accuracy are ignored. -func (x *Float) MarshalText() (text []byte, err error) { - if x == nil { - return []byte(""), nil - } - var buf []byte - return x.Append(buf, 'g', -1), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// The result is rounded per the precision and rounding mode of z. -// If z's precision is 0, it is changed to 64 before rounding takes -// effect. -func (z *Float) UnmarshalText(text []byte) error { - // TODO(gri): get rid of the []byte/string conversion - _, _, err := z.Parse(string(text), 0) - if err != nil { - err = fmt.Errorf("math/big: cannot unmarshal %q into a *big.Float (%v)", text, err) - } - return err -} diff --git a/src/cmd/compile/internal/big/floatmarsh_test.go b/src/cmd/compile/internal/big/floatmarsh_test.go deleted file mode 100644 index 5bd906ddae..0000000000 --- a/src/cmd/compile/internal/big/floatmarsh_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// 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" - "encoding/gob" - "encoding/json" - "io" - "testing" -) - -var floatVals = []string{ - "0", - "1", - "0.1", - "2.71828", - "1234567890", - "3.14e1234", - "3.14e-1234", - "0.738957395793475734757349579759957975985497e100", - "0.73895739579347546656564656573475734957975995797598589749859834759476745986795497e100", - "inf", - "Inf", -} - -func TestFloatGobEncoding(t *testing.T) { - var medium bytes.Buffer - enc := gob.NewEncoder(&medium) - dec := gob.NewDecoder(&medium) - for _, test := range floatVals { - for _, sign := range []string{"", "+", "-"} { - for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} { - for _, mode := range []RoundingMode{ToNearestEven, ToNearestAway, ToZero, AwayFromZero, ToNegativeInf, ToPositiveInf} { - medium.Reset() // empty buffer for each test case (in case of failures) - x := sign + test - - var tx Float - _, _, err := tx.SetPrec(prec).SetMode(mode).Parse(x, 0) - if err != nil { - t.Errorf("parsing of %s (%dbits, %v) failed (invalid test case): %v", x, prec, mode, err) - continue - } - - // If tx was set to prec == 0, tx.Parse(x, 0) assumes precision 64. Correct it. - if prec == 0 { - tx.SetPrec(0) - } - - if err := enc.Encode(&tx); err != nil { - t.Errorf("encoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err) - continue - } - - var rx Float - if err := dec.Decode(&rx); err != nil { - t.Errorf("decoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err) - continue - } - - if rx.Cmp(&tx) != 0 { - t.Errorf("transmission of %s failed: got %s want %s", x, rx.String(), tx.String()) - continue - } - - if rx.Prec() != prec { - t.Errorf("transmission of %s's prec failed: got %d want %d", x, rx.Prec(), prec) - } - - if rx.Mode() != mode { - t.Errorf("transmission of %s's mode failed: got %s want %s", x, rx.Mode(), mode) - } - - if rx.Acc() != tx.Acc() { - t.Errorf("transmission of %s's accuracy failed: got %s want %s", x, rx.Acc(), tx.Acc()) - } - } - } - } - } -} - -func TestFloatCorruptGob(t *testing.T) { - var buf bytes.Buffer - tx := NewFloat(4 / 3).SetPrec(1000).SetMode(ToPositiveInf) - if err := gob.NewEncoder(&buf).Encode(tx); err != nil { - t.Fatal(err) - } - b := buf.Bytes() - - var rx Float - if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err != nil { - t.Fatal(err) - } - - if err := gob.NewDecoder(bytes.NewReader(b[:10])).Decode(&rx); err != io.ErrUnexpectedEOF { - t.Errorf("got %v want EOF", err) - } - - b[1] = 0 - if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err == nil { - t.Fatal("got nil want version error") - } -} - -func TestFloatJSONEncoding(t *testing.T) { - for _, test := range floatVals { - for _, sign := range []string{"", "+", "-"} { - for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} { - x := sign + test - var tx Float - _, _, err := tx.SetPrec(prec).Parse(x, 0) - if err != nil { - t.Errorf("parsing of %s (prec = %d) failed (invalid test case): %v", x, prec, err) - continue - } - b, err := json.Marshal(&tx) - if err != nil { - t.Errorf("marshaling of %v (prec = %d) failed: %v", &tx, prec, err) - continue - } - var rx Float - rx.SetPrec(prec) - if err := json.Unmarshal(b, &rx); err != nil { - t.Errorf("unmarshaling of %v (prec = %d) failed: %v", &tx, prec, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("JSON encoding of %v (prec = %d) failed: got %v want %v", &tx, prec, &rx, &tx) - } - } - } - } -} diff --git a/src/cmd/compile/internal/big/ftoa.go b/src/cmd/compile/internal/big/ftoa.go deleted file mode 100644 index 57b16e1ad1..0000000000 --- a/src/cmd/compile/internal/big/ftoa.go +++ /dev/null @@ -1,459 +0,0 @@ -// 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 ( - "bytes" - "fmt" - "strconv" -) - -// 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 decimal digits necessary to identify the value x uniquely using -// x.Prec() mantissa bits. -// The prec value is ignored for the 'b' or 'p' format. -func (x *Float) Text(format byte, prec int) string { - cap := 10 // TODO(gri) determine a good/better value here - if prec > 0 { - cap += prec - } - return string(x.Append(make([]byte, 0, cap), format, prec)) -} - -// String formats x like x.Text('g', 10). -// (String must be called explicitly, Float.Format does not support %s verb.) -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 { - // x != 0 - d.init(x.mant, int(x.exp)-x.mant.bitLen()) - } - - // 2) round to desired precision - shortest := false - if prec < 0 { - shortest = true - roundShortest(&d, x) - // 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) -} - -func roundShortest(d *decimal, x *Float) { - // if the mantissa is zero, the number is zero - stop now - if len(d.mant) == 0 { - return - } - - // Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp] - // (possibly exclusive) round to x for the given precision of x. - // Compute the lower and upper bound in decimal form and find the - // shortest decimal number d such that lower <= d <= upper. - - // TODO(gri) strconv/ftoa.do describes a shortcut in some cases. - // See if we can use it (in adjusted form) here as well. - - // 1) Compute normalized mantissa mant and exponent exp for x such - // that the lsb of mant corresponds to 1/2 ulp for the precision of - // x (i.e., for mant we want x.prec + 1 bits). - mant := nat(nil).set(x.mant) - exp := int(x.exp) - mant.bitLen() - s := mant.bitLen() - int(x.prec+1) - switch { - case s < 0: - mant = mant.shl(mant, uint(-s)) - case s > 0: - mant = mant.shr(mant, uint(+s)) - } - exp += s - // x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec - - // 2) Compute lower bound by subtracting 1/2 ulp. - var lower decimal - var tmp nat - lower.init(tmp.sub(mant, natOne), exp) - - // 3) Compute upper bound by adding 1/2 ulp. - var upper decimal - upper.init(tmp.add(mant, natOne), exp) - - // The upper and lower bounds are possible outputs only if - // the original mantissa is even, so that ToNearestEven rounding - // would round to the original mantissa and not the neighbors. - inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1 - - // Now we can figure out the minimum number of digits required. - // Walk along until d has distinguished itself from upper and lower. - for i, m := range d.mant { - l := lower.at(i) - u := upper.at(i) - - // Okay to round down (truncate) if lower has a different digit - // or if lower is inclusive and is exactly the result of rounding - // down (i.e., and we have reached the final digit of lower). - okdown := l != m || inclusive && i+1 == len(lower.mant) - - // Okay to round up if upper has a different digit and either upper - // is inclusive or upper is bigger than the result of rounding up. - okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant)) - - // If it's okay to do either, then round to the nearest one. - // If it's okay to do only one, do it. - switch { - case okdown && okup: - d.round(i + 1) - return - case okdown: - d.roundDown(i + 1) - return - case okup: - d.roundUp(i + 1) - return - } - } -} - -// %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++ { - buf = append(buf, d.at(d.exp+i)) - } - } - - 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.utoa(10)...) - 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, -// and 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, bytes.TrimRight(m.utoa(16), "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 ('b', 'e', 'E', 'f', 'F', -// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the -// interpretation of '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 flags -// '+' and ' ' for sign control, '0' for space or zero padding, -// and '-' for left or right justification. See the fmt package -// for details. -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 { - 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/src/cmd/compile/internal/big/gcd_test.go b/src/cmd/compile/internal/big/gcd_test.go deleted file mode 100644 index a929bf597f..0000000000 --- a/src/cmd/compile/internal/big/gcd_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2012 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 a GCD benchmark. -// Usage: go test math/big -test.bench GCD - -package big - -import ( - "math/rand" - "testing" -) - -// randInt returns a pseudo-random Int in the range [1<<(size-1), (1< 1<<(size-1) -} - -func runGCD(b *testing.B, aSize, bSize uint) { - b.Run("WithoutXY", func(b *testing.B) { - runGCDExt(b, aSize, bSize, false) - }) - b.Run("WithXY", func(b *testing.B) { - runGCDExt(b, aSize, bSize, true) - }) -} - -func runGCDExt(b *testing.B, aSize, bSize uint, calcXY bool) { - b.StopTimer() - var r = rand.New(rand.NewSource(1234)) - aa := randInt(r, aSize) - bb := randInt(r, bSize) - var x, y *Int - if calcXY { - x = new(Int) - y = new(Int) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - new(Int).GCD(x, y, aa, bb) - } -} - -func BenchmarkGCD10x10(b *testing.B) { runGCD(b, 10, 10) } -func BenchmarkGCD10x100(b *testing.B) { runGCD(b, 10, 100) } -func BenchmarkGCD10x1000(b *testing.B) { runGCD(b, 10, 1000) } -func BenchmarkGCD10x10000(b *testing.B) { runGCD(b, 10, 10000) } -func BenchmarkGCD10x100000(b *testing.B) { runGCD(b, 10, 100000) } -func BenchmarkGCD100x100(b *testing.B) { runGCD(b, 100, 100) } -func BenchmarkGCD100x1000(b *testing.B) { runGCD(b, 100, 1000) } -func BenchmarkGCD100x10000(b *testing.B) { runGCD(b, 100, 10000) } -func BenchmarkGCD100x100000(b *testing.B) { runGCD(b, 100, 100000) } -func BenchmarkGCD1000x1000(b *testing.B) { runGCD(b, 1000, 1000) } -func BenchmarkGCD1000x10000(b *testing.B) { runGCD(b, 1000, 10000) } -func BenchmarkGCD1000x100000(b *testing.B) { runGCD(b, 1000, 100000) } -func BenchmarkGCD10000x10000(b *testing.B) { runGCD(b, 10000, 10000) } -func BenchmarkGCD10000x100000(b *testing.B) { runGCD(b, 10000, 100000) } -func BenchmarkGCD100000x100000(b *testing.B) { runGCD(b, 100000, 100000) } diff --git a/src/cmd/compile/internal/big/hilbert_test.go b/src/cmd/compile/internal/big/hilbert_test.go deleted file mode 100644 index 1a84341b3c..0000000000 --- a/src/cmd/compile/internal/big/hilbert_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2009 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. - -// A little test program and benchmark for rational arithmetics. -// Computes a Hilbert matrix, its inverse, multiplies them -// and verifies that the product is the identity matrix. - -package big - -import ( - "fmt" - "testing" -) - -type matrix struct { - n, m int - a []*Rat -} - -func (a *matrix) at(i, j int) *Rat { - if !(0 <= i && i < a.n && 0 <= j && j < a.m) { - panic("index out of range") - } - return a.a[i*a.m+j] -} - -func (a *matrix) set(i, j int, x *Rat) { - if !(0 <= i && i < a.n && 0 <= j && j < a.m) { - panic("index out of range") - } - a.a[i*a.m+j] = x -} - -func newMatrix(n, m int) *matrix { - if !(0 <= n && 0 <= m) { - panic("illegal matrix") - } - a := new(matrix) - a.n = n - a.m = m - a.a = make([]*Rat, n*m) - return a -} - -func newUnit(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - x := NewRat(0, 1) - if i == j { - x.SetInt64(1) - } - a.set(i, j, x) - } - } - return a -} - -func newHilbert(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - a.set(i, j, NewRat(1, int64(i+j+1))) - } - } - return a -} - -func newInverseHilbert(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - x1 := new(Rat).SetInt64(int64(i + j + 1)) - x2 := new(Rat).SetInt(new(Int).Binomial(int64(n+i), int64(n-j-1))) - x3 := new(Rat).SetInt(new(Int).Binomial(int64(n+j), int64(n-i-1))) - x4 := new(Rat).SetInt(new(Int).Binomial(int64(i+j), int64(i))) - - x1.Mul(x1, x2) - x1.Mul(x1, x3) - x1.Mul(x1, x4) - x1.Mul(x1, x4) - - if (i+j)&1 != 0 { - x1.Neg(x1) - } - - a.set(i, j, x1) - } - } - return a -} - -func (a *matrix) mul(b *matrix) *matrix { - if a.m != b.n { - panic("illegal matrix multiply") - } - c := newMatrix(a.n, b.m) - for i := 0; i < c.n; i++ { - for j := 0; j < c.m; j++ { - x := NewRat(0, 1) - for k := 0; k < a.m; k++ { - x.Add(x, new(Rat).Mul(a.at(i, k), b.at(k, j))) - } - c.set(i, j, x) - } - } - return c -} - -func (a *matrix) eql(b *matrix) bool { - if a.n != b.n || a.m != b.m { - return false - } - for i := 0; i < a.n; i++ { - for j := 0; j < a.m; j++ { - if a.at(i, j).Cmp(b.at(i, j)) != 0 { - return false - } - } - } - return true -} - -func (a *matrix) String() string { - s := "" - for i := 0; i < a.n; i++ { - for j := 0; j < a.m; j++ { - s += fmt.Sprintf("\t%s", a.at(i, j)) - } - s += "\n" - } - return s -} - -func doHilbert(t *testing.T, n int) { - a := newHilbert(n) - b := newInverseHilbert(n) - I := newUnit(n) - ab := a.mul(b) - if !ab.eql(I) { - if t == nil { - panic("Hilbert failed") - } - t.Errorf("a = %s\n", a) - t.Errorf("b = %s\n", b) - t.Errorf("a*b = %s\n", ab) - t.Errorf("I = %s\n", I) - } -} - -func TestHilbert(t *testing.T) { - doHilbert(t, 10) -} - -func BenchmarkHilbert(b *testing.B) { - for i := 0; i < b.N; i++ { - doHilbert(nil, 10) - } -} diff --git a/src/cmd/compile/internal/big/int.go b/src/cmd/compile/internal/big/int.go deleted file mode 100644 index f2a75d1cd5..0000000000 --- a/src/cmd/compile/internal/big/int.go +++ /dev/null @@ -1,934 +0,0 @@ -// Copyright 2009 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 signed multi-precision integers. - -package big - -import ( - "fmt" - "io" - "math/rand" - "strings" -) - -// An Int represents a signed multi-precision integer. -// The zero value for an Int represents the value 0. -type Int struct { - neg bool // sign - abs nat // absolute value of the integer -} - -var intOne = &Int{false, natOne} - -// Sign returns: -// -// -1 if x < 0 -// 0 if x == 0 -// +1 if x > 0 -// -func (x *Int) Sign() int { - if len(x.abs) == 0 { - return 0 - } - if x.neg { - return -1 - } - return 1 -} - -// SetInt64 sets z to x and returns z. -func (z *Int) SetInt64(x int64) *Int { - neg := false - if x < 0 { - neg = true - x = -x - } - z.abs = z.abs.setUint64(uint64(x)) - z.neg = neg - return z -} - -// SetUint64 sets z to x and returns z. -func (z *Int) SetUint64(x uint64) *Int { - z.abs = z.abs.setUint64(x) - z.neg = false - return z -} - -// NewInt allocates and returns a new Int set to x. -func NewInt(x int64) *Int { - return new(Int).SetInt64(x) -} - -// Set sets z to x and returns z. -func (z *Int) Set(x *Int) *Int { - if z != x { - z.abs = z.abs.set(x.abs) - z.neg = x.neg - } - return z -} - -// Bits provides raw (unchecked but fast) access to x by returning its -// absolute value as a little-endian Word slice. The result and x share -// the same underlying array. -// Bits is intended to support implementation of missing low-level Int -// functionality outside this package; it should be avoided otherwise. -func (x *Int) Bits() []Word { - return x.abs -} - -// SetBits provides raw (unchecked but fast) access to z by setting its -// value to abs, interpreted as a little-endian Word slice, and returning -// z. The result and abs share the same underlying array. -// SetBits is intended to support implementation of missing low-level Int -// functionality outside this package; it should be avoided otherwise. -func (z *Int) SetBits(abs []Word) *Int { - z.abs = nat(abs).norm() - z.neg = false - return z -} - -// Abs sets z to |x| (the absolute value of x) and returns z. -func (z *Int) Abs(x *Int) *Int { - z.Set(x) - z.neg = false - return z -} - -// Neg sets z to -x and returns z. -func (z *Int) Neg(x *Int) *Int { - z.Set(x) - z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign - return z -} - -// Add sets z to the sum x+y and returns z. -func (z *Int) Add(x, y *Int) *Int { - neg := x.neg - if x.neg == y.neg { - // x + y == x + y - // (-x) + (-y) == -(x + y) - z.abs = z.abs.add(x.abs, y.abs) - } else { - // x + (-y) == x - y == -(y - x) - // (-x) + y == y - x == -(x - y) - if x.abs.cmp(y.abs) >= 0 { - z.abs = z.abs.sub(x.abs, y.abs) - } else { - neg = !neg - z.abs = z.abs.sub(y.abs, x.abs) - } - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - return z -} - -// Sub sets z to the difference x-y and returns z. -func (z *Int) Sub(x, y *Int) *Int { - neg := x.neg - if x.neg != y.neg { - // x - (-y) == x + y - // (-x) - y == -(x + y) - z.abs = z.abs.add(x.abs, y.abs) - } else { - // x - y == x - y == -(y - x) - // (-x) - (-y) == y - x == -(x - y) - if x.abs.cmp(y.abs) >= 0 { - z.abs = z.abs.sub(x.abs, y.abs) - } else { - neg = !neg - z.abs = z.abs.sub(y.abs, x.abs) - } - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - return z -} - -// Mul sets z to the product x*y and returns z. -func (z *Int) Mul(x, y *Int) *Int { - // x * y == x * y - // x * (-y) == -(x * y) - // (-x) * y == -(x * y) - // (-x) * (-y) == x * y - z.abs = z.abs.mul(x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign - return z -} - -// MulRange sets z to the product of all integers -// in the range [a, b] inclusively and returns z. -// If a > b (empty range), the result is 1. -func (z *Int) MulRange(a, b int64) *Int { - switch { - case a > b: - return z.SetInt64(1) // empty range - case a <= 0 && b >= 0: - return z.SetInt64(0) // range includes 0 - } - // a <= b && (b < 0 || a > 0) - - neg := false - if a < 0 { - neg = (b-a)&1 == 0 - a, b = -b, -a - } - - z.abs = z.abs.mulRange(uint64(a), uint64(b)) - z.neg = neg - return z -} - -// 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) - return z.Quo(&a, &b) -} - -// Quo sets z to the quotient x/y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Quo implements truncated division (like Go); see QuoRem for more details. -func (z *Int) Quo(x, y *Int) *Int { - z.abs, _ = z.abs.div(nil, x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign - return z -} - -// Rem sets z to the remainder x%y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Rem implements truncated modulus (like Go); see QuoRem for more details. -func (z *Int) Rem(x, y *Int) *Int { - _, z.abs = nat(nil).div(z.abs, x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg // 0 has no sign - return z -} - -// QuoRem sets z to the quotient x/y and r to the remainder x%y -// and returns the pair (z, r) for y != 0. -// If y == 0, a division-by-zero run-time panic occurs. -// -// QuoRem implements T-division and modulus (like Go): -// -// q = x/y with the result truncated to zero -// r = x - y*q -// -// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.) -// See DivMod for Euclidean division and modulus (unlike Go). -// -func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) { - z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs) - z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign - return z, r -} - -// Div sets z to the quotient x/y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Div implements Euclidean division (unlike Go); see DivMod for more details. -func (z *Int) Div(x, y *Int) *Int { - y_neg := y.neg // z may be an alias for y - var r Int - z.QuoRem(x, y, &r) - if r.neg { - if y_neg { - z.Add(z, intOne) - } else { - z.Sub(z, intOne) - } - } - return z -} - -// Mod sets z to the modulus x%y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Mod implements Euclidean modulus (unlike Go); see DivMod for more details. -func (z *Int) Mod(x, y *Int) *Int { - y0 := y // save y - if z == y || alias(z.abs, y.abs) { - y0 = new(Int).Set(y) - } - var q Int - q.QuoRem(x, y, z) - if z.neg { - if y0.neg { - z.Sub(z, y0) - } else { - z.Add(z, y0) - } - } - return z -} - -// DivMod sets z to the quotient x div y and m to the modulus x mod y -// and returns the pair (z, m) for y != 0. -// If y == 0, a division-by-zero run-time panic occurs. -// -// DivMod implements Euclidean division and modulus (unlike Go): -// -// q = x div y such that -// m = x - y*q with 0 <= m < |y| -// -// (See Raymond T. Boute, ``The Euclidean definition of the functions -// div and mod''. ACM Transactions on Programming Languages and -// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992. -// ACM press.) -// See QuoRem for T-division and modulus (like Go). -// -func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { - y0 := y // save y - if z == y || alias(z.abs, y.abs) { - y0 = new(Int).Set(y) - } - z.QuoRem(x, y, m) - if m.neg { - if y0.neg { - z.Add(z, intOne) - m.Sub(m, y0) - } else { - z.Sub(z, intOne) - m.Add(m, y0) - } - } - return z, m -} - -// Cmp compares x and y and returns: -// -// -1 if x < y -// 0 if x == y -// +1 if x > y -// -func (x *Int) Cmp(y *Int) (r int) { - // x cmp y == x cmp y - // x cmp (-y) == x - // (-x) cmp y == y - // (-x) cmp (-y) == -(x cmp y) - switch { - case x.neg == y.neg: - r = x.abs.cmp(y.abs) - if x.neg { - r = -r - } - case x.neg: - r = -1 - default: - r = 1 - } - return -} - -// low32 returns the least significant 32 bits of z. -func low32(z nat) uint32 { - if len(z) == 0 { - return 0 - } - return uint32(z[0]) -} - -// low64 returns the least significant 64 bits of z. -func low64(z nat) uint64 { - if len(z) == 0 { - return 0 - } - v := uint64(z[0]) - if _W == 32 && len(z) > 1 { - v |= uint64(z[1]) << 32 - } - return v -} - -// Int64 returns the int64 representation of x. -// If x cannot be represented in an int64, the result is undefined. -func (x *Int) Int64() int64 { - v := int64(low64(x.abs)) - if x.neg { - v = -v - } - return v -} - -// Uint64 returns the uint64 representation of x. -// If x cannot be represented in a uint64, the result is undefined. -func (x *Int) Uint64() uint64 { - return low64(x.abs) -} - -// SetString sets z to the value of s, interpreted in the given base, -// 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 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. -// -func (z *Int) SetString(s string, base int) (*Int, bool) { - r := strings.NewReader(s) - _, _, err := z.scan(r, base) - if err != nil { - return nil, false - } - _, err = r.ReadByte() - if err != io.EOF { - return nil, false - } - return z, true // err == io.EOF => scan consumed all of s -} - -// SetBytes interprets buf as the bytes of a big-endian unsigned -// integer, sets z to that value, and returns z. -func (z *Int) SetBytes(buf []byte) *Int { - z.abs = z.abs.setBytes(buf) - z.neg = false - return z -} - -// Bytes returns the absolute value of x as a big-endian byte slice. -func (x *Int) Bytes() []byte { - buf := make([]byte, len(x.abs)*_S) - return buf[x.abs.bytes(buf):] -} - -// BitLen returns the length of the absolute value of x in bits. -// The bit length of 0 is 0. -func (x *Int) BitLen() int { - return x.abs.bitLen() -} - -// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z. -// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y. -// See Knuth, volume 2, section 4.6.3. -func (z *Int) Exp(x, y, m *Int) *Int { - var yWords nat - if !y.neg { - yWords = y.abs - } - // y >= 0 - - var mWords nat - if m != nil { - mWords = m.abs // m.abs may be nil for m == 0 - } - - z.abs = z.abs.expNN(x.abs, yWords, mWords) - z.neg = len(z.abs) > 0 && x.neg && len(yWords) > 0 && yWords[0]&1 == 1 // 0 has no sign - if z.neg && len(mWords) > 0 { - // make modulus result positive - z.abs = z.abs.sub(mWords, z.abs) // z == x**y mod |m| && 0 <= z < |m| - z.neg = false - } - - return z -} - -// GCD sets z to the greatest common divisor of a and b, which both must -// be > 0, and returns z. -// If x and y are not nil, GCD sets x and y such that z = a*x + b*y. -// If either a or b is <= 0, GCD sets z = x = y = 0. -func (z *Int) GCD(x, y, a, b *Int) *Int { - if a.Sign() <= 0 || b.Sign() <= 0 { - z.SetInt64(0) - if x != nil { - x.SetInt64(0) - } - if y != nil { - y.SetInt64(0) - } - return z - } - if x == nil && y == nil { - return z.binaryGCD(a, b) - } - - A := new(Int).Set(a) - B := new(Int).Set(b) - - X := new(Int) - Y := new(Int).SetInt64(1) - - lastX := new(Int).SetInt64(1) - lastY := new(Int) - - q := new(Int) - temp := new(Int) - - r := new(Int) - for len(B.abs) > 0 { - q, r = q.QuoRem(A, B, r) - - A, B, r = B, r, A - - temp.Set(X) - X.Mul(X, q) - X.neg = !X.neg - X.Add(X, lastX) - lastX.Set(temp) - - temp.Set(Y) - Y.Mul(Y, q) - Y.neg = !Y.neg - Y.Add(Y, lastY) - lastY.Set(temp) - } - - if x != nil { - *x = *lastX - } - - if y != nil { - *y = *lastY - } - - *z = *A - return z -} - -// binaryGCD sets z to the greatest common divisor of a and b, which both must -// be > 0, and returns z. -// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B. -func (z *Int) binaryGCD(a, b *Int) *Int { - u := z - v := new(Int) - - // use one Euclidean iteration to ensure that u and v are approx. the same size - switch { - case len(a.abs) > len(b.abs): - // 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): - v.Rem(b, a) - 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 { - return u - } - // u > 0 && v > 0 - - // determine largest k such that u = u' << k, v = v' << k - k := u.abs.trailingZeroBits() - if vk := v.abs.trailingZeroBits(); vk < k { - k = vk - } - u.Rsh(u, k) - v.Rsh(v, k) - - // determine t (we know that u > 0) - t := new(Int) - if u.abs[0]&1 != 0 { - // u is odd - t.Neg(v) - } else { - t.Set(u) - } - - for len(t.abs) > 0 { - // reduce t - t.Rsh(t, t.abs.trailingZeroBits()) - if t.neg { - v, t = t, v - v.neg = len(v.abs) > 0 && !v.neg // 0 has no sign - } else { - u, t = t, u - } - t.Sub(u, v) - } - - return z.Lsh(u, k) -} - -// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime. -// If x is prime, it returns true. -// If x is not prime, it returns false with probability at least 1 - ¼ⁿ. -// -// It is not suitable for judging primes that an adversary may have crafted -// to fool this test. -func (x *Int) ProbablyPrime(n int) bool { - if n <= 0 { - panic("non-positive n for ProbablyPrime") - } - return !x.neg && x.abs.probablyPrime(n) -} - -// Rand sets z to a pseudo-random number in [0, n) and returns z. -func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { - z.neg = false - if n.neg == true || len(n.abs) == 0 { - z.abs = nil - return z - } - z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen()) - return z -} - -// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ -// and returns z. If g and n are not relatively prime, the result is undefined. -func (z *Int) ModInverse(g, n *Int) *Int { - var d Int - d.GCD(z, nil, g, n) - // x and y are such that g*x + n*y = d. Since g and n are - // relatively prime, d = 1. Taking that modulo n results in - // g*x = 1, therefore x is the inverse element. - if z.neg { - z.Add(z, n) - } - 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) - } -} - -// modSqrt3Mod4 uses the identity -// (a^((p+1)/4))^2 mod p -// == u^(p+1) mod p -// == u^2 mod p -// to calculate the square root of any quadratic residue mod p quickly for 3 -// mod 4 primes. -func (z *Int) modSqrt3Mod4Prime(x, p *Int) *Int { - z.Set(p) // z = p - z.Add(z, intOne) // z = p + 1 - z.Rsh(z, 2) // z = (p + 1) / 4 - z.Exp(x, z, p) // z = x^z mod p - return z -} - -// modSqrtTonelliShanks uses the Tonelli-Shanks algorithm to find the square -// root of a quadratic residue modulo any prime. -func (z *Int) modSqrtTonelliShanks(x, p *Int) *Int { - // 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 - } -} - -// 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) - } - - // Check whether p is 3 mod 4, and if so, use the faster algorithm. - if len(p.abs) > 0 && p.abs[0]%4 == 3 { - return z.modSqrt3Mod4Prime(x, p) - } - // Otherwise, use Tonelli-Shanks. - return z.modSqrtTonelliShanks(x, p) -} - -// 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) - z.neg = x.neg - return z -} - -// Rsh sets z = x >> n and returns z. -func (z *Int) Rsh(x *Int, n uint) *Int { - if x.neg { - // (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1) - t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0 - t = t.shr(t, n) - z.abs = t.add(t, natOne) - z.neg = true // z cannot be zero if x is negative - return z - } - - z.abs = z.abs.shr(x.abs, n) - z.neg = false - return z -} - -// Bit returns the value of the i'th bit of x. That is, it -// returns (x>>i)&1. The bit index i must be >= 0. -func (x *Int) Bit(i int) uint { - if i == 0 { - // optimization for common case: odd/even test of x - if len(x.abs) > 0 { - return uint(x.abs[0] & 1) // bit 0 is same for -x - } - return 0 - } - if i < 0 { - panic("negative bit index") - } - if x.neg { - t := nat(nil).sub(x.abs, natOne) - return t.bit(uint(i)) ^ 1 - } - - return x.abs.bit(uint(i)) -} - -// SetBit sets z to x, with x's i'th bit set to b (0 or 1). -// That is, if b is 1 SetBit sets z = x | (1 << i); -// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1, -// SetBit will panic. -func (z *Int) SetBit(x *Int, i int, b uint) *Int { - if i < 0 { - panic("negative bit index") - } - if x.neg { - t := z.abs.sub(x.abs, natOne) - t = t.setBit(t, uint(i), b^1) - z.abs = t.add(t, natOne) - z.neg = len(z.abs) > 0 - return z - } - z.abs = z.abs.setBit(x.abs, uint(i), b) - z.neg = false - return z -} - -// And sets z = x & y and returns z. -func (z *Int) And(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) - x1 := nat(nil).sub(x.abs, natOne) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.or(x1, y1), natOne) - z.neg = true // z cannot be zero if x and y are negative - return z - } - - // x & y == x & y - z.abs = z.abs.and(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // & is symmetric - } - - // x & (-y) == x & ^(y-1) == x &^ (y-1) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.andNot(x.abs, y1) - z.neg = false - return z -} - -// AndNot sets z = x &^ y and returns z. -func (z *Int) AndNot(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1) - x1 := nat(nil).sub(x.abs, natOne) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.andNot(y1, x1) - z.neg = false - return z - } - - // x &^ y == x &^ y - z.abs = z.abs.andNot(x.abs, y.abs) - z.neg = false - return z - } - - if x.neg { - // (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1) - x1 := nat(nil).sub(x.abs, natOne) - z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne) - z.neg = true // z cannot be zero if x is negative and y is positive - return z - } - - // x &^ (-y) == x &^ ^(y-1) == x & (y-1) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.and(x.abs, y1) - z.neg = false - return z -} - -// Or sets z = x | y and returns z. -func (z *Int) Or(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1) - x1 := nat(nil).sub(x.abs, natOne) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.and(x1, y1), natOne) - z.neg = true // z cannot be zero if x and y are negative - return z - } - - // x | y == x | y - z.abs = z.abs.or(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // | is symmetric - } - - // x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne) - z.neg = true // z cannot be zero if one of x or y is negative - return z -} - -// Xor sets z = x ^ y and returns z. -func (z *Int) Xor(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1) - x1 := nat(nil).sub(x.abs, natOne) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.xor(x1, y1) - z.neg = false - return z - } - - // x ^ y == x ^ y - z.abs = z.abs.xor(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // ^ is symmetric - } - - // x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1) - y1 := nat(nil).sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne) - z.neg = true // z cannot be zero if only one of x or y is negative - return z -} - -// Not sets z = ^x and returns z. -func (z *Int) Not(x *Int) *Int { - if x.neg { - // ^(-x) == ^(^(x-1)) == x-1 - z.abs = z.abs.sub(x.abs, natOne) - z.neg = false - return z - } - - // ^x == -x-1 == -(x+1) - z.abs = z.abs.add(x.abs, natOne) - z.neg = true // z cannot be zero if x is positive - return z -} diff --git a/src/cmd/compile/internal/big/int_test.go b/src/cmd/compile/internal/big/int_test.go deleted file mode 100644 index 45a3765d3e..0000000000 --- a/src/cmd/compile/internal/big/int_test.go +++ /dev/null @@ -1,1482 +0,0 @@ -// Copyright 2009 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" - "encoding/hex" - "fmt" - "math/rand" - "testing" - "testing/quick" -) - -func isNormalized(x *Int) bool { - if len(x.abs) == 0 { - return !x.neg - } - // len(x.abs) > 0 - return x.abs[len(x.abs)-1] != 0 -} - -type funZZ func(z, x, y *Int) *Int -type argZZ struct { - z, x, y *Int -} - -var sumZZ = []argZZ{ - {NewInt(0), NewInt(0), NewInt(0)}, - {NewInt(1), NewInt(1), NewInt(0)}, - {NewInt(1111111110), NewInt(123456789), NewInt(987654321)}, - {NewInt(-1), NewInt(-1), NewInt(0)}, - {NewInt(864197532), NewInt(-123456789), NewInt(987654321)}, - {NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)}, -} - -var prodZZ = []argZZ{ - {NewInt(0), NewInt(0), NewInt(0)}, - {NewInt(0), NewInt(1), NewInt(0)}, - {NewInt(1), NewInt(1), NewInt(1)}, - {NewInt(-991 * 991), NewInt(991), NewInt(-991)}, - // TODO(gri) add larger products -} - -func TestSignZ(t *testing.T) { - var zero Int - for _, a := range sumZZ { - s := a.z.Sign() - e := a.z.Cmp(&zero) - if s != e { - t.Errorf("got %d; want %d for z = %v", s, e, a.z) - } - } -} - -func TestSetZ(t *testing.T) { - for _, a := range sumZZ { - var z Int - z.Set(a.z) - if !isNormalized(&z) { - t.Errorf("%v is not normalized", z) - } - if (&z).Cmp(a.z) != 0 { - t.Errorf("got z = %v; want %v", z, a.z) - } - } -} - -func TestAbsZ(t *testing.T) { - var zero Int - for _, a := range sumZZ { - var z Int - z.Abs(a.z) - var e Int - e.Set(a.z) - if e.Cmp(&zero) < 0 { - e.Sub(&zero, &e) - } - if z.Cmp(&e) != 0 { - t.Errorf("got z = %v; want %v", z, e) - } - } -} - -func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) { - var z Int - f(&z, a.x, a.y) - if !isNormalized(&z) { - t.Errorf("%s%v is not normalized", msg, z) - } - if (&z).Cmp(a.z) != 0 { - t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z) - } -} - -func TestSumZZ(t *testing.T) { - AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) } - SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) } - for _, a := range sumZZ { - arg := a - testFunZZ(t, "AddZZ", AddZZ, arg) - - arg = argZZ{a.z, a.y, a.x} - testFunZZ(t, "AddZZ symmetric", AddZZ, arg) - - arg = argZZ{a.x, a.z, a.y} - testFunZZ(t, "SubZZ", SubZZ, arg) - - arg = argZZ{a.y, a.z, a.x} - testFunZZ(t, "SubZZ symmetric", SubZZ, arg) - } -} - -func TestProdZZ(t *testing.T) { - MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) } - for _, a := range prodZZ { - arg := a - testFunZZ(t, "MulZZ", MulZZ, arg) - - arg = argZZ{a.z, a.y, a.x} - testFunZZ(t, "MulZZ symmetric", MulZZ, arg) - } -} - -// mulBytes returns x*y via grade school multiplication. Both inputs -// and the result are assumed to be in big-endian representation (to -// match the semantics of Int.Bytes and Int.SetBytes). -func mulBytes(x, y []byte) []byte { - z := make([]byte, len(x)+len(y)) - - // multiply - k0 := len(z) - 1 - for j := len(y) - 1; j >= 0; j-- { - d := int(y[j]) - if d != 0 { - k := k0 - carry := 0 - for i := len(x) - 1; i >= 0; i-- { - t := int(z[k]) + int(x[i])*d + carry - z[k], carry = byte(t), t>>8 - k-- - } - z[k] = byte(carry) - } - k0-- - } - - // normalize (remove leading 0's) - i := 0 - for i < len(z) && z[i] == 0 { - i++ - } - - return z[i:] -} - -func checkMul(a, b []byte) bool { - var x, y, z1 Int - x.SetBytes(a) - y.SetBytes(b) - z1.Mul(&x, &y) - - var z2 Int - z2.SetBytes(mulBytes(a, b)) - - return z1.Cmp(&z2) == 0 -} - -func TestMul(t *testing.T) { - if err := quick.Check(checkMul, nil); err != nil { - t.Error(err) - } -} - -var mulRangesZ = []struct { - a, b int64 - prod string -}{ - // entirely positive ranges are covered by mulRangesN - {-1, 1, "0"}, - {-2, -1, "2"}, - {-3, -2, "6"}, - {-3, -1, "-6"}, - {1, 3, "6"}, - {-10, -10, "-10"}, - {0, -1, "1"}, // empty range - {-1, -100, "1"}, // empty range - {-1, 1, "0"}, // range includes 0 - {-1e9, 0, "0"}, // range includes 0 - {-1e9, 1e9, "0"}, // range includes 0 - {-10, -1, "3628800"}, // 10! - {-20, -2, "-2432902008176640000"}, // -20! - {-99, -1, - "-933262154439441526816992388562667004907159682643816214685929" + - "638952175999932299156089414639761565182862536979208272237582" + - "511852109168640000000000000000000000", // -99! - }, -} - -func TestMulRangeZ(t *testing.T) { - var tmp Int - // test entirely positive ranges - for i, r := range mulRangesN { - prod := tmp.MulRange(int64(r.a), int64(r.b)).String() - if prod != r.prod { - t.Errorf("#%da: got %s; want %s", i, prod, r.prod) - } - } - // test other ranges - for i, r := range mulRangesZ { - prod := tmp.MulRange(r.a, r.b).String() - if prod != r.prod { - t.Errorf("#%db: got %s; want %s", i, prod, r.prod) - } - } -} - -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) - } -} - -// Examples from the Go Language Spec, section "Arithmetic operators" -var divisionSignsTests = []struct { - x, y int64 - q, r int64 // T-division - d, m int64 // Euclidian division -}{ - {5, 3, 1, 2, 1, 2}, - {-5, 3, -1, -2, -2, 1}, - {5, -3, -1, 2, -1, 2}, - {-5, -3, 1, -2, 2, 1}, - {1, 2, 0, 1, 0, 1}, - {8, 4, 2, 0, 2, 0}, -} - -func TestDivisionSigns(t *testing.T) { - for i, test := range divisionSignsTests { - x := NewInt(test.x) - y := NewInt(test.y) - q := NewInt(test.q) - r := NewInt(test.r) - d := NewInt(test.d) - m := NewInt(test.m) - - q1 := new(Int).Quo(x, y) - r1 := new(Int).Rem(x, y) - if !isNormalized(q1) { - t.Errorf("#%d Quo: %v is not normalized", i, *q1) - } - if !isNormalized(r1) { - t.Errorf("#%d Rem: %v is not normalized", i, *r1) - } - if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 { - t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r) - } - - q2, r2 := new(Int).QuoRem(x, y, new(Int)) - if !isNormalized(q2) { - t.Errorf("#%d Quo: %v is not normalized", i, *q2) - } - if !isNormalized(r2) { - t.Errorf("#%d Rem: %v is not normalized", i, *r2) - } - if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 { - t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r) - } - - d1 := new(Int).Div(x, y) - m1 := new(Int).Mod(x, y) - if !isNormalized(d1) { - t.Errorf("#%d Div: %v is not normalized", i, *d1) - } - if !isNormalized(m1) { - t.Errorf("#%d Mod: %v is not normalized", i, *m1) - } - if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 { - t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m) - } - - d2, m2 := new(Int).DivMod(x, y, new(Int)) - if !isNormalized(d2) { - t.Errorf("#%d Div: %v is not normalized", i, *d2) - } - if !isNormalized(m2) { - t.Errorf("#%d Mod: %v is not normalized", i, *m2) - } - if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 { - t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m) - } - } -} - -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) - - for len(hex1) < len(hex2) { - hex1 = "0" + hex1 - } - - for len(hex1) > len(hex2) { - hex2 = "0" + hex2 - } - - return hex1 == hex2 -} - -func TestSetBytes(t *testing.T) { - if err := quick.Check(checkSetBytes, nil); err != nil { - t.Error(err) - } -} - -func checkBytes(b []byte) bool { - // trim leading zero bytes since Bytes() won't return them - // (was issue 12231) - for len(b) > 0 && b[0] == 0 { - b = b[1:] - } - b2 := new(Int).SetBytes(b).Bytes() - return bytes.Equal(b, b2) -} - -func TestBytes(t *testing.T) { - if err := quick.Check(checkBytes, nil); err != nil { - t.Error(err) - } -} - -func checkQuo(x, y []byte) bool { - u := new(Int).SetBytes(x) - v := new(Int).SetBytes(y) - - if len(v.abs) == 0 { - return true - } - - r := new(Int) - q, r := new(Int).QuoRem(u, v, r) - - if r.Cmp(v) >= 0 { - return false - } - - uprime := new(Int).Set(q) - uprime.Mul(uprime, v) - uprime.Add(uprime, r) - - return uprime.Cmp(u) == 0 -} - -var quoTests = []struct { - x, y string - q, r string -}{ - { - "476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357", - "9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996", - "50911", - "1", - }, - { - "11510768301994997771168", - "1328165573307167369775", - "8", - "885443715537658812968", - }, -} - -func TestQuo(t *testing.T) { - if err := quick.Check(checkQuo, nil); err != nil { - t.Error(err) - } - - for i, test := range quoTests { - x, _ := new(Int).SetString(test.x, 10) - y, _ := new(Int).SetString(test.y, 10) - expectedQ, _ := new(Int).SetString(test.q, 10) - expectedR, _ := new(Int).SetString(test.r, 10) - - r := new(Int) - q, r := new(Int).QuoRem(x, y, r) - - if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 { - t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR) - } - } -} - -func TestQuoStepD6(t *testing.T) { - // See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises - // a code path which only triggers 1 in 10^{-19} cases. - - u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}} - v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}} - - r := new(Int) - q, r := new(Int).QuoRem(u, v, r) - const expectedQ64 = "18446744073709551613" - const expectedR64 = "3138550867693340382088035895064302439801311770021610913807" - const expectedQ32 = "4294967293" - const expectedR32 = "39614081266355540837921718287" - if q.String() != expectedQ64 && q.String() != expectedQ32 || - r.String() != expectedR64 && r.String() != expectedR32 { - t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32) - } -} - -var bitLenTests = []struct { - in string - out int -}{ - {"-1", 1}, - {"0", 0}, - {"1", 1}, - {"2", 2}, - {"4", 3}, - {"0xabc", 12}, - {"0x8000", 16}, - {"0x80000000", 32}, - {"0x800000000000", 48}, - {"0x8000000000000000", 64}, - {"0x80000000000000000000", 80}, - {"-0x4000000000000000000000", 87}, -} - -func TestBitLen(t *testing.T) { - for i, test := range bitLenTests { - x, ok := new(Int).SetString(test.in, 0) - if !ok { - t.Errorf("#%d test input invalid: %s", i, test.in) - continue - } - - if n := x.BitLen(); n != test.out { - t.Errorf("#%d got %d want %d", i, n, test.out) - } - } -} - -var expTests = []struct { - x, y, m string - out string -}{ - // y <= 0 - {"0", "0", "", "1"}, - {"1", "0", "", "1"}, - {"-10", "0", "", "1"}, - {"1234", "-1", "", "1"}, - - // m == 1 - {"0", "0", "1", "0"}, - {"1", "0", "1", "0"}, - {"-10", "0", "1", "0"}, - {"1234", "-1", "1", "0"}, - - // misc - {"5", "1", "3", "2"}, - {"5", "-7", "", "1"}, - {"-5", "-7", "", "1"}, - {"5", "0", "", "1"}, - {"-5", "0", "", "1"}, - {"5", "1", "", "5"}, - {"-5", "1", "", "-5"}, - {"-5", "1", "7", "2"}, - {"-2", "3", "2", "0"}, - {"5", "2", "", "25"}, - {"1", "65537", "2", "1"}, - {"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, - {"0x8000000000000000", "2", "6719", "4944"}, - {"0x8000000000000000", "3", "6719", "5447"}, - {"0x8000000000000000", "1000", "6719", "1603"}, - {"0x8000000000000000", "1000000", "6719", "3199"}, - {"0x8000000000000000", "-1000000", "6719", "1"}, - - {"0xffffffffffffffffffffffffffffffff", "0x12345678123456781234567812345678123456789", "0x01112222333344445555666677778889", "0x36168FA1DB3AAE6C8CE647E137F97A"}, - - { - "2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347", - "298472983472983471903246121093472394872319615612417471234712061", - "29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464", - "23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291", - }, - // test case for issue 8822 - { - "11001289118363089646017359372117963499250546375269047542777928006103246876688756735760905680604646624353196869572752623285140408755420374049317646428185270079555372763503115646054602867593662923894140940837479507194934267532831694565516466765025434902348314525627418515646588160955862839022051353653052947073136084780742729727874803457643848197499548297570026926927502505634297079527299004267769780768565695459945235586892627059178884998772989397505061206395455591503771677500931269477503508150175717121828518985901959919560700853226255420793148986854391552859459511723547532575574664944815966793196961286234040892865", - "0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD", - "0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", - "21484252197776302499639938883777710321993113097987201050501182909581359357618579566746556372589385361683610524730509041328855066514963385522570894839035884713051640171474186548713546686476761306436434146475140156284389181808675016576845833340494848283681088886584219750554408060556769486628029028720727393293111678826356480455433909233520504112074401376133077150471237549474149190242010469539006449596611576612573955754349042329130631128234637924786466585703488460540228477440853493392086251021228087076124706778899179648655221663765993962724699135217212118535057766739392069738618682722216712319320435674779146070442", - }, - { - "-0x1BCE04427D8032319A89E5C4136456671AC620883F2C4139E57F91307C485AD2D6204F4F87A58262652DB5DBBAC72B0613E51B835E7153BEC6068F5C8D696B74DBD18FEC316AEF73985CF0475663208EB46B4F17DD9DA55367B03323E5491A70997B90C059FB34809E6EE55BCFBD5F2F52233BFE62E6AA9E4E26A1D4C2439883D14F2633D55D8AA66A1ACD5595E778AC3A280517F1157989E70C1A437B849F1877B779CC3CDDEDE2DAA6594A6C66D181A00A5F777EE60596D8773998F6E988DEAE4CCA60E4DDCF9590543C89F74F603259FCAD71660D30294FBBE6490300F78A9D63FA660DC9417B8B9DDA28BEB3977B621B988E23D4D954F322C3540541BC649ABD504C50FADFD9F0987D58A2BF689313A285E773FF02899A6EF887D1D4A0D2", - "0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD", - "0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", - "21484252197776302499639938883777710321993113097987201050501182909581359357618579566746556372589385361683610524730509041328855066514963385522570894839035884713051640171474186548713546686476761306436434146475140156284389181808675016576845833340494848283681088886584219750554408060556769486628029028720727393293111678826356480455433909233520504112074401376133077150471237549474149190242010469539006449596611576612573955754349042329130631128234637924786466585703488460540228477440853493392086251021228087076124706778899179648655221663765993962724699135217212118535057766739392069738618682722216712319320435674779146070442", - }, - - // test cases for issue 13907 - {"0xffffffff00000001", "0xffffffff00000001", "0xffffffff00000001", "0"}, - {"0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0"}, - {"0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0"}, - {"0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0"}, -} - -func TestExp(t *testing.T) { - for i, test := range expTests { - x, ok1 := new(Int).SetString(test.x, 0) - y, ok2 := new(Int).SetString(test.y, 0) - out, ok3 := new(Int).SetString(test.out, 0) - - var ok4 bool - var m *Int - - if len(test.m) == 0 { - m, ok4 = nil, true - } else { - m, ok4 = new(Int).SetString(test.m, 0) - } - - if !ok1 || !ok2 || !ok3 || !ok4 { - t.Errorf("#%d: error in input", i) - continue - } - - z1 := new(Int).Exp(x, y, m) - if !isNormalized(z1) { - t.Errorf("#%d: %v is not normalized", i, *z1) - } - if z1.Cmp(out) != 0 { - t.Errorf("#%d: got %x want %x", i, z1, out) - } - - if m == nil { - // The result should be the same as for m == 0; - // specifically, there should be no div-zero panic. - m = &Int{abs: nat{}} // m != nil && len(m.abs) == 0 - z2 := new(Int).Exp(x, y, m) - if z2.Cmp(z1) != 0 { - t.Errorf("#%d: got %x want %x", i, z2, z1) - } - } - } -} - -func checkGcd(aBytes, bBytes []byte) bool { - x := new(Int) - y := new(Int) - a := new(Int).SetBytes(aBytes) - b := new(Int).SetBytes(bBytes) - - d := new(Int).GCD(x, y, a, b) - x.Mul(x, a) - y.Mul(y, b) - x.Add(x, y) - - return x.Cmp(d) == 0 -} - -var gcdTests = []struct { - d, x, y, a, b string -}{ - // a <= 0 || b <= 0 - {"0", "0", "0", "0", "0"}, - {"0", "0", "0", "0", "7"}, - {"0", "0", "0", "11", "0"}, - {"0", "0", "0", "-77", "35"}, - {"0", "0", "0", "64515", "-24310"}, - {"0", "0", "0", "-64515", "-24310"}, - - {"1", "-9", "47", "120", "23"}, - {"7", "1", "-2", "77", "35"}, - {"935", "-3", "8", "64515", "24310"}, - {"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"}, - {"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"}, - - // test early exit (after one Euclidean iteration) in binaryGCD - {"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"}, -} - -func testGcd(t *testing.T, d, x, y, a, b *Int) { - var X *Int - if x != nil { - X = new(Int) - } - var Y *Int - if y != nil { - Y = new(Int) - } - - D := new(Int).GCD(X, Y, a, b) - if D.Cmp(d) != 0 { - t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d) - } - if x != nil && X.Cmp(x) != 0 { - t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x) - } - if y != nil && Y.Cmp(y) != 0 { - t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y) - } - - // binaryGCD requires a > 0 && b > 0 - if a.Sign() <= 0 || b.Sign() <= 0 { - return - } - - D.binaryGCD(a, b) - 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) { - for _, test := range gcdTests { - d, _ := new(Int).SetString(test.d, 0) - x, _ := new(Int).SetString(test.x, 0) - y, _ := new(Int).SetString(test.y, 0) - a, _ := new(Int).SetString(test.a, 0) - b, _ := new(Int).SetString(test.b, 0) - - testGcd(t, d, nil, nil, a, b) - testGcd(t, d, x, nil, a, b) - testGcd(t, d, nil, y, a, b) - testGcd(t, d, x, y, a, b) - } - - if err := quick.Check(checkGcd, nil); err != nil { - t.Error(err) - } -} - -var primes = []string{ - "2", - "3", - "5", - "7", - "11", - - "13756265695458089029", - "13496181268022124907", - "10953742525620032441", - "17908251027575790097", - - // https://golang.org/issue/638 - "18699199384836356663", - - "98920366548084643601728869055592650835572950932266967461790948584315647051443", - "94560208308847015747498523884063394671606671904944666360068158221458669711639", - - // http://primes.utm.edu/lists/small/small3.html - "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163", - "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", - "82793403787388584738507275144194252681", -} - -func TestProbablyPrime(t *testing.T) { - nreps := 20 - if testing.Short() { - nreps = 1 - } - for i, s := range primes { - p, _ := new(Int).SetString(s, 10) - if !p.ProbablyPrime(nreps) { - t.Errorf("#%d prime found to be non-prime (%s)", i, s) - } - } - - for i, s := range composites { - c, _ := new(Int).SetString(s, 10) - if c.ProbablyPrime(nreps) { - t.Errorf("#%d composite found to be prime (%s)", i, s) - } - if testing.Short() { - 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 { - in string - shift uint - out string -} - -var rshTests = []intShiftTest{ - {"0", 0, "0"}, - {"-0", 0, "0"}, - {"0", 1, "0"}, - {"0", 2, "0"}, - {"1", 0, "1"}, - {"1", 1, "0"}, - {"1", 2, "0"}, - {"2", 0, "2"}, - {"2", 1, "1"}, - {"-1", 0, "-1"}, - {"-1", 1, "-1"}, - {"-1", 10, "-1"}, - {"-100", 2, "-25"}, - {"-100", 3, "-13"}, - {"-100", 100, "-1"}, - {"4294967296", 0, "4294967296"}, - {"4294967296", 1, "2147483648"}, - {"4294967296", 2, "1073741824"}, - {"18446744073709551616", 0, "18446744073709551616"}, - {"18446744073709551616", 1, "9223372036854775808"}, - {"18446744073709551616", 2, "4611686018427387904"}, - {"18446744073709551616", 64, "1"}, - {"340282366920938463463374607431768211456", 64, "18446744073709551616"}, - {"340282366920938463463374607431768211456", 128, "1"}, -} - -func TestRsh(t *testing.T) { - for i, test := range rshTests { - in, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - out := new(Int).Rsh(in, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - } -} - -func TestRshSelf(t *testing.T) { - for i, test := range rshTests { - z, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - z.Rsh(z, test.shift) - - if !isNormalized(z) { - t.Errorf("#%d: %v is not normalized", i, *z) - } - if z.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, z, expected) - } - } -} - -var lshTests = []intShiftTest{ - {"0", 0, "0"}, - {"0", 1, "0"}, - {"0", 2, "0"}, - {"1", 0, "1"}, - {"1", 1, "2"}, - {"1", 2, "4"}, - {"2", 0, "2"}, - {"2", 1, "4"}, - {"2", 2, "8"}, - {"-87", 1, "-174"}, - {"4294967296", 0, "4294967296"}, - {"4294967296", 1, "8589934592"}, - {"4294967296", 2, "17179869184"}, - {"18446744073709551616", 0, "18446744073709551616"}, - {"9223372036854775808", 1, "18446744073709551616"}, - {"4611686018427387904", 2, "18446744073709551616"}, - {"1", 64, "18446744073709551616"}, - {"18446744073709551616", 64, "340282366920938463463374607431768211456"}, - {"1", 128, "340282366920938463463374607431768211456"}, -} - -func TestLsh(t *testing.T) { - for i, test := range lshTests { - in, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - out := new(Int).Lsh(in, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - } -} - -func TestLshSelf(t *testing.T) { - for i, test := range lshTests { - z, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - z.Lsh(z, test.shift) - - if !isNormalized(z) { - t.Errorf("#%d: %v is not normalized", i, *z) - } - if z.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, z, expected) - } - } -} - -func TestLshRsh(t *testing.T) { - for i, test := range rshTests { - in, _ := new(Int).SetString(test.in, 10) - out := new(Int).Lsh(in, test.shift) - out = out.Rsh(out, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if in.Cmp(out) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } - for i, test := range lshTests { - in, _ := new(Int).SetString(test.in, 10) - out := new(Int).Lsh(in, test.shift) - out.Rsh(out, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if in.Cmp(out) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } -} - -var int64Tests = []int64{ - 0, - 1, - -1, - 4294967295, - -4294967295, - 4294967296, - -4294967296, - 9223372036854775807, - -9223372036854775807, - -9223372036854775808, -} - -func TestInt64(t *testing.T) { - for i, testVal := range int64Tests { - in := NewInt(testVal) - out := in.Int64() - - if out != testVal { - t.Errorf("#%d got %d want %d", i, out, testVal) - } - } -} - -var uint64Tests = []uint64{ - 0, - 1, - 4294967295, - 4294967296, - 8589934591, - 8589934592, - 9223372036854775807, - 9223372036854775808, - 18446744073709551615, // 1<<64 - 1 -} - -func TestUint64(t *testing.T) { - in := new(Int) - for i, testVal := range uint64Tests { - in.SetUint64(testVal) - out := in.Uint64() - - if out != testVal { - t.Errorf("#%d got %d want %d", i, out, testVal) - } - - str := fmt.Sprint(testVal) - strOut := in.String() - if strOut != str { - t.Errorf("#%d.String got %s want %s", i, strOut, str) - } - } -} - -var bitwiseTests = []struct { - x, y string - and, or, xor, andNot string -}{ - {"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"}, - {"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"}, - {"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"}, - {"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"}, - {"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"}, - {"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"}, - {"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"}, - {"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"}, - {"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"}, - {"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"}, - {"0xff", "-0x0a", "0xf6", "-0x01", "-0xf7", "0x09"}, - {"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"}, - {"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"}, - {"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"}, - { - "0x1000009dc6e3d9822cba04129bcbe3401", - "0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "0x1000001186210100001000009048c2001", - "0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd", - "0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc", - "0x8c40c2d8822caa04120b8321400", - }, - { - "0x1000009dc6e3d9822cba04129bcbe3401", - "-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "0x8c40c2d8822caa04120b8321401", - "-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd", - "-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe", - "0x1000001186210100001000009048c2000", - }, - { - "-0x1000009dc6e3d9822cba04129bcbe3401", - "-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd", - "-0x1000001186210100001000009048c2001", - "0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc", - "0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc", - }, -} - -type bitFun func(z, x, y *Int) *Int - -func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { - expected := new(Int) - expected.SetString(exp, 0) - - out := f(new(Int), x, y) - if out.Cmp(expected) != 0 { - t.Errorf("%s: got %s want %s", msg, out, expected) - } -} - -func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { - self := new(Int) - self.Set(x) - expected := new(Int) - expected.SetString(exp, 0) - - self = f(self, self, y) - if self.Cmp(expected) != 0 { - t.Errorf("%s: got %s want %s", msg, self, expected) - } -} - -func altBit(x *Int, i int) uint { - z := new(Int).Rsh(x, uint(i)) - z = z.And(z, NewInt(1)) - if z.Cmp(new(Int)) != 0 { - return 1 - } - return 0 -} - -func altSetBit(z *Int, x *Int, i int, b uint) *Int { - one := NewInt(1) - m := one.Lsh(one, uint(i)) - switch b { - case 1: - return z.Or(x, m) - case 0: - return z.AndNot(x, m) - } - panic("set bit is not 0 or 1") -} - -func testBitset(t *testing.T, x *Int) { - n := x.BitLen() - z := new(Int).Set(x) - z1 := new(Int).Set(x) - for i := 0; i < n+10; i++ { - old := z.Bit(i) - old1 := altBit(z1, i) - if old != old1 { - t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1) - } - z := new(Int).SetBit(z, i, 1) - z1 := altSetBit(new(Int), z1, i, 1) - if z.Bit(i) == 0 { - t.Errorf("bitset: bit %d of %s got 0 want 1", i, x) - } - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1) - } - z.SetBit(z, i, 0) - altSetBit(z1, z1, i, 0) - if z.Bit(i) != 0 { - t.Errorf("bitset: bit %d of %s got 1 want 0", i, x) - } - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1) - } - altSetBit(z1, z1, i, old) - z.SetBit(z, i, old) - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1) - } - } - if z.Cmp(x) != 0 { - t.Errorf("bitset: got %s want %s", z, x) - } -} - -var bitsetTests = []struct { - x string - i int - b uint -}{ - {"0", 0, 0}, - {"0", 200, 0}, - {"1", 0, 1}, - {"1", 1, 0}, - {"-1", 0, 1}, - {"-1", 200, 1}, - {"0x2000000000000000000000000000", 108, 0}, - {"0x2000000000000000000000000000", 109, 1}, - {"0x2000000000000000000000000000", 110, 0}, - {"-0x2000000000000000000000000001", 108, 1}, - {"-0x2000000000000000000000000001", 109, 0}, - {"-0x2000000000000000000000000001", 110, 1}, -} - -func TestBitSet(t *testing.T) { - for _, test := range bitwiseTests { - x := new(Int) - x.SetString(test.x, 0) - testBitset(t, x) - x = new(Int) - x.SetString(test.y, 0) - testBitset(t, x) - } - for i, test := range bitsetTests { - x := new(Int) - x.SetString(test.x, 0) - b := x.Bit(test.i) - if b != test.b { - t.Errorf("#%d got %v want %v", i, b, test.b) - } - } - z := NewInt(1) - z.SetBit(NewInt(0), 2, 1) - if z.Cmp(NewInt(4)) != 0 { - t.Errorf("destination leaked into result; got %s want 4", z) - } -} - -func BenchmarkBitset(b *testing.B) { - z := new(Int) - z.SetBit(z, 512, 1) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - z.SetBit(z, i&512, 1) - } -} - -func BenchmarkBitsetNeg(b *testing.B) { - z := NewInt(-1) - z.SetBit(z, 512, 0) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - z.SetBit(z, i&512, 0) - } -} - -func BenchmarkBitsetOrig(b *testing.B) { - z := new(Int) - altSetBit(z, z, 512, 1) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - altSetBit(z, z, i&512, 1) - } -} - -func BenchmarkBitsetNegOrig(b *testing.B) { - z := NewInt(-1) - altSetBit(z, z, 512, 0) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - altSetBit(z, z, i&512, 0) - } -} - -// tri generates the trinomial 2**(n*2) - 2**n - 1, which is always 3 mod 4 and -// 7 mod 8, so that 2 is always a quadratic residue. -func tri(n uint) *Int { - x := NewInt(1) - x.Lsh(x, n) - x2 := new(Int).Lsh(x, n) - x2.Sub(x2, x) - x2.Sub(x2, intOne) - return x2 -} - -func BenchmarkModSqrt225_Tonelli(b *testing.B) { - p := tri(225) - x := NewInt(2) - for i := 0; i < b.N; i++ { - x.SetUint64(2) - x.modSqrtTonelliShanks(x, p) - } -} - -func BenchmarkModSqrt224_3Mod4(b *testing.B) { - p := tri(225) - x := new(Int).SetUint64(2) - for i := 0; i < b.N; i++ { - x.SetUint64(2) - x.modSqrt3Mod4Prime(x, p) - } -} - -func BenchmarkModSqrt5430_Tonelli(b *testing.B) { - p := tri(5430) - x := new(Int).SetUint64(2) - for i := 0; i < b.N; i++ { - x.SetUint64(2) - x.modSqrtTonelliShanks(x, p) - } -} - -func BenchmarkModSqrt5430_3Mod4(b *testing.B) { - p := tri(5430) - x := new(Int).SetUint64(2) - for i := 0; i < b.N; i++ { - x.SetUint64(2) - x.modSqrt3Mod4Prime(x, p) - } -} - -func TestBitwise(t *testing.T) { - x := new(Int) - y := new(Int) - for _, test := range bitwiseTests { - x.SetString(test.x, 0) - y.SetString(test.y, 0) - - testBitFun(t, "and", (*Int).And, x, y, test.and) - testBitFunSelf(t, "and", (*Int).And, x, y, test.and) - testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot) - testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot) - testBitFun(t, "or", (*Int).Or, x, y, test.or) - testBitFunSelf(t, "or", (*Int).Or, x, y, test.or) - testBitFun(t, "xor", (*Int).Xor, x, y, test.xor) - testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor) - } -} - -var notTests = []struct { - in string - out string -}{ - {"0", "-1"}, - {"1", "-2"}, - {"7", "-8"}, - {"0", "-1"}, - {"-81910", "81909"}, - { - "298472983472983471903246121093472394872319615612417471234712061", - "-298472983472983471903246121093472394872319615612417471234712062", - }, -} - -func TestNot(t *testing.T) { - in := new(Int) - out := new(Int) - expected := new(Int) - for i, test := range notTests { - in.SetString(test.in, 10) - expected.SetString(test.out, 10) - out = out.Not(in) - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - out = out.Not(out) - if out.Cmp(in) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } -} - -var modInverseTests = []struct { - element string - modulus string -}{ - {"1234567", "458948883992"}, - {"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"}, -} - -func TestModInverse(t *testing.T) { - var element, modulus, gcd, inverse Int - one := NewInt(1) - for i, test := range modInverseTests { - (&element).SetString(test.element, 10) - (&modulus).SetString(test.modulus, 10) - (&inverse).ModInverse(&element, &modulus) - (&inverse).Mul(&inverse, &element) - (&inverse).Mod(&inverse, &modulus) - if (&inverse).Cmp(one) != 0 { - t.Errorf("#%d: failed (e·e^(-1)=%s)", i, &inverse) - } - } - // exhaustive test for small values - for n := 2; n < 100; n++ { - (&modulus).SetInt64(int64(n)) - for x := 1; x < n; x++ { - (&element).SetInt64(int64(x)) - (&gcd).GCD(nil, nil, &element, &modulus) - if (&gcd).Cmp(one) != 0 { - continue - } - (&inverse).ModInverse(&element, &modulus) - (&inverse).Mul(&inverse, &element) - (&inverse).Mod(&inverse, &modulus) - if (&inverse).Cmp(one) != 0 { - t.Errorf("ModInverse(%d,%d)*%d%%%d=%d, not 1", &element, &modulus, &element, &modulus, &inverse) - } - } - } -} - -// 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) - } - } - - if testing.Short() && i > 2 { - break - } - } - - if testing.Short() { - return - } - - // 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) -} - -func TestIssue2607(t *testing.T) { - // This code sequence used to hang. - n := NewInt(10) - n.Rand(rand.New(rand.NewSource(9)), n) -} diff --git a/src/cmd/compile/internal/big/intconv.go b/src/cmd/compile/internal/big/intconv.go deleted file mode 100644 index daf674aef4..0000000000 --- a/src/cmd/compile/internal/big/intconv.go +++ /dev/null @@ -1,248 +0,0 @@ -// 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" -) - -// TODO(gri) Should rename itoa to utoa (there's no sign). That -// would permit the introduction of itoa which is like utoa but -// reserves a byte for a possible sign that's passed in. That -// would permit Int.Text to be implemented w/o the need for -// string copy if the number is negative. - -// Text returns the string representation of x in the given base. -// Base must be between 2 and 36, inclusive. The result uses the -// lower-case letters 'a' to 'z' for digit values >= 10. No base -// prefix (such as "0x") is added to the string. -func (x *Int) Text(base int) string { - if x == nil { - return "" - } - return string(x.abs.itoa(x.neg, base)) -} - -// Append appends the string representation of x, as generated by -// x.Text(base), to buf and returns the extended buffer. -func (x *Int) Append(buf []byte, base int) []byte { - if x == nil { - return append(buf, ""...) - } - return append(buf, x.abs.itoa(x.neg, base)...) -} - -func (x *Int) String() string { - return x.Text(10) -} - -// 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 implements 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 -// flags 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 '-' for left or right -// justification. -// -func (x *Int) Format(s fmt.State, ch rune) { - // determine base - var base int - switch ch { - case 'b': - base = 2 - case 'o': - base = 8 - case 'd', 's', 'v': - base = 10 - case 'x', 'X': - base = 16 - default: - // unknown format - fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String()) - return - } - - if x == nil { - fmt.Fprint(s, "") - 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" - } - } - - digits := x.abs.utoa(base) - if ch == 'X' { - // faster than bytes.ToUpper - for i, d := range digits { - if 'a' <= d && d <= 'z' { - digits[i] = 'A' + (d - 'a') - } - } - } - - // number of characters for the three classes of number padding - var left int // space characters to left of digits for right justification ("%8d") - var zeros 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: - zeros = precision - len(digits) // count of zero padding - case len(digits) == 1 && digits[0] == '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) + zeros + 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 zeros unless precision also specified - zeros = 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", zeros) - s.Write(digits) - 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/src/cmd/compile/internal/big/intconv_test.go b/src/cmd/compile/internal/big/intconv_test.go deleted file mode 100644 index 514208145f..0000000000 --- a/src/cmd/compile/internal/big/intconv_test.go +++ /dev/null @@ -1,391 +0,0 @@ -// 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: ""}, - {in: "a"}, - {in: "z"}, - {in: "+"}, - {in: "-"}, - {in: "0b"}, - {in: "0x"}, - {in: "2", base: 2}, - {in: "0b2", base: 0}, - {in: "08"}, - {in: "8", base: 8}, - {in: "0xg", base: 0}, - {in: "g", base: 16}, - {"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}, - {"-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 TestIntText(t *testing.T) { - z := new(Int) - for _, test := range stringTests { - if !test.ok { - continue - } - - _, ok := z.SetString(test.in, test.base) - if !ok { - t.Errorf("%v: failed to parse", test) - continue - } - - base := test.base - if base == 0 { - base = 10 - } - - if got := z.Text(base); got != test.out { - t.Errorf("%v: got %s; want %s", test, got, test.out) - } - } -} - -func TestAppendText(t *testing.T) { - z := new(Int) - var buf []byte - for _, test := range stringTests { - if !test.ok { - continue - } - - _, ok := z.SetString(test.in, test.base) - if !ok { - t.Errorf("%v: failed to parse", test) - continue - } - - base := test.base - if base == 0 { - base = 10 - } - - i := len(buf) - buf = z.Append(buf, base) - if got := string(buf[i:]); got != test.out { - t.Errorf("%v: got %s; want %s", test, got, test.out) - } - } -} - -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 { - if got := z.String(); got != test.out { - t.Errorf("#%da got %s; want %s", i, got, test.out) - } - } - - if got := fmt.Sprintf(format(test.base), z); got != test.out { - t.Errorf("#%db got %s; want %s", i, got, 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 -}{ - {"", "%x", ""}, - {"", "%#x", ""}, - {"", "%#y", "%!y(big.Int=)"}, - - {"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 != "" { - 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/src/cmd/compile/internal/big/intmarsh.go b/src/cmd/compile/internal/big/intmarsh.go deleted file mode 100644 index 34bc73e978..0000000000 --- a/src/cmd/compile/internal/big/intmarsh.go +++ /dev/null @@ -1,78 +0,0 @@ -// 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 encoding/decoding of Ints. - -package big - -import "fmt" - -// Gob codec version. Permits backward-compatible changes to the encoding. -const intGobVersion byte = 1 - -// GobEncode implements the gob.GobEncoder interface. -func (x *Int) GobEncode() ([]byte, error) { - if x == nil { - return nil, nil - } - buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit - i := x.abs.bytes(buf) - 1 // i >= 0 - b := intGobVersion << 1 // make space for sign bit - if x.neg { - b |= 1 - } - buf[i] = b - return buf[i:], nil -} - -// GobDecode implements the gob.GobDecoder interface. -func (z *Int) GobDecode(buf []byte) error { - if len(buf) == 0 { - // Other side sent a nil or default value. - *z = Int{} - return nil - } - b := buf[0] - if b>>1 != intGobVersion { - return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1) - } - z.neg = b&1 != 0 - z.abs = z.abs.setBytes(buf[1:]) - return nil -} - -// MarshalText implements the encoding.TextMarshaler interface. -func (x *Int) MarshalText() (text []byte, err error) { - if x == nil { - return []byte(""), nil - } - return x.abs.itoa(x.neg, 10), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -func (z *Int) UnmarshalText(text []byte) error { - // TODO(gri): get rid of the []byte/string conversion - if _, ok := z.SetString(string(text), 0); !ok { - return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text) - } - return nil -} - -// The JSON marshallers are only here for API backward compatibility -// (programs that explicitly look for these two methods). JSON works -// fine with the TextMarshaler only. - -// MarshalJSON implements the json.Marshaler interface. -func (x *Int) MarshalJSON() ([]byte, error) { - return x.MarshalText() -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (z *Int) UnmarshalJSON(text []byte) error { - // Ignore null, like in the main JSON package. - if string(text) == "null" { - return nil - } - return z.UnmarshalText(text) -} diff --git a/src/cmd/compile/internal/big/intmarsh_test.go b/src/cmd/compile/internal/big/intmarsh_test.go deleted file mode 100644 index f82956ceaf..0000000000 --- a/src/cmd/compile/internal/big/intmarsh_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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" - "encoding/gob" - "encoding/json" - "encoding/xml" - "testing" -) - -var encodingTests = []string{ - "0", - "1", - "2", - "10", - "1000", - "1234567890", - "298472983472983471903246121093472394872319615612417471234712061", -} - -func TestIntGobEncoding(t *testing.T) { - var medium bytes.Buffer - enc := gob.NewEncoder(&medium) - dec := gob.NewDecoder(&medium) - for _, test := range encodingTests { - for _, sign := range []string{"", "+", "-"} { - x := sign + test - medium.Reset() // empty buffer for each test case (in case of failures) - var tx Int - tx.SetString(x, 10) - if err := enc.Encode(&tx); err != nil { - t.Errorf("encoding of %s failed: %s", &tx, err) - continue - } - var rx Int - if err := dec.Decode(&rx); err != nil { - t.Errorf("decoding of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx) - } - } - } -} - -// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero. -// TODO: top-level nils. -func TestGobEncodingNilIntInSlice(t *testing.T) { - buf := new(bytes.Buffer) - enc := gob.NewEncoder(buf) - dec := gob.NewDecoder(buf) - - var in = make([]*Int, 1) - err := enc.Encode(&in) - if err != nil { - t.Errorf("gob encode failed: %q", err) - } - var out []*Int - err = dec.Decode(&out) - if err != nil { - t.Fatalf("gob decode failed: %q", err) - } - if len(out) != 1 { - t.Fatalf("wrong len; want 1 got %d", len(out)) - } - var zero Int - if out[0].Cmp(&zero) != 0 { - t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out) - } -} - -func TestIntJSONEncoding(t *testing.T) { - for _, test := range encodingTests { - for _, sign := range []string{"", "+", "-"} { - x := sign + test - var tx Int - tx.SetString(x, 10) - b, err := json.Marshal(&tx) - if err != nil { - t.Errorf("marshaling of %s failed: %s", &tx, err) - continue - } - var rx Int - if err := json.Unmarshal(b, &rx); err != nil { - t.Errorf("unmarshaling of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx) - } - } - } -} - -func TestIntXMLEncoding(t *testing.T) { - for _, test := range encodingTests { - for _, sign := range []string{"", "+", "-"} { - x := sign + test - var tx Int - tx.SetString(x, 0) - b, err := xml.Marshal(&tx) - if err != nil { - t.Errorf("marshaling of %s failed: %s", &tx, err) - continue - } - var rx Int - if err := xml.Unmarshal(b, &rx); err != nil { - t.Errorf("unmarshaling of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx) - } - } - } -} diff --git a/src/cmd/compile/internal/big/nat.go b/src/cmd/compile/internal/big/nat.go deleted file mode 100644 index 2e65d2a7ef..0000000000 --- a/src/cmd/compile/internal/big/nat.go +++ /dev/null @@ -1,1305 +0,0 @@ -// Copyright 2009 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 unsigned multi-precision integers (natural -// numbers). They are the building blocks for the implementation -// of signed integers, rationals, and floating-point numbers. - -package big - -import ( - "math/rand" - "sync" -) - -// An unsigned integer x of the form -// -// x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0] -// -// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n, -// with the digits x[i] as the slice elements. -// -// A number is normalized if the slice contains no leading 0 digits. -// During arithmetic operations, denormalized values may occur but are -// always normalized before returning the final result. The normalized -// representation of 0 is the empty or nil slice (length = 0). -// -type nat []Word - -var ( - natOne = nat{1} - natTwo = nat{2} - natTen = nat{10} -) - -func (z nat) clear() { - for i := range z { - z[i] = 0 - } -} - -func (z nat) norm() nat { - i := len(z) - for i > 0 && z[i-1] == 0 { - i-- - } - return z[0:i] -} - -func (z nat) make(n int) nat { - if n <= cap(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. - const e = 4 // extra capacity - return make(nat, n, n+e) -} - -func (z nat) setWord(x Word) nat { - if x == 0 { - return z[:0] - } - z = z.make(1) - z[0] = x - return z -} - -func (z nat) setUint64(x uint64) nat { - // single-digit values - if w := Word(x); uint64(w) == x { - return z.setWord(w) - } - - // compute number of words n required to represent x - n := 0 - for t := x; t > 0; t >>= _W { - n++ - } - - // split x into n words - z = z.make(n) - for i := range z { - z[i] = Word(x & _M) - x >>= _W - } - - return z -} - -func (z nat) set(x nat) nat { - z = z.make(len(x)) - copy(z, x) - return z -} - -func (z nat) add(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - return z.add(y, x) - case m == 0: - // n == 0 because m >= n; result is 0 - return z[:0] - case n == 0: - // result is x - return z.set(x) - } - // m > 0 - - z = z.make(m + 1) - c := addVV(z[0:n], x, y) - if m > n { - c = addVW(z[n:m], x[n:], c) - } - z[m] = c - - return z.norm() -} - -func (z nat) sub(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - panic("underflow") - case m == 0: - // n == 0 because m >= n; result is 0 - return z[:0] - case n == 0: - // result is x - return z.set(x) - } - // m > 0 - - z = z.make(m) - c := subVV(z[0:n], x, y) - if m > n { - c = subVW(z[n:], x[n:], c) - } - if c != 0 { - panic("underflow") - } - - return z.norm() -} - -func (x nat) cmp(y nat) (r int) { - m := len(x) - n := len(y) - if m != n || m == 0 { - switch { - case m < n: - r = -1 - case m > n: - r = 1 - } - return - } - - i := m - 1 - for i > 0 && x[i] == y[i] { - i-- - } - - switch { - case x[i] < y[i]: - r = -1 - case x[i] > y[i]: - r = 1 - } - return -} - -func (z nat) mulAddWW(x nat, y, r Word) nat { - m := len(x) - if m == 0 || y == 0 { - return z.setWord(r) // result is r - } - // m > 0 - - z = z.make(m + 1) - z[m] = mulAddVWW(z[0:m], x, y, r) - - return z.norm() -} - -// basicMul multiplies x and y and leaves the result in z. -// The (non-normalized) result is placed in z[0 : len(x) + len(y)]. -func basicMul(z, x, y nat) { - z[0 : len(x)+len(y)].clear() // initialize z - for i, d := range y { - if d != 0 { - z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d) - } - } -} - -// montgomery computes z mod m = 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. -// See Gueron, "Efficient Software Implementations of Modular Exponentiation". -// https://eprint.iacr.org/2011/239.pdf -// In the terminology of that paper, this is an "Almost Montgomery Multiplication": -// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result -// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m. -func (z nat) montgomery(x, y, m nat, k Word, n int) nat { - // This code assumes x, y, m are all the same length, n. - // (required by addMulVVW and the for loop). - // It also assumes that x, y are already reduced mod m, - // or else the result will not be properly reduced. - if len(x) != n || len(y) != n || len(m) != n { - panic("math/big: mismatched montgomery number lengths") - } - z = z.make(n) - z.clear() - var c Word - for i := 0; i < n; i++ { - d := y[i] - c2 := addMulVVW(z, x, d) - t := z[0] * k - c3 := addMulVVW(z, m, t) - copy(z, z[1:]) - cx := c + c2 - cy := cx + c3 - z[n-1] = cy - if cx < c2 || cy < c3 { - c = 1 - } else { - c = 0 - } - } - if c != 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) { - if c := addVV(z[0:n], z, x); c != 0 { - addVW(z[n:n+n>>1], z[n:], c) - } -} - -// Like karatsubaAdd, but does subtract. -func karatsubaSub(z, x nat, n int) { - if c := subVV(z[0:n], z, x); c != 0 { - subVW(z[n:n+n>>1], z[n:], c) - } -} - -// Operands that are shorter than karatsubaThreshold are multiplied using -// "grade school" multiplication; for longer operands the Karatsuba algorithm -// is used. -var karatsubaThreshold int = 40 // computed by calibrate.go - -// karatsuba multiplies x and y and leaves the result in z. -// Both x and y must have the same length n and n must be a -// power of 2. The result vector z must have len(z) >= 6*n. -// The (non-normalized) result is placed in z[0 : 2*n]. -func karatsuba(z, x, y nat) { - n := len(y) - - // Switch to basic multiplication if numbers are odd or small. - // (n is always even if karatsubaThreshold is even, but be - // conservative) - if n&1 != 0 || n < karatsubaThreshold || n < 2 { - basicMul(z, x, y) - return - } - // n&1 == 0 && n >= karatsubaThreshold && n >= 2 - - // Karatsuba multiplication is based on the observation that - // for two numbers x and y with: - // - // x = x1*b + x0 - // y = y1*b + y0 - // - // the product x*y can be obtained with 3 products z2, z1, z0 - // instead of 4: - // - // x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0 - // = z2*b*b + z1*b + z0 - // - // with: - // - // xd = x1 - x0 - // yd = y0 - y1 - // - // z1 = xd*yd + z2 + z0 - // = (x1-x0)*(y0 - y1) + z2 + z0 - // = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0 - // = x1*y0 - z2 - z0 + x0*y1 + z2 + z0 - // = x1*y0 + x0*y1 - - // split x, y into "digits" - n2 := n >> 1 // n2 >= 1 - x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0 - y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0 - - // z is used for the result and temporary storage: - // - // 6*n 5*n 4*n 3*n 2*n 1*n 0*n - // z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ] - // - // For each recursive call of karatsuba, an unused slice of - // z is passed in that has (at least) half the length of the - // caller's z. - - // compute z0 and z2 with the result "in place" in z - karatsuba(z, x0, y0) // z0 = x0*y0 - karatsuba(z[n:], x1, y1) // z2 = x1*y1 - - // compute xd (or the negative value if underflow occurs) - s := 1 // sign of product xd*yd - xd := z[2*n : 2*n+n2] - if subVV(xd, x1, x0) != 0 { // x1-x0 - s = -s - subVV(xd, x0, x1) // x0-x1 - } - - // compute yd (or the negative value if underflow occurs) - yd := z[2*n+n2 : 3*n] - if subVV(yd, y0, y1) != 0 { // y0-y1 - s = -s - subVV(yd, y1, y0) // y1-y0 - } - - // p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0 - // p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0 - p := z[n*3:] - karatsuba(p, xd, yd) - - // save original z2:z0 - // (ok to use upper half of z since we're done recursing) - r := z[n*4:] - copy(r, z[:n*2]) - - // add up all partial products - // - // 2*n n 0 - // z = [ z2 | z0 ] - // + [ z0 ] - // + [ z2 ] - // + [ p ] - // - karatsubaAdd(z[n2:], r, n) - karatsubaAdd(z[n2:], r[n:], n) - if s > 0 { - karatsubaAdd(z[n2:], p, n) - } else { - karatsubaSub(z[n2:], p, n) - } -} - -// 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] -} - -// addAt implements z += x<<(_W*i); z must be long enough. -// (we don't use nat.add because we need z to stay the same -// slice, and we don't need to normalize z after each addition) -func addAt(z, x nat, i int) { - if n := len(x); n > 0 { - if c := addVV(z[i:i+n], z[i:], x); c != 0 { - j := i + n - if j < len(z) { - addVW(z[j:], z[j:], c) - } - } - } -} - -func max(x, y int) int { - if x > y { - return x - } - return y -} - -// karatsubaLen computes an approximation to the maximum k <= n such that -// k = p<= 0. Thus, the -// result is the largest number that can be divided repeatedly by 2 before -// becoming about the value of karatsubaThreshold. -func karatsubaLen(n int) int { - i := uint(0) - for n > karatsubaThreshold { - n >>= 1 - i++ - } - return n << i -} - -func (z nat) mul(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - return z.mul(y, x) - case m == 0 || n == 0: - return z[:0] - case n == 1: - return z.mulAddWW(x, y[0], 0) - } - // m >= n > 1 - - // determine if z can be reused - if alias(z, x) || alias(z, y) { - z = nil // z is an alias for x or y - cannot reuse - } - - // use basic multiplication if the numbers are small - if n < karatsubaThreshold { - z = z.make(m + n) - basicMul(z, x, y) - return z.norm() - } - // m >= n && n >= karatsubaThreshold && n >= 2 - - // determine Karatsuba length k such that - // - // x = xh*b + x0 (0 <= x0 < b) - // y = yh*b + y0 (0 <= y0 < b) - // b = 1<<(_W*k) ("base" of digits xi, yi) - // - k := karatsubaLen(n) - // k <= n - - // multiply x0 and y0 via Karatsuba - x0 := x[0:k] // x0 is not normalized - y0 := y[0:k] // y0 is not normalized - z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y - karatsuba(z, x0, y0) - z = z[0 : m+n] // z has final length but may be incomplete - z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m) - - // If xh != 0 or yh != 0, add the missing terms to z. For - // - // xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b) - // yh = y1*b (0 <= y1 < b) - // - // the missing terms are - // - // x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0 - // - // since all the yi for i > 1 are 0 by choice of k: If any of them - // were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would - // be a larger valid threshold contradicting the assumption about k. - // - if k < n || m != n { - var t nat - - // add x0*y1*b - x0 := x0.norm() - y1 := y[k:] // y1 is normalized because y is - t = t.mul(x0, y1) // update t so we don't lose t's underlying array - addAt(z, t, k) - - // add xi*y0< k { - xi = xi[:k] - } - xi = xi.norm() - t = t.mul(xi, y0) - addAt(z, t, i) - t = t.mul(xi, y1) - addAt(z, t, i+k) - } - } - - return z.norm() -} - -// mulRange computes the product of all the unsigned integers in the -// range [a, b] inclusively. If a > b (empty range), the result is 1. -func (z nat) mulRange(a, b uint64) nat { - switch { - case a == 0: - // cut long ranges short (optimization) - return z.setUint64(0) - case a > b: - return z.setUint64(1) - case a == b: - return z.setUint64(a) - case a+1 == b: - return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b)) - } - m := (a + b) / 2 - return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b)) -} - -// q = (x-r)/y, with 0 <= r < y -func (z nat) divW(x nat, y Word) (q nat, r Word) { - m := len(x) - switch { - case y == 0: - panic("division by zero") - case y == 1: - q = z.set(x) // result is x - return - case m == 0: - q = z[:0] // result is 0 - return - } - // m > 0 - z = z.make(m) - r = divWVW(z, 0, x, y) - q = z.norm() - return -} - -func (z nat) div(z2, u, v nat) (q, r nat) { - if len(v) == 0 { - panic("division by zero") - } - - if u.cmp(v) < 0 { - q = z[:0] - r = z2.set(u) - return - } - - if len(v) == 1 { - var r2 Word - q, r2 = z.divW(u, v[0]) - r = z2.setWord(r2) - return - } - - q, r = z.divLarge(z2, u, v) - return -} - -// getNat returns a nat of len n. The contents may not be zero. -func getNat(n int) nat { - var z nat - if v := natPool.Get(); v != nil { - z = v.(nat) - } - return z.make(n) -} - -func putNat(x nat) { - natPool.Put(x) -} - -var natPool sync.Pool - -// q = (uIn-r)/v, with 0 <= r < y -// Uses z as storage for q, and u as storage for r if possible. -// See Knuth, Volume 2, section 4.3.1, Algorithm D. -// Preconditions: -// len(v) >= 2 -// len(uIn) >= len(v) -func (z nat) divLarge(u, uIn, v nat) (q, r nat) { - n := len(v) - m := len(uIn) - n - - // determine if z can be reused - // TODO(gri) should find a better solution - this if statement - // is very costly (see e.g. time pidigits -s -n 10000) - if alias(z, uIn) || alias(z, v) { - z = nil // z is an alias for uIn or v - cannot reuse - } - q = z.make(m + 1) - - qhatv := getNat(n + 1) - if alias(u, uIn) || alias(u, v) { - u = nil // u is an alias for uIn or v - cannot reuse - } - u = u.make(len(uIn) + 1) - u.clear() // TODO(gri) no need to clear if we allocated a new u - - // D1. - var v1 nat - shift := nlz(v[n-1]) - if shift > 0 { - // do not modify v, it may be used by another goroutine simultaneously - v1 = getNat(n) - shlVU(v1, v, shift) - v = v1 - } - u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift) - - // D2. - for j := m; j >= 0; j-- { - // D3. - qhat := Word(_M) - if u[j+n] != v[n-1] { - var rhat Word - qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1]) - - // x1 | x2 = q̂v_{n-2} - x1, x2 := mulWW(qhat, v[n-2]) - // test if q̂v_{n-2} > br̂ + u_{j+n-2} - for greaterThan(x1, x2, rhat, u[j+n-2]) { - qhat-- - prevRhat := rhat - rhat += v[n-1] - // v[n-1] >= 0, so this tests for overflow. - if rhat < prevRhat { - break - } - x1, x2 = mulWW(qhat, v[n-2]) - } - } - - // D4. - qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) - - c := subVV(u[j:j+len(qhatv)], u[j:], qhatv) - if c != 0 { - c := addVV(u[j:j+n], u[j:], v) - u[j+n] += c - qhat-- - } - - q[j] = qhat - } - if v1 != nil { - putNat(v1) - } - putNat(qhatv) - - q = q.norm() - shrVU(u, u, shift) - r = u.norm() - - return q, r -} - -// Length of x in bits. x must be normalized. -func (x nat) bitLen() int { - if i := len(x) - 1; i >= 0 { - return i*_W + bitLen(x[i]) - } - return 0 -} - -const deBruijn32 = 0x077CB531 - -var deBruijn32Lookup = []byte{ - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, -} - -const deBruijn64 = 0x03f79d71b4ca8b09 - -var deBruijn64Lookup = []byte{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} - -// trailingZeroBits returns the number of consecutive least significant zero -// bits of x. -func trailingZeroBits(x Word) uint { - // x & -x leaves only the right-most bit set in the word. Let k be the - // index of that bit. Since only a single bit is set, the value is two - // to the power of k. Multiplying by a power of two is equivalent to - // left shifting, in this case by k bits. The de Bruijn constant is - // such that all six bit, consecutive substrings are distinct. - // Therefore, if we have a left shifted version of this constant we can - // find by how many bits it was shifted by looking at which six bit - // substring ended up at the top of the word. - // (Knuth, volume 4, section 7.3.1) - switch _W { - case 32: - return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27]) - case 64: - return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58]) - default: - panic("unknown word size") - } -} - -// trailingZeroBits returns the number of consecutive least significant zero -// bits of x. -func (x nat) trailingZeroBits() uint { - if len(x) == 0 { - return 0 - } - var i uint - for x[i] == 0 { - i++ - } - // x[i] != 0 - return i*_W + trailingZeroBits(x[i]) -} - -// z = x << s -func (z nat) shl(x nat, s uint) nat { - m := len(x) - if m == 0 { - return z[:0] - } - // m > 0 - - n := m + int(s/_W) - z = z.make(n + 1) - z[n] = shlVU(z[n-m:n], x, s%_W) - z[0 : n-m].clear() - - return z.norm() -} - -// z = x >> s -func (z nat) shr(x nat, s uint) nat { - m := len(x) - n := m - int(s/_W) - if n <= 0 { - return z[:0] - } - // n > 0 - - z = z.make(n) - shrVU(z, x[m-n:], s%_W) - - return z.norm() -} - -func (z nat) setBit(x nat, i uint, b uint) nat { - j := int(i / _W) - m := Word(1) << (i % _W) - n := len(x) - switch b { - case 0: - z = z.make(n) - copy(z, x) - if j >= n { - // no need to grow - return z - } - z[j] &^= m - return z.norm() - case 1: - if j >= n { - z = z.make(j + 1) - z[n:].clear() - } else { - z = z.make(n) - } - copy(z, x) - z[j] |= m - // no need to normalize - return z - } - panic("set bit is not 0 or 1") -} - -// 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 - } - // 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 { - m := len(x) - n := len(y) - if m > n { - m = n - } - // m <= n - - z = z.make(m) - for i := 0; i < m; i++ { - z[i] = x[i] & y[i] - } - - return z.norm() -} - -func (z nat) andNot(x, y nat) nat { - m := len(x) - n := len(y) - if n > m { - n = m - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] &^ y[i] - } - copy(z[n:m], x[n:m]) - - return z.norm() -} - -func (z nat) or(x, y nat) nat { - m := len(x) - n := len(y) - s := x - if m < n { - n, m = m, n - s = y - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] | y[i] - } - copy(z[n:m], s[n:m]) - - return z.norm() -} - -func (z nat) xor(x, y nat) nat { - m := len(x) - n := len(y) - s := x - if m < n { - n, m = m, n - s = y - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] ^ y[i] - } - copy(z[n:m], s[n:m]) - - return z.norm() -} - -// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2) -func greaterThan(x1, x2, y1, y2 Word) bool { - return x1 > y1 || x1 == y1 && x2 > y2 -} - -// modW returns x % d. -func (x nat) modW(d Word) (r Word) { - // TODO(agl): we don't actually need to store the q value. - var q nat - q = q.make(len(x)) - return divWVW(q, 0, x, d) -} - -// random creates a random integer in [0..limit), using the space in z if -// possible. n is the bit length of limit. -func (z nat) random(rand *rand.Rand, limit nat, n int) nat { - if alias(z, limit) { - z = nil // z is an alias for limit - cannot reuse - } - z = z.make(len(limit)) - - bitLengthOfMSW := uint(n % _W) - if bitLengthOfMSW == 0 { - bitLengthOfMSW = _W - } - mask := Word((1 << bitLengthOfMSW) - 1) - - for { - switch _W { - case 32: - for i := range z { - z[i] = Word(rand.Uint32()) - } - case 64: - for i := range z { - z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32 - } - default: - panic("unknown word size") - } - z[len(limit)-1] &= mask - if z.cmp(limit) < 0 { - break - } - } - - return z.norm() -} - -// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m; -// otherwise it sets z to x**y. The result is the value of z. -func (z nat) expNN(x, y, m nat) nat { - if alias(z, x) || alias(z, y) { - // We cannot allow in-place modification of x or y. - z = nil - } - - // x**y mod 1 == 0 - if len(m) == 1 && m[0] == 1 { - return z.setWord(0) - } - // m == 0 || m > 1 - - // x**0 == 1 - if len(y) == 0 { - return z.setWord(1) - } - // 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)) - } - z = z.set(x) - - // If the base is non-trivial and the exponent is large, we use - // 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. 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 := nlz(v) + 1 - v <<= shift - var q nat - - const mask = 1 << (_W - 1) - - // We walk through the bits of the exponent one by one. Each time we - // see a bit, we square, thus doubling the power. If the bit is a one, - // we also multiply by x, thus adding one to the power. - - w := _W - int(shift) - // zz and r are used to avoid allocating in mul and div as - // otherwise the arguments would alias. - var zz, r nat - for j := 0; j < w; j++ { - zz = zz.mul(z, z) - zz, z = z, zz - - if v&mask != 0 { - zz = zz.mul(z, x) - zz, z = z, zz - } - - if len(m) != 0 { - zz, r = zz.div(r, z, m) - zz, r, q, z = q, z, zz, r - } - - v <<= 1 - } - - for i := len(y) - 2; i >= 0; i-- { - v = y[i] - - for j := 0; j < _W; j++ { - zz = zz.mul(z, z) - zz, z = z, zz - - if v&mask != 0 { - zz = zz.mul(z, x) - zz, z = z, zz - } - - if len(m) != 0 { - zz, r = zz.div(r, z, m) - zz, r, q, z = q, z, zz, r - } - - v <<= 1 - } - } - - return z.norm() -} - -// expNNWindowed calculates x**y mod m using a fixed, 4-bit window. -func (z nat) expNNWindowed(x, y, m nat) nat { - // zz and r are used to avoid allocating in mul and div as otherwise - // the arguments would alias. - var zz, r nat - - const n = 4 - // powers[i] contains x^i. - var powers [1 << n]nat - powers[0] = natOne - powers[1] = x - for i := 2; i < 1<= 0; i-- { - yi := y[i] - for j := 0; j < _W; j += n { - if i != len(y)-1 || j != 0 { - // Unrolled loop for significant performance - // gain. Use go test -bench=".*" in crypto/rsa - // to check performance before making changes. - zz = zz.mul(z, z) - zz, z = z, zz - zz, r = zz.div(r, z, m) - z, r = r, z - - zz = zz.mul(z, z) - zz, z = z, zz - zz, r = zz.div(r, z, m) - z, r = r, z - - zz = zz.mul(z, z) - zz, z = z, zz - zz, r = zz.div(r, z, m) - z, r = r, z - - zz = zz.mul(z, z) - zz, z = z, zz - zz, r = zz.div(r, z, m) - z, r = r, z - } - - zz = zz.mul(z, powers[yi>>(_W-n)]) - zz, z = z, zz - zz, r = zz.div(r, z, m) - z, r = r, z - - yi <<= n - } - } - - 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 { - numWords := len(m) - - // We want the lengths of x and m to be equal. - // It is OK if x >= m as long as len(x) == len(m). - if len(x) > numWords { - _, x = nat(nil).div(nil, x, m) - // Note: now len(x) <= numWords, not guaranteed ==. - } - if len(x) < numWords { - rr := make(nat, numWords) - copy(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 := nat(nil).setWord(1) - zz := nat(nil).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 := make(nat, numWords) - 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<= 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) - - // One last reduction, just in case. - // See golang.org/issue/13907. - if zz.cmp(m) >= 0 { - // Common case is m has high bit set; in that case, - // since zz is the same length as m, there can be just - // one multiple of m to remove. Just subtract. - // We think that the subtract should be sufficient in general, - // so do that unconditionally, but double-check, - // in case our beliefs are wrong. - // The div is not expected to be reached. - zz = zz.sub(zz, m) - if zz.cmp(m) >= 0 { - _, zz = nat(nil).div(nil, zz, m) - } - } - - return zz.norm() -} - -// probablyPrime performs n Miller-Rabin tests to check whether x is prime. -// If x is prime, it returns true. -// If x is not prime, it returns false with probability at least 1 - ¼ⁿ. -// -// It is not suitable for judging primes that an adversary may have crafted -// to fool this test. -func (n nat) probablyPrime(reps int) bool { - if len(n) == 0 { - return false - } - - if len(n) == 1 { - if n[0] < 2 { - return false - } - - if n[0]%2 == 0 { - return n[0] == 2 - } - - // We have to exclude these cases because we reject all - // multiples of these numbers below. - switch n[0] { - case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53: - return true - } - } - - 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} - - var r Word - switch _W { - case 32: - r = n.modW(primesProduct32) - case 64: - r = n.modW(primesProduct64 & _M) - default: - panic("Unknown word size") - } - - if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 || - r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 { - return false - } - - if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 || - r%43 == 0 || r%47 == 0 || r%53 == 0) { - return false - } - - nm1 := nat(nil).sub(n, natOne) - // determine q, k such that nm1 = q << k - k := nm1.trailingZeroBits() - q := nat(nil).shr(nm1, k) - - nm3 := nat(nil).sub(nm1, natTwo) - rand := rand.New(rand.NewSource(int64(n[0]))) - - var x, y, quotient nat - nm3Len := nm3.bitLen() - -NextRandom: - for i := 0; i < reps; i++ { - x = x.random(rand, nm3, nm3Len) - x = x.add(x, natTwo) - y = y.expNN(x, q, n) - if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 { - continue - } - for j := uint(1); j < k; j++ { - y = y.mul(y, y) - quotient, y = quotient.div(y, y, n) - if y.cmp(nm1) == 0 { - continue NextRandom - } - if y.cmp(natOne) == 0 { - return false - } - } - return false - } - - return true -} - -// bytes writes the value of z into buf using big-endian encoding. -// len(buf) must be >= len(z)*_S. The value of z is encoded in the -// slice buf[i:]. The number i of unused bytes at the beginning of -// buf is returned as result. -func (z nat) bytes(buf []byte) (i int) { - i = len(buf) - for _, d := range z { - for j := 0; j < _S; j++ { - i-- - buf[i] = byte(d) - d >>= 8 - } - } - - for i < len(buf) && buf[i] == 0 { - i++ - } - - return -} - -// setBytes interprets buf as the bytes of a big-endian unsigned -// integer, sets z to that value, and returns z. -func (z nat) setBytes(buf []byte) nat { - z = z.make((len(buf) + _S - 1) / _S) - - k := 0 - s := uint(0) - var d Word - for i := len(buf); i > 0; i-- { - d |= Word(buf[i-1]) << s - if s += 8; s == _S*8 { - z[k] = d - k++ - s = 0 - d = 0 - } - } - if k < len(z) { - z[k] = d - } - - return z.norm() -} diff --git a/src/cmd/compile/internal/big/nat_test.go b/src/cmd/compile/internal/big/nat_test.go deleted file mode 100644 index ebb2985654..0000000000 --- a/src/cmd/compile/internal/big/nat_test.go +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright 2009 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" - "runtime" - "strings" - "testing" -) - -var cmpTests = []struct { - x, y nat - r int -}{ - {nil, nil, 0}, - {nil, nat(nil), 0}, - {nat(nil), nil, 0}, - {nat(nil), nat(nil), 0}, - {nat{0}, nat{0}, 0}, - {nat{0}, nat{1}, -1}, - {nat{1}, nat{0}, 1}, - {nat{1}, nat{1}, 0}, - {nat{0, _M}, nat{1}, 1}, - {nat{1}, nat{0, _M}, -1}, - {nat{1, _M}, nat{0, _M}, 1}, - {nat{0, _M}, nat{1, _M}, -1}, - {nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1}, - {nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1}, -} - -func TestCmp(t *testing.T) { - for i, a := range cmpTests { - r := a.x.cmp(a.y) - if r != a.r { - t.Errorf("#%d got r = %v; want %v", i, r, a.r) - } - } -} - -type funNN func(z, x, y nat) nat -type argNN struct { - z, x, y nat -} - -var sumNN = []argNN{ - {}, - {nat{1}, nil, nat{1}}, - {nat{1111111110}, nat{123456789}, nat{987654321}}, - {nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}}, - {nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}}, - {nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}}, -} - -var prodNN = []argNN{ - {}, - {nil, nil, nil}, - {nil, nat{991}, nil}, - {nat{991}, nat{991}, nat{1}}, - {nat{991 * 991}, nat{991}, nat{991}}, - {nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}}, - {nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}}, - {nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}}, - // 3^100 * 3^28 = 3^128 - { - natFromString("11790184577738583171520872861412518665678211592275841109096961"), - natFromString("515377520732011331036461129765621272702107522001"), - natFromString("22876792454961"), - }, - // z = 111....1 (70000 digits) - // x = 10^(99*700) + ... + 10^1400 + 10^700 + 1 - // y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit) - { - natFromString(strings.Repeat("1", 70000)), - natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)), - natFromString(strings.Repeat("1", 700)), - }, - // z = 111....1 (20000 digits) - // x = 10^10000 + 1 - // y = 111....1 (10000 digits) - { - natFromString(strings.Repeat("1", 20000)), - natFromString("1" + strings.Repeat("0", 9999) + "1"), - natFromString(strings.Repeat("1", 10000)), - }, -} - -func natFromString(s string) nat { - x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false) - if err != nil { - panic(err) - } - return x -} - -func TestSet(t *testing.T) { - for _, a := range sumNN { - z := nat(nil).set(a.z) - if z.cmp(a.z) != 0 { - t.Errorf("got z = %v; want %v", z, a.z) - } - } -} - -func testFunNN(t *testing.T, msg string, f funNN, a argNN) { - z := f(nil, a.x, a.y) - if z.cmp(a.z) != 0 { - t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z) - } -} - -func TestFunNN(t *testing.T) { - for _, a := range sumNN { - arg := a - testFunNN(t, "add", nat.add, arg) - - arg = argNN{a.z, a.y, a.x} - testFunNN(t, "add symmetric", nat.add, arg) - - arg = argNN{a.x, a.z, a.y} - testFunNN(t, "sub", nat.sub, arg) - - arg = argNN{a.y, a.z, a.x} - testFunNN(t, "sub symmetric", nat.sub, arg) - } - - for _, a := range prodNN { - arg := a - testFunNN(t, "mul", nat.mul, arg) - - arg = argNN{a.z, a.y, a.x} - testFunNN(t, "mul symmetric", nat.mul, arg) - } -} - -var mulRangesN = []struct { - a, b uint64 - prod string -}{ - {0, 0, "0"}, - {1, 1, "1"}, - {1, 2, "2"}, - {1, 3, "6"}, - {10, 10, "10"}, - {0, 100, "0"}, - {0, 1e9, "0"}, - {1, 0, "1"}, // empty range - {100, 1, "1"}, // empty range - {1, 10, "3628800"}, // 10! - {1, 20, "2432902008176640000"}, // 20! - {1, 100, - "933262154439441526816992388562667004907159682643816214685929" + - "638952175999932299156089414639761565182862536979208272237582" + - "51185210916864000000000000000000000000", // 100! - }, -} - -func TestMulRangeN(t *testing.T) { - for i, r := range mulRangesN { - prod := string(nat(nil).mulRange(r.a, r.b).utoa(10)) - if prod != r.prod { - t.Errorf("#%d: got %s; want %s", i, prod, r.prod) - } - } -} - -// allocBytes returns the number of bytes allocated by invoking f. -func allocBytes(f func()) uint64 { - var stats runtime.MemStats - runtime.ReadMemStats(&stats) - t := stats.TotalAlloc - f() - runtime.ReadMemStats(&stats) - return stats.TotalAlloc - t -} - -// TestMulUnbalanced tests that multiplying numbers of different lengths -// does not cause deep recursion and in turn allocate too much memory. -// Test case for issue 3807. -func TestMulUnbalanced(t *testing.T) { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) - x := rndNat(50000) - y := rndNat(40) - allocSize := allocBytes(func() { - nat(nil).mul(x, y) - }) - inputSize := uint64(len(x)+len(y)) * _S - if ratio := allocSize / uint64(inputSize); ratio > 10 { - t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio) - } -} - -func rndNat(n int) nat { - return nat(rndV(n)).norm() -} - -func BenchmarkMul(b *testing.B) { - mulx := rndNat(1e4) - muly := rndNat(1e4) - b.ResetTimer() - for i := 0; i < b.N; i++ { - var z nat - z.mul(mulx, muly) - } -} - -func TestNLZ(t *testing.T) { - var x Word = _B >> 1 - for i := 0; i <= _W; i++ { - if int(nlz(x)) != i { - t.Errorf("failed at %x: got %d want %d", x, nlz(x), i) - } - x >>= 1 - } -} - -type shiftTest struct { - in nat - shift uint - out nat -} - -var leftShiftTests = []shiftTest{ - {nil, 0, nil}, - {nil, 1, nil}, - {natOne, 0, natOne}, - {natOne, 1, natTwo}, - {nat{1 << (_W - 1)}, 1, nat{0}}, - {nat{1 << (_W - 1), 0}, 1, nat{0, 1}}, -} - -func TestShiftLeft(t *testing.T) { - for i, test := range leftShiftTests { - var z nat - z = z.shl(test.in, test.shift) - for j, d := range test.out { - if j >= len(z) || z[j] != d { - t.Errorf("#%d: got: %v want: %v", i, z, test.out) - break - } - } - } -} - -var rightShiftTests = []shiftTest{ - {nil, 0, nil}, - {nil, 1, nil}, - {natOne, 0, natOne}, - {natOne, 1, nil}, - {natTwo, 1, natOne}, - {nat{0, 1}, 1, nat{1 << (_W - 1)}}, - {nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}}, -} - -func TestShiftRight(t *testing.T) { - for i, test := range rightShiftTests { - var z nat - z = z.shr(test.in, test.shift) - for j, d := range test.out { - if j >= len(z) || z[j] != d { - t.Errorf("#%d: got: %v want: %v", i, z, test.out) - break - } - } - } -} - -type modWTest struct { - in string - dividend string - out string -} - -var modWTests32 = []modWTest{ - {"23492635982634928349238759823742", "252341", "220170"}, -} - -var modWTests64 = []modWTest{ - {"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"}, -} - -func runModWTests(t *testing.T, tests []modWTest) { - for i, test := range tests { - in, _ := new(Int).SetString(test.in, 10) - d, _ := new(Int).SetString(test.dividend, 10) - out, _ := new(Int).SetString(test.out, 10) - - r := in.abs.modW(d.abs[0]) - if r != out.abs[0] { - t.Errorf("#%d failed: got %d want %s", i, r, out) - } - } -} - -func TestModW(t *testing.T) { - if _W >= 32 { - runModWTests(t, modWTests32) - } - if _W >= 64 { - runModWTests(t, modWTests64) - } -} - -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++ { - n := trailingZeroBits(x) - 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.utoa(16), n, i) - } - y = y.shl(y, 1) - } -} - -var montgomeryTests = []struct { - x, y, m string - k0 uint64 - out32, out64 string -}{ - { - "0xffffffffffffffffffffffffffffffffffffffffffffffffe", - "0xffffffffffffffffffffffffffffffffffffffffffffffffe", - "0xfffffffffffffffffffffffffffffffffffffffffffffffff", - 1, - "0x1000000000000000000000000000000000000000000", - "0x10000000000000000000000000000000000", - }, - { - "0x000000000ffffff5", - "0x000000000ffffff0", - "0x0000000010000001", - 0xff0000000fffffff, - "0x000000000bfffff4", - "0x0000000003400001", - }, - { - "0x0000000080000000", - "0x00000000ffffffff", - "0x1000000000000001", - 0xfffffffffffffff, - "0x0800000008000001", - "0x0800000008000001", - }, - { - "0x0000000080000000", - "0x0000000080000000", - "0xffffffff00000001", - 0xfffffffeffffffff, - "0xbfffffff40000001", - "0xbfffffff40000001", - }, - { - "0x0000000080000000", - "0x0000000080000000", - "0x00ffffff00000001", - 0xfffffeffffffff, - "0xbfffff40000001", - "0xbfffff40000001", - }, - { - "0x0000000080000000", - "0x0000000080000000", - "0x0000ffff00000001", - 0xfffeffffffff, - "0xbfff40000001", - "0xbfff40000001", - }, - { - "0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0", - "0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0", - "0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1", - 0xdecc8f1249812adf, - "0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5", - "0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0", - }, - { - "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444", - "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1", - 0xdecc8f1249812adf, - "0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715", - "0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6", - }, -} - -func TestMontgomery(t *testing.T) { - one := NewInt(1) - _B := new(Int).Lsh(one, _W) - for i, test := range montgomeryTests { - x := natFromString(test.x) - y := natFromString(test.y) - m := natFromString(test.m) - for len(x) < len(m) { - x = append(x, 0) - } - for len(y) < len(m) { - y = append(y, 0) - } - - if x.cmp(m) > 0 { - _, r := nat(nil).div(nil, x, m) - t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16)) - } - if y.cmp(m) > 0 { - _, r := nat(nil).div(nil, x, m) - t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16)) - } - - var out nat - if _W == 32 { - out = natFromString(test.out32) - } else { - out = natFromString(test.out64) - } - - // t.Logf("#%d: len=%d\n", i, len(m)) - - // check output in table - xi := &Int{abs: x} - yi := &Int{abs: y} - mi := &Int{abs: m} - p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi) - if out.cmp(p.abs.norm()) != 0 { - t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16)) - } - - // check k0 in table - k := new(Int).Mod(&Int{abs: m}, _B) - k = new(Int).Sub(_B, k) - k = new(Int).Mod(k, _B) - k0 := Word(new(Int).ModInverse(k, _B).Uint64()) - if k0 != Word(test.k0) { - t.Errorf("#%d: k0 in table=%#x, computed=%#x\n", i, test.k0, k0) - } - - // check montgomery with correct k0 produces correct output - z := nat(nil).montgomery(x, y, m, k0, len(m)) - z = z.norm() - if z.cmp(out) != 0 { - t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16)) - } - } -} - -var expNNTests = []struct { - x, y, m string - out string -}{ - {"0", "0", "0", "1"}, - {"0", "0", "1", "0"}, - {"1", "1", "1", "0"}, - {"2", "1", "1", "0"}, - {"2", "2", "1", "0"}, - {"10", "100000000000", "1", "0"}, - {"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, - {"0x8000000000000000", "2", "6719", "4944"}, - {"0x8000000000000000", "3", "6719", "5447"}, - {"0x8000000000000000", "1000", "6719", "1603"}, - {"0x8000000000000000", "1000000", "6719", "3199"}, - { - "2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347", - "298472983472983471903246121093472394872319615612417471234712061", - "29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464", - "23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291", - }, - { - "11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379", - "426343618817810911523", - "444747819283133684179", - "42", - }, -} - -func TestExpNN(t *testing.T) { - for i, test := range expNNTests { - x := natFromString(test.x) - y := natFromString(test.y) - out := natFromString(test.out) - - var m nat - if len(test.m) > 0 { - m = natFromString(test.m) - } - - z := nat(nil).expNN(x, y, m) - if z.cmp(out) != 0 { - t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10)) - } - } -} - -func BenchmarkExp3Power(b *testing.B) { - const x = 3 - for _, y := range []Word{ - 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, - } { - b.Run(fmt.Sprintf("%#x", y), func(b *testing.B) { - var z nat - for i := 0; i < b.N; i++ { - z.expWW(x, y) - } - }) - } -} - -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 := string(fibo(n).utoa(10)) - 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/src/cmd/compile/internal/big/natconv.go b/src/cmd/compile/internal/big/natconv.go deleted file mode 100644 index 44547842c1..0000000000 --- a/src/cmd/compile/internal/big/natconv.go +++ /dev/null @@ -1,492 +0,0 @@ -// 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" -) - -const digits = "0123456789abcdefghijklmnopqrstuvwxyz" - -// Note: MaxBase = len(digits), but it must remain a rune constant -// for API compatibility. - -// 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 -} - -// utoa converts x to an ASCII representation in the given base; -// base must be between 2 and MaxBase, inclusive. -func (x nat) utoa(base int) []byte { - return x.itoa(false, base) -} - -// itoa is like utoa but it prepends a '-' if neg && x != 0. -func (x nat) itoa(neg bool, base int) []byte { - if base < 2 || base > MaxBase { - panic("invalid base") - } - - // x == 0 - if len(x) == 0 { - return []byte("0") - } - // len(x) > 0 - - // allocate buffer for conversion - i := int(float64(x.bitLen())/math.Log2(float64(base))) + 1 // off by 1 at most - if neg { - i++ - } - s := make([]byte, i) - - // convert power of two and non power of two bases separately - if b := Word(base); b == b&-b { - // shift is base b digit size in bits - shift := trailingZeroBits(b) // shift > 0 because b >= 2 - mask := Word(1<= shift { - i-- - s[i] = digits[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 word w (== x[k-1]) and next word x[k] - w |= x[k] << nbits - i-- - s[i] = digits[w&mask] - - // advance - w = x[k] >> (shift - nbits) - nbits = _W - (shift - nbits) - } - } - - // convert digits of most-significant word w (omit leading zeros) - for w != 0 { - i-- - s[i] = digits[w&mask] - w >>= shift - } - - } else { - bb, ndigits := maxPow(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, 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 s[i] == '0' { - i++ - } - } - - if neg { - i-- - s[i] = '-' - } - - return 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, 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:], b, ndigits, bb, table[0:index]) - s = s[:h] // == q.convertWords(s, 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] = '0' + byte(r-t*10) - 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] = digits[r%b] - r /= b - } - } - } - - // prepend high-order zeros - for i > 0 { // while need more leading zeros - i-- - s[i] = '0' - } -} - -// 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 zeros) ~= 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/src/cmd/compile/internal/big/natconv_test.go b/src/cmd/compile/internal/big/natconv_test.go deleted file mode 100644 index 79901d1880..0000000000 --- a/src/cmd/compile/internal/big/natconv_test.go +++ /dev/null @@ -1,379 +0,0 @@ -// 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" - "io" - "strings" - "testing" -) - -func itoa(x nat, base int) []byte { - // special cases - switch { - case base < 2: - panic("illegal base") - case len(x) == 0: - return []byte("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] = digits[r] - } - - return s[i:] -} - -var strTests = []struct { - x nat // nat value to be converted - b int // conversion base - s string // expected result -}{ - {nil, 2, "0"}, - {nat{1}, 2, "1"}, - {nat{0xc5}, 2, "11000101"}, - {nat{03271}, 8, "3271"}, - {nat{10}, 10, "10"}, - {nat{1234567890}, 10, "1234567890"}, - {nat{0xdeadbeef}, 16, "deadbeef"}, - {nat{0x229be7}, 17, "1a2b3c"}, - {nat{0x309663e6}, 32, "o9cov6"}, -} - -func TestString(t *testing.T) { - // test invalid base explicitly - var panicStr string - func() { - defer func() { - panicStr = recover().(string) - }() - natOne.utoa(1) - }() - if panicStr != "invalid base" { - t.Errorf("expected panic for invalid base") - } - - for _, a := range strTests { - s := string(a.x.utoa(a.b)) - 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), a.b, false) - 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.b) - } - 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 := string(z.utoa(10)); 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 string(x.utoa(10)) != pi { - panic("benchmark incorrect: conversion failed") - } - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - x.utoa(10) - } - }) -} - -func BenchmarkScan(b *testing.B) { - const x = 10 - for _, base := range []int{2, 8, 10, 16} { - for _, y := range []Word{10, 100, 1000, 10000, 100000} { - b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) { - b.StopTimer() - var z nat - z = z.expWW(x, y) - - s := z.utoa(base) - if t := itoa(z, base); !bytes.Equal(s, t) { - b.Fatalf("scanning: got %s; want %s", s, t) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - z.scan(bytes.NewReader(s), base, false) - } - }) - } - } -} - -func BenchmarkString(b *testing.B) { - const x = 10 - for _, base := range []int{2, 8, 10, 16} { - for _, y := range []Word{10, 100, 1000, 10000, 100000} { - b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) { - b.StopTimer() - var z nat - z = z.expWW(x, y) - z.utoa(base) // warm divisor cache - b.StartTimer() - - for i := 0; i < b.N; i++ { - _ = z.utoa(base) - } - }) - } - } -} - -func BenchmarkLeafSize(b *testing.B) { - for n := 0; n <= 16; n++ { - b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) }) - } - // Try some large lengths - for _, n := range []int{32, 64} { - b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) }) - } -} - -func LeafSizeHelper(b *testing.B, base, 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(Word(base), Word(d)) // build target number - _ = z.utoa(base) // warm divisor cache - b.StartTimer() - - for i := 0; i < b.N; i++ { - _ = z.utoa(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 p Word - for b := 2; b <= 16; b++ { - for p = 0; p <= 512; p++ { - x := nat(nil).expWW(Word(b), p) - xs := x.utoa(b) - xs2 := itoa(x, b) - if !bytes.Equal(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/src/cmd/compile/internal/big/rat.go b/src/cmd/compile/internal/big/rat.go deleted file mode 100644 index 56ce33d882..0000000000 --- a/src/cmd/compile/internal/big/rat.go +++ /dev/null @@ -1,510 +0,0 @@ -// Copyright 2010 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 rational numbers. - -package big - -import ( - "fmt" - "math" -) - -// A Rat represents a quotient a/b of arbitrary precision. -// The zero value for a Rat represents the value 0. -type Rat struct { - // To make zero values for Rat work w/o initialization, - // a zero value of b (len(b) == 0) acts like b == 1. - // a.neg determines the sign of the Rat, b.neg is ignored. - a, b Int -} - -// NewRat creates a new Rat with numerator a and denominator b. -func NewRat(a, b int64) *Rat { - return new(Rat).SetFrac64(a, b) -} - -// SetFloat64 sets z to exactly f and returns z. -// If f is not finite, SetFloat returns nil. -func (z *Rat) SetFloat64(f float64) *Rat { - const expMask = 1<<11 - 1 - bits := math.Float64bits(f) - mantissa := bits & (1<<52 - 1) - exp := int((bits >> 52) & expMask) - switch exp { - case expMask: // non-finite - return nil - case 0: // denormal - exp -= 1022 - default: // normal - mantissa |= 1 << 52 - exp -= 1023 - } - - shift := 52 - exp - - // Optimization (?): partially pre-normalise. - for mantissa&1 == 0 && shift > 0 { - mantissa >>= 1 - shift-- - } - - z.a.SetUint64(mantissa) - z.a.neg = f < 0 - z.b.Set(intOne) - if shift > 0 { - z.b.Lsh(&z.b, uint(shift)) - } else { - z.a.Lsh(&z.a, uint(-shift)) - } - return z.norm() -} - -// quotToFloat32 returns the non-negative float32 value -// nearest to the quotient a/b, using round-to-even in -// halfway cases. It does not mutate its arguments. -// Preconditions: b is non-zero; a and b have no common factors. -func quotToFloat32(a, b nat) (f float32, exact bool) { - const ( - // float size in bits - Fsize = 32 - - // mantissa - Msize = 23 - Msize1 = Msize + 1 // incl. implicit 1 - Msize2 = Msize1 + 1 - - // exponent - Esize = Fsize - Msize1 - Ebias = 1<<(Esize-1) - 1 - Emin = 1 - Ebias - Emax = Ebias - ) - - // TODO(adonovan): specialize common degenerate cases: 1.0, integers. - alen := a.bitLen() - if alen == 0 { - return 0, true - } - blen := b.bitLen() - if blen == 0 { - panic("division by zero") - } - - // 1. Left-shift A or B such that quotient A/B is in [1<= B). - // This is 2 or 3 more than the float32 mantissa field width of Msize: - // - the optional extra bit is shifted away in step 3 below. - // - the high-order 1 is omitted in "normal" representation; - // - the low-order 1 will be used during rounding then discarded. - exp := alen - blen - var a2, b2 nat - a2 = a2.set(a) - b2 = b2.set(b) - if shift := Msize2 - exp; shift > 0 { - a2 = a2.shl(a2, uint(shift)) - } else if shift < 0 { - b2 = b2.shl(b2, uint(-shift)) - } - - // 2. Compute quotient and remainder (q, r). NB: due to the - // extra shift, the low-order bit of q is logically the - // high-order bit of r. - var q nat - q, r := q.div(a2, a2, b2) // (recycle a2) - mantissa := low32(q) - haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half - - // 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1 - // (in effect---we accomplish this incrementally). - if mantissa>>Msize2 == 1 { - if mantissa&1 == 1 { - haveRem = true - } - mantissa >>= 1 - exp++ - } - if mantissa>>Msize1 != 1 { - panic(fmt.Sprintf("expected exactly %d bits of result", Msize2)) - } - - // 4. Rounding. - if Emin-Msize <= exp && exp <= Emin { - // Denormal case; lose 'shift' bits of precision. - shift := uint(Emin - (exp - 1)) // [1..Esize1) - lostbits := mantissa & (1<>= shift - exp = 2 - Ebias // == exp + shift - } - // Round q using round-half-to-even. - exact = !haveRem - if mantissa&1 != 0 { - exact = false - if haveRem || mantissa&2 != 0 { - if mantissa++; mantissa >= 1< 100...0, so shift is safe - mantissa >>= 1 - exp++ - } - } - } - mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1<= B). - // This is 2 or 3 more than the float64 mantissa field width of Msize: - // - the optional extra bit is shifted away in step 3 below. - // - the high-order 1 is omitted in "normal" representation; - // - the low-order 1 will be used during rounding then discarded. - exp := alen - blen - var a2, b2 nat - a2 = a2.set(a) - b2 = b2.set(b) - if shift := Msize2 - exp; shift > 0 { - a2 = a2.shl(a2, uint(shift)) - } else if shift < 0 { - b2 = b2.shl(b2, uint(-shift)) - } - - // 2. Compute quotient and remainder (q, r). NB: due to the - // extra shift, the low-order bit of q is logically the - // high-order bit of r. - var q nat - q, r := q.div(a2, a2, b2) // (recycle a2) - mantissa := low64(q) - haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half - - // 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1 - // (in effect---we accomplish this incrementally). - if mantissa>>Msize2 == 1 { - if mantissa&1 == 1 { - haveRem = true - } - mantissa >>= 1 - exp++ - } - if mantissa>>Msize1 != 1 { - panic(fmt.Sprintf("expected exactly %d bits of result", Msize2)) - } - - // 4. Rounding. - if Emin-Msize <= exp && exp <= Emin { - // Denormal case; lose 'shift' bits of precision. - shift := uint(Emin - (exp - 1)) // [1..Esize1) - lostbits := mantissa & (1<>= shift - exp = 2 - Ebias // == exp + shift - } - // Round q using round-half-to-even. - exact = !haveRem - if mantissa&1 != 0 { - exact = false - if haveRem || mantissa&2 != 0 { - if mantissa++; mantissa >= 1< 100...0, so shift is safe - mantissa >>= 1 - exp++ - } - } - } - mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1< 0 && !z.a.neg // 0 has no sign - return z -} - -// Inv sets z to 1/x and returns z. -func (z *Rat) Inv(x *Rat) *Rat { - if len(x.a.abs) == 0 { - panic("division by zero") - } - z.Set(x) - a := z.b.abs - if len(a) == 0 { - a = a.set(natOne) // materialize numerator - } - b := z.a.abs - if b.cmp(natOne) == 0 { - b = b[:0] // normalize denominator - } - z.a.abs, z.b.abs = a, b // sign doesn't change - return z -} - -// Sign returns: -// -// -1 if x < 0 -// 0 if x == 0 -// +1 if x > 0 -// -func (x *Rat) Sign() int { - return x.a.Sign() -} - -// 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 -} - -// Num returns the numerator of x; it may be <= 0. -// The result is a reference to x's numerator; it -// may change if a new value is assigned to x, and vice versa. -// The sign of the numerator corresponds to the sign of x. -func (x *Rat) Num() *Int { - return &x.a -} - -// Denom returns the denominator of x; it is always > 0. -// The result is a reference to x's denominator; it -// may change if a new value is assigned to x, and vice versa. -func (x *Rat) Denom() *Int { - x.b.neg = false // the result is always >= 0 - if len(x.b.abs) == 0 { - x.b.abs = x.b.abs.set(natOne) // materialize denominator - } - return &x.b -} - -func (z *Rat) norm() *Rat { - switch { - case len(z.a.abs) == 0: - // z == 0 - normalize sign and denominator - z.a.neg = false - 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[:0] - default: - neg := z.a.neg - z.a.neg = false - z.b.neg = false - if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 { - z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs) - 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[:0] - } - } - z.a.neg = neg - } - return z -} - -// mulDenom sets z to the denominator product x*y (by taking into -// account that 0 values for x or y must be interpreted as 1) and -// returns z. -func mulDenom(z, x, y nat) nat { - switch { - case len(x) == 0: - return z.set(y) - case len(y) == 0: - return z.set(x) - } - return z.mul(x, y) -} - -// scaleDenom computes x*f. -// If f == 0 (zero value of denominator), the result is (a copy of) x. -func scaleDenom(x *Int, f nat) *Int { - var z Int - if len(f) == 0 { - return z.Set(x) - } - z.abs = z.abs.mul(x.abs, f) - z.neg = x.neg - return &z -} - -// Cmp compares x and y and returns: -// -// -1 if x < y -// 0 if x == y -// +1 if x > y -// -func (x *Rat) Cmp(y *Rat) int { - return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs)) -} - -// Add sets z to the sum x+y and returns z. -func (z *Rat) Add(x, y *Rat) *Rat { - a1 := scaleDenom(&x.a, y.b.abs) - a2 := scaleDenom(&y.a, x.b.abs) - z.a.Add(a1, a2) - z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs) - return z.norm() -} - -// Sub sets z to the difference x-y and returns z. -func (z *Rat) Sub(x, y *Rat) *Rat { - a1 := scaleDenom(&x.a, y.b.abs) - a2 := scaleDenom(&y.a, x.b.abs) - z.a.Sub(a1, a2) - z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs) - return z.norm() -} - -// Mul sets z to the product x*y and returns z. -func (z *Rat) Mul(x, y *Rat) *Rat { - z.a.Mul(&x.a, &y.a) - z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs) - return z.norm() -} - -// Quo sets z to the quotient x/y and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -func (z *Rat) Quo(x, y *Rat) *Rat { - if len(y.a.abs) == 0 { - panic("division by zero") - } - a := scaleDenom(&x.a, y.b.abs) - b := scaleDenom(&y.a, x.b.abs) - z.a.abs = a.abs - z.b.abs = b.abs - z.a.neg = a.neg != b.neg - return z.norm() -} diff --git a/src/cmd/compile/internal/big/rat_test.go b/src/cmd/compile/internal/big/rat_test.go deleted file mode 100644 index 3a06fca3c3..0000000000 --- a/src/cmd/compile/internal/big/rat_test.go +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright 2010 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 ( - "math" - "testing" -) - -func TestZeroRat(t *testing.T) { - var x, y, z Rat - y.SetFrac64(0, 42) - - if x.Cmp(&y) != 0 { - t.Errorf("x and y should be both equal and zero") - } - - if s := x.String(); s != "0/1" { - t.Errorf("got x = %s, want 0/1", s) - } - - if s := x.RatString(); s != "0" { - t.Errorf("got x = %s, want 0", s) - } - - z.Add(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x+y = %s, want 0", s) - } - - z.Sub(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x-y = %s, want 0", s) - } - - z.Mul(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x*y = %s, want 0", s) - } - - // check for division by zero - defer func() { - if s := recover(); s == nil || s.(string) != "division by zero" { - panic(s) - } - }() - z.Quo(&x, &y) -} - -func TestRatSign(t *testing.T) { - zero := NewRat(0, 1) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - s := x.Sign() - e := x.Cmp(zero) - if s != e { - t.Errorf("got %d; want %d for z = %v", s, e, &x) - } - } -} - -var ratCmpTests = []struct { - rat1, rat2 string - out int -}{ - {"0", "0/1", 0}, - {"1/1", "1", 0}, - {"-1", "-2/2", 0}, - {"1", "0", 1}, - {"0/1", "1/1", -1}, - {"-5/1434770811533343057144", "-5/1434770811533343057145", -1}, - {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1}, - {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1}, - {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0}, -} - -func TestRatCmp(t *testing.T) { - for i, test := range ratCmpTests { - x, _ := new(Rat).SetString(test.rat1) - y, _ := new(Rat).SetString(test.rat2) - - out := x.Cmp(y) - if out != test.out { - t.Errorf("#%d got out = %v; want %v", i, out, test.out) - } - } -} - -func TestIsInt(t *testing.T) { - one := NewInt(1) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - i := x.IsInt() - e := x.Denom().Cmp(one) == 0 - if i != e { - t.Errorf("got IsInt(%v) == %v; want %v", x, i, e) - } - } -} - -func TestRatAbs(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - e := new(Rat).Set(x) - if e.Cmp(zero) < 0 { - e.Sub(zero, e) - } - z := new(Rat).Abs(x) - if z.Cmp(e) != 0 { - t.Errorf("got Abs(%v) = %v; want %v", x, z, e) - } - } -} - -func TestRatNeg(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - e := new(Rat).Sub(zero, x) - z := new(Rat).Neg(x) - if z.Cmp(e) != 0 { - t.Errorf("got Neg(%v) = %v; want %v", x, z, e) - } - } -} - -func TestRatInv(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - if x.Cmp(zero) == 0 { - continue // avoid division by zero - } - e := new(Rat).SetFrac(x.Denom(), x.Num()) - z := new(Rat).Inv(x) - if z.Cmp(e) != 0 { - t.Errorf("got Inv(%v) = %v; want %v", x, z, e) - } - } -} - -type ratBinFun func(z, x, y *Rat) *Rat -type ratBinArg struct { - x, y, z string -} - -func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) { - x, _ := new(Rat).SetString(a.x) - y, _ := new(Rat).SetString(a.y) - z, _ := new(Rat).SetString(a.z) - out := f(new(Rat), x, y) - - if out.Cmp(z) != 0 { - t.Errorf("%s #%d got %s want %s", name, i, out, z) - } -} - -var ratBinTests = []struct { - x, y string - sum, prod string -}{ - {"0", "0", "0", "0"}, - {"0", "1", "1", "0"}, - {"-1", "0", "-1", "0"}, - {"-1", "1", "0", "-1"}, - {"1", "1", "2", "1"}, - {"1/2", "1/2", "1", "1/4"}, - {"1/4", "1/3", "7/12", "1/12"}, - {"2/5", "-14/3", "-64/15", "-28/15"}, - {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"}, - {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"}, - {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"}, - {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"}, - {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"}, - {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"}, - {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"}, - {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"}, - {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"}, - {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"}, -} - -func TestRatBin(t *testing.T) { - for i, test := range ratBinTests { - arg := ratBinArg{test.x, test.y, test.sum} - testRatBin(t, i, "Add", (*Rat).Add, arg) - - arg = ratBinArg{test.y, test.x, test.sum} - testRatBin(t, i, "Add symmetric", (*Rat).Add, arg) - - arg = ratBinArg{test.sum, test.x, test.y} - testRatBin(t, i, "Sub", (*Rat).Sub, arg) - - arg = ratBinArg{test.sum, test.y, test.x} - testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg) - - arg = ratBinArg{test.x, test.y, test.prod} - testRatBin(t, i, "Mul", (*Rat).Mul, arg) - - arg = ratBinArg{test.y, test.x, test.prod} - testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg) - - if test.x != "0" { - arg = ratBinArg{test.prod, test.x, test.y} - testRatBin(t, i, "Quo", (*Rat).Quo, arg) - } - - if test.y != "0" { - arg = ratBinArg{test.prod, test.y, test.x} - testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg) - } - } -} - -func TestIssue820(t *testing.T) { - x := NewRat(3, 1) - y := NewRat(2, 1) - z := y.Quo(x, y) - q := NewRat(3, 2) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } - - y = NewRat(3, 1) - x = NewRat(2, 1) - z = y.Quo(x, y) - q = NewRat(2, 3) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } - - x = NewRat(3, 1) - z = x.Quo(x, x) - q = NewRat(3, 3) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } -} - -var setFrac64Tests = []struct { - a, b int64 - out string -}{ - {0, 1, "0"}, - {0, -1, "0"}, - {1, 1, "1"}, - {-1, 1, "-1"}, - {1, -1, "-1"}, - {-1, -1, "1"}, - {-9223372036854775808, -9223372036854775808, "1"}, -} - -func TestRatSetFrac64Rat(t *testing.T) { - for i, test := range setFrac64Tests { - x := new(Rat).SetFrac64(test.a, test.b) - if x.RatString() != test.out { - t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) - } - } -} - -func TestIssue2379(t *testing.T) { - // 1) no aliasing - q := NewRat(3, 2) - x := new(Rat) - x.SetFrac(NewInt(3), NewInt(2)) - if x.Cmp(q) != 0 { - t.Errorf("1) got %s want %s", x, q) - } - - // 2) aliasing of numerator - x = NewRat(2, 3) - x.SetFrac(NewInt(3), x.Num()) - if x.Cmp(q) != 0 { - t.Errorf("2) got %s want %s", x, q) - } - - // 3) aliasing of denominator - x = NewRat(2, 3) - x.SetFrac(x.Denom(), NewInt(2)) - if x.Cmp(q) != 0 { - t.Errorf("3) got %s want %s", x, q) - } - - // 4) aliasing of numerator and denominator - x = NewRat(2, 3) - x.SetFrac(x.Denom(), x.Num()) - if x.Cmp(q) != 0 { - t.Errorf("4) got %s want %s", x, q) - } - - // 5) numerator and denominator are the same - q = NewRat(1, 1) - x = new(Rat) - n := NewInt(7) - x.SetFrac(n, n) - if x.Cmp(q) != 0 { - t.Errorf("5) got %s want %s", x, q) - } -} - -func TestIssue3521(t *testing.T) { - a := new(Int) - b := new(Int) - a.SetString("64375784358435883458348587", 0) - b.SetString("4789759874531", 0) - - // 0) a raw zero value has 1 as denominator - zero := new(Rat) - one := NewInt(1) - if zero.Denom().Cmp(one) != 0 { - t.Errorf("0) got %s want %s", zero.Denom(), one) - } - - // 1a) a zero value remains zero independent of denominator - x := new(Rat) - x.Denom().Set(new(Int).Neg(b)) - if x.Cmp(zero) != 0 { - t.Errorf("1a) got %s want %s", x, zero) - } - - // 1b) a zero value may have a denominator != 0 and != 1 - x.Num().Set(a) - qab := new(Rat).SetFrac(a, b) - if x.Cmp(qab) != 0 { - t.Errorf("1b) got %s want %s", x, qab) - } - - // 2a) an integral value becomes a fraction depending on denominator - x.SetFrac64(10, 2) - x.Denom().SetInt64(3) - q53 := NewRat(5, 3) - if x.Cmp(q53) != 0 { - t.Errorf("2a) got %s want %s", x, q53) - } - - // 2b) an integral value becomes a fraction depending on denominator - x = NewRat(10, 2) - x.Denom().SetInt64(3) - if x.Cmp(q53) != 0 { - t.Errorf("2b) got %s want %s", x, q53) - } - - // 3) changing the numerator/denominator of a Rat changes the Rat - x.SetFrac(a, b) - a = x.Num() - b = x.Denom() - a.SetInt64(5) - b.SetInt64(3) - if x.Cmp(q53) != 0 { - t.Errorf("3) got %s want %s", x, q53) - } -} - -func TestFloat32Distribution(t *testing.T) { - // Generate a distribution of (sign, mantissa, exp) values - // broader than the float32 range, and check Rat.Float32() - // always picks the closest float32 approximation. - var add = []int64{ - 0, - 1, - 3, - 5, - 7, - 9, - 11, - } - var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64) - if testing.Short() { - winc, einc = 5, 15 // quick test (~60ms on x86-64) - } - - for _, sign := range "+-" { - for _, a := range add { - for wid := uint64(0); wid < 30; wid += winc { - b := 1< 0 { - num.Lsh(num, uint(exp)) - } else { - den.Lsh(den, uint(-exp)) - } - r := new(Rat).SetFrac(num, den) - f, _ := r.Float32() - - if !checkIsBestApprox32(t, f, r) { - // Append context information. - t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)", - b, exp, f, f, math.Ldexp(float64(b), exp), r) - } - - checkNonLossyRoundtrip32(t, f) - } - } - } - } -} - -func TestFloat64Distribution(t *testing.T) { - // Generate a distribution of (sign, mantissa, exp) values - // broader than the float64 range, and check Rat.Float64() - // always picks the closest float64 approximation. - var add = []int64{ - 0, - 1, - 3, - 5, - 7, - 9, - 11, - } - var winc, einc = uint64(1), 1 // soak test (~75s on x86-64) - if testing.Short() { - winc, einc = 10, 500 // quick test (~12ms on x86-64) - } - - for _, sign := range "+-" { - for _, a := range add { - for wid := uint64(0); wid < 60; wid += winc { - b := 1< 0 { - num.Lsh(num, uint(exp)) - } else { - den.Lsh(den, uint(-exp)) - } - r := new(Rat).SetFrac(num, den) - f, _ := r.Float64() - - if !checkIsBestApprox64(t, f, r) { - // Append context information. - t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)", - b, exp, f, f, math.Ldexp(float64(b), exp), r) - } - - checkNonLossyRoundtrip64(t, f) - } - } - } - } -} - -// TestSetFloat64NonFinite checks that SetFloat64 of a non-finite value -// returns nil. -func TestSetFloat64NonFinite(t *testing.T) { - for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} { - var r Rat - if r2 := r.SetFloat64(f); r2 != nil { - t.Errorf("SetFloat64(%g) was %v, want nil", f, r2) - } - } -} - -// checkNonLossyRoundtrip32 checks that a float->Rat->float roundtrip is -// non-lossy for finite f. -func checkNonLossyRoundtrip32(t *testing.T, f float32) { - if !isFinite(float64(f)) { - return - } - r := new(Rat).SetFloat64(float64(f)) - if r == nil { - t.Errorf("Rat.SetFloat64(float64(%g) (%b)) == nil", f, f) - return - } - f2, exact := r.Float32() - if f != f2 || !exact { - t.Errorf("Rat.SetFloat64(float64(%g)).Float32() = %g (%b), %v, want %g (%b), %v; delta = %b", - f, f2, f2, exact, f, f, true, f2-f) - } -} - -// checkNonLossyRoundtrip64 checks that a float->Rat->float roundtrip is -// non-lossy for finite f. -func checkNonLossyRoundtrip64(t *testing.T, f float64) { - if !isFinite(f) { - return - } - r := new(Rat).SetFloat64(f) - if r == nil { - t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f) - return - } - f2, exact := r.Float64() - if f != f2 || !exact { - t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b", - f, f2, f2, exact, f, f, true, f2-f) - } -} - -// delta returns the absolute difference between r and f. -func delta(r *Rat, f float64) *Rat { - d := new(Rat).Sub(r, new(Rat).SetFloat64(f)) - return d.Abs(d) -} - -// checkIsBestApprox32 checks that f is the best possible float32 -// approximation of r. -// Returns true on success. -func checkIsBestApprox32(t *testing.T, f float32, r *Rat) bool { - if math.Abs(float64(f)) >= math.MaxFloat32 { - // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32). - // But we have tests for these special cases. - return true - } - - // r must be strictly between f0 and f1, the floats bracketing f. - f0 := math.Nextafter32(f, float32(math.Inf(-1))) - f1 := math.Nextafter32(f, float32(math.Inf(+1))) - - // For f to be correct, r must be closer to f than to f0 or f1. - df := delta(r, float64(f)) - df0 := delta(r, float64(f0)) - df1 := delta(r, float64(f1)) - if df.Cmp(df0) > 0 { - t.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r, f, f, f0, f0) - return false - } - if df.Cmp(df1) > 0 { - t.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r, f, f, f1, f1) - return false - } - if df.Cmp(df0) == 0 && !isEven32(f) { - t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0) - return false - } - if df.Cmp(df1) == 0 && !isEven32(f) { - t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1) - return false - } - return true -} - -// checkIsBestApprox64 checks that f is the best possible float64 -// approximation of r. -// Returns true on success. -func checkIsBestApprox64(t *testing.T, f float64, r *Rat) bool { - if math.Abs(f) >= math.MaxFloat64 { - // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64). - // But we have tests for these special cases. - return true - } - - // r must be strictly between f0 and f1, the floats bracketing f. - f0 := math.Nextafter(f, math.Inf(-1)) - f1 := math.Nextafter(f, math.Inf(+1)) - - // For f to be correct, r must be closer to f than to f0 or f1. - df := delta(r, f) - df0 := delta(r, f0) - df1 := delta(r, f1) - if df.Cmp(df0) > 0 { - t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0) - return false - } - if df.Cmp(df1) > 0 { - t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1) - return false - } - if df.Cmp(df0) == 0 && !isEven64(f) { - t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0) - return false - } - if df.Cmp(df1) == 0 && !isEven64(f) { - t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1) - return false - } - return true -} - -func isEven32(f float32) bool { return math.Float32bits(f)&1 == 0 } -func isEven64(f float64) bool { return math.Float64bits(f)&1 == 0 } - -func TestIsFinite(t *testing.T) { - finites := []float64{ - 1.0 / 3, - 4891559871276714924261e+222, - math.MaxFloat64, - math.SmallestNonzeroFloat64, - -math.MaxFloat64, - -math.SmallestNonzeroFloat64, - } - for _, f := range finites { - if !isFinite(f) { - t.Errorf("!IsFinite(%g (%b))", f, f) - } - } - nonfinites := []float64{ - math.NaN(), - math.Inf(-1), - math.Inf(+1), - } - for _, f := range nonfinites { - if isFinite(f) { - t.Errorf("IsFinite(%g, (%b))", f, f) - } - } -} diff --git a/src/cmd/compile/internal/big/ratconv.go b/src/cmd/compile/internal/big/ratconv.go deleted file mode 100644 index ef2b6750d0..0000000000 --- a/src/cmd/compile/internal/big/ratconv.go +++ /dev/null @@ -1,270 +0,0 @@ -// 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.ContainsRune("+-/0123456789.eE", ch) -} - -// 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.ContainsRune("efgEFGv", ch) { - 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 - } - - // special-case 0 (see also issue #16176) - if len(z.a.abs) == 0 { - return z, true - } - // len(z.a.abs) > 0 - - // 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, 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 { - var buf []byte - buf = x.a.Append(buf, 10) - buf = append(buf, '/') - if len(x.b.abs) != 0 { - buf = x.b.Append(buf, 10) - } else { - buf = append(buf, '1') - } - return string(buf) -} - -// 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 { - var buf []byte - - if x.IsInt() { - buf = x.a.Append(buf, 10) - if prec > 0 { - buf = append(buf, '.') - for i := prec; i > 0; i-- { - buf = append(buf, '0') - } - } - return string(buf) - } - // 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) - } - } - - if x.a.neg { - buf = append(buf, '-') - } - buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0 - - if prec > 0 { - buf = append(buf, '.') - rs := r.utoa(10) - for i := prec - len(rs); i > 0; i-- { - buf = append(buf, '0') - } - buf = append(buf, rs...) - } - - return string(buf) -} diff --git a/src/cmd/compile/internal/big/ratconv_test.go b/src/cmd/compile/internal/big/ratconv_test.go deleted file mode 100644 index 35ad6ccea7..0000000000 --- a/src/cmd/compile/internal/big/ratconv_test.go +++ /dev/null @@ -1,454 +0,0 @@ -// 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}, - {"0e9999999999", "0", true}, // issue #16176 - {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/src/cmd/compile/internal/big/ratmarsh.go b/src/cmd/compile/internal/big/ratmarsh.go deleted file mode 100644 index b82e8d4ae8..0000000000 --- a/src/cmd/compile/internal/big/ratmarsh.go +++ /dev/null @@ -1,73 +0,0 @@ -// 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 encoding/decoding of Rats. - -package big - -import ( - "encoding/binary" - "errors" - "fmt" -) - -// Gob codec version. Permits backward-compatible changes to the encoding. -const ratGobVersion byte = 1 - -// GobEncode implements the gob.GobEncoder interface. -func (x *Rat) GobEncode() ([]byte, error) { - if x == nil { - return nil, nil - } - 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[:i]) - n := i - j - if int(uint32(n)) != n { - // this should never happen - return nil, errors.New("Rat.GobEncode: numerator too large") - } - binary.BigEndian.PutUint32(buf[j-4:j], uint32(n)) - j -= 1 + 4 - b := ratGobVersion << 1 // make space for sign bit - if x.a.neg { - b |= 1 - } - buf[j] = b - return buf[j:], nil -} - -// GobDecode implements the gob.GobDecoder interface. -func (z *Rat) GobDecode(buf []byte) error { - if len(buf) == 0 { - // Other side sent a nil or default value. - *z = Rat{} - return nil - } - b := buf[0] - if b>>1 != ratGobVersion { - 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]) - z.a.neg = b&1 != 0 - z.a.abs = z.a.abs.setBytes(buf[j:i]) - z.b.abs = z.b.abs.setBytes(buf[i:]) - return nil -} - -// MarshalText implements the encoding.TextMarshaler interface. -func (x *Rat) MarshalText() (text []byte, err error) { - // TODO(gri): get rid of the []byte/string conversion - return []byte(x.RatString()), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -func (z *Rat) UnmarshalText(text []byte) error { - // TODO(gri): get rid of the []byte/string conversion - if _, ok := z.SetString(string(text)); !ok { - return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text) - } - return nil -} diff --git a/src/cmd/compile/internal/big/ratmarsh_test.go b/src/cmd/compile/internal/big/ratmarsh_test.go deleted file mode 100644 index 351d109f8d..0000000000 --- a/src/cmd/compile/internal/big/ratmarsh_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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" - "encoding/gob" - "encoding/json" - "encoding/xml" - "testing" -) - -func TestRatGobEncoding(t *testing.T) { - var medium bytes.Buffer - enc := gob.NewEncoder(&medium) - dec := gob.NewDecoder(&medium) - for _, test := range encodingTests { - medium.Reset() // empty buffer for each test case (in case of failures) - var tx Rat - tx.SetString(test + ".14159265") - if err := enc.Encode(&tx); err != nil { - t.Errorf("encoding of %s failed: %s", &tx, err) - continue - } - var rx Rat - if err := dec.Decode(&rx); err != nil { - t.Errorf("decoding of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx) - } - } -} - -// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero. -// TODO: top-level nils. -func TestGobEncodingNilRatInSlice(t *testing.T) { - buf := new(bytes.Buffer) - enc := gob.NewEncoder(buf) - dec := gob.NewDecoder(buf) - - var in = make([]*Rat, 1) - err := enc.Encode(&in) - if err != nil { - t.Errorf("gob encode failed: %q", err) - } - var out []*Rat - err = dec.Decode(&out) - if err != nil { - t.Fatalf("gob decode failed: %q", err) - } - if len(out) != 1 { - t.Fatalf("wrong len; want 1 got %d", len(out)) - } - var zero Rat - if out[0].Cmp(&zero) != 0 { - t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out) - } -} - -var ratNums = []string{ - "-141592653589793238462643383279502884197169399375105820974944592307816406286", - "-1415926535897932384626433832795028841971", - "-141592653589793", - "-1", - "0", - "1", - "141592653589793", - "1415926535897932384626433832795028841971", - "141592653589793238462643383279502884197169399375105820974944592307816406286", -} - -var ratDenoms = []string{ - "1", - "718281828459045", - "7182818284590452353602874713526624977572", - "718281828459045235360287471352662497757247093699959574966967627724076630353", -} - -func TestRatJSONEncoding(t *testing.T) { - for _, num := range ratNums { - for _, denom := range ratDenoms { - var tx Rat - tx.SetString(num + "/" + denom) - b, err := json.Marshal(&tx) - if err != nil { - t.Errorf("marshaling of %s failed: %s", &tx, err) - continue - } - var rx Rat - if err := json.Unmarshal(b, &rx); err != nil { - t.Errorf("unmarshaling of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx) - } - } - } -} - -func TestRatXMLEncoding(t *testing.T) { - for _, num := range ratNums { - for _, denom := range ratDenoms { - var tx Rat - tx.SetString(num + "/" + denom) - b, err := xml.Marshal(&tx) - if err != nil { - t.Errorf("marshaling of %s failed: %s", &tx, err) - continue - } - var rx Rat - if err := xml.Unmarshal(b, &rx); err != nil { - t.Errorf("unmarshaling of %s failed: %s", &tx, err) - continue - } - if rx.Cmp(&tx) != 0 { - t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx) - } - } - } -} diff --git a/src/cmd/compile/internal/big/roundingmode_string.go b/src/cmd/compile/internal/big/roundingmode_string.go deleted file mode 100644 index 05024b8065..0000000000 --- a/src/cmd/compile/internal/big/roundingmode_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// 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/src/cmd/compile/internal/big/vendor.bash b/src/cmd/compile/internal/big/vendor.bash deleted file mode 100755 index ac3ec9b4a7..0000000000 --- a/src/cmd/compile/internal/big/vendor.bash +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# Run this script to obtain an up-to-date vendored version of math/big. - -BIGDIR=../../../../math/big - -# Start from scratch. -rm *.go - -# We don't want any assembly files. -cp $BIGDIR/*.go . - -# Use pure Go arith ops w/o build tag. -sed 's|^// \+build math_big_pure_go$||' arith_decl_pure.go > arith_decl.go -rm arith_decl_pure.go - -# Import vendored math/big in external tests (e.g., floatexample_test.go). -for f in *_test.go; do - sed 's|"math/big"|"cmd/compile/internal/big"|' $f > foo.go - mv foo.go $f -done - -# gofmt to clean up after sed -gofmt -w . - -# Test that it works -go test -short diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index ed47854aec..03223b421e 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -132,7 +132,7 @@ package gc import ( "bufio" "bytes" - "cmd/compile/internal/big" + "math/big" "encoding/binary" "fmt" "sort" diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go index 92a116bddb..3c75b8f087 100644 --- a/src/cmd/compile/internal/gc/bimport.go +++ b/src/cmd/compile/internal/gc/bimport.go @@ -10,7 +10,7 @@ package gc import ( "bufio" - "cmd/compile/internal/big" + "math/big" "encoding/binary" "fmt" "strconv" diff --git a/src/cmd/compile/internal/gc/mpfloat.go b/src/cmd/compile/internal/gc/mpfloat.go index 55168e91e0..c851022bc5 100644 --- a/src/cmd/compile/internal/gc/mpfloat.go +++ b/src/cmd/compile/internal/gc/mpfloat.go @@ -5,9 +5,9 @@ package gc import ( - "cmd/compile/internal/big" "fmt" "math" + "math/big" ) // implements float arithmetic diff --git a/src/cmd/compile/internal/gc/mpint.go b/src/cmd/compile/internal/gc/mpint.go index 31fbe857aa..fba82607b5 100644 --- a/src/cmd/compile/internal/gc/mpint.go +++ b/src/cmd/compile/internal/gc/mpint.go @@ -5,8 +5,8 @@ package gc import ( - "cmd/compile/internal/big" "fmt" + "math/big" ) // implements integer arithmetic diff --git a/src/cmd/compile/internal/gc/swt_test.go b/src/cmd/compile/internal/gc/swt_test.go index 1026202c90..413989855c 100644 --- a/src/cmd/compile/internal/gc/swt_test.go +++ b/src/cmd/compile/internal/gc/swt_test.go @@ -5,7 +5,7 @@ package gc import ( - "cmd/compile/internal/big" + "math/big" "testing" ) diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index c700a5d8c9..136e45eeb4 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -18,49 +18,60 @@ import ( // bootstrapDirs is a list of directories holding code that must be // compiled with a Go 1.4 toolchain to produce the bootstrapTargets. -// All directories in this list are relative to and must be below $GOROOT/src/cmd. -// The list is assumed to have two kinds of entries: names without slashes, -// which are commands, and entries beginning with internal/, which are -// packages supporting the commands. +// All directories in this list are relative to and must be below $GOROOT/src. +// +// The list has have two kinds of entries: names beginning with cmd/ with +// no other slashes, which are commands, and other paths, which are packages +// supporting the commands. Packages in the standard library can be listed +// if a newer copy needs to be substituted for the Go 1.4 copy when used +// by the command packages. +// These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big. var bootstrapDirs = []string{ - "asm", - "asm/internal/arch", - "asm/internal/asm", - "asm/internal/flags", - "asm/internal/lex", - "compile", - "compile/internal/amd64", - "compile/internal/arm", - "compile/internal/arm64", - "compile/internal/big", - "compile/internal/gc", - "compile/internal/mips64", - "compile/internal/ppc64", - "compile/internal/s390x", - "compile/internal/ssa", - "compile/internal/syntax", - "compile/internal/x86", - "internal/bio", - "internal/gcprog", - "internal/dwarf", - "internal/obj", - "internal/obj/arm", - "internal/obj/arm64", - "internal/obj/mips", - "internal/obj/ppc64", - "internal/obj/s390x", - "internal/obj/x86", - "internal/sys", - "link", - "link/internal/amd64", - "link/internal/arm", - "link/internal/arm64", - "link/internal/pe", - "link/internal/ld", - "link/internal/mips64", - "link/internal/ppc64", - "link/internal/s390x", - "link/internal/x86", + "cmd/asm", + "cmd/asm/internal/arch", + "cmd/asm/internal/asm", + "cmd/asm/internal/flags", + "cmd/asm/internal/lex", + "cmd/compile", + "cmd/compile/internal/amd64", + "cmd/compile/internal/arm", + "cmd/compile/internal/arm64", + "cmd/compile/internal/gc", + "cmd/compile/internal/mips64", + "cmd/compile/internal/ppc64", + "cmd/compile/internal/s390x", + "cmd/compile/internal/ssa", + "cmd/compile/internal/syntax", + "cmd/compile/internal/x86", + "cmd/internal/bio", + "cmd/internal/gcprog", + "cmd/internal/dwarf", + "cmd/internal/obj", + "cmd/internal/obj/arm", + "cmd/internal/obj/arm64", + "cmd/internal/obj/mips", + "cmd/internal/obj/ppc64", + "cmd/internal/obj/s390x", + "cmd/internal/obj/x86", + "cmd/internal/sys", + "cmd/link", + "cmd/link/internal/amd64", + "cmd/link/internal/arm", + "cmd/link/internal/arm64", + "cmd/link/internal/ld", + "cmd/link/internal/mips64", + "cmd/link/internal/pe", + "cmd/link/internal/ppc64", + "cmd/link/internal/s390x", + "cmd/link/internal/x86", + "math/big", +} + +// File suffixes that use build tags introduced since Go 1.4. +// These must not be copied into the bootstrap build directory. +var ignoreSuffixes = []string{ + "_arm64.s", + "_arm64.go", } func bootstrapBuildTools() { @@ -84,10 +95,16 @@ func bootstrapBuildTools() { // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths. for _, dir := range bootstrapDirs { - src := pathf("%s/src/cmd/%s", goroot, dir) + src := pathf("%s/src/%s", goroot, dir) dst := pathf("%s/%s", base, dir) xmkdirall(dst) + Dir: for _, name := range xreaddirfiles(src) { + for _, suf := range ignoreSuffixes { + if strings.HasSuffix(name, suf) { + continue Dir + } + } srcFile := pathf("%s/%s", src, name) text := readfile(srcFile) text = bootstrapFixImports(text, srcFile) @@ -122,10 +139,14 @@ func bootstrapBuildTools() { // Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to // workaround bugs in Go 1.4's compiler. See discussion thread: // https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ - run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/...") + run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/cmd/...") // Copy binaries into tool binary directory. for _, name := range bootstrapDirs { + if !strings.HasPrefix(name, "cmd/") { + continue + } + name = name[len("cmd/"):] if !strings.Contains(name, "/") { copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) } @@ -148,7 +169,14 @@ func bootstrapFixImports(text, srcFile string) string { } if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) || inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) { - lines[i] = strings.Replace(line, `"cmd/`, `"bootstrap/`, -1) + line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1) + for _, dir := range bootstrapDirs { + if strings.HasPrefix(dir, "cmd/") { + continue + } + line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1) + } + lines[i] = line } } -- 2.48.1