summaryrefslogtreecommitdiff
path: root/libgo/go/math
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-02-03 21:58:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-02-03 21:58:02 +0000
commitf98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch)
tree2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/math
parentb081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff)
libgo: Update to go1.6rc1.
Reviewed-on: https://go-review.googlesource.com/19200 From-SVN: r233110
Diffstat (limited to 'libgo/go/math')
-rw-r--r--libgo/go/math/abs.go9
-rw-r--r--libgo/go/math/all_test.go26
-rw-r--r--libgo/go/math/big/decimal.go18
-rw-r--r--libgo/go/math/big/decimal_test.go10
-rw-r--r--libgo/go/math/big/doc.go99
-rw-r--r--libgo/go/math/big/example_rat_test.go67
-rw-r--r--libgo/go/math/big/float.go8
-rw-r--r--libgo/go/math/big/floatconv.go110
-rw-r--r--libgo/go/math/big/floatconv_test.go179
-rw-r--r--libgo/go/math/big/floatexample_test.go30
-rw-r--r--libgo/go/math/big/floatmarsh.go33
-rw-r--r--libgo/go/math/big/floatmarsh_test.go54
-rw-r--r--libgo/go/math/big/ftoa.go104
-rw-r--r--libgo/go/math/big/int.go128
-rw-r--r--libgo/go/math/big/int_test.go218
-rw-r--r--libgo/go/math/big/intconv.go94
-rw-r--r--libgo/go/math/big/intconv_test.go89
-rw-r--r--libgo/go/math/big/intmarsh.go74
-rw-r--r--libgo/go/math/big/intmarsh_test.go121
-rw-r--r--libgo/go/math/big/nat.go120
-rw-r--r--libgo/go/math/big/nat_test.go109
-rw-r--r--libgo/go/math/big/natconv.go103
-rw-r--r--libgo/go/math/big/natconv_test.go85
-rw-r--r--libgo/go/math/big/rat.go60
-rw-r--r--libgo/go/math/big/rat_test.go114
-rw-r--r--libgo/go/math/big/ratconv.go36
-rw-r--r--libgo/go/math/big/ratmarsh.go73
-rw-r--r--libgo/go/math/big/ratmarsh_test.go125
-rw-r--r--libgo/go/math/cmplx/cmath_test.go10
-rw-r--r--libgo/go/math/cmplx/sqrt.go2
-rw-r--r--libgo/go/math/expm1.go2
-rw-r--r--libgo/go/math/floor_asm.go12
-rw-r--r--libgo/go/math/j0.go4
-rw-r--r--libgo/go/math/j1.go4
-rw-r--r--libgo/go/math/jn.go2
-rw-r--r--libgo/go/math/modf.go5
-rw-r--r--libgo/go/math/rand/rand.go47
-rw-r--r--libgo/go/math/rand/rand_test.go84
-rw-r--r--libgo/go/math/rand/regress_test.go77
-rw-r--r--libgo/go/math/sqrt.go2
40 files changed, 1743 insertions, 804 deletions
diff --git a/libgo/go/math/abs.go b/libgo/go/math/abs.go
index 433d0f72737..1b7c7c1820c 100644
--- a/libgo/go/math/abs.go
+++ b/libgo/go/math/abs.go
@@ -18,10 +18,13 @@ func Abs(x float64) float64 {
}
func abs(x float64) float64 {
- switch {
- case x < 0:
+ // TODO: once golang.org/issue/13095 is fixed, change this to:
+ // return Float64frombits(Float64bits(x) &^ (1 << 63))
+ // But for now, this generates better code and can also be inlined:
+ if x < 0 {
return -x
- case x == 0:
+ }
+ if x == 0 {
return 0 // return correctly abs(-0)
}
return x
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index e18e45e0202..968a7b18372 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -234,6 +234,18 @@ var expm1 = []float64{
1.842068661871398836913874273e-02,
-8.3193870863553801814961137573e-02,
}
+var expm1Large = []float64{
+ 4.2031418113550844e+21,
+ 4.0690789717473863e+33,
+ -0.9372627915981363e+00,
+ -1.0,
+ 7.077694784145933e+41,
+ 5.117936223839153e+12,
+ 5.124137759001189e+22,
+ 7.03546003972584e+11,
+ 8.456921800389698e+07,
+ -1.0,
+}
var exp2 = []float64{
3.1537839463286288034313104e+01,
2.1361549283756232296144849e+02,
@@ -447,7 +459,7 @@ var log2 = []float64{
var modf = [][2]float64{
{4.0000000000000000e+00, 9.7901192488367350108546816e-01},
{7.0000000000000000e+00, 7.3887247457810456552351752e-01},
- {0.0000000000000000e+00, -2.7688005719200159404635997e-01},
+ {Copysign(0, -1), -2.7688005719200159404635997e-01},
{-5.0000000000000000e+00, -1.060361827107492160848778e-02},
{9.0000000000000000e+00, 6.3629370719841737980004837e-01},
{2.0000000000000000e+00, 9.2637723924396464525443662e-01},
@@ -1356,12 +1368,14 @@ var log1pSC = []float64{
var vfmodfSC = []float64{
Inf(-1),
+ Copysign(0, -1),
Inf(1),
NaN(),
}
var modfSC = [][2]float64{
{Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)},
- {Inf(1), NaN()}, // [2]float64{0, Inf(1)},
+ {Copysign(0, -1), Copysign(0, -1)},
+ {Inf(1), NaN()}, // [2]float64{0, Inf(1)},
{NaN(), NaN()},
}
@@ -1609,6 +1623,7 @@ var vfsqrtSC = []float64{
0,
Inf(1),
NaN(),
+ Float64frombits(2), // subnormal; see https://golang.org/issue/13013
}
var sqrtSC = []float64{
NaN(),
@@ -1617,6 +1632,7 @@ var sqrtSC = []float64{
0,
Inf(1),
NaN(),
+ 3.1434555694052576e-162,
}
var vftanhSC = []float64{
@@ -1983,6 +1999,12 @@ func TestExpm1(t *testing.T) {
t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i])
}
}
+ for i := 0; i < len(vf); i++ {
+ a := vf[i] * 10
+ if f := Expm1(a); !close(expm1Large[i], f) {
+ t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i])
+ }
+ }
for i := 0; i < len(vfexpm1SC); i++ {
if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) {
t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i])
diff --git a/libgo/go/math/big/decimal.go b/libgo/go/math/big/decimal.go
index 2595e5f8c12..2c0c9daebc1 100644
--- a/libgo/go/math/big/decimal.go
+++ b/libgo/go/math/big/decimal.go
@@ -20,7 +20,7 @@
package big
// A decimal represents an unsigned floating-point number in decimal representation.
-// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// 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.
@@ -29,6 +29,14 @@ type decimal struct {
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<<maxShift - 1)*10 + 9 must fit into Word.
const maxShift = _W - 4
@@ -72,7 +80,7 @@ func (x *decimal) init(m nat, shift int) {
}
// Convert mantissa into decimal representation.
- s := m.decimalString() // TODO(gri) avoid string conversion here
+ s := m.utoa(10)
n := len(s)
x.exp = n
// Trim trailing zeros; instead the exponent is tracking
@@ -92,12 +100,6 @@ func (x *decimal) init(m nat, shift int) {
}
}
-// Possibly optimization: The current implementation of nat.string takes
-// a charset argument. When a right shift is needed, we could provide
-// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
-// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
-// single +'0' pass at the end).
-
// shr implements x >> s, for s <= maxShift.
func shr(x *decimal, s uint) {
// Division by 1<<s using shift-and-subtract algorithm.
diff --git a/libgo/go/math/big/decimal_test.go b/libgo/go/math/big/decimal_test.go
index 81e022a47dd..15bdb181e72 100644
--- a/libgo/go/math/big/decimal_test.go
+++ b/libgo/go/math/big/decimal_test.go
@@ -104,3 +104,13 @@ func TestDecimalRounding(t *testing.T) {
}
}
}
+
+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)
+ d.String()
+ }
+ }
+}
diff --git a/libgo/go/math/big/doc.go b/libgo/go/math/big/doc.go
new file mode 100644
index 00000000000..a3c23751ba4
--- /dev/null
+++ b/libgo/go/math/big/doc.go
@@ -0,0 +1,99 @@
+// 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/libgo/go/math/big/example_rat_test.go b/libgo/go/math/big/example_rat_test.go
new file mode 100644
index 00000000000..f3127bb4717
--- /dev/null
+++ b/libgo/go/math/big/example_rat_test.go
@@ -0,0 +1,67 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package big_test
+
+import (
+ "fmt"
+ "math/big"
+)
+
+// 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/libgo/go/math/big/float.go b/libgo/go/math/big/float.go
index d7aa8953c43..b1c748c9a54 100644
--- a/libgo/go/math/big/float.go
+++ b/libgo/go/math/big/float.go
@@ -124,7 +124,7 @@ const (
// rounding error is described by the Float's Accuracy.
type RoundingMode byte
-// The following rounding modes are supported.
+// These constants define supported rounding modes.
const (
ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
ToNearestAway // == IEEE 754-2008 roundTiesToAway
@@ -298,7 +298,7 @@ func (z *Float) setExpAndRound(exp int64, sbit uint) {
// not require 0.5 <= |mant| < 1.0. Specifically:
//
// mant := new(Float)
-// new(Float).SetMantExp(mant, x.SetMantExp(mant)).Cmp(x).Eql() is true
+// new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0
//
// Special cases are:
//
@@ -1123,7 +1123,7 @@ func (x *Float) Int(z *Int) (*Int, Accuracy) {
// Rat returns the rational number corresponding to x;
// or nil if x is an infinity.
-// The result is Exact is x is not an Inf.
+// 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) {
@@ -1272,7 +1272,7 @@ func (z *Float) usub(x, y *Float) {
ex = ey
}
- // operands may have cancelled each other out
+ // operands may have canceled each other out
if len(z.mant) == 0 {
z.acc = Exact
z.form = zero
diff --git a/libgo/go/math/big/floatconv.go b/libgo/go/math/big/floatconv.go
index 4a070ca64d4..37d5c06a6f3 100644
--- a/libgo/go/math/big/floatconv.go
+++ b/libgo/go/math/big/floatconv.go
@@ -72,37 +72,46 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
// ebase**exp. Finally, mantissa normalization (shift left) requires
// a correcting multiplication by 2**(-shiftcount). Multiplications
// are commutative, so we can apply them in any order as long as there
- // is no loss of precision. We only have powers of 2 and 10; keep
- // track via separate exponents exp2 and exp10.
+ // 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 get initial binary exponent
- var exp2 = int64(len(z.mant))*_W - fnorm(z.mant)
+ // 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
- var exp10 int64
if fcount < 0 {
// The mantissa has a "decimal" point ddd.dddd; and
// -fcount is the number of digits to the right of '.'.
// Adjust relevant exponent accodingly.
+ d := int64(fcount)
switch b {
- case 16:
- fcount *= 4 // hexadecimal digits are 4 bits each
- fallthrough
+ case 10:
+ exp5 = d
+ fallthrough // 10**e == 5**e * 2**e
case 2:
- exp2 += int64(fcount)
- default: // b == 10
- exp10 = int64(fcount)
+ exp2 += d
+ case 16:
+ exp2 += d * 4 // hexadecimal digits are 4 bits each
+ default:
+ panic("unexpected mantissa base")
}
- // we don't need fcount anymore
+ // fcount consumed - not needed anymore
}
// take actual exponent into account
- if ebase == 2 {
+ switch ebase {
+ case 10:
+ exp5 += exp
+ fallthrough
+ case 2:
exp2 += exp
- } else { // ebase == 10
- exp10 += exp
+ default:
+ panic("unexpected exponent base")
}
- // we don't need exp anymore
+ // exp consumed - not needed anymore
// apply 2**exp2
if MinExp <= exp2 && exp2 <= MaxExp {
@@ -115,49 +124,76 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
return
}
- if exp10 == 0 {
- // no decimal exponent to consider
+ if exp5 == 0 {
+ // no decimal exponent contribution
z.round(0)
return
}
- // exp10 != 0
+ // exp5 != 0
- // apply 10**exp10
+ // apply 5**exp5
p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
- if exp10 < 0 {
- z.uquo(z, p.pow10(-exp10))
+ if exp5 < 0 {
+ z.Quo(z, p.pow5(uint64(-exp5)))
} else {
- z.umul(z, p.pow10(exp10))
+ z.Mul(z, p.pow5(uint64(exp5)))
}
return
}
-// These powers of 10 can be represented exactly as a float64.
-var pow10tab = [...]float64{
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+// 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,
}
-// pow10 sets z to 10**n and returns z.
+// pow5 sets z to 5**n and returns z.
// n must not be negative.
-func (z *Float) pow10(n int64) *Float {
- if n < 0 {
- panic("pow10 called with negative argument")
- }
-
- const m = int64(len(pow10tab) - 1)
+func (z *Float) pow5(n uint64) *Float {
+ const m = uint64(len(pow5tab) - 1)
if n <= m {
- return z.SetFloat64(pow10tab[n])
+ return z.SetUint64(pow5tab[n])
}
// n > m
- z.SetFloat64(pow10tab[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).SetInt64(10)
+ f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
for n > 0 {
if n&1 != 0 {
diff --git a/libgo/go/math/big/floatconv_test.go b/libgo/go/math/big/floatconv_test.go
index 4f239534a14..b6f99936082 100644
--- a/libgo/go/math/big/floatconv_test.go
+++ b/libgo/go/math/big/floatconv_test.go
@@ -139,6 +139,8 @@ func TestFloatSetFloat64String(t *testing.T) {
}
}
+func fdiv(a, b float64) float64 { return a / b }
+
const (
below1e23 = 99999999999999974834176
above1e23 = 100000000000000008388608
@@ -187,11 +189,11 @@ func TestFloat64Text(t *testing.T) {
{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"},
+ {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"},
@@ -207,22 +209,22 @@ func TestFloat64Text(t *testing.T) {
{0, 'e', 5, "0.00000e+00"},
{0, 'f', 5, "0.00000"},
{0, 'g', 5, "0"},
- // {0, 'g', -1, "0"},
+ {0, 'g', -1, "0"},
{-1, 'e', 5, "-1.00000e+00"},
{-1, 'f', 5, "-1.00000"},
{-1, 'g', 5, "-1"},
- // {-1, 'g', -1, "-1"},
+ {-1, 'g', -1, "-1"},
{12, 'e', 5, "1.20000e+01"},
{12, 'f', 5, "12.00000"},
{12, 'g', 5, "12"},
- // {12, 'g', -1, "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"},
+ {123456700, 'g', -1, "1.234567e+08"},
{1.2345e6, 'e', 5, "1.23450e+06"},
{1.2345e6, 'f', 5, "1234500.00000"},
@@ -232,36 +234,38 @@ func TestFloat64Text(t *testing.T) {
{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"},
+ {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"},
+ {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, 'g', 17, "1.0000000000000001e+23"},
- // {above1e23, 'e', -1, "1.0000000000000001e+23"},
- // {above1e23, 'f', -1, "100000000000000010000000"},
- // {above1e23, 'g', -1, "1.0000000000000001e+23"},
+ {above1e23, 'e', -1, "1.0000000000000001e+23"},
+ {above1e23, 'f', -1, "100000000000000010000000"},
+ {above1e23, 'g', -1, "1.0000000000000001e+23"},
- // {fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
- // {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+ {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"},
+ {32, 'g', -1, "32"},
+ {32, 'g', 0, "3e+01"},
- // {100, 'x', -1, "%x"},
+ {100, 'x', -1, "%x"},
- // {math.NaN(), 'g', -1, "NaN"},
- // {-math.NaN(), 'g', -1, "NaN"},
+ // {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"},
@@ -279,18 +283,24 @@ func TestFloat64Text(t *testing.T) {
{1.5, 'f', 0, "2"},
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
- // {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-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"},
+ {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
// Issue 2625.
{383260575764816448, 'f', 0, "383260575764816448"},
- // {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
+ {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
} {
- f := new(Float).SetFloat64(test.x)
+ // 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 {
@@ -308,6 +318,15 @@ func TestFloat64Text(t *testing.T) {
}
}
+// 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
@@ -367,9 +386,19 @@ func TestFloatText(t *testing.T) {
// make sure "stupid" exponents don't stall the machine
{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
- {"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p+1538481529"},
+ {"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-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"},
+ {"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
@@ -438,9 +467,6 @@ func TestFloatFormat(t *testing.T) {
value interface{} // float32, float64, or string (== 512bit *Float)
want string
}{
- // TODO(gri) uncomment the disabled 'g'/'G' formats
- // below once (*Float).Text supports prec < 0
-
// from fmt/fmt_test.go
{"%+.3e", 0.0, "+0.000e+00"},
{"%+.3e", 1.0, "+1.000e+00"},
@@ -471,9 +497,9 @@ func TestFloatFormat(t *testing.T) {
{"%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", 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"},
@@ -482,9 +508,9 @@ func TestFloatFormat(t *testing.T) {
{"%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", 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"},
@@ -500,9 +526,9 @@ func TestFloatFormat(t *testing.T) {
{"%-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"},
+ {"%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 "},
@@ -541,7 +567,6 @@ func TestFloatFormat(t *testing.T) {
{"%v", -1e-9, "-1e-09"},
{"%v", float32(-1e-9), "-1e-09"},
{"%010v", 0.0, "0000000000"},
- {"%010v", 0.0, "0000000000"},
// *Float cases
{"%.20f", "1e-20", "0.00000000000000000001"},
@@ -571,3 +596,67 @@ func TestFloatFormat(t *testing.T) {
}
}
}
+
+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/libgo/go/math/big/floatexample_test.go b/libgo/go/math/big/floatexample_test.go
index 69686b7d16b..05bce613a80 100644
--- a/libgo/go/math/big/floatexample_test.go
+++ b/libgo/go/math/big/floatexample_test.go
@@ -111,3 +111,33 @@ func ExampleFloat_Cmp() {
// +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/libgo/go/math/big/floatmarsh.go b/libgo/go/math/big/floatmarsh.go
new file mode 100644
index 00000000000..44987ee03a6
--- /dev/null
+++ b/libgo/go/math/big/floatmarsh.go
@@ -0,0 +1,33 @@
+// 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 "fmt"
+
+// 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>"), 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/libgo/go/math/big/floatmarsh_test.go b/libgo/go/math/big/floatmarsh_test.go
new file mode 100644
index 00000000000..d7ef2fca68f
--- /dev/null
+++ b/libgo/go/math/big/floatmarsh_test.go
@@ -0,0 +1,54 @@
+// 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 (
+ "encoding/json"
+ "testing"
+)
+
+var floatVals = []string{
+ "0",
+ "1",
+ "0.1",
+ "2.71828",
+ "1234567890",
+ "3.14e1234",
+ "3.14e-1234",
+ "0.738957395793475734757349579759957975985497e100",
+ "0.73895739579347546656564656573475734957975995797598589749859834759476745986795497e100",
+ "inf",
+ "Inf",
+}
+
+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/libgo/go/math/big/ftoa.go b/libgo/go/math/big/ftoa.go
index 5c5f2cea460..c5cdb5eb705 100644
--- a/libgo/go/math/big/ftoa.go
+++ b/libgo/go/math/big/ftoa.go
@@ -9,9 +9,9 @@
package big
import (
+ "bytes"
"fmt"
"strconv"
- "strings"
)
// Text converts the floating-point number x to a string according
@@ -37,16 +37,16 @@ import (
// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
// it is the number of digits after the decimal point. For 'g' and 'G' it is
// the total number of digits. A negative precision selects the smallest
-// number of digits necessary to identify the value x uniquely.
+// 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.
-//
-// BUG(gri) Float.Text does not accept negative precisions (issue #10991).
func (x *Float) Text(format byte, prec int) string {
const extra = 10 // TODO(gri) determine a good/better value here
return string(x.Append(make([]byte, 0, prec+extra), format, prec))
}
// String formats x like x.Text('g', 10).
+// (String must be called explicitly, Float.Format does not support %s verb.)
func (x *Float) String() string {
return x.Text('g', 10)
}
@@ -83,6 +83,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
// 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())
}
@@ -90,9 +91,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
shortest := false
if prec < 0 {
shortest = true
- panic("unimplemented")
- // TODO(gri) complete this
- // roundShortest(&d, f.mant, int(f.exp))
+ roundShortest(&d, x)
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
@@ -158,6 +157,80 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
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
@@ -219,11 +292,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte {
if prec > 0 {
buf = append(buf, '.')
for i := 0; i < prec; i++ {
- ch := byte('0')
- if j := d.exp + i; 0 <= j && j < len(d.mant) {
- ch = d.mant[j]
- }
- buf = append(buf, ch)
+ buf = append(buf, d.at(d.exp+i))
}
}
@@ -255,7 +324,7 @@ func (x *Float) fmtB(buf []byte) []byte {
m = nat(nil).shr(m, uint(w-x.prec))
}
- buf = append(buf, m.decimalString()...)
+ buf = append(buf, m.utoa(10)...)
buf = append(buf, 'p')
e := int64(x.exp) - int64(x.prec)
if e >= 0 {
@@ -289,7 +358,7 @@ func (x *Float) fmtP(buf []byte) []byte {
m = m[i:]
buf = append(buf, "0x."...)
- buf = append(buf, strings.TrimRight(m.hexString(), "0")...)
+ buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
buf = append(buf, 'p')
if x.exp >= 0 {
buf = append(buf, '+')
@@ -314,10 +383,6 @@ func min(x, y int) int {
// '+' and ' ' for sign control, '0' for space or zero padding,
// and '-' for left or right justification. See the fmt package
// for details.
-//
-// BUG(gri) A missing precision for the 'g' format, or a negative
-// (via '*') precision is not yet supported. Instead the
-// default precision (6) is used in that case (issue #10991).
func (x *Float) Format(s fmt.State, format rune) {
prec, hasPrec := s.Precision()
if !hasPrec {
@@ -336,8 +401,7 @@ func (x *Float) Format(s fmt.State, format rune) {
fallthrough
case 'g', 'G':
if !hasPrec {
- // TODO(gri) uncomment once (*Float).Text handles prec < 0
- // prec = -1 // default precision for 'g', 'G'
+ prec = -1 // default precision for 'g', 'G'
}
default:
fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index 65334e0ef55..67ab7042ffe 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -273,7 +273,7 @@ func (z *Int) Mod(x, y *Int) *Int {
// DivMod implements Euclidean division and modulus (unlike Go):
//
// q = x div y such that
-// m = x - y*q with 0 <= m < |q|
+// 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
@@ -551,8 +551,11 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
}
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
-// If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime. n must be > 0.
+// 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")
@@ -640,23 +643,23 @@ func Jacobi(x, y *Int) int {
}
}
-// 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)
- }
+// 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)
@@ -703,6 +706,31 @@ func (z *Int) ModSqrt(x, p *Int) *Int {
}
}
+// 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)
@@ -904,65 +932,3 @@ func (z *Int) Not(x *Int) *Int {
z.neg = true // z cannot be zero if x is positive
return z
}
-
-// 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
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (z *Int) MarshalJSON() ([]byte, error) {
- // TODO(gri): get rid of the []byte/string conversions
- return []byte(z.String()), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (z *Int) UnmarshalJSON(text []byte) error {
- // TODO(gri): get rid of the []byte/string conversions
- if _, ok := z.SetString(string(text), 0); !ok {
- return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
- }
- return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (z *Int) MarshalText() (text []byte, err error) {
- return []byte(z.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (z *Int) UnmarshalText(text []byte) error {
- if _, ok := z.SetString(string(text), 0); !ok {
- return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
- }
- return nil
-}
diff --git a/libgo/go/math/big/int_test.go b/libgo/go/math/big/int_test.go
index 88c8c2bb641..45a3765d3ee 100644
--- a/libgo/go/math/big/int_test.go
+++ b/libgo/go/math/big/int_test.go
@@ -6,10 +6,7 @@ package big
import (
"bytes"
- "encoding/gob"
"encoding/hex"
- "encoding/json"
- "encoding/xml"
"fmt"
"math/rand"
"testing"
@@ -387,6 +384,11 @@ func TestSetBytes(t *testing.T) {
}
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)
}
@@ -542,6 +544,9 @@ var expTests = []struct {
{"0x8000000000000000", "1000", "6719", "1603"},
{"0x8000000000000000", "1000000", "6719", "3199"},
{"0x8000000000000000", "-1000000", "6719", "1"},
+
+ {"0xffffffffffffffffffffffffffffffff", "0x12345678123456781234567812345678123456789", "0x01112222333344445555666677778889", "0x36168FA1DB3AAE6C8CE647E137F97A"},
+
{
"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
"298472983472983471903246121093472394872319615612417471234712061",
@@ -550,11 +555,23 @@ var expTests = []struct {
},
// 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) {
@@ -582,7 +599,7 @@ func TestExp(t *testing.T) {
t.Errorf("#%d: %v is not normalized", i, *z1)
}
if z1.Cmp(out) != 0 {
- t.Errorf("#%d: got %s want %s", i, z1, out)
+ t.Errorf("#%d: got %x want %x", i, z1, out)
}
if m == nil {
@@ -591,7 +608,7 @@ func TestExp(t *testing.T) {
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 %s want %s", i, z2, z1)
+ t.Errorf("#%d: got %x want %x", i, z2, z1)
}
}
}
@@ -693,7 +710,9 @@ func TestGcd(t *testing.T) {
testGcd(t, d, x, y, a, b)
}
- quick.Check(checkGcd, nil)
+ if err := quick.Check(checkGcd, nil); err != nil {
+ t.Error(err)
+ }
}
var primes = []string{
@@ -1180,6 +1199,53 @@ func BenchmarkBitsetNegOrig(b *testing.B) {
}
}
+// 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)
@@ -1318,6 +1384,14 @@ func TestModSqrt(t *testing.T) {
t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
}
}
+
+ if testing.Short() && i > 2 {
+ break
+ }
+ }
+
+ if testing.Short() {
+ return
}
// exhaustive test for small values
@@ -1401,138 +1475,6 @@ func TestJacobiPanic(t *testing.T) {
panic(failureMsg)
}
-var encodingTests = []string{
- "-539345864568634858364538753846587364875430589374589",
- "-678645873",
- "-100",
- "-2",
- "-1",
- "0",
- "1",
- "2",
- "10",
- "42",
- "1234567890",
- "298472983472983471903246121093472394872319615612417471234712061",
-}
-
-func TestIntGobEncoding(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 Int
- tx.SetString(test, 10)
- if err := enc.Encode(&tx); err != nil {
- t.Errorf("encoding of %s failed: %s", &tx, err)
- }
- var rx Int
- if err := dec.Decode(&rx); err != nil {
- t.Errorf("decoding of %s failed: %s", &tx, err)
- }
- 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.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
- }
-}
-
-func TestIntJSONEncoding(t *testing.T) {
- for _, test := range encodingTests {
- var tx Int
- tx.SetString(test, 10)
- b, err := json.Marshal(&tx)
- if err != nil {
- t.Errorf("marshaling of %s failed: %s", &tx, err)
- }
- var rx Int
- if err := json.Unmarshal(b, &rx); err != nil {
- t.Errorf("unmarshaling of %s failed: %s", &tx, err)
- }
- if rx.Cmp(&tx) != 0 {
- t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
- }
- }
-}
-
-var intVals = []string{
- "-141592653589793238462643383279502884197169399375105820974944592307816406286",
- "-1415926535897932384626433832795028841971",
- "-141592653589793",
- "-1",
- "0",
- "1",
- "141592653589793",
- "1415926535897932384626433832795028841971",
- "141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-func TestIntJSONEncodingTextMarshaller(t *testing.T) {
- for _, num := range intVals {
- var tx Int
- tx.SetString(num, 0)
- 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 TestIntXMLEncodingTextMarshaller(t *testing.T) {
- for _, num := range intVals {
- var tx Int
- tx.SetString(num, 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)
- }
- }
-}
-
func TestIssue2607(t *testing.T) {
// This code sequence used to hang.
n := NewInt(10)
diff --git a/libgo/go/math/big/intconv.go b/libgo/go/math/big/intconv.go
index 9c68a22bed8..56a75f87ae2 100644
--- a/libgo/go/math/big/intconv.go
+++ b/libgo/go/math/big/intconv.go
@@ -12,30 +12,34 @@ import (
"io"
)
-func (x *Int) String() string {
- switch {
- case x == nil:
+// 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 "<nil>"
- case x.neg:
- return "-" + x.abs.decimalString()
}
- return x.abs.decimalString()
+ return string(x.abs.itoa(x.neg, base))
}
-func charset(ch rune) string {
- switch ch {
- case 'b':
- return lowercaseDigits[0:2]
- case 'o':
- return lowercaseDigits[0:8]
- case 'd', 's', 'v':
- return lowercaseDigits[0:10]
- case 'x':
- return lowercaseDigits[0:16]
- case 'X':
- return uppercaseDigits[0:16]
+// 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, "<nil>"...)
}
- return "" // unknown format
+ 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
@@ -60,15 +64,24 @@ func writeMultiple(s fmt.State, text string, count int) {
// right justification.
//
func (x *Int) Format(s fmt.State, ch rune) {
- cs := charset(ch)
-
- // special cases
- switch {
- case cs == "":
+ // 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
- case x == nil:
+ }
+
+ if x == nil {
fmt.Fprint(s, "<nil>")
return
}
@@ -97,35 +110,42 @@ func (x *Int) Format(s fmt.State, ch rune) {
}
}
- // determine digits with base set by len(cs) and digit characters from cs
- digits := x.abs.string(cs)
+ 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 zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
- var right int // space characters to right of digits for left justification ("%-8d")
+ 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:
- zeroes = precision - len(digits) // count of zero padding
- case digits == "0" && precision == 0:
+ 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) + zeroes + len(digits)
+ 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 zeroes unless precision also specified
- zeroes = d
+ // pad with zeros unless precision also specified
+ zeros = d
default:
// pad on the left with spaces
left = d
@@ -136,8 +156,8 @@ func (x *Int) Format(s fmt.State, ch rune) {
writeMultiple(s, " ", left)
writeMultiple(s, sign, 1)
writeMultiple(s, prefix, 1)
- writeMultiple(s, "0", zeroes)
- writeMultiple(s, digits, 1)
+ writeMultiple(s, "0", zeros)
+ s.Write(digits)
writeMultiple(s, " ", right)
}
diff --git a/libgo/go/math/big/intconv_test.go b/libgo/go/math/big/intconv_test.go
index 2deb84b48f6..514208145fd 100644
--- a/libgo/go/math/big/intconv_test.go
+++ b/libgo/go/math/big/intconv_test.go
@@ -17,19 +17,19 @@ var stringTests = []struct {
val int64
ok bool
}{
- {in: "", ok: false},
- {in: "a", ok: false},
- {in: "z", ok: false},
- {in: "+", ok: false},
- {in: "-", ok: false},
- {in: "0b", ok: false},
- {in: "0x", ok: false},
- {in: "2", base: 2, ok: false},
- {in: "0b2", base: 0, ok: false},
- {in: "08", ok: false},
- {in: "8", base: 8, ok: false},
- {in: "0xg", base: 0, ok: false},
- {in: "g", base: 16, ok: false},
+ {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},
@@ -41,7 +41,7 @@ var stringTests = []struct {
{"-10", "-10", 16, -16, true},
{"+10", "10", 16, 16, true},
{"0x10", "16", 0, 16, true},
- {in: "0x10", base: 16, ok: false},
+ {in: "0x10", base: 16},
{"-0x10", "-16", 0, -16, true},
{"+0x10", "16", 0, 16, true},
{"00", "0", 0, 0, true},
@@ -58,6 +58,57 @@ var stringTests = []struct {
{"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:
@@ -79,15 +130,13 @@ func TestGetString(t *testing.T) {
z.SetInt64(test.val)
if test.base == 10 {
- s := z.String()
- if s != test.out {
- t.Errorf("#%da got %s; want %s", i, s, test.out)
+ if got := z.String(); got != test.out {
+ t.Errorf("#%da got %s; want %s", i, got, test.out)
}
}
- s := fmt.Sprintf(format(test.base), z)
- if s != test.out {
- t.Errorf("#%db got %s; want %s", i, s, test.out)
+ if got := fmt.Sprintf(format(test.base), z); got != test.out {
+ t.Errorf("#%db got %s; want %s", i, got, test.out)
}
}
}
diff --git a/libgo/go/math/big/intmarsh.go b/libgo/go/math/big/intmarsh.go
new file mode 100644
index 00000000000..4ff57b6464e
--- /dev/null
+++ b/libgo/go/math/big/intmarsh.go
@@ -0,0 +1,74 @@
+// 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>"), 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 {
+ return z.UnmarshalText(text)
+}
diff --git a/libgo/go/math/big/intmarsh_test.go b/libgo/go/math/big/intmarsh_test.go
new file mode 100644
index 00000000000..f82956ceaf2
--- /dev/null
+++ b/libgo/go/math/big/intmarsh_test.go
@@ -0,0 +1,121 @@
+// 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/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go
index 6545bc17ed3..79cf6e07f7f 100644
--- a/libgo/go/math/big/nat.go
+++ b/libgo/go/math/big/nat.go
@@ -2,31 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package big implements multi-precision arithmetic (big numbers).
-// The following numeric types are supported:
-//
-// Int signed integers
-// Rat rational numbers
-// Float floating-point numbers
-//
-// Methods are typically of the form:
-//
-// func (z *T) Unary(x *T) *T // z = op x
-// func (z *T) Binary(x, y *T) *T // z = x op y
-// func (x *T) M() T1 // v = x.M()
-//
-// with T one of Int, Rat, or Float. For unary and binary operations, the
-// result is the receiver (usually named z in that case); if it is one of
-// the operands x or y it may be overwritten (and its memory reused).
-// To enable chaining of operations, the result is also returned. Methods
-// returning a result other than *Int, *Rat, or *Float take an operand as
-// the receiver (usually named x in that case).
-//
-package big
+// 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.
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
+package big
import "math/rand"
@@ -216,29 +196,42 @@ func basicMul(z, x, y nat) {
}
}
-// montgomery computes x*y*2^(-n*_W) mod m,
-// assuming k = -1/m mod 2^_W.
+// 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 {
- var c1, c2 Word
+ // 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]
- c1 += addMulVVW(z, x, d)
+ c2 := addMulVVW(z, x, d)
t := z[0] * k
- c2 = addMulVVW(z, m, t)
-
+ c3 := addMulVVW(z, m, t)
copy(z, z[1:])
- z[n-1] = c1 + c2
- if z[n-1] < c1 {
- c1 = 1
+ cx := c + c2
+ cy := cx + c3
+ z[n-1] = cy
+ if cx < c2 || cy < c3 {
+ c = 1
} else {
- c1 = 0
+ c = 0
}
}
- if c1 != 0 {
+ if c != 0 {
subVV(z, z, m)
}
return z
@@ -1063,26 +1056,22 @@ func (z nat) expNNWindowed(x, y, m nat) nat {
// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
// Uses Montgomery representation.
func (z nat) expNNMontgomery(x, y, m nat) nat {
- var zz, one, rr, RR nat
-
numWords := len(m)
// We want the lengths of x and m to be equal.
+ // It is OK if x >= m as long as len(x) == len(m).
if len(x) > numWords {
- _, rr = rr.div(rr, x, m)
- } else if len(x) < numWords {
- rr = rr.make(numWords)
- rr.clear()
- for i := range x {
- rr[i] = x[i]
- }
- } else {
- rr = x
+ _, x = 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
}
- 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
+ // 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
@@ -1092,9 +1081,9 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
}
k0 = -k0
- // RR = 2ˆ(2*_W*len(m)) mod m
- RR = RR.setWord(1)
- zz = zz.shl(RR, uint(2*numWords*_W))
+ // 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)
@@ -1102,8 +1091,7 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
RR = zz
}
// one = 1, with equal length to that of m
- one = one.make(numWords)
- one.clear()
+ one := make(nat, numWords)
one[0] = 1
const n = 4
@@ -1138,12 +1126,32 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
}
// 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 reps Miller-Rabin tests to check whether n is prime.
-// If it returns true, n is prime with probability 1 - 1/4^reps.
-// If it returns false, n is not prime.
+// 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
diff --git a/libgo/go/math/big/nat_test.go b/libgo/go/math/big/nat_test.go
index 7ac3cb8a846..563ccb30523 100644
--- a/libgo/go/math/big/nat_test.go
+++ b/libgo/go/math/big/nat_test.go
@@ -158,7 +158,7 @@ var mulRangesN = []struct {
func TestMulRangeN(t *testing.T) {
for i, r := range mulRangesN {
- prod := nat(nil).mulRange(r.a, r.b).decimalString()
+ 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)
}
@@ -326,7 +326,7 @@ func TestTrailingZeroBits(t *testing.T) {
for i := uint(0); i <= 3*_W; i++ {
n := y.trailingZeroBits()
if n != i {
- t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
+ t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
}
y = y.shl(y, 1)
}
@@ -341,25 +341,57 @@ var montgomeryTests = []struct {
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
"0xfffffffffffffffffffffffffffffffffffffffffffffffff",
- 0x0000000000000000,
- "0xffffffffffffffffffffffffffffffffffffffffff",
- "0xffffffffffffffffffffffffffffffffff",
+ 1,
+ "0x1000000000000000000000000000000000000000000",
+ "0x10000000000000000000000000000000000",
},
{
- "0x0000000080000000",
- "0x00000000ffffffff",
+ "0x000000000ffffff5",
+ "0x000000000ffffff0",
"0x0000000010000001",
0xff0000000fffffff,
- "0x0000000088000000",
- "0x0000000007800001",
+ "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",
},
{
- "0xffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
- "0xffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+ "0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
+ "0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
"0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
0xdecc8f1249812adf,
- "0x22bb05b6d95eaaeca2bb7c05e51f807bce9064b5fbad177161695e4558f9474e91cd79",
- "0x14beb58d230f85b6d95eaaeca2bb7c05e51f807bce9064b5fb45669afa695f228e48cd",
+ "0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5",
+ "0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0",
},
{
"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
@@ -372,10 +404,27 @@ var montgomeryTests = []struct {
}
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 {
@@ -384,11 +433,31 @@ func TestMontgomery(t *testing.T) {
out = natFromString(test.out64)
}
- k0 := Word(test.k0 & _M) // mask k0 to ensure that it fits for 32-bit systems.
+ // 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 %s want %s", i, z.decimalString(), out.decimalString())
+ t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
}
}
}
@@ -414,6 +483,12 @@ var expNNTests = []struct {
"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
},
+ {
+ "11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
+ "426343618817810911523",
+ "444747819283133684179",
+ "42",
+ },
}
func TestExpNN(t *testing.T) {
@@ -429,7 +504,7 @@ func TestExpNN(t *testing.T) {
z := nat(nil).expNN(x, y, m)
if z.cmp(out) != 0 {
- t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+ t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
}
}
}
@@ -486,7 +561,7 @@ var fiboNums = []string{
func TestFibo(t *testing.T) {
for i, want := range fiboNums {
n := i * 10
- got := fibo(n).decimalString()
+ got := string(fibo(n).utoa(10))
if got != want {
t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
}
diff --git a/libgo/go/math/big/natconv.go b/libgo/go/math/big/natconv.go
index 022dcfe38c8..d2ce667fb60 100644
--- a/libgo/go/math/big/natconv.go
+++ b/libgo/go/math/big/natconv.go
@@ -14,6 +14,11 @@ import (
"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
@@ -229,56 +234,45 @@ func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count in
return
}
-// Character sets for string conversion.
-const (
- lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
- uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
- return x.string(lowercaseDigits[:10])
+// 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)
}
-// hexString returns a hexadecimal representation of x.
-// It calls x.string with the charset "0123456789abcdef".
-func (x nat) hexString() string {
- return x.string(lowercaseDigits[:16])
-}
+// 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")
+ }
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2 and <= 256.
-func (x nat) string(charset string) string {
- b := Word(len(charset))
-
- // special cases
- switch {
- case b < 2 || b > 256:
- panic("invalid character set length")
- case len(x) == 0:
- return string(charset[0])
+ // x == 0
+ if len(x) == 0 {
+ return []byte("0")
}
+ // len(x) > 0
// allocate buffer for conversion
- i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+ 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 == b&-b {
- // shift is base-b digit size in bits
+ 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 - 1
- w := x[0]
+ mask := Word(1<<shift - 1)
+ w := x[0] // current word
nbits := uint(_W) // number of unprocessed bits in w
- // convert less-significant words
+ // convert less-significant words (include leading zeros)
for k := 1; k < len(x); k++ {
// convert full digits
for nbits >= shift {
i--
- s[i] = charset[w&mask]
+ s[i] = digits[w&mask]
w >>= shift
nbits -= shift
}
@@ -289,10 +283,10 @@ func (x nat) string(charset string) string {
w = x[k]
nbits = _W
} else {
- // partial digit in current (k-1) and next (k) word
+ // partial digit in current word w (== x[k-1]) and next word x[k]
w |= x[k] << nbits
i--
- s[i] = charset[w&mask]
+ s[i] = digits[w&mask]
// advance
w = x[k] >> (shift - nbits)
@@ -300,12 +294,11 @@ func (x nat) string(charset string) string {
}
}
- // convert digits of most-significant word (omit leading zeros)
- for nbits >= 0 && w != 0 {
+ // convert digits of most-significant word w (omit leading zeros)
+ for w != 0 {
i--
- s[i] = charset[w&mask]
+ s[i] = digits[w&mask]
w >>= shift
- nbits -= shift
}
} else {
@@ -319,18 +312,23 @@ func (x nat) string(charset string) string {
q := nat(nil).set(x)
// convert q to string s in base b
- q.convertWords(s, charset, b, ndigits, bb, table)
+ 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 zero := charset[0]; s[i] == zero; {
+ for s[i] == '0' {
i++
}
}
- return string(s[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"
@@ -349,7 +347,7 @@ func (x nat) string(charset string) string {
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
// specific hardware.
//
-func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+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
@@ -374,8 +372,8 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
// convert subblocks and collect results in s[:h] and s[h:]
h := len(s) - table[index].ndigits
- r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
- s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+ r.convertWords(s[h:], b, ndigits, bb, table[0:index])
+ s = s[:h] // == q.convertWords(s, b, ndigits, bb, table[0:index+1])
}
}
@@ -393,7 +391,7 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
// this appears to be faster for BenchmarkString10000Base10
// and smaller strings (but a bit slower for larger ones)
t := r / 10
- s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+ s[i] = '0' + byte(r-t<<3-t-t) // TODO(gri) replace w/ t*10 once compiler produces better code
r = t
}
}
@@ -403,17 +401,16 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
q, r = q.divW(q, bb)
for j := 0; j < ndigits && i > 0; j++ {
i--
- s[i] = charset[r%b]
+ s[i] = digits[r%b]
r /= b
}
}
}
- // prepend high-order zeroes
- zero := charset[0]
- for i > 0 { // while need more leading zeroes
+ // prepend high-order zeros
+ for i > 0 { // while need more leading zeros
i--
- s[i] = zero
+ s[i] = '0'
}
}
@@ -425,7 +422,7 @@ var leafSize int = 8 // number of Word-size binary values treat as a monolithic
type divisor struct {
bbb nat // divisor
- nbits int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+ nbits int // bit length of divisor (discounting leading zeros) ~= log2(bbb)
ndigits int // digit length of divisor in terms of output base digits
}
diff --git a/libgo/go/math/big/natconv_test.go b/libgo/go/math/big/natconv_test.go
index f321fbc2df0..028e5a858eb 100644
--- a/libgo/go/math/big/natconv_test.go
+++ b/libgo/go/math/big/natconv_test.go
@@ -5,20 +5,19 @@
package big
import (
+ "bytes"
"io"
"strings"
"testing"
)
-func toString(x nat, charset string) string {
- base := len(charset)
-
+func itoa(x nat, base int) []byte {
// special cases
switch {
case base < 2:
panic("illegal base")
case len(x) == 0:
- return string(charset[0])
+ return []byte("0")
}
// allocate buffer for conversion
@@ -33,54 +32,53 @@ func toString(x nat, charset string) string {
i--
var r Word
q, r = q.divW(q, Word(base))
- s[i] = charset[r]
+ s[i] = digits[r]
}
- return string(s[i:])
+ return s[i:]
}
var strTests = []struct {
x nat // nat value to be converted
- c string // conversion charset
+ b int // conversion base
s string // expected result
}{
- {nil, "01", "0"},
- {nat{1}, "01", "1"},
- {nat{0xc5}, "01", "11000101"},
- {nat{03271}, lowercaseDigits[:8], "3271"},
- {nat{10}, lowercaseDigits[:10], "10"},
- {nat{1234567890}, uppercaseDigits[:10], "1234567890"},
- {nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
- {nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
- {nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
- {nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
+ {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 character set explicitly
+ // test invalid base explicitly
var panicStr string
func() {
defer func() {
panicStr = recover().(string)
}()
- natOne.string("0")
+ natOne.utoa(1)
}()
- if panicStr != "invalid character set length" {
- t.Errorf("expected panic for invalid character set")
+ if panicStr != "invalid base" {
+ t.Errorf("expected panic for invalid base")
}
for _, a := range strTests {
- s := a.x.string(a.c)
+ 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), len(a.c), false)
+ 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 != len(a.c) {
- t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+ 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)
@@ -236,7 +234,7 @@ func TestScanPi(t *testing.T) {
if err != nil {
t.Errorf("scanning pi: %s", err)
}
- if s := z.decimalString(); s != pi {
+ if s := string(z.utoa(10)); s != pi {
t.Errorf("scanning pi: got %s", s)
}
}
@@ -265,12 +263,12 @@ func BenchmarkScanPi(b *testing.B) {
func BenchmarkStringPiParallel(b *testing.B) {
var x nat
x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
- if x.decimalString() != pi {
+ if string(x.utoa(10)) != pi {
panic("benchmark incorrect: conversion failed")
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
- x.decimalString()
+ x.utoa(10)
}
})
}
@@ -304,15 +302,14 @@ func ScanHelper(b *testing.B, base int, x, y Word) {
var z nat
z = z.expWW(x, y)
- var s string
- s = z.string(lowercaseDigits[:base])
- if t := toString(z, lowercaseDigits[:base]); t != s {
+ 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(strings.NewReader(s), base, false)
+ z.scan(bytes.NewReader(s), base, false)
}
}
@@ -344,11 +341,11 @@ func StringHelper(b *testing.B, base int, x, y Word) {
b.StopTimer()
var z nat
z = z.expWW(x, y)
- z.string(lowercaseDigits[:base]) // warm divisor cache
+ z.utoa(base) // warm divisor cache
b.StartTimer()
for i := 0; i < b.N; i++ {
- _ = z.string(lowercaseDigits[:base])
+ _ = z.utoa(base)
}
}
@@ -372,7 +369,7 @@ func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
-func LeafSizeHelper(b *testing.B, base Word, size int) {
+func LeafSizeHelper(b *testing.B, base, size int) {
b.StopTimer()
originalLeafSize := leafSize
resetTable(cacheBase10.table[:])
@@ -382,12 +379,12 @@ func LeafSizeHelper(b *testing.B, base Word, size int) {
for d := 1; d <= 10000; d *= 10 {
b.StopTimer()
var z nat
- z = z.expWW(base, Word(d)) // build target number
- _ = z.string(lowercaseDigits[:base]) // warm divisor cache
+ 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.string(lowercaseDigits[:base])
+ _ = z.utoa(base)
}
}
@@ -408,13 +405,13 @@ func resetTable(table []divisor) {
}
func TestStringPowers(t *testing.T) {
- var b, p Word
- for b = 2; b <= 16; b++ {
+ var p Word
+ for b := 2; b <= 16; b++ {
for p = 0; p <= 512; p++ {
- x := nat(nil).expWW(b, p)
- xs := x.string(lowercaseDigits[:b])
- xs2 := toString(x, lowercaseDigits[:b])
- if xs != xs2 {
+ 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)
}
}
diff --git a/libgo/go/math/big/rat.go b/libgo/go/math/big/rat.go
index fb16f18a964..2cd9ed09388 100644
--- a/libgo/go/math/big/rat.go
+++ b/libgo/go/math/big/rat.go
@@ -7,8 +7,6 @@
package big
import (
- "encoding/binary"
- "errors"
"fmt"
"math"
)
@@ -510,61 +508,3 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
z.a.neg = a.neg != b.neg
return z.norm()
}
-
-// 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 (r *Rat) MarshalText() (text []byte, err error) {
- return []byte(r.RatString()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (r *Rat) UnmarshalText(text []byte) error {
- if _, ok := r.SetString(string(text)); !ok {
- return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
- }
- return nil
-}
diff --git a/libgo/go/math/big/rat_test.go b/libgo/go/math/big/rat_test.go
index 012d0c47ec4..3a06fca3c34 100644
--- a/libgo/go/math/big/rat_test.go
+++ b/libgo/go/math/big/rat_test.go
@@ -5,10 +5,6 @@
package big
import (
- "bytes"
- "encoding/gob"
- "encoding/json"
- "encoding/xml"
"math"
"testing"
)
@@ -280,116 +276,6 @@ func TestRatSetFrac64Rat(t *testing.T) {
}
}
-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)
- }
- var rx Rat
- if err := dec.Decode(&rx); err != nil {
- t.Errorf("decoding of %s failed: %s", &tx, err)
- }
- 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.Errorf("transmission of (*Int)(nill) 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)
- }
- }
- }
-}
-
func TestIssue2379(t *testing.T) {
// 1) no aliasing
q := NewRat(3, 2)
diff --git a/libgo/go/math/big/ratconv.go b/libgo/go/math/big/ratconv.go
index 961ff649a50..4566ff4e39d 100644
--- a/libgo/go/math/big/ratconv.go
+++ b/libgo/go/math/big/ratconv.go
@@ -188,11 +188,15 @@ func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err err
// String returns a string representation of x in the form "a/b" (even if b == 1).
func (x *Rat) String() string {
- s := "/1"
+ var buf []byte
+ buf = x.a.Append(buf, 10)
+ buf = append(buf, '/')
if len(x.b.abs) != 0 {
- s = "/" + x.b.abs.decimalString()
+ buf = x.b.Append(buf, 10)
+ } else {
+ buf = append(buf, '1')
}
- return x.a.String() + s
+ return string(buf)
}
// RatString returns a string representation of x in the form "a/b" if b != 1,
@@ -208,12 +212,17 @@ func (x *Rat) RatString() string {
// 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() {
- s := x.a.String()
+ buf = x.a.Append(buf, 10)
if prec > 0 {
- s += "." + strings.Repeat("0", prec)
+ buf = append(buf, '.')
+ for i := prec; i > 0; i-- {
+ buf = append(buf, '0')
+ }
}
- return s
+ return string(buf)
}
// x.b.abs != 0
@@ -237,16 +246,19 @@ func (x *Rat) FloatString(prec int) string {
}
}
- s := q.decimalString()
if x.a.neg {
- s = "-" + s
+ buf = append(buf, '-')
}
+ buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
if prec > 0 {
- rs := r.decimalString()
- leadingZeros := prec - len(rs)
- s += "." + strings.Repeat("0", leadingZeros) + rs
+ buf = append(buf, '.')
+ rs := r.utoa(10)
+ for i := prec - len(rs); i > 0; i-- {
+ buf = append(buf, '0')
+ }
+ buf = append(buf, rs...)
}
- return s
+ return string(buf)
}
diff --git a/libgo/go/math/big/ratmarsh.go b/libgo/go/math/big/ratmarsh.go
new file mode 100644
index 00000000000..b82e8d4ae8d
--- /dev/null
+++ b/libgo/go/math/big/ratmarsh.go
@@ -0,0 +1,73 @@
+// 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/libgo/go/math/big/ratmarsh_test.go b/libgo/go/math/big/ratmarsh_test.go
new file mode 100644
index 00000000000..351d109f8d8
--- /dev/null
+++ b/libgo/go/math/big/ratmarsh_test.go
@@ -0,0 +1,125 @@
+// 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/libgo/go/math/cmplx/cmath_test.go b/libgo/go/math/cmplx/cmath_test.go
index f285646af7a..18d9be81948 100644
--- a/libgo/go/math/cmplx/cmath_test.go
+++ b/libgo/go/math/cmplx/cmath_test.go
@@ -438,8 +438,10 @@ func tolerance(a, b, e float64) bool {
d = -d
}
- if a != 0 {
- e = e * a
+ // note: b is correct (expected) value, a is actual value.
+ // make error tolerance a fraction of b, not a.
+ if b != 0 {
+ e = e * b
if e < 0 {
e = -e
}
@@ -460,8 +462,8 @@ func alike(a, b float64) bool {
func cTolerance(a, b complex128, e float64) bool {
d := Abs(a - b)
- if a != 0 {
- e = e * Abs(a)
+ if b != 0 {
+ e = e * Abs(b)
if e < 0 {
e = -e
}
diff --git a/libgo/go/math/cmplx/sqrt.go b/libgo/go/math/cmplx/sqrt.go
index 4ef6807addc..276be07ae9a 100644
--- a/libgo/go/math/cmplx/sqrt.go
+++ b/libgo/go/math/cmplx/sqrt.go
@@ -40,7 +40,7 @@ import "math"
// 1/2
// Im w = [ (r - x)/2 ] .
//
-// Cancellation error in r-x or r+x is avoided by using the
+// Cancelation error in r-x or r+x is avoided by using the
// identity 2 Re w Im w = y.
//
// Note that -w is also a square root of z. The root chosen
diff --git a/libgo/go/math/expm1.go b/libgo/go/math/expm1.go
index 8d7b3d365a6..b4dcdc52a20 100644
--- a/libgo/go/math/expm1.go
+++ b/libgo/go/math/expm1.go
@@ -233,7 +233,7 @@ func expm1(x float64) float64 {
y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
return y
}
- t := Float64frombits(uint64((0x3ff - k) << 52)) // 2**-k
+ t := Float64frombits(uint64(0x3ff-k) << 52) // 2**-k
y := x - (e + t)
y += 1
y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
diff --git a/libgo/go/math/floor_asm.go b/libgo/go/math/floor_asm.go
new file mode 100644
index 00000000000..28e56a5d51b
--- /dev/null
+++ b/libgo/go/math/floor_asm.go
@@ -0,0 +1,12 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 amd64p32
+
+package math
+
+//defined in floor_amd64.s
+func hasSSE4() bool
+
+var useSSE4 = hasSSE4()
diff --git a/libgo/go/math/j0.go b/libgo/go/math/j0.go
index c20a9b22a89..de7738880e6 100644
--- a/libgo/go/math/j0.go
+++ b/libgo/go/math/j0.go
@@ -38,7 +38,7 @@ package math
// = 1/sqrt(2) * (cos(x) + sin(x))
// sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
// = 1/sqrt(2) * (sin(x) - cos(x))
-// (To avoid cancellation, use
+// (To avoid cancelation, use
// sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
// to compute the worse one.)
//
@@ -188,7 +188,7 @@ func Y0(x float64) float64 {
// = 1/sqrt(2) * (sin(x) + cos(x))
// sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
// = 1/sqrt(2) * (sin(x) - cos(x))
- // To avoid cancellation, use
+ // To avoid cancelation, use
// sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
// to compute the worse one.
diff --git a/libgo/go/math/j1.go b/libgo/go/math/j1.go
index 7ac186b72aa..c537a72eb25 100644
--- a/libgo/go/math/j1.go
+++ b/libgo/go/math/j1.go
@@ -39,7 +39,7 @@ package math
// = 1/sqrt(2) * (sin(x) - cos(x))
// sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
// = -1/sqrt(2) * (sin(x) + cos(x))
-// (To avoid cancellation, use
+// (To avoid cancelation, use
// sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
// to compute the worse one.)
//
@@ -197,7 +197,7 @@ func Y1(x float64) float64 {
// = 1/sqrt(2) * (sin(x) - cos(x))
// sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
// = -1/sqrt(2) * (cos(x) + sin(x))
- // To avoid cancellation, use
+ // To avoid cancelation, use
// sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
// to compute the worse one.
diff --git a/libgo/go/math/jn.go b/libgo/go/math/jn.go
index a7909eb24cd..ffb8a00f50f 100644
--- a/libgo/go/math/jn.go
+++ b/libgo/go/math/jn.go
@@ -200,13 +200,11 @@ func Jn(n int, x float64) float64 {
for i := n - 1; i > 0; i-- {
di := float64(i + i)
a, b = b, b*di/x-a
- di -= 2
}
} else {
for i := n - 1; i > 0; i-- {
di := float64(i + i)
a, b = b, b*di/x-a
- di -= 2
// scale b to avoid spurious overflow
if b > 1e100 {
a /= b
diff --git a/libgo/go/math/modf.go b/libgo/go/math/modf.go
index ecec4b756c7..5d2f489b709 100644
--- a/libgo/go/math/modf.go
+++ b/libgo/go/math/modf.go
@@ -16,9 +16,12 @@ func Modf(f float64) (int float64, frac float64) {
func modf(f float64) (int float64, frac float64) {
if f < 1 {
- if f < 0 {
+ switch {
+ case f < 0:
int, frac = Modf(-f)
return -int, -frac
+ case f == 0:
+ return f, f // Return -0, -0 when f == -0
}
return 0, f
}
diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go
index 6360128e391..d693bfb52f2 100644
--- a/libgo/go/math/rand/rand.go
+++ b/libgo/go/math/rand/rand.go
@@ -113,19 +113,18 @@ func (r *Rand) Float64() float64 {
//
// There is one bug in the value stream: r.Int63() may be so close
// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
- // that the result is always less than 1.0. To fix that, we treat the
- // range as cyclic and map 1 back to 0. This is justified by observing
- // that while some of the values rounded down to 0, nothing was
- // rounding up to 0, so 0 was underrepresented in the results.
- // Mapping 1 back to zero restores some balance.
- // (The balance is not perfect because the implementation
- // returns denormalized numbers for very small r.Int63(),
- // and those steal from what would normally be 0 results.)
- // The remapping only happens 1/2⁵³ of the time, so most clients
+ // that the result is always less than 1.0.
+ //
+ // We tried to fix this by mapping 1.0 back to 0.0, but since float64
+ // values near 0 are much denser than near 1, mapping 1 to 0 caused
+ // a theoretically significant overshoot in the probability of returning 0.
+ // Instead of that, if we round up to 1, just try again.
+ // Getting 1 only happens 1/2⁵³ of the time, so most clients
// will not observe it anyway.
+again:
f := float64(r.Int63()) / (1 << 63)
if f == 1 {
- f = 0
+ goto again // resample; this branch is taken O(never)
}
return f
}
@@ -134,13 +133,11 @@ func (r *Rand) Float64() float64 {
func (r *Rand) Float32() float32 {
// Same rationale as in Float64: we want to preserve the Go 1 value
// stream except we want to fix it not to return 1.0
- // There is a double rounding going on here, but the argument for
- // mapping 1 to 0 still applies: 0 was underrepresented before,
- // so mapping 1 to 0 doesn't cause too many 0s.
// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
+again:
f := float32(r.Float64())
if f == 1 {
- f = 0
+ goto again // resample; this branch is taken O(very rarely)
}
return f
}
@@ -148,6 +145,11 @@ func (r *Rand) Float32() float32 {
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int {
m := make([]int, n)
+ // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
+ // A change to remove this useless iteration is to assign 1 to i in the init
+ // statement. But Perm also effects r. Making this change will affect
+ // the final state of r. So this change can't be made for compatibility
+ // reasons for Go 1.
for i := 0; i < n; i++ {
j := r.Intn(i + 1)
m[i] = m[j]
@@ -156,6 +158,19 @@ func (r *Rand) Perm(n int) []int {
return m
}
+// Read generates len(p) random bytes and writes them into p. It
+// always returns len(p) and a nil error.
+func (r *Rand) Read(p []byte) (n int, err error) {
+ for i := 0; i < len(p); i += 7 {
+ val := r.src.Int63()
+ for j := 0; i+j < len(p) && j < 7; j++ {
+ p[i+j] = byte(val)
+ val >>= 8
+ }
+ }
+ return len(p), nil
+}
+
/*
* Top-level convenience functions
*/
@@ -209,6 +224,10 @@ func Float32() float32 { return globalRand.Float32() }
// from the default Source.
func Perm(n int) []int { return globalRand.Perm(n) }
+// Read generates len(p) random bytes from the default Source and
+// writes them into p. It always returns len(p) and a nil error.
+func Read(p []byte) (n int, err error) { return globalRand.Read(p) }
+
// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
// standard normal distribution (mean = 0, stddev = 1)
diff --git a/libgo/go/math/rand/rand_test.go b/libgo/go/math/rand/rand_test.go
index c61494f8eb8..8d68335fdd4 100644
--- a/libgo/go/math/rand/rand_test.go
+++ b/libgo/go/math/rand/rand_test.go
@@ -7,6 +7,7 @@ package rand
import (
"errors"
"fmt"
+ "internal/testenv"
"math"
"os"
"runtime"
@@ -327,9 +328,10 @@ func TestExpTables(t *testing.T) {
func TestFloat32(t *testing.T) {
// For issue 6721, the problem came after 7533753 calls, so check 10e6.
num := int(10e6)
+ // But do the full amount only on builders (not locally).
// But ARM5 floating point emulation is slow (Issue 10749), so
// do less for that builder:
- if testing.Short() && runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" {
+ if testing.Short() && (testenv.Builder() == "" || runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5") {
num /= 100 // 1.72 seconds instead of 172 seconds
}
@@ -342,6 +344,59 @@ func TestFloat32(t *testing.T) {
}
}
+func testReadUniformity(t *testing.T, n int, seed int64) {
+ r := New(NewSource(seed))
+ buf := make([]byte, n)
+ nRead, err := r.Read(buf)
+ if err != nil {
+ t.Errorf("Read err %v", err)
+ }
+ if nRead != n {
+ t.Errorf("Read returned unexpected n; %d != %d", nRead, n)
+ }
+
+ // Expect a uniform distribution of byte values, which lie in [0, 255].
+ var (
+ mean = 255.0 / 2
+ stddev = math.Sqrt(255.0 * 255.0 / 12.0)
+ errorScale = stddev / math.Sqrt(float64(n))
+ )
+
+ expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
+
+ // Cast bytes as floats to use the common distribution-validity checks.
+ samples := make([]float64, n)
+ for i, val := range buf {
+ samples[i] = float64(val)
+ }
+ // Make sure that the entire set matches the expected distribution.
+ checkSampleDistribution(t, samples, expected)
+}
+
+func TestRead(t *testing.T) {
+ testBufferSizes := []int{
+ 2, 4, 7, 64, 1024, 1 << 16, 1 << 20,
+ }
+ for _, seed := range testSeeds {
+ for _, n := range testBufferSizes {
+ testReadUniformity(t, n, seed)
+ }
+ }
+}
+
+func TestReadEmpty(t *testing.T) {
+ r := New(NewSource(1))
+ buf := make([]byte, 0)
+ n, err := r.Read(buf)
+ if err != nil {
+ t.Errorf("Read err into empty buffer; %v", err)
+ }
+ if n != 0 {
+ t.Errorf("Read into empty buffer returned unexpected n of %d", n)
+ }
+
+}
+
// Benchmarks
func BenchmarkInt63Threadsafe(b *testing.B) {
@@ -405,3 +460,30 @@ func BenchmarkPerm30(b *testing.B) {
r.Perm(30)
}
}
+
+func BenchmarkRead3(b *testing.B) {
+ r := New(NewSource(1))
+ buf := make([]byte, 3)
+ b.ResetTimer()
+ for n := b.N; n > 0; n-- {
+ r.Read(buf)
+ }
+}
+
+func BenchmarkRead64(b *testing.B) {
+ r := New(NewSource(1))
+ buf := make([]byte, 64)
+ b.ResetTimer()
+ for n := b.N; n > 0; n-- {
+ r.Read(buf)
+ }
+}
+
+func BenchmarkRead1000(b *testing.B) {
+ r := New(NewSource(1))
+ buf := make([]byte, 1000)
+ b.ResetTimer()
+ for n := b.N; n > 0; n-- {
+ r.Read(buf)
+ }
+}
diff --git a/libgo/go/math/rand/regress_test.go b/libgo/go/math/rand/regress_test.go
index 2b012af893c..9ae53574478 100644
--- a/libgo/go/math/rand/regress_test.go
+++ b/libgo/go/math/rand/regress_test.go
@@ -25,6 +25,7 @@ func TestRegress(t *testing.T) {
var int32s = []int32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1}
var int64s = []int64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1}
var permSizes = []int{0, 1, 5, 8, 9, 10, 16}
+ var readBufferSizes = []int{1, 7, 8, 9, 10}
r := New(NewSource(0))
rv := reflect.ValueOf(r)
@@ -40,9 +41,6 @@ func TestRegress(t *testing.T) {
if mt.NumOut() == 0 {
continue
}
- if mt.NumOut() != 1 {
- t.Fatalf("unexpected result count for r.%s", m.Name)
- }
r.Seed(0)
for repeat := 0; repeat < 20; repeat++ {
var args []reflect.Value
@@ -74,14 +72,25 @@ func TestRegress(t *testing.T) {
case reflect.Int64:
x = int64s[repeat%len(int64s)]
+
+ case reflect.Slice:
+ if m.Name == "Read" {
+ n := readBufferSizes[repeat%len(readBufferSizes)]
+ x = make([]byte, n)
+ }
}
argstr = fmt.Sprint(x)
args = append(args, reflect.ValueOf(x))
}
- out := mv.Call(args)[0].Interface()
+
+ var out interface{}
+ out = mv.Call(args)[0].Interface()
if m.Name == "Int" || m.Name == "Intn" {
out = int64(out.(int))
}
+ if m.Name == "Read" {
+ out = args[0].Interface().([]byte)
+ }
if *printgolden {
var val string
big := int64(1 << 60)
@@ -332,24 +341,44 @@ var regressGolden = []interface{}{
[]int{2, 1, 7, 0, 6, 3, 4, 5}, // Perm(8)
[]int{8, 7, 5, 3, 4, 6, 0, 1, 2}, // Perm(9)
[]int{1, 0, 2, 5, 7, 6, 9, 8, 3, 4}, // Perm(10)
- uint32(4059586549), // Uint32()
- uint32(1052117029), // Uint32()
- uint32(2817310706), // Uint32()
- uint32(233405013), // Uint32()
- uint32(1578775030), // Uint32()
- uint32(1243308993), // Uint32()
- uint32(826517535), // Uint32()
- uint32(2814630155), // Uint32()
- uint32(3853314576), // Uint32()
- uint32(718781857), // Uint32()
- uint32(1239465936), // Uint32()
- uint32(3876658295), // Uint32()
- uint32(3649778518), // Uint32()
- uint32(1172727096), // Uint32()
- uint32(2615979505), // Uint32()
- uint32(1089444252), // Uint32()
- uint32(3327114623), // Uint32()
- uint32(75079301), // Uint32()
- uint32(3380456901), // Uint32()
- uint32(3433369789), // Uint32()
+ []byte{0x1}, // Read([0])
+ []byte{0xc0, 0x41, 0xd3, 0xff, 0x12, 0x4, 0x5b}, // Read([0 0 0 0 0 0 0])
+ []byte{0x73, 0xc8, 0x6e, 0x4f, 0xf9, 0x5f, 0xf6, 0x62}, // Read([0 0 0 0 0 0 0 0])
+ []byte{0x4a, 0x2d, 0xb, 0x75, 0xfb, 0x18, 0xd, 0xaf, 0x48}, // Read([0 0 0 0 0 0 0 0 0])
+ []byte{0x39, 0x46, 0x51, 0x85, 0xf, 0xd4, 0xa1, 0x78, 0x89, 0x2e}, // Read([0 0 0 0 0 0 0 0 0 0])
+ []byte{0x51}, // Read([0])
+ []byte{0x4e, 0xe2, 0xd3, 0xd0, 0xd0, 0xde, 0x6b}, // Read([0 0 0 0 0 0 0])
+ []byte{0xf8, 0xf9, 0xb4, 0x4c, 0xe8, 0x5f, 0xf0, 0x44}, // Read([0 0 0 0 0 0 0 0])
+ []byte{0x3b, 0xbf, 0x85, 0x7a, 0xab, 0x99, 0xc5, 0xb2, 0x52}, // Read([0 0 0 0 0 0 0 0 0])
+ []byte{0xa8, 0xae, 0xb7, 0x9e, 0xf8, 0x56, 0xf6, 0x59, 0xc1, 0x8f}, // Read([0 0 0 0 0 0 0 0 0 0])
+ []byte{0xc7}, // Read([0])
+ []byte{0x5f, 0x67, 0xcf, 0xe2, 0x42, 0xcf, 0x3c}, // Read([0 0 0 0 0 0 0])
+ []byte{0xc3, 0x54, 0xf3, 0xed, 0xe2, 0xd6, 0xbe, 0xcc}, // Read([0 0 0 0 0 0 0 0])
+ []byte{0x6a, 0x9f, 0x4a, 0x57, 0x8b, 0xcb, 0x9e, 0xf2, 0xd4}, // Read([0 0 0 0 0 0 0 0 0])
+ []byte{0x6d, 0x29, 0x97, 0x61, 0xea, 0x9e, 0x4f, 0x5a, 0xa6, 0xae}, // Read([0 0 0 0 0 0 0 0 0 0])
+ []byte{0xaa}, // Read([0])
+ []byte{0x20, 0xef, 0xcd, 0x6c, 0xea, 0x84, 0xb6}, // Read([0 0 0 0 0 0 0])
+ []byte{0x92, 0x5e, 0x60, 0x7b, 0xe0, 0x63, 0x71, 0x6f}, // Read([0 0 0 0 0 0 0 0])
+ []byte{0x4, 0x5c, 0x3f, 0x0, 0xf, 0x8a, 0x79, 0x6b, 0xce}, // Read([0 0 0 0 0 0 0 0 0])
+ []byte{0xaa, 0xca, 0xee, 0xdf, 0xad, 0x5b, 0x50, 0x66, 0x64, 0xe8}, // Read([0 0 0 0 0 0 0 0 0 0])
+ uint32(4059586549), // Uint32()
+ uint32(1052117029), // Uint32()
+ uint32(2817310706), // Uint32()
+ uint32(233405013), // Uint32()
+ uint32(1578775030), // Uint32()
+ uint32(1243308993), // Uint32()
+ uint32(826517535), // Uint32()
+ uint32(2814630155), // Uint32()
+ uint32(3853314576), // Uint32()
+ uint32(718781857), // Uint32()
+ uint32(1239465936), // Uint32()
+ uint32(3876658295), // Uint32()
+ uint32(3649778518), // Uint32()
+ uint32(1172727096), // Uint32()
+ uint32(2615979505), // Uint32()
+ uint32(1089444252), // Uint32()
+ uint32(3327114623), // Uint32()
+ uint32(75079301), // Uint32()
+ uint32(3380456901), // Uint32()
+ uint32(3433369789), // Uint32()
}
diff --git a/libgo/go/math/sqrt.go b/libgo/go/math/sqrt.go
index 215d6485442..86c04523478 100644
--- a/libgo/go/math/sqrt.go
+++ b/libgo/go/math/sqrt.go
@@ -114,7 +114,7 @@ func sqrt(x float64) float64 {
// normalize x
exp := int((ix >> shift) & mask)
if exp == 0 { // subnormal x
- for ix&1<<shift == 0 {
+ for ix&(1<<shift) == 0 {
ix <<= 1
exp--
}