Commit 15040c11 authored by Russ Cox's avatar Russ Cox

cmd/dist: copy needed packages from standard library during bootstrap

This allows use of newer math/big (and later debug/pe)
without maintaining a vendored copy somewhere in cmd.

Use for math/big, deleting cmd/compile/internal/big.

Change-Id: I2bffa7a9ef115015be29fafdb02acc3e7a665d11
Reviewed-on: https://go-review.googlesource.com/31010Reviewed-by: default avatarMinux Ma <minux@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent f444b48f
...@@ -506,9 +506,7 @@ func formatReplace(in string, f func(i int, s string) string) string { ...@@ -506,9 +506,7 @@ func formatReplace(in string, f func(i int, s string) string) string {
// blacklistedPackages is the set of packages which can // blacklistedPackages is the set of packages which can
// be ignored. // be ignored.
var blacklistedPackages = map[string]bool{ var blacklistedPackages = map[string]bool{}
"cmd/compile/internal/big": true,
}
// blacklistedFunctions is the set of functions which may have // blacklistedFunctions is the set of functions which may have
// format-like arguments but which don't do any formatting and // format-like arguments but which don't do any formatting and
...@@ -537,7 +535,7 @@ func init() { ...@@ -537,7 +535,7 @@ func init() {
// To print out a new table, run: go test -run Formats -v. // To print out a new table, run: go test -run Formats -v.
var knownFormats = map[string]string{ var knownFormats = map[string]string{
"*bytes.Buffer %s": "", "*bytes.Buffer %s": "",
"*cmd/compile/internal/big.Int %#x": "", "*math/big.Int %#x": "",
"*cmd/compile/internal/gc.Bits %v": "", "*cmd/compile/internal/gc.Bits %v": "",
"*cmd/compile/internal/gc.Field %p": "", "*cmd/compile/internal/gc.Field %p": "",
"*cmd/compile/internal/gc.Field %v": "", "*cmd/compile/internal/gc.Field %v": "",
......
// generated by stringer -type=Accuracy; DO NOT EDIT
package big
import "fmt"
const _Accuracy_name = "BelowExactAbove"
var _Accuracy_index = [...]uint8{0, 5, 10, 15}
func (i Accuracy) String() string {
i -= -1
if i < 0 || i+1 >= Accuracy(len(_Accuracy_index)) {
return fmt.Sprintf("Accuracy(%d)", i+-1)
}
return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]]
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file provides Go implementations of elementary multi-precision
// arithmetic operations on word vectors. Needed for platforms without
// assembly implementations of these routines.
package big
// A Word represents a single digit of a multi-precision unsigned integer.
type Word uintptr
const (
// Compute the size _S of a Word in bytes.
_m = ^Word(0)
_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
_S = 1 << _logS
_W = _S << 3 // word size in bits
_B = 1 << _W // digit base
_M = _B - 1 // digit mask
_W2 = _W / 2 // half word size in bits
_B2 = 1 << _W2 // half digit base
_M2 = _B2 - 1 // half digit mask
)
// ----------------------------------------------------------------------------
// Elementary operations on words
//
// These operations are used by the vector operations below.
// z1<<_W + z0 = x+y+c, with c == 0 or 1
func addWW_g(x, y, c Word) (z1, z0 Word) {
yc := y + c
z0 = x + yc
if z0 < x || yc < y {
z1 = 1
}
return
}
// z1<<_W + z0 = x-y-c, with c == 0 or 1
func subWW_g(x, y, c Word) (z1, z0 Word) {
yc := y + c
z0 = x - yc
if z0 > x || yc < y {
z1 = 1
}
return
}
// z1<<_W + z0 = x*y
// Adapted from Warren, Hacker's Delight, p. 132.
func mulWW_g(x, y Word) (z1, z0 Word) {
x0 := x & _M2
x1 := x >> _W2
y0 := y & _M2
y1 := y >> _W2
w0 := x0 * y0
t := x1*y0 + w0>>_W2
w1 := t & _M2
w2 := t >> _W2
w1 += x0 * y1
z1 = x1*y1 + w2 + w1>>_W2
z0 = x * y
return
}
// z1<<_W + z0 = x*y + c
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
z1, zz0 := mulWW_g(x, y)
if z0 = zz0 + c; z0 < zz0 {
z1++
}
return
}
// Length of x in bits.
func bitLen_g(x Word) (n int) {
for ; x >= 0x8000; x >>= 16 {
n += 16
}
if x >= 0x80 {
x >>= 8
n += 8
}
if x >= 0x8 {
x >>= 4
n += 4
}
if x >= 0x2 {
x >>= 2
n += 2
}
if x >= 0x1 {
n++
}
return
}
// log2 computes the integer binary logarithm of x.
// The result is the integer n for which 2^n <= x < 2^(n+1).
// If x == 0, the result is -1.
func log2(x Word) int {
return bitLen(x) - 1
}
// nlz returns the number of leading zeros in x.
func nlz(x Word) uint {
return uint(_W - bitLen(x))
}
// nlz64 returns the number of leading zeros in x.
func nlz64(x uint64) uint {
switch _W {
case 32:
w := x >> 32
if w == 0 {
return 32 + nlz(Word(x))
}
return nlz(Word(w))
case 64:
return nlz(Word(x))
}
panic("unreachable")
}
// q = (u1<<_W + u0 - r)/y
// Adapted from Warren, Hacker's Delight, p. 152.
func divWW_g(u1, u0, v Word) (q, r Word) {
if u1 >= v {
return 1<<_W - 1, 1<<_W - 1
}
s := nlz(v)
v <<= s
vn1 := v >> _W2
vn0 := v & _M2
un32 := u1<<s | u0>>(_W-s)
un10 := u0 << s
un1 := un10 >> _W2
un0 := un10 & _M2
q1 := un32 / vn1
rhat := un32 - q1*vn1
for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
q1--
rhat += vn1
if rhat >= _B2 {
break
}
}
un21 := un32*_B2 + un1 - q1*v
q0 := un21 / vn1
rhat = un21 - q0*vn1
for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
q0--
rhat += vn1
if rhat >= _B2 {
break
}
}
return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
}
// Keep for performance debugging.
// Using addWW_g is likely slower.
const use_addWW_g = false
// The resulting carry c is either 0 or 1.
func addVV_g(z, x, y []Word) (c Word) {
if use_addWW_g {
for i := range z {
c, z[i] = addWW_g(x[i], y[i], c)
}
return
}
for i, xi := range x[:len(z)] {
yi := y[i]
zi := xi + yi + c
z[i] = zi
// see "Hacker's Delight", section 2-12 (overflow detection)
c = (xi&yi | (xi|yi)&^zi) >> (_W - 1)
}
return
}
// The resulting carry c is either 0 or 1.
func subVV_g(z, x, y []Word) (c Word) {
if use_addWW_g {
for i := range z {
c, z[i] = subWW_g(x[i], y[i], c)
}
return
}
for i, xi := range x[:len(z)] {
yi := y[i]
zi := xi - yi - c
z[i] = zi
// see "Hacker's Delight", section 2-12 (overflow detection)
c = (yi&^xi | (yi|^xi)&zi) >> (_W - 1)
}
return
}
// The resulting carry c is either 0 or 1.
func addVW_g(z, x []Word, y Word) (c Word) {
if use_addWW_g {
c = y
for i := range z {
c, z[i] = addWW_g(x[i], c, 0)
}
return
}
c = y
for i, xi := range x[:len(z)] {
zi := xi + c
z[i] = zi
c = xi &^ zi >> (_W - 1)
}
return
}
func subVW_g(z, x []Word, y Word) (c Word) {
if use_addWW_g {
c = y
for i := range z {
c, z[i] = subWW_g(x[i], c, 0)
}
return
}
c = y
for i, xi := range x[:len(z)] {
zi := xi - c
z[i] = zi
c = (zi &^ xi) >> (_W - 1)
}
return
}
func shlVU_g(z, x []Word, s uint) (c Word) {
if n := len(z); n > 0 {
ŝ := _W - s
w1 := x[n-1]
c = w1 >> ŝ
for i := n - 1; i > 0; i-- {
w := w1
w1 = x[i-1]
z[i] = w<<s | w1>>ŝ
}
z[0] = w1 << s
}
return
}
func shrVU_g(z, x []Word, s uint) (c Word) {
if n := len(z); n > 0 {
ŝ := _W - s
w1 := x[0]
c = w1 << ŝ
for i := 0; i < n-1; i++ {
w := w1
w1 = x[i+1]
z[i] = w>>s | w1<<ŝ
}
z[n-1] = w1 >> s
}
return
}
func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
c = r
for i := range z {
c, z[i] = mulAddWWW_g(x[i], y, c)
}
return
}
// TODO(gri) Remove use of addWW_g here and then we can remove addWW_g and subWW_g.
func addMulVVW_g(z, x []Word, y Word) (c Word) {
for i := range z {
z1, z0 := mulAddWWW_g(x[i], y, z[i])
c, z[i] = addWW_g(z0, c, 0)
c += z1
}
return
}
func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
r = xn
for i := len(z) - 1; i >= 0; i-- {
z[i], r = divWW_g(r, x[i], y)
}
return
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
func mulWW(x, y Word) (z1, z0 Word) {
return mulWW_g(x, y)
}
func divWW(x1, x0, y Word) (q, r Word) {
return divWW_g(x1, x0, y)
}
func addVV(z, x, y []Word) (c Word) {
return addVV_g(z, x, y)
}
func subVV(z, x, y []Word) (c Word) {
return subVV_g(z, x, y)
}
func addVW(z, x []Word, y Word) (c Word) {
return addVW_g(z, x, y)
}
func subVW(z, x []Word, y Word) (c Word) {
return subVW_g(z, x, y)
}
func shlVU(z, x []Word, s uint) (c Word) {
return shlVU_g(z, x, s)
}
func shrVU(z, x []Word, s uint) (c Word) {
return shrVU_g(z, x, s)
}
func mulAddVWW(z, x []Word, y, r Word) (c Word) {
return mulAddVWW_g(z, x, y, r)
}
func addMulVVW(z, x []Word, y Word) (c Word) {
return addMulVVW_g(z, x, y)
}
func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
return divWVW_g(z, xn, x, y)
}
func bitLen(x Word) (n int) {
return bitLen_g(x)
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"fmt"
"math/rand"
"testing"
)
type funWW func(x, y, c Word) (z1, z0 Word)
type argWW struct {
x, y, c, z1, z0 Word
}
var sumWW = []argWW{
{0, 0, 0, 0, 0},
{0, 1, 0, 0, 1},
{0, 0, 1, 0, 1},
{0, 1, 1, 0, 2},
{12345, 67890, 0, 0, 80235},
{12345, 67890, 1, 0, 80236},
{_M, 1, 0, 1, 0},
{_M, 0, 1, 1, 0},
{_M, 1, 1, 1, 1},
{_M, _M, 0, 1, _M - 1},
{_M, _M, 1, 1, _M},
}
func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
z1, z0 := f(a.x, a.y, a.c)
if z1 != a.z1 || z0 != a.z0 {
t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
}
}
func TestFunWW(t *testing.T) {
for _, a := range sumWW {
arg := a
testFunWW(t, "addWW_g", addWW_g, arg)
arg = argWW{a.y, a.x, a.c, a.z1, a.z0}
testFunWW(t, "addWW_g symmetric", addWW_g, arg)
arg = argWW{a.z0, a.x, a.c, a.z1, a.y}
testFunWW(t, "subWW_g", subWW_g, arg)
arg = argWW{a.z0, a.y, a.c, a.z1, a.x}
testFunWW(t, "subWW_g symmetric", subWW_g, arg)
}
}
type funVV func(z, x, y []Word) (c Word)
type argVV struct {
z, x, y nat
c Word
}
var sumVV = []argVV{
{},
{nat{0}, nat{0}, nat{0}, 0},
{nat{1}, nat{1}, nat{0}, 0},
{nat{0}, nat{_M}, nat{1}, 1},
{nat{80235}, nat{12345}, nat{67890}, 0},
{nat{_M - 1}, nat{_M}, nat{_M}, 1},
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1},
{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0},
{nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1},
}
func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
z := make(nat, len(a.z))
c := f(z, a.x, a.y)
for i, zi := range z {
if zi != a.z[i] {
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
break
}
}
if c != a.c {
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
}
}
func TestFunVV(t *testing.T) {
for _, a := range sumVV {
arg := a
testFunVV(t, "addVV_g", addVV_g, arg)
testFunVV(t, "addVV", addVV, arg)
arg = argVV{a.z, a.y, a.x, a.c}
testFunVV(t, "addVV_g symmetric", addVV_g, arg)
testFunVV(t, "addVV symmetric", addVV, arg)
arg = argVV{a.x, a.z, a.y, a.c}
testFunVV(t, "subVV_g", subVV_g, arg)
testFunVV(t, "subVV", subVV, arg)
arg = argVV{a.y, a.z, a.x, a.c}
testFunVV(t, "subVV_g symmetric", subVV_g, arg)
testFunVV(t, "subVV symmetric", subVV, arg)
}
}
// Always the same seed for reproducible results.
var rnd = rand.New(rand.NewSource(0))
func rndW() Word {
return Word(rnd.Int63()<<1 | rnd.Int63n(2))
}
func rndV(n int) []Word {
v := make([]Word, n)
for i := range v {
v[i] = rndW()
}
return v
}
var benchSizes = []int{1, 2, 3, 4, 5, 1e1, 1e2, 1e3, 1e4, 1e5}
func BenchmarkAddVV(b *testing.B) {
for _, n := range benchSizes {
x := rndV(n)
y := rndV(n)
z := make([]Word, n)
b.Run(fmt.Sprint(n), func(b *testing.B) {
b.SetBytes(int64(n * _W))
for i := 0; i < b.N; i++ {
addVV(z, x, y)
}
})
}
}
type funVW func(z, x []Word, y Word) (c Word)
type argVW struct {
z, x nat
y Word
c Word
}
var sumVW = []argVW{
{},
{nil, nil, 2, 2},
{nat{0}, nat{0}, 0, 0},
{nat{1}, nat{0}, 1, 0},
{nat{1}, nat{1}, 0, 0},
{nat{0}, nat{_M}, 1, 1},
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
{nat{585}, nat{314}, 271, 0},
}
var lshVW = []argVW{
{},
{nat{0}, nat{0}, 0, 0},
{nat{0}, nat{0}, 1, 0},
{nat{0}, nat{0}, 20, 0},
{nat{_M}, nat{_M}, 0, 0},
{nat{_M << 1 & _M}, nat{_M}, 1, 1},
{nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)},
{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
{nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1},
{nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)},
}
var rshVW = []argVW{
{},
{nat{0}, nat{0}, 0, 0},
{nat{0}, nat{0}, 1, 0},
{nat{0}, nat{0}, 20, 0},
{nat{_M}, nat{_M}, 0, 0},
{nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M},
{nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M},
{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
{nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M},
{nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M},
}
func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
z := make(nat, len(a.z))
c := f(z, a.x, a.y)
for i, zi := range z {
if zi != a.z[i] {
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
break
}
}
if c != a.c {
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
}
}
func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW {
return func(z, x []Word, s Word) (c Word) {
return f(z, x, uint(s))
}
}
func TestFunVW(t *testing.T) {
for _, a := range sumVW {
arg := a
testFunVW(t, "addVW_g", addVW_g, arg)
testFunVW(t, "addVW", addVW, arg)
arg = argVW{a.x, a.z, a.y, a.c}
testFunVW(t, "subVW_g", subVW_g, arg)
testFunVW(t, "subVW", subVW, arg)
}
shlVW_g := makeFunVW(shlVU_g)
shlVW := makeFunVW(shlVU)
for _, a := range lshVW {
arg := a
testFunVW(t, "shlVU_g", shlVW_g, arg)
testFunVW(t, "shlVU", shlVW, arg)
}
shrVW_g := makeFunVW(shrVU_g)
shrVW := makeFunVW(shrVU)
for _, a := range rshVW {
arg := a
testFunVW(t, "shrVU_g", shrVW_g, arg)
testFunVW(t, "shrVU", shrVW, arg)
}
}
func BenchmarkAddVW(b *testing.B) {
for _, n := range benchSizes {
x := rndV(n)
y := rndW()
z := make([]Word, n)
b.Run(fmt.Sprint(n), func(b *testing.B) {
b.SetBytes(int64(n * _S))
for i := 0; i < b.N; i++ {
addVW(z, x, y)
}
})
}
}
type funVWW func(z, x []Word, y, r Word) (c Word)
type argVWW struct {
z, x nat
y, r Word
c Word
}
var prodVWW = []argVWW{
{},
{nat{0}, nat{0}, 0, 0, 0},
{nat{991}, nat{0}, 0, 991, 0},
{nat{0}, nat{_M}, 0, 0, 0},
{nat{991}, nat{_M}, 0, 991, 0},
{nat{0}, nat{0}, _M, 0, 0},
{nat{991}, nat{0}, _M, 991, 0},
{nat{1}, nat{1}, 1, 0, 0},
{nat{992}, nat{1}, 1, 991, 0},
{nat{22793}, nat{991}, 23, 0, 0},
{nat{22800}, nat{991}, 23, 7, 0},
{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0},
{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0},
{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0},
{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0},
{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)},
{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)},
{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)},
{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)},
{nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
}
func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
z := make(nat, len(a.z))
c := f(z, a.x, a.y, a.r)
for i, zi := range z {
if zi != a.z[i] {
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
break
}
}
if c != a.c {
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
}
}
// TODO(gri) mulAddVWW and divWVW are symmetric operations but
// their signature is not symmetric. Try to unify.
type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word)
type argWVW struct {
z nat
xn Word
x nat
y Word
r Word
}
func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
z := make(nat, len(a.z))
r := f(z, a.xn, a.x, a.y)
for i, zi := range z {
if zi != a.z[i] {
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
break
}
}
if r != a.r {
t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
}
}
func TestFunVWW(t *testing.T) {
for _, a := range prodVWW {
arg := a
testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg)
testFunVWW(t, "mulAddVWW", mulAddVWW, arg)
if a.y != 0 && a.r < a.y {
arg := argWVW{a.x, a.c, a.z, a.y, a.r}
testFunWVW(t, "divWVW_g", divWVW_g, arg)
testFunWVW(t, "divWVW", divWVW, arg)
}
}
}
var mulWWTests = []struct {
x, y Word
q, r Word
}{
{_M, _M, _M - 1, 1},
// 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
}
func TestMulWW(t *testing.T) {
for i, test := range mulWWTests {
q, r := mulWW_g(test.x, test.y)
if q != test.q || r != test.r {
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
}
}
}
var mulAddWWWTests = []struct {
x, y, c Word
q, r Word
}{
// TODO(agl): These will only work on 64-bit platforms.
// {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
// {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
{_M, _M, 0, _M - 1, 1},
{_M, _M, _M, _M, 0},
}
func TestMulAddWWW(t *testing.T) {
for i, test := range mulAddWWWTests {
q, r := mulAddWWW_g(test.x, test.y, test.c)
if q != test.q || r != test.r {
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
}
}
}
func BenchmarkAddMulVVW(b *testing.B) {
for _, n := range benchSizes {
x := rndV(n)
y := rndW()
z := make([]Word, n)
b.Run(fmt.Sprint(n), func(b *testing.B) {
b.SetBytes(int64(n * _W))
for i := 0; i < b.N; i++ {
addMulVVW(z, x, y)
}
})
}
}
func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
for i := 0; i <= _W; i++ {
x := Word(1) << uint(i-1) // i == 0 => x == 0
n := f(x)
if n != i {
t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
}
}
}
func TestWordBitLen(t *testing.T) {
testWordBitLen(t, "bitLen", bitLen)
testWordBitLen(t, "bitLen_g", bitLen_g)
}
// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
func BenchmarkBitLen(b *testing.B) {
// Individual bitLen tests. Numbers chosen to examine both sides
// of powers-of-two boundaries.
for _, nbits := range []uint{0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 31} {
testword := Word((uint64(1) << nbits) - 1)
b.Run(fmt.Sprint(nbits), func(b *testing.B) {
for i := 0; i < b.N; i++ {
bitLen(testword)
}
})
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements the Bits type used for testing Float operations
// via an independent (albeit slower) representations for floating-point
// numbers.
package big
import (
"fmt"
"sort"
"testing"
)
// A Bits value b represents a finite floating-point number x of the form
//
// x = 2**b[0] + 2**b[1] + ... 2**b[len(b)-1]
//
// The order of slice elements is not significant. Negative elements may be
// used to form fractions. A Bits value is normalized if each b[i] occurs at
// most once. For instance Bits{0, 0, 1} is not normalized but represents the
// same floating-point number as Bits{2}, which is normalized. The zero (nil)
// value of Bits is a ready to use Bits value and represents the value 0.
type Bits []int
func (x Bits) add(y Bits) Bits {
return append(x, y...)
}
func (x Bits) mul(y Bits) Bits {
var p Bits
for _, x := range x {
for _, y := range y {
p = append(p, x+y)
}
}
return p
}
func TestMulBits(t *testing.T) {
for _, test := range []struct {
x, y, want Bits
}{
{nil, nil, nil},
{Bits{}, Bits{}, nil},
{Bits{0}, Bits{0}, Bits{0}},
{Bits{0}, Bits{1}, Bits{1}},
{Bits{1}, Bits{1, 2, 3}, Bits{2, 3, 4}},
{Bits{-1}, Bits{1}, Bits{0}},
{Bits{-10, -1, 0, 1, 10}, Bits{1, 2, 3}, Bits{-9, -8, -7, 0, 1, 2, 1, 2, 3, 2, 3, 4, 11, 12, 13}},
} {
got := fmt.Sprintf("%v", test.x.mul(test.y))
want := fmt.Sprintf("%v", test.want)
if got != want {
t.Errorf("%v * %v = %s; want %s", test.x, test.y, got, want)
}
}
}
// norm returns the normalized bits for x: It removes multiple equal entries
// by treating them as an addition (e.g., Bits{5, 5} => Bits{6}), and it sorts
// the result list for reproducible results.
func (x Bits) norm() Bits {
m := make(map[int]bool)
for _, b := range x {
for m[b] {
m[b] = false
b++
}
m[b] = true
}
var z Bits
for b, set := range m {
if set {
z = append(z, b)
}
}
sort.Ints([]int(z))
return z
}
func TestNormBits(t *testing.T) {
for _, test := range []struct {
x, want Bits
}{
{nil, nil},
{Bits{}, Bits{}},
{Bits{0}, Bits{0}},
{Bits{0, 0}, Bits{1}},
{Bits{3, 1, 1}, Bits{2, 3}},
{Bits{10, 9, 8, 7, 6, 6}, Bits{11}},
} {
got := fmt.Sprintf("%v", test.x.norm())
want := fmt.Sprintf("%v", test.want)
if got != want {
t.Errorf("normBits(%v) = %s; want %s", test.x, got, want)
}
}
}
// round returns the Float value corresponding to x after rounding x
// to prec bits according to mode.
func (x Bits) round(prec uint, mode RoundingMode) *Float {
x = x.norm()
// determine range
var min, max int
for i, b := range x {
if i == 0 || b < min {
min = b
}
if i == 0 || b > max {
max = b
}
}
prec0 := uint(max + 1 - min)
if prec >= prec0 {
return x.Float()
}
// prec < prec0
// determine bit 0, rounding, and sticky bit, and result bits z
var bit0, rbit, sbit uint
var z Bits
r := max - int(prec)
for _, b := range x {
switch {
case b == r:
rbit = 1
case b < r:
sbit = 1
default:
// b > r
if b == r+1 {
bit0 = 1
}
z = append(z, b)
}
}
// round
f := z.Float() // rounded to zero
if mode == ToNearestAway {
panic("not yet implemented")
}
if mode == ToNearestEven && rbit == 1 && (sbit == 1 || sbit == 0 && bit0 != 0) || mode == AwayFromZero {
// round away from zero
f.SetMode(ToZero).SetPrec(prec)
f.Add(f, Bits{int(r) + 1}.Float())
}
return f
}
// Float returns the *Float z of the smallest possible precision such that
// z = sum(2**bits[i]), with i = range bits. If multiple bits[i] are equal,
// they are added: Bits{0, 1, 0}.Float() == 2**0 + 2**1 + 2**0 = 4.
func (bits Bits) Float() *Float {
// handle 0
if len(bits) == 0 {
return new(Float)
}
// len(bits) > 0
// determine lsb exponent
var min int
for i, b := range bits {
if i == 0 || b < min {
min = b
}
}
// create bit pattern
x := NewInt(0)
for _, b := range bits {
badj := b - min
// propagate carry if necessary
for x.Bit(badj) != 0 {
x.SetBit(x, badj, 0)
badj++
}
x.SetBit(x, badj, 1)
}
// create corresponding float
z := new(Float).SetInt(x) // normalized
if e := int64(z.exp) + int64(min); MinExp <= e && e <= MaxExp {
z.exp = int32(e)
} else {
// this should never happen for our test cases
panic("exponent out of range")
}
return z
}
func TestFromBits(t *testing.T) {
for _, test := range []struct {
bits Bits
want string
}{
// all different bit numbers
{nil, "0"},
{Bits{0}, "0x.8p+1"},
{Bits{1}, "0x.8p+2"},
{Bits{-1}, "0x.8p+0"},
{Bits{63}, "0x.8p+64"},
{Bits{33, -30}, "0x.8000000000000001p+34"},
{Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p+256"},
// multiple equal bit numbers
{Bits{0, 0}, "0x.8p+2"},
{Bits{0, 0, 0, 0}, "0x.8p+3"},
{Bits{0, 1, 0}, "0x.8p+3"},
{append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p+5" /* 17 */},
} {
f := test.bits.Float()
if got := f.Text('p', 0); got != test.want {
t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
}
}
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file prints execution times for the Mul benchmark
// given different Karatsuba thresholds. The result may be
// used to manually fine-tune the threshold constant. The
// results are somewhat fragile; use repeated runs to get
// a clear picture.
// Usage: go test -run=TestCalibrate -calibrate
package big
import (
"flag"
"fmt"
"testing"
"time"
)
var calibrate = flag.Bool("calibrate", false, "run calibration test")
func karatsubaLoad(b *testing.B) {
BenchmarkMul(b)
}
// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
// given Karatsuba threshold th.
func measureKaratsuba(th int) time.Duration {
th, karatsubaThreshold = karatsubaThreshold, th
res := testing.Benchmark(karatsubaLoad)
karatsubaThreshold = th
return time.Duration(res.NsPerOp())
}
func computeThresholds() {
fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
fmt.Printf("(run repeatedly for good results)\n")
// determine Tk, the work load execution time using basic multiplication
Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
fmt.Printf("Tb = %10s\n", Tb)
// thresholds
th := 4
th1 := -1
th2 := -1
var deltaOld time.Duration
for count := -1; count != 0 && th < 128; count-- {
// determine Tk, the work load execution time using Karatsuba multiplication
Tk := measureKaratsuba(th)
// improvement over Tb
delta := (Tb - Tk) * 100 / Tb
fmt.Printf("th = %3d Tk = %10s %4d%%", th, Tk, delta)
// determine break-even point
if Tk < Tb && th1 < 0 {
th1 = th
fmt.Print(" break-even point")
}
// determine diminishing return
if 0 < delta && delta < deltaOld && th2 < 0 {
th2 = th
fmt.Print(" diminishing return")
}
deltaOld = delta
fmt.Println()
// trigger counter
if th1 >= 0 && th2 >= 0 && count < 0 {
count = 10 // this many extra measurements after we got both thresholds
}
th++
}
}
func TestCalibrate(t *testing.T) {
if *calibrate {
computeThresholds()
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements multi-precision decimal numbers.
// The implementation is for float to decimal conversion only;
// not general purpose use.
// The only operations are precise conversion from binary to
// decimal and rounding.
//
// The key observation and some code (shr) is borrowed from
// strconv/decimal.go: conversion of binary fractional values can be done
// precisely in multi-precision decimal because 2 divides 10 (required for
// >> of mantissa); but conversion of decimal floating-point values cannot
// be done precisely in binary representation.
//
// In contrast to strconv/decimal.go, only right shift is implemented in
// decimal format - left shift can be done precisely in binary format.
package big
// A decimal represents an unsigned floating-point number in decimal representation.
// The value of a non-zero decimal d is d.mant * 10**d.exp with 0.5 <= d.mant < 1,
// with the most-significant mantissa digit at index 0. For the zero decimal, the
// mantissa length and exponent are 0.
// The zero value for decimal represents a ready-to-use 0.0.
type decimal struct {
mant []byte // mantissa ASCII digits, big-endian
exp int // exponent
}
// at returns the i'th mantissa digit, starting with the most significant digit at 0.
func (d *decimal) at(i int) byte {
if 0 <= i && i < len(d.mant) {
return d.mant[i]
}
return '0'
}
// Maximum shift amount that can be done in one pass without overflow.
// A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
const maxShift = _W - 4
// TODO(gri) Since we know the desired decimal precision when converting
// a floating-point number, we may be able to limit the number of decimal
// digits that need to be computed by init by providing an additional
// precision argument and keeping track of when a number was truncated early
// (equivalent of "sticky bit" in binary rounding).
// TODO(gri) Along the same lines, enforce some limit to shift magnitudes
// to avoid "infinitely" long running conversions (until we run out of space).
// Init initializes x to the decimal representation of m << shift (for
// shift >= 0), or m >> -shift (for shift < 0).
func (x *decimal) init(m nat, shift int) {
// special case 0
if len(m) == 0 {
x.mant = x.mant[:0]
x.exp = 0
return
}
// Optimization: If we need to shift right, first remove any trailing
// zero bits from m to reduce shift amount that needs to be done in
// decimal format (since that is likely slower).
if shift < 0 {
ntz := m.trailingZeroBits()
s := uint(-shift)
if s >= ntz {
s = ntz // shift at most ntz bits
}
m = nat(nil).shr(m, s)
shift += int(s)
}
// Do any shift left in binary representation.
if shift > 0 {
m = nat(nil).shl(m, uint(shift))
shift = 0
}
// Convert mantissa into decimal representation.
s := m.utoa(10)
n := len(s)
x.exp = n
// Trim trailing zeros; instead the exponent is tracking
// the decimal point independent of the number of digits.
for n > 0 && s[n-1] == '0' {
n--
}
x.mant = append(x.mant[:0], s[:n]...)
// Do any (remaining) shift right in decimal representation.
if shift < 0 {
for shift < -maxShift {
shr(x, maxShift)
shift += maxShift
}
shr(x, uint(-shift))
}
}
// shr implements x >> s, for s <= maxShift.
func shr(x *decimal, s uint) {
// Division by 1<<s using shift-and-subtract algorithm.
// pick up enough leading digits to cover first shift
r := 0 // read index
var n Word
for n>>s == 0 && r < len(x.mant) {
ch := Word(x.mant[r])
r++
n = n*10 + ch - '0'
}
if n == 0 {
// x == 0; shouldn't get here, but handle anyway
x.mant = x.mant[:0]
return
}
for n>>s == 0 {
r++
n *= 10
}
x.exp += 1 - r
// read a digit, write a digit
w := 0 // write index
for r < len(x.mant) {
ch := Word(x.mant[r])
r++
d := n >> s
n -= d << s
x.mant[w] = byte(d + '0')
w++
n = n*10 + ch - '0'
}
// write extra digits that still fit
for n > 0 && w < len(x.mant) {
d := n >> s
n -= d << s
x.mant[w] = byte(d + '0')
w++
n = n * 10
}
x.mant = x.mant[:w] // the number may be shorter (e.g. 1024 >> 10)
// append additional digits that didn't fit
for n > 0 {
d := n >> s
n -= d << s
x.mant = append(x.mant, byte(d+'0'))
n = n * 10
}
trim(x)
}
func (x *decimal) String() string {
if len(x.mant) == 0 {
return "0"
}
var buf []byte
switch {
case x.exp <= 0:
// 0.00ddd
buf = append(buf, "0."...)
buf = appendZeros(buf, -x.exp)
buf = append(buf, x.mant...)
case /* 0 < */ x.exp < len(x.mant):
// dd.ddd
buf = append(buf, x.mant[:x.exp]...)
buf = append(buf, '.')
buf = append(buf, x.mant[x.exp:]...)
default: // len(x.mant) <= x.exp
// ddd00
buf = append(buf, x.mant...)
buf = appendZeros(buf, x.exp-len(x.mant))
}
return string(buf)
}
// appendZeros appends n 0 digits to buf and returns buf.
func appendZeros(buf []byte, n int) []byte {
for ; n > 0; n-- {
buf = append(buf, '0')
}
return buf
}
// shouldRoundUp reports if x should be rounded up
// if shortened to n digits. n must be a valid index
// for x.mant.
func shouldRoundUp(x *decimal, n int) bool {
if x.mant[n] == '5' && n+1 == len(x.mant) {
// exactly halfway - round to even
return n > 0 && (x.mant[n-1]-'0')&1 != 0
}
// not halfway - digit tells all (x.mant has no trailing zeros)
return x.mant[n] >= '5'
}
// round sets x to (at most) n mantissa digits by rounding it
// to the nearest even value with n (or fever) mantissa digits.
// If n < 0, x remains unchanged.
func (x *decimal) round(n int) {
if n < 0 || n >= len(x.mant) {
return // nothing to do
}
if shouldRoundUp(x, n) {
x.roundUp(n)
} else {
x.roundDown(n)
}
}
func (x *decimal) roundUp(n int) {
if n < 0 || n >= len(x.mant) {
return // nothing to do
}
// 0 <= n < len(x.mant)
// find first digit < '9'
for n > 0 && x.mant[n-1] >= '9' {
n--
}
if n == 0 {
// all digits are '9's => round up to '1' and update exponent
x.mant[0] = '1' // ok since len(x.mant) > n
x.mant = x.mant[:1]
x.exp++
return
}
// n > 0 && x.mant[n-1] < '9'
x.mant[n-1]++
x.mant = x.mant[:n]
// x already trimmed
}
func (x *decimal) roundDown(n int) {
if n < 0 || n >= len(x.mant) {
return // nothing to do
}
x.mant = x.mant[:n]
trim(x)
}
// trim cuts off any trailing zeros from x's mantissa;
// they are meaningless for the value of x.
func trim(x *decimal) {
i := len(x.mant)
for i > 0 && x.mant[i-1] == '0' {
i--
}
x.mant = x.mant[:i]
if i == 0 {
x.exp = 0
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import "testing"
func TestDecimalString(t *testing.T) {
for _, test := range []struct {
x decimal
want string
}{
{want: "0"},
{decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
{decimal{[]byte("12345"), 0}, "0.12345"},
{decimal{[]byte("12345"), -3}, "0.00012345"},
{decimal{[]byte("12345"), +3}, "123.45"},
{decimal{[]byte("12345"), +10}, "1234500000"},
} {
if got := test.x.String(); got != test.want {
t.Errorf("%v == %s; want %s", test.x, got, test.want)
}
}
}
func TestDecimalInit(t *testing.T) {
for _, test := range []struct {
x Word
shift int
want string
}{
{0, 0, "0"},
{0, -100, "0"},
{0, 100, "0"},
{1, 0, "1"},
{1, 10, "1024"},
{1, 100, "1267650600228229401496703205376"},
{1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
{12345678, 8, "3160493568"},
{12345678, -8, "48225.3046875"},
{195312, 9, "99999744"},
{1953125, 9, "1000000000"},
} {
var d decimal
d.init(nat{test.x}.norm(), test.shift)
if got := d.String(); got != test.want {
t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
}
}
}
func TestDecimalRounding(t *testing.T) {
for _, test := range []struct {
x uint64
n int
down, even, up string
}{
{0, 0, "0", "0", "0"},
{0, 1, "0", "0", "0"},
{1, 0, "0", "0", "10"},
{5, 0, "0", "0", "10"},
{9, 0, "0", "10", "10"},
{15, 1, "10", "20", "20"},
{45, 1, "40", "40", "50"},
{95, 1, "90", "100", "100"},
{12344999, 4, "12340000", "12340000", "12350000"},
{12345000, 4, "12340000", "12340000", "12350000"},
{12345001, 4, "12340000", "12350000", "12350000"},
{23454999, 4, "23450000", "23450000", "23460000"},
{23455000, 4, "23450000", "23460000", "23460000"},
{23455001, 4, "23450000", "23460000", "23460000"},
{99994999, 4, "99990000", "99990000", "100000000"},
{99995000, 4, "99990000", "100000000", "100000000"},
{99999999, 4, "99990000", "100000000", "100000000"},
{12994999, 4, "12990000", "12990000", "13000000"},
{12995000, 4, "12990000", "13000000", "13000000"},
{12999999, 4, "12990000", "13000000", "13000000"},
} {
x := nat(nil).setUint64(test.x)
var d decimal
d.init(x, 0)
d.roundDown(test.n)
if got := d.String(); got != test.down {
t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
}
d.init(x, 0)
d.round(test.n)
if got := d.String(); got != test.even {
t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
}
d.init(x, 0)
d.roundUp(test.n)
if got := d.String(); got != test.up {
t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
}
}
}
var sink string
func BenchmarkDecimalConversion(b *testing.B) {
for i := 0; i < b.N; i++ {
for shift := -100; shift <= +100; shift++ {
var d decimal
d.init(natOne, shift)
sink = d.String()
}
}
}
// 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
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big_test
import (
"cmd/compile/internal/big"
"fmt"
)
// Use the classic continued fraction for e
// e = [1; 0, 1, 1, 2, 1, 1, ... 2n, 1, 1, ...]
// i.e., for the nth term, use
// 1 if n mod 3 != 1
// (n-1)/3 * 2 if n mod 3 == 1
func recur(n, lim int64) *big.Rat {
term := new(big.Rat)
if n%3 != 1 {
term.SetInt64(1)
} else {
term.SetInt64((n - 1) / 3 * 2)
}
if n > lim {
return term
}
// Directly initialize frac as the fractional
// inverse of the result of recur.
frac := new(big.Rat).Inv(recur(n+1, lim))
return term.Add(term, frac)
}
// This example demonstrates how to use big.Rat to compute the
// first 15 terms in the sequence of rational convergents for
// the constant e (base of natural logarithm).
func Example_eConvergents() {
for i := 1; i <= 15; i++ {
r := recur(0, int64(i))
// Print r both as a fraction and as a floating-point number.
// Since big.Rat implements fmt.Formatter, we can use %-13s to
// get a left-aligned string representation of the fraction.
fmt.Printf("%-13s = %s\n", r, r.FloatString(8))
}
// Output:
// 2/1 = 2.00000000
// 3/1 = 3.00000000
// 8/3 = 2.66666667
// 11/4 = 2.75000000
// 19/7 = 2.71428571
// 87/32 = 2.71875000
// 106/39 = 2.71794872
// 193/71 = 2.71830986
// 1264/465 = 2.71827957
// 1457/536 = 2.71828358
// 2721/1001 = 2.71828172
// 23225/8544 = 2.71828184
// 25946/9545 = 2.71828182
// 49171/18089 = 2.71828183
// 517656/190435 = 2.71828183
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big_test
import (
"cmd/compile/internal/big"
"fmt"
"log"
"math"
)
func ExampleRat_SetString() {
r := new(big.Rat)
r.SetString("355/113")
fmt.Println(r.FloatString(3))
// Output: 3.142
}
func ExampleInt_SetString() {
i := new(big.Int)
i.SetString("644", 8) // octal
fmt.Println(i)
// Output: 420
}
func ExampleRat_Scan() {
// The Scan function is rarely used directly;
// the fmt package recognizes it as an implementation of fmt.Scanner.
r := new(big.Rat)
_, err := fmt.Sscan("1.5000", r)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(r)
}
// Output: 3/2
}
func ExampleInt_Scan() {
// The Scan function is rarely used directly;
// the fmt package recognizes it as an implementation of fmt.Scanner.
i := new(big.Int)
_, err := fmt.Sscan("18446744073709551617", i)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(i)
}
// Output: 18446744073709551617
}
// This example demonstrates how to use big.Int to compute the smallest
// Fibonacci number with 100 decimal digits and to test whether it is prime.
func Example_fibonacci() {
// Initialize two big ints with the first two numbers in the sequence.
a := big.NewInt(0)
b := big.NewInt(1)
// Initialize limit as 10^99, the smallest integer with 100 digits.
var limit big.Int
limit.Exp(big.NewInt(10), big.NewInt(99), nil)
// Loop while a is smaller than 1e100.
for a.Cmp(&limit) < 0 {
// Compute the next Fibonacci number, storing it in a.
a.Add(a, b)
// Swap a and b so that b is the next number in the sequence.
a, b = b, a
}
fmt.Println(a) // 100-digit Fibonacci number
// Test a for primality.
// (ProbablyPrimes' argument sets the number of Miller-Rabin
// rounds to be performed. 20 is a good value.)
fmt.Println(a.ProbablyPrime(20))
// Output:
// 1344719667586153181419716641724567886890850696275767987106294472017884974410332069524504824747437757
// false
}
// This example shows how to use big.Float to compute the square root of 2 with
// a precision of 200 bits, and how to print the result as a decimal number.
func Example_sqrt2() {
// We'll do computations with 200 bits of precision in the mantissa.
const prec = 200
// Compute the square root of 2 using Newton's Method. We start with
// an initial estimate for sqrt(2), and then iterate:
// x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) )
// Since Newton's Method doubles the number of correct digits at each
// iteration, we need at least log_2(prec) steps.
steps := int(math.Log2(prec))
// Initialize values we need for the computation.
two := new(big.Float).SetPrec(prec).SetInt64(2)
half := new(big.Float).SetPrec(prec).SetFloat64(0.5)
// Use 1 as the initial estimate.
x := new(big.Float).SetPrec(prec).SetInt64(1)
// We use t as a temporary variable. There's no need to set its precision
// since big.Float values with unset (== 0) precision automatically assume
// the largest precision of the arguments when used as the result (receiver)
// of a big.Float operation.
t := new(big.Float)
// Iterate.
for i := 0; i <= steps; i++ {
t.Quo(two, x) // t = 2.0 / x_n
t.Add(x, t) // t = x_n + (2.0 / x_n)
x.Mul(half, t) // x_{n+1} = 0.5 * t
}
// We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter
fmt.Printf("sqrt(2) = %.50f\n", x)
// Print the error between 2 and x*x.
t.Mul(x, x) // t = x*x
fmt.Printf("error = %e\n", t.Sub(two, t))
// Output:
// sqrt(2) = 1.41421356237309504880168872420969807856967187537695
// error = 0.000000e+00
}
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements multi-precision floating-point numbers.
// Like in the GNU MPFR library (http://www.mpfr.org/), operands
// can be of mixed precision. Unlike MPFR, the rounding mode is
// not specified with each operation, but with each operand. The
// rounding mode of the result operand determines the rounding
// mode of an operation. This is a from-scratch implementation.
package big
import (
"fmt"
"math"
)
const debugFloat = false // enable for debugging
// A nonzero finite Float represents a multi-precision floating point number
//
// sign × mantissa × 2**exponent
//
// with 0.5 <= mantissa < 1.0, and MinExp <= exponent <= MaxExp.
// A Float may also be zero (+0, -0) or infinite (+Inf, -Inf).
// All Floats are ordered, and the ordering of two Floats x and y
// is defined by x.Cmp(y).
//
// Each Float value also has a precision, rounding mode, and accuracy.
// The precision is the maximum number of mantissa bits available to
// represent the value. The rounding mode specifies how a result should
// be rounded to fit into the mantissa bits, and accuracy describes the
// rounding error with respect to the exact result.
//
// Unless specified otherwise, all operations (including setters) that
// specify a *Float variable for the result (usually via the receiver
// with the exception of MantExp), round the numeric result according
// to the precision and rounding mode of the result variable.
//
// If the provided result precision is 0 (see below), it is set to the
// precision of the argument with the largest precision value before any
// rounding takes place, and the rounding mode remains unchanged. Thus,
// uninitialized Floats provided as result arguments will have their
// precision set to a reasonable value determined by the operands and
// their mode is the zero value for RoundingMode (ToNearestEven).
//
// By setting the desired precision to 24 or 53 and using matching rounding
// mode (typically ToNearestEven), Float operations produce the same results
// as the corresponding float32 or float64 IEEE-754 arithmetic for operands
// that correspond to normal (i.e., not denormal) float32 or float64 numbers.
// Exponent underflow and overflow lead to a 0 or an Infinity for different
// values than IEEE-754 because Float exponents have a much larger range.
//
// The zero (uninitialized) value for a Float is ready to use and represents
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
//
type Float struct {
prec uint32
mode RoundingMode
acc Accuracy
form form
neg bool
mant nat
exp int32
}
// An ErrNaN panic is raised by a Float operation that would lead to
// a NaN under IEEE-754 rules. An ErrNaN implements the error interface.
type ErrNaN struct {
msg string
}
func (err ErrNaN) Error() string {
return err.msg
}
// NewFloat allocates and returns a new Float set to x,
// with precision 53 and rounding mode ToNearestEven.
// NewFloat panics with ErrNaN if x is a NaN.
func NewFloat(x float64) *Float {
if math.IsNaN(x) {
panic(ErrNaN{"NewFloat(NaN)"})
}
return new(Float).SetFloat64(x)
}
// Exponent and precision limits.
const (
MaxExp = math.MaxInt32 // largest supported exponent
MinExp = math.MinInt32 // smallest supported exponent
MaxPrec = math.MaxUint32 // largest (theoretically) supported precision; likely memory-limited
)
// Internal representation: The mantissa bits x.mant of a nonzero finite
// Float x are stored in a nat slice long enough to hold up to x.prec bits;
// the slice may (but doesn't have to) be shorter if the mantissa contains
// trailing 0 bits. x.mant is normalized if the msb of x.mant == 1 (i.e.,
// the msb is shifted all the way "to the left"). Thus, if the mantissa has
// trailing 0 bits or x.prec is not a multiple of the the Word size _W,
// x.mant[0] has trailing zero bits. The msb of the mantissa corresponds
// to the value 0.5; the exponent x.exp shifts the binary point as needed.
//
// A zero or non-finite Float x ignores x.mant and x.exp.
//
// x form neg mant exp
// ----------------------------------------------------------
// ±0 zero sign - -
// 0 < |x| < +Inf finite sign mantissa exponent
// ±Inf inf sign - -
// A form value describes the internal representation.
type form byte
// The form value order is relevant - do not change!
const (
zero form = iota
finite
inf
)
// RoundingMode determines how a Float value is rounded to the
// desired precision. Rounding may change the Float value; the
// rounding error is described by the Float's Accuracy.
type RoundingMode byte
// These constants define supported rounding modes.
const (
ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
ToNearestAway // == IEEE 754-2008 roundTiesToAway
ToZero // == IEEE 754-2008 roundTowardZero
AwayFromZero // no IEEE 754-2008 equivalent
ToNegativeInf // == IEEE 754-2008 roundTowardNegative
ToPositiveInf // == IEEE 754-2008 roundTowardPositive
)
//go:generate stringer -type=RoundingMode
// Accuracy describes the rounding error produced by the most recent
// operation that generated a Float value, relative to the exact value.
type Accuracy int8
// Constants describing the Accuracy of a Float.
const (
Below Accuracy = -1
Exact Accuracy = 0
Above Accuracy = +1
)
//go:generate stringer -type=Accuracy
// SetPrec sets z's precision to prec and returns the (possibly) rounded
// value of z. Rounding occurs according to z's rounding mode if the mantissa
// cannot be represented in prec bits without loss of precision.
// SetPrec(0) maps all finite values to ±0; infinite values remain unchanged.
// If prec > MaxPrec, it is set to MaxPrec.
func (z *Float) SetPrec(prec uint) *Float {
z.acc = Exact // optimistically assume no rounding is needed
// special case
if prec == 0 {
z.prec = 0
if z.form == finite {
// truncate z to 0
z.acc = makeAcc(z.neg)
z.form = zero
}
return z
}
// general case
if prec > MaxPrec {
prec = MaxPrec
}
old := z.prec
z.prec = uint32(prec)
if z.prec < old {
z.round(0)
}
return z
}
func makeAcc(above bool) Accuracy {
if above {
return Above
}
return Below
}
// SetMode sets z's rounding mode to mode and returns an exact z.
// z remains unchanged otherwise.
// z.SetMode(z.Mode()) is a cheap way to set z's accuracy to Exact.
func (z *Float) SetMode(mode RoundingMode) *Float {
z.mode = mode
z.acc = Exact
return z
}
// Prec returns the mantissa precision of x in bits.
// The result may be 0 for |x| == 0 and |x| == Inf.
func (x *Float) Prec() uint {
return uint(x.prec)
}
// MinPrec returns the minimum precision required to represent x exactly
// (i.e., the smallest prec before x.SetPrec(prec) would start rounding x).
// The result is 0 for |x| == 0 and |x| == Inf.
func (x *Float) MinPrec() uint {
if x.form != finite {
return 0
}
return uint(len(x.mant))*_W - x.mant.trailingZeroBits()
}
// Mode returns the rounding mode of x.
func (x *Float) Mode() RoundingMode {
return x.mode
}
// Acc returns the accuracy of x produced by the most recent operation.
func (x *Float) Acc() Accuracy {
return x.acc
}
// Sign returns:
//
// -1 if x < 0
// 0 if x is ±0
// +1 if x > 0
//
func (x *Float) Sign() int {
if debugFloat {
x.validate()
}
if x.form == zero {
return 0
}
if x.neg {
return -1
}
return 1
}
// MantExp breaks x into its mantissa and exponent components
// and returns the exponent. If a non-nil mant argument is
// provided its value is set to the mantissa of x, with the
// same precision and rounding mode as x. The components
// satisfy x == mant × 2**exp, with 0.5 <= |mant| < 1.0.
// Calling MantExp with a nil argument is an efficient way to
// get the exponent of the receiver.
//
// Special cases are:
//
// ( ±0).MantExp(mant) = 0, with mant set to ±0
// (±Inf).MantExp(mant) = 0, with mant set to ±Inf
//
// x and mant may be the same in which case x is set to its
// mantissa value.
func (x *Float) MantExp(mant *Float) (exp int) {
if debugFloat {
x.validate()
}
if x.form == finite {
exp = int(x.exp)
}
if mant != nil {
mant.Copy(x)
if mant.form == finite {
mant.exp = 0
}
}
return
}
func (z *Float) setExpAndRound(exp int64, sbit uint) {
if exp < MinExp {
// underflow
z.acc = makeAcc(z.neg)
z.form = zero
return
}
if exp > MaxExp {
// overflow
z.acc = makeAcc(!z.neg)
z.form = inf
return
}
z.form = finite
z.exp = int32(exp)
z.round(sbit)
}
// SetMantExp sets z to mant × 2**exp and and returns z.
// The result z has the same precision and rounding mode
// as mant. SetMantExp is an inverse of MantExp but does
// not require 0.5 <= |mant| < 1.0. Specifically:
//
// mant := new(Float)
// new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0
//
// Special cases are:
//
// z.SetMantExp( ±0, exp) = ±0
// z.SetMantExp(±Inf, exp) = ±Inf
//
// z and mant may be the same in which case z's exponent
// is set to exp.
func (z *Float) SetMantExp(mant *Float, exp int) *Float {
if debugFloat {
z.validate()
mant.validate()
}
z.Copy(mant)
if z.form != finite {
return z
}
z.setExpAndRound(int64(z.exp)+int64(exp), 0)
return z
}
// Signbit returns true if x is negative or negative zero.
func (x *Float) Signbit() bool {
return x.neg
}
// IsInf reports whether x is +Inf or -Inf.
func (x *Float) IsInf() bool {
return x.form == inf
}
// IsInt reports whether x is an integer.
// ±Inf values are not integers.
func (x *Float) IsInt() bool {
if debugFloat {
x.validate()
}
// special cases
if x.form != finite {
return x.form == zero
}
// x.form == finite
if x.exp <= 0 {
return false
}
// x.exp > 0
return x.prec <= uint32(x.exp) || x.MinPrec() <= uint(x.exp) // not enough bits for fractional mantissa
}
// debugging support
func (x *Float) validate() {
if !debugFloat {
// avoid performance bugs
panic("validate called but debugFloat is not set")
}
if x.form != finite {
return
}
m := len(x.mant)
if m == 0 {
panic("nonzero finite number with empty mantissa")
}
const msb = 1 << (_W - 1)
if x.mant[m-1]&msb == 0 {
panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Text('p', 0)))
}
if x.prec == 0 {
panic("zero precision finite number")
}
}
// round rounds z according to z.mode to z.prec bits and sets z.acc accordingly.
// sbit must be 0 or 1 and summarizes any "sticky bit" information one might
// have before calling round. z's mantissa must be normalized (with the msb set)
// or empty.
//
// CAUTION: The rounding modes ToNegativeInf, ToPositiveInf are affected by the
// sign of z. For correct rounding, the sign of z must be set correctly before
// calling round.
func (z *Float) round(sbit uint) {
if debugFloat {
z.validate()
}
z.acc = Exact
if z.form != finite {
// ±0 or ±Inf => nothing left to do
return
}
// z.form == finite && len(z.mant) > 0
// m > 0 implies z.prec > 0 (checked by validate)
m := uint32(len(z.mant)) // present mantissa length in words
bits := m * _W // present mantissa bits; bits > 0
if bits <= z.prec {
// mantissa fits => nothing to do
return
}
// bits > z.prec
// Rounding is based on two bits: the rounding bit (rbit) and the
// sticky bit (sbit). The rbit is the bit immediately before the
// z.prec leading mantissa bits (the "0.5"). The sbit is set if any
// of the bits before the rbit are set (the "0.25", "0.125", etc.):
//
// rbit sbit => "fractional part"
//
// 0 0 == 0
// 0 1 > 0 , < 0.5
// 1 0 == 0.5
// 1 1 > 0.5, < 1.0
// bits > z.prec: mantissa too large => round
r := uint(bits - z.prec - 1) // rounding bit position; r >= 0
rbit := z.mant.bit(r) & 1 // rounding bit; be safe and ensure it's a single bit
if sbit == 0 {
// TODO(gri) if rbit != 0 we don't need to compute sbit for some rounding modes (optimization)
sbit = z.mant.sticky(r)
}
sbit &= 1 // be safe and ensure it's a single bit
// cut off extra words
n := (z.prec + (_W - 1)) / _W // mantissa length in words for desired precision
if m > n {
copy(z.mant, z.mant[m-n:]) // move n last words to front
z.mant = z.mant[:n]
}
// determine number of trailing zero bits (ntz) and compute lsb mask of mantissa's least-significant word
ntz := n*_W - z.prec // 0 <= ntz < _W
lsb := Word(1) << ntz
// round if result is inexact
if rbit|sbit != 0 {
// Make rounding decision: The result mantissa is truncated ("rounded down")
// by default. Decide if we need to increment, or "round up", the (unsigned)
// mantissa.
inc := false
switch z.mode {
case ToNegativeInf:
inc = z.neg
case ToZero:
// nothing to do
case ToNearestEven:
inc = rbit != 0 && (sbit != 0 || z.mant[0]&lsb != 0)
case ToNearestAway:
inc = rbit != 0
case AwayFromZero:
inc = true
case ToPositiveInf:
inc = !z.neg
default:
panic("unreachable")
}
// A positive result (!z.neg) is Above the exact result if we increment,
// and it's Below if we truncate (Exact results require no rounding).
// For a negative result (z.neg) it is exactly the opposite.
z.acc = makeAcc(inc != z.neg)
if inc {
// add 1 to mantissa
if addVW(z.mant, z.mant, lsb) != 0 {
// mantissa overflow => adjust exponent
if z.exp >= MaxExp {
// exponent overflow
z.form = inf
return
}
z.exp++
// adjust mantissa: divide by 2 to compensate for exponent adjustment
shrVU(z.mant, z.mant, 1)
// set msb == carry == 1 from the mantissa overflow above
const msb = 1 << (_W - 1)
z.mant[n-1] |= msb
}
}
}
// zero out trailing bits in least-significant word
z.mant[0] &^= lsb - 1
if debugFloat {
z.validate()
}
}
func (z *Float) setBits64(neg bool, x uint64) *Float {
if z.prec == 0 {
z.prec = 64
}
z.acc = Exact
z.neg = neg
if x == 0 {
z.form = zero
return z
}
// x != 0
z.form = finite
s := nlz64(x)
z.mant = z.mant.setUint64(x << s)
z.exp = int32(64 - s) // always fits
if z.prec < 64 {
z.round(0)
}
return z
}
// SetUint64 sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to 64 (and rounding will have
// no effect).
func (z *Float) SetUint64(x uint64) *Float {
return z.setBits64(false, x)
}
// SetInt64 sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to 64 (and rounding will have
// no effect).
func (z *Float) SetInt64(x int64) *Float {
u := x
if u < 0 {
u = -u
}
// We cannot simply call z.SetUint64(uint64(u)) and change
// the sign afterwards because the sign affects rounding.
return z.setBits64(x < 0, uint64(u))
}
// SetFloat64 sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to 53 (and rounding will have
// no effect). SetFloat64 panics with ErrNaN if x is a NaN.
func (z *Float) SetFloat64(x float64) *Float {
if z.prec == 0 {
z.prec = 53
}
if math.IsNaN(x) {
panic(ErrNaN{"Float.SetFloat64(NaN)"})
}
z.acc = Exact
z.neg = math.Signbit(x) // handle -0, -Inf correctly
if x == 0 {
z.form = zero
return z
}
if math.IsInf(x, 0) {
z.form = inf
return z
}
// normalized x != 0
z.form = finite
fmant, exp := math.Frexp(x) // get normalized mantissa
z.mant = z.mant.setUint64(1<<63 | math.Float64bits(fmant)<<11)
z.exp = int32(exp) // always fits
if z.prec < 53 {
z.round(0)
}
return z
}
// fnorm normalizes mantissa m by shifting it to the left
// such that the msb of the most-significant word (msw) is 1.
// It returns the shift amount. It assumes that len(m) != 0.
func fnorm(m nat) int64 {
if debugFloat && (len(m) == 0 || m[len(m)-1] == 0) {
panic("msw of mantissa is 0")
}
s := nlz(m[len(m)-1])
if s > 0 {
c := shlVU(m, m, s)
if debugFloat && c != 0 {
panic("nlz or shlVU incorrect")
}
}
return int64(s)
}
// SetInt sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to the larger of x.BitLen()
// or 64 (and rounding will have no effect).
func (z *Float) SetInt(x *Int) *Float {
// TODO(gri) can be more efficient if z.prec > 0
// but small compared to the size of x, or if there
// are many trailing 0's.
bits := uint32(x.BitLen())
if z.prec == 0 {
z.prec = umax32(bits, 64)
}
z.acc = Exact
z.neg = x.neg
if len(x.abs) == 0 {
z.form = zero
return z
}
// x != 0
z.mant = z.mant.set(x.abs)
fnorm(z.mant)
z.setExpAndRound(int64(bits), 0)
return z
}
// SetRat sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to the largest of a.BitLen(),
// b.BitLen(), or 64; with x = a/b.
func (z *Float) SetRat(x *Rat) *Float {
if x.IsInt() {
return z.SetInt(x.Num())
}
var a, b Float
a.SetInt(x.Num())
b.SetInt(x.Denom())
if z.prec == 0 {
z.prec = umax32(a.prec, b.prec)
}
return z.Quo(&a, &b)
}
// SetInf sets z to the infinite Float -Inf if signbit is
// set, or +Inf if signbit is not set, and returns z. The
// precision of z is unchanged and the result is always
// Exact.
func (z *Float) SetInf(signbit bool) *Float {
z.acc = Exact
z.form = inf
z.neg = signbit
return z
}
// Set sets z to the (possibly rounded) value of x and returns z.
// If z's precision is 0, it is changed to the precision of x
// before setting z (and rounding will have no effect).
// Rounding is performed according to z's precision and rounding
// mode; and z's accuracy reports the result error relative to the
// exact (not rounded) result.
func (z *Float) Set(x *Float) *Float {
if debugFloat {
x.validate()
}
z.acc = Exact
if z != x {
z.form = x.form
z.neg = x.neg
if x.form == finite {
z.exp = x.exp
z.mant = z.mant.set(x.mant)
}
if z.prec == 0 {
z.prec = x.prec
} else if z.prec < x.prec {
z.round(0)
}
}
return z
}
// Copy sets z to x, with the same precision, rounding mode, and
// accuracy as x, and returns z. x is not changed even if z and
// x are the same.
func (z *Float) Copy(x *Float) *Float {
if debugFloat {
x.validate()
}
if z != x {
z.prec = x.prec
z.mode = x.mode
z.acc = x.acc
z.form = x.form
z.neg = x.neg
if z.form == finite {
z.mant = z.mant.set(x.mant)
z.exp = x.exp
}
}
return z
}
// msb32 returns the 32 most significant bits of x.
func msb32(x nat) uint32 {
i := len(x) - 1
if i < 0 {
return 0
}
if debugFloat && x[i]&(1<<(_W-1)) == 0 {
panic("x not normalized")
}
switch _W {
case 32:
return uint32(x[i])
case 64:
return uint32(x[i] >> 32)
}
panic("unreachable")
}
// msb64 returns the 64 most significant bits of x.
func msb64(x nat) uint64 {
i := len(x) - 1
if i < 0 {
return 0
}
if debugFloat && x[i]&(1<<(_W-1)) == 0 {
panic("x not normalized")
}
switch _W {
case 32:
v := uint64(x[i]) << 32
if i > 0 {
v |= uint64(x[i-1])
}
return v
case 64:
return uint64(x[i])
}
panic("unreachable")
}
// Uint64 returns the unsigned integer resulting from truncating x
// towards zero. If 0 <= x <= math.MaxUint64, the result is Exact
// if x is an integer and Below otherwise.
// The result is (0, Above) for x < 0, and (math.MaxUint64, Below)
// for x > math.MaxUint64.
func (x *Float) Uint64() (uint64, Accuracy) {
if debugFloat {
x.validate()
}
switch x.form {
case finite:
if x.neg {
return 0, Above
}
// 0 < x < +Inf
if x.exp <= 0 {
// 0 < x < 1
return 0, Below
}
// 1 <= x < Inf
if x.exp <= 64 {
// u = trunc(x) fits into a uint64
u := msb64(x.mant) >> (64 - uint32(x.exp))
if x.MinPrec() <= 64 {
return u, Exact
}
return u, Below // x truncated
}
// x too large
return math.MaxUint64, Below
case zero:
return 0, Exact
case inf:
if x.neg {
return 0, Above
}
return math.MaxUint64, Below
}
panic("unreachable")
}
// Int64 returns the integer resulting from truncating x towards zero.
// If math.MinInt64 <= x <= math.MaxInt64, the result is Exact if x is
// an integer, and Above (x < 0) or Below (x > 0) otherwise.
// The result is (math.MinInt64, Above) for x < math.MinInt64,
// and (math.MaxInt64, Below) for x > math.MaxInt64.
func (x *Float) Int64() (int64, Accuracy) {
if debugFloat {
x.validate()
}
switch x.form {
case finite:
// 0 < |x| < +Inf
acc := makeAcc(x.neg)
if x.exp <= 0 {
// 0 < |x| < 1
return 0, acc
}
// x.exp > 0
// 1 <= |x| < +Inf
if x.exp <= 63 {
// i = trunc(x) fits into an int64 (excluding math.MinInt64)
i := int64(msb64(x.mant) >> (64 - uint32(x.exp)))
if x.neg {
i = -i
}
if x.MinPrec() <= uint(x.exp) {
return i, Exact
}
return i, acc // x truncated
}
if x.neg {
// check for special case x == math.MinInt64 (i.e., x == -(0.5 << 64))
if x.exp == 64 && x.MinPrec() == 1 {
acc = Exact
}
return math.MinInt64, acc
}
// x too large
return math.MaxInt64, Below
case zero:
return 0, Exact
case inf:
if x.neg {
return math.MinInt64, Above
}
return math.MaxInt64, Below
}
panic("unreachable")
}
// Float32 returns the float32 value nearest to x. If x is too small to be
// represented by a float32 (|x| < math.SmallestNonzeroFloat32), the result
// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
// If x is too large to be represented by a float32 (|x| > math.MaxFloat32),
// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
func (x *Float) Float32() (float32, Accuracy) {
if debugFloat {
x.validate()
}
switch x.form {
case finite:
// 0 < |x| < +Inf
const (
fbits = 32 // float size
mbits = 23 // mantissa size (excluding implicit msb)
ebits = fbits - mbits - 1 // 8 exponent size
bias = 1<<(ebits-1) - 1 // 127 exponent bias
dmin = 1 - bias - mbits // -149 smallest unbiased exponent (denormal)
emin = 1 - bias // -126 smallest unbiased exponent (normal)
emax = bias // 127 largest unbiased exponent (normal)
)
// Float mantissa m is 0.5 <= m < 1.0; compute exponent e for float32 mantissa.
e := x.exp - 1 // exponent for normal mantissa m with 1.0 <= m < 2.0
// Compute precision p for float32 mantissa.
// If the exponent is too small, we have a denormal number before
// rounding and fewer than p mantissa bits of precision available
// (the exponent remains fixed but the mantissa gets shifted right).
p := mbits + 1 // precision of normal float
if e < emin {
// recompute precision
p = mbits + 1 - emin + int(e)
// If p == 0, the mantissa of x is shifted so much to the right
// that its msb falls immediately to the right of the float32
// mantissa space. In other words, if the smallest denormal is
// considered "1.0", for p == 0, the mantissa value m is >= 0.5.
// If m > 0.5, it is rounded up to 1.0; i.e., the smallest denormal.
// If m == 0.5, it is rounded down to even, i.e., 0.0.
// If p < 0, the mantissa value m is <= "0.25" which is never rounded up.
if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ {
// underflow to ±0
if x.neg {
var z float32
return -z, Above
}
return 0.0, Below
}
// otherwise, round up
// We handle p == 0 explicitly because it's easy and because
// Float.round doesn't support rounding to 0 bits of precision.
if p == 0 {
if x.neg {
return -math.SmallestNonzeroFloat32, Below
}
return math.SmallestNonzeroFloat32, Above
}
}
// p > 0
// round
var r Float
r.prec = uint32(p)
r.Set(x)
e = r.exp - 1
// Rounding may have caused r to overflow to ±Inf
// (rounding never causes underflows to 0).
// If the exponent is too large, also overflow to ±Inf.
if r.form == inf || e > emax {
// overflow
if x.neg {
return float32(math.Inf(-1)), Below
}
return float32(math.Inf(+1)), Above
}
// e <= emax
// Determine sign, biased exponent, and mantissa.
var sign, bexp, mant uint32
if x.neg {
sign = 1 << (fbits - 1)
}
// Rounding may have caused a denormal number to
// become normal. Check again.
if e < emin {
// denormal number: recompute precision
// Since rounding may have at best increased precision
// and we have eliminated p <= 0 early, we know p > 0.
// bexp == 0 for denormals
p = mbits + 1 - emin + int(e)
mant = msb32(r.mant) >> uint(fbits-p)
} else {
// normal number: emin <= e <= emax
bexp = uint32(e+bias) << mbits
mant = msb32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}
return math.Float32frombits(sign | bexp | mant), r.acc
case zero:
if x.neg {
var z float32
return -z, Exact
}
return 0.0, Exact
case inf:
if x.neg {
return float32(math.Inf(-1)), Exact
}
return float32(math.Inf(+1)), Exact
}
panic("unreachable")
}
// Float64 returns the float64 value nearest to x. If x is too small to be
// represented by a float64 (|x| < math.SmallestNonzeroFloat64), the result
// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
// If x is too large to be represented by a float64 (|x| > math.MaxFloat64),
// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
func (x *Float) Float64() (float64, Accuracy) {
if debugFloat {
x.validate()
}
switch x.form {
case finite:
// 0 < |x| < +Inf
const (
fbits = 64 // float size
mbits = 52 // mantissa size (excluding implicit msb)
ebits = fbits - mbits - 1 // 11 exponent size
bias = 1<<(ebits-1) - 1 // 1023 exponent bias
dmin = 1 - bias - mbits // -1074 smallest unbiased exponent (denormal)
emin = 1 - bias // -1022 smallest unbiased exponent (normal)
emax = bias // 1023 largest unbiased exponent (normal)
)
// Float mantissa m is 0.5 <= m < 1.0; compute exponent e for float64 mantissa.
e := x.exp - 1 // exponent for normal mantissa m with 1.0 <= m < 2.0
// Compute precision p for float64 mantissa.
// If the exponent is too small, we have a denormal number before
// rounding and fewer than p mantissa bits of precision available
// (the exponent remains fixed but the mantissa gets shifted right).
p := mbits + 1 // precision of normal float
if e < emin {
// recompute precision
p = mbits + 1 - emin + int(e)
// If p == 0, the mantissa of x is shifted so much to the right
// that its msb falls immediately to the right of the float64
// mantissa space. In other words, if the smallest denormal is
// considered "1.0", for p == 0, the mantissa value m is >= 0.5.
// If m > 0.5, it is rounded up to 1.0; i.e., the smallest denormal.
// If m == 0.5, it is rounded down to even, i.e., 0.0.
// If p < 0, the mantissa value m is <= "0.25" which is never rounded up.
if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ {
// underflow to ±0
if x.neg {
var z float64
return -z, Above
}
return 0.0, Below
}
// otherwise, round up
// We handle p == 0 explicitly because it's easy and because
// Float.round doesn't support rounding to 0 bits of precision.
if p == 0 {
if x.neg {
return -math.SmallestNonzeroFloat64, Below
}
return math.SmallestNonzeroFloat64, Above
}
}
// p > 0
// round
var r Float
r.prec = uint32(p)
r.Set(x)
e = r.exp - 1
// Rounding may have caused r to overflow to ±Inf
// (rounding never causes underflows to 0).
// If the exponent is too large, also overflow to ±Inf.
if r.form == inf || e > emax {
// overflow
if x.neg {
return math.Inf(-1), Below
}
return math.Inf(+1), Above
}
// e <= emax
// Determine sign, biased exponent, and mantissa.
var sign, bexp, mant uint64
if x.neg {
sign = 1 << (fbits - 1)
}
// Rounding may have caused a denormal number to
// become normal. Check again.
if e < emin {
// denormal number: recompute precision
// Since rounding may have at best increased precision
// and we have eliminated p <= 0 early, we know p > 0.
// bexp == 0 for denormals
p = mbits + 1 - emin + int(e)
mant = msb64(r.mant) >> uint(fbits-p)
} else {
// normal number: emin <= e <= emax
bexp = uint64(e+bias) << mbits
mant = msb64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}
return math.Float64frombits(sign | bexp | mant), r.acc
case zero:
if x.neg {
var z float64
return -z, Exact
}
return 0.0, Exact
case inf:
if x.neg {
return math.Inf(-1), Exact
}
return math.Inf(+1), Exact
}
panic("unreachable")
}
// Int returns the result of truncating x towards zero;
// or nil if x is an infinity.
// The result is Exact if x.IsInt(); otherwise it is Below
// for x > 0, and Above for x < 0.
// If a non-nil *Int argument z is provided, Int stores
// the result in z instead of allocating a new Int.
func (x *Float) Int(z *Int) (*Int, Accuracy) {
if debugFloat {
x.validate()
}
if z == nil && x.form <= finite {
z = new(Int)
}
switch x.form {
case finite:
// 0 < |x| < +Inf
acc := makeAcc(x.neg)
if x.exp <= 0 {
// 0 < |x| < 1
return z.SetInt64(0), acc
}
// x.exp > 0
// 1 <= |x| < +Inf
// determine minimum required precision for x
allBits := uint(len(x.mant)) * _W
exp := uint(x.exp)
if x.MinPrec() <= exp {
acc = Exact
}
// shift mantissa as needed
if z == nil {
z = new(Int)
}
z.neg = x.neg
switch {
case exp > allBits:
z.abs = z.abs.shl(x.mant, exp-allBits)
default:
z.abs = z.abs.set(x.mant)
case exp < allBits:
z.abs = z.abs.shr(x.mant, allBits-exp)
}
return z, acc
case zero:
return z.SetInt64(0), Exact
case inf:
return nil, makeAcc(x.neg)
}
panic("unreachable")
}
// Rat returns the rational number corresponding to x;
// or nil if x is an infinity.
// The result is Exact if x is not an Inf.
// If a non-nil *Rat argument z is provided, Rat stores
// the result in z instead of allocating a new Rat.
func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
if debugFloat {
x.validate()
}
if z == nil && x.form <= finite {
z = new(Rat)
}
switch x.form {
case finite:
// 0 < |x| < +Inf
allBits := int32(len(x.mant)) * _W
// build up numerator and denominator
z.a.neg = x.neg
switch {
case x.exp > allBits:
z.a.abs = z.a.abs.shl(x.mant, uint(x.exp-allBits))
z.b.abs = z.b.abs[:0] // == 1 (see Rat)
// z already in normal form
default:
z.a.abs = z.a.abs.set(x.mant)
z.b.abs = z.b.abs[:0] // == 1 (see Rat)
// z already in normal form
case x.exp < allBits:
z.a.abs = z.a.abs.set(x.mant)
t := z.b.abs.setUint64(1)
z.b.abs = t.shl(t, uint(allBits-x.exp))
z.norm()
}
return z, Exact
case zero:
return z.SetInt64(0), Exact
case inf:
return nil, makeAcc(x.neg)
}
panic("unreachable")
}
// Abs sets z to the (possibly rounded) value |x| (the absolute value of x)
// and returns z.
func (z *Float) Abs(x *Float) *Float {
z.Set(x)
z.neg = false
return z
}
// Neg sets z to the (possibly rounded) value of x with its sign negated,
// and returns z.
func (z *Float) Neg(x *Float) *Float {
z.Set(x)
z.neg = !z.neg
return z
}
func validateBinaryOperands(x, y *Float) {
if !debugFloat {
// avoid performance bugs
panic("validateBinaryOperands called but debugFloat is not set")
}
if len(x.mant) == 0 {
panic("empty mantissa for x")
}
if len(y.mant) == 0 {
panic("empty mantissa for y")
}
}
// z = x + y, ignoring signs of x and y for the addition
// but using the sign of z for rounding the result.
// x and y must have a non-empty mantissa and valid exponent.
func (z *Float) uadd(x, y *Float) {
// Note: This implementation requires 2 shifts most of the
// time. It is also inefficient if exponents or precisions
// differ by wide margins. The following article describes
// an efficient (but much more complicated) implementation
// compatible with the internal representation used here:
//
// Vincent Lefèvre: "The Generic Multiple-Precision Floating-
// Point Addition With Exact Rounding (as in the MPFR Library)"
// http://www.vinc17.net/research/papers/rnc6.pdf
if debugFloat {
validateBinaryOperands(x, y)
}
// compute exponents ex, ey for mantissa with "binary point"
// on the right (mantissa.0) - use int64 to avoid overflow
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
// TODO(gri) having a combined add-and-shift primitive
// could make this code significantly faster
switch {
case ex < ey:
// cannot re-use z.mant w/o testing for aliasing
t := nat(nil).shl(y.mant, uint(ey-ex))
z.mant = z.mant.add(x.mant, t)
default:
// ex == ey, no shift needed
z.mant = z.mant.add(x.mant, y.mant)
case ex > ey:
// cannot re-use z.mant w/o testing for aliasing
t := nat(nil).shl(x.mant, uint(ex-ey))
z.mant = z.mant.add(t, y.mant)
ex = ey
}
// len(z.mant) > 0
z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
}
// z = x - y for |x| > |y|, ignoring signs of x and y for the subtraction
// but using the sign of z for rounding the result.
// x and y must have a non-empty mantissa and valid exponent.
func (z *Float) usub(x, y *Float) {
// This code is symmetric to uadd.
// We have not factored the common code out because
// eventually uadd (and usub) should be optimized
// by special-casing, and the code will diverge.
if debugFloat {
validateBinaryOperands(x, y)
}
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
switch {
case ex < ey:
// cannot re-use z.mant w/o testing for aliasing
t := nat(nil).shl(y.mant, uint(ey-ex))
z.mant = t.sub(x.mant, t)
default:
// ex == ey, no shift needed
z.mant = z.mant.sub(x.mant, y.mant)
case ex > ey:
// cannot re-use z.mant w/o testing for aliasing
t := nat(nil).shl(x.mant, uint(ex-ey))
z.mant = t.sub(t, y.mant)
ex = ey
}
// operands may have canceled each other out
if len(z.mant) == 0 {
z.acc = Exact
z.form = zero
z.neg = false
return
}
// len(z.mant) > 0
z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
}
// z = x * y, ignoring signs of x and y for the multiplication
// but using the sign of z for rounding the result.
// x and y must have a non-empty mantissa and valid exponent.
func (z *Float) umul(x, y *Float) {
if debugFloat {
validateBinaryOperands(x, y)
}
// Note: This is doing too much work if the precision
// of z is less than the sum of the precisions of x
// and y which is often the case (e.g., if all floats
// have the same precision).
// TODO(gri) Optimize this for the common case.
e := int64(x.exp) + int64(y.exp)
z.mant = z.mant.mul(x.mant, y.mant)
z.setExpAndRound(e-fnorm(z.mant), 0)
}
// z = x / y, ignoring signs of x and y for the division
// but using the sign of z for rounding the result.
// x and y must have a non-empty mantissa and valid exponent.
func (z *Float) uquo(x, y *Float) {
if debugFloat {
validateBinaryOperands(x, y)
}
// mantissa length in words for desired result precision + 1
// (at least one extra bit so we get the rounding bit after
// the division)
n := int(z.prec/_W) + 1
// compute adjusted x.mant such that we get enough result precision
xadj := x.mant
if d := n - len(x.mant) + len(y.mant); d > 0 {
// d extra words needed => add d "0 digits" to x
xadj = make(nat, len(x.mant)+d)
copy(xadj[d:], x.mant)
}
// TODO(gri): If we have too many digits (d < 0), we should be able
// to shorten x for faster division. But we must be extra careful
// with rounding in that case.
// Compute d before division since there may be aliasing of x.mant
// (via xadj) or y.mant with z.mant.
d := len(xadj) - len(y.mant)
// divide
var r nat
z.mant, r = z.mant.div(nil, xadj, y.mant)
e := int64(x.exp) - int64(y.exp) - int64(d-len(z.mant))*_W
// The result is long enough to include (at least) the rounding bit.
// If there's a non-zero remainder, the corresponding fractional part
// (if it were computed), would have a non-zero sticky bit (if it were
// zero, it couldn't have a non-zero remainder).
var sbit uint
if len(r) > 0 {
sbit = 1
}
z.setExpAndRound(e-fnorm(z.mant), sbit)
}
// ucmp returns -1, 0, or +1, depending on whether
// |x| < |y|, |x| == |y|, or |x| > |y|.
// x and y must have a non-empty mantissa and valid exponent.
func (x *Float) ucmp(y *Float) int {
if debugFloat {
validateBinaryOperands(x, y)
}
switch {
case x.exp < y.exp:
return -1
case x.exp > y.exp:
return +1
}
// x.exp == y.exp
// compare mantissas
i := len(x.mant)
j := len(y.mant)
for i > 0 || j > 0 {
var xm, ym Word
if i > 0 {
i--
xm = x.mant[i]
}
if j > 0 {
j--
ym = y.mant[j]
}
switch {
case xm < ym:
return -1
case xm > ym:
return +1
}
}
return 0
}
// Handling of sign bit as defined by IEEE 754-2008, section 6.3:
//
// When neither the inputs nor result are NaN, the sign of a product or
// quotient is the exclusive OR of the operands’ signs; the sign of a sum,
// or of a difference x−y regarded as a sum x+(−y), differs from at most
// one of the addends’ signs; and the sign of the result of conversions,
// the quantize operation, the roundToIntegral operations, and the
// roundToIntegralExact (see 5.3.1) is the sign of the first or only operand.
// These rules shall apply even when operands or results are zero or infinite.
//
// When the sum of two operands with opposite signs (or the difference of
// two operands with like signs) is exactly zero, the sign of that sum (or
// difference) shall be +0 in all rounding-direction attributes except
// roundTowardNegative; under that attribute, the sign of an exact zero
// sum (or difference) shall be −0. However, x+x = x−(−x) retains the same
// sign as x even when x is zero.
//
// See also: https://play.golang.org/p/RtH3UCt5IH
// Add sets z to the rounded sum x+y and returns z. If z's precision is 0,
// it is changed to the larger of x's or y's precision before the operation.
// Rounding is performed according to z's precision and rounding mode; and
// z's accuracy reports the result error relative to the exact (not rounded)
// result. Add panics with ErrNaN if x and y are infinities with opposite
// signs. The value of z is undefined in that case.
//
// BUG(gri) When rounding ToNegativeInf, the sign of Float values rounded to 0 is incorrect.
func (z *Float) Add(x, y *Float) *Float {
if debugFloat {
x.validate()
y.validate()
}
if z.prec == 0 {
z.prec = umax32(x.prec, y.prec)
}
if x.form == finite && y.form == finite {
// x + y (common case)
z.neg = x.neg
if x.neg == y.neg {
// x + y == x + y
// (-x) + (-y) == -(x + y)
z.uadd(x, y)
} else {
// x + (-y) == x - y == -(y - x)
// (-x) + y == y - x == -(x - y)
if x.ucmp(y) > 0 {
z.usub(x, y)
} else {
z.neg = !z.neg
z.usub(y, x)
}
}
return z
}
if x.form == inf && y.form == inf && x.neg != y.neg {
// +Inf + -Inf
// -Inf + +Inf
// value of z is undefined but make sure it's valid
z.acc = Exact
z.form = zero
z.neg = false
panic(ErrNaN{"addition of infinities with opposite signs"})
}
if x.form == zero && y.form == zero {
// ±0 + ±0
z.acc = Exact
z.form = zero
z.neg = x.neg && y.neg // -0 + -0 == -0
return z
}
if x.form == inf || y.form == zero {
// ±Inf + y
// x + ±0
return z.Set(x)
}
// ±0 + y
// x + ±Inf
return z.Set(y)
}
// Sub sets z to the rounded difference x-y and returns z.
// Precision, rounding, and accuracy reporting are as for Add.
// Sub panics with ErrNaN if x and y are infinities with equal
// signs. The value of z is undefined in that case.
func (z *Float) Sub(x, y *Float) *Float {
if debugFloat {
x.validate()
y.validate()
}
if z.prec == 0 {
z.prec = umax32(x.prec, y.prec)
}
if x.form == finite && y.form == finite {
// x - y (common case)
z.neg = x.neg
if x.neg != y.neg {
// x - (-y) == x + y
// (-x) - y == -(x + y)
z.uadd(x, y)
} else {
// x - y == x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y)
if x.ucmp(y) > 0 {
z.usub(x, y)
} else {
z.neg = !z.neg
z.usub(y, x)
}
}
return z
}
if x.form == inf && y.form == inf && x.neg == y.neg {
// +Inf - +Inf
// -Inf - -Inf
// value of z is undefined but make sure it's valid
z.acc = Exact
z.form = zero
z.neg = false
panic(ErrNaN{"subtraction of infinities with equal signs"})
}
if x.form == zero && y.form == zero {
// ±0 - ±0
z.acc = Exact
z.form = zero
z.neg = x.neg && !y.neg // -0 - +0 == -0
return z
}
if x.form == inf || y.form == zero {
// ±Inf - y
// x - ±0
return z.Set(x)
}
// ±0 - y
// x - ±Inf
return z.Neg(y)
}
// Mul sets z to the rounded product x*y and returns z.
// Precision, rounding, and accuracy reporting are as for Add.
// Mul panics with ErrNaN if one operand is zero and the other
// operand an infinity. The value of z is undefined in that case.
func (z *Float) Mul(x, y *Float) *Float {
if debugFloat {
x.validate()
y.validate()
}
if z.prec == 0 {
z.prec = umax32(x.prec, y.prec)
}
z.neg = x.neg != y.neg
if x.form == finite && y.form == finite {
// x * y (common case)
z.umul(x, y)
return z
}
z.acc = Exact
if x.form == zero && y.form == inf || x.form == inf && y.form == zero {
// ±0 * ±Inf
// ±Inf * ±0
// value of z is undefined but make sure it's valid
z.form = zero
z.neg = false
panic(ErrNaN{"multiplication of zero with infinity"})
}
if x.form == inf || y.form == inf {
// ±Inf * y
// x * ±Inf
z.form = inf
return z
}
// ±0 * y
// x * ±0
z.form = zero
return z
}
// Quo sets z to the rounded quotient x/y and returns z.
// Precision, rounding, and accuracy reporting are as for Add.
// Quo panics with ErrNaN if both operands are zero or infinities.
// The value of z is undefined in that case.
func (z *Float) Quo(x, y *Float) *Float {
if debugFloat {
x.validate()
y.validate()
}
if z.prec == 0 {
z.prec = umax32(x.prec, y.prec)
}
z.neg = x.neg != y.neg
if x.form == finite && y.form == finite {
// x / y (common case)
z.uquo(x, y)
return z
}
z.acc = Exact
if x.form == zero && y.form == zero || x.form == inf && y.form == inf {
// ±0 / ±0
// ±Inf / ±Inf
// value of z is undefined but make sure it's valid
z.form = zero
z.neg = false
panic(ErrNaN{"division of zero by zero or infinity by infinity"})
}
if x.form == zero || y.form == inf {
// ±0 / y
// x / ±Inf
z.form = zero
return z
}
// x / ±0
// ±Inf / y
z.form = inf
return z
}
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y (incl. -0 == 0, -Inf == -Inf, and +Inf == +Inf)
// +1 if x > y
//
func (x *Float) Cmp(y *Float) int {
if debugFloat {
x.validate()
y.validate()
}
mx := x.ord()
my := y.ord()
switch {
case mx < my:
return -1
case mx > my:
return +1
}
// mx == my
// only if |mx| == 1 we have to compare the mantissae
switch mx {
case -1:
return y.ucmp(x)
case +1:
return x.ucmp(y)
}
return 0
}
// ord classifies x and returns:
//
// -2 if -Inf == x
// -1 if -Inf < x < 0
// 0 if x == 0 (signed or unsigned)
// +1 if 0 < x < +Inf
// +2 if x == +Inf
//
func (x *Float) ord() int {
var m int
switch x.form {
case finite:
m = 1
case zero:
return 0
case inf:
m = 2
}
if x.neg {
m = -m
}
return m
}
func umax32(x, y uint32) uint32 {
if x > y {
return x
}
return y
}
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"fmt"
"math"
"strconv"
"strings"
"testing"
)
// Verify that ErrNaN implements the error interface.
var _ error = ErrNaN{}
func (x *Float) uint64() uint64 {
u, acc := x.Uint64()
if acc != Exact {
panic(fmt.Sprintf("%s is not a uint64", x.Text('g', 10)))
}
return u
}
func (x *Float) int64() int64 {
i, acc := x.Int64()
if acc != Exact {
panic(fmt.Sprintf("%s is not an int64", x.Text('g', 10)))
}
return i
}
func TestFloatZeroValue(t *testing.T) {
// zero (uninitialized) value is a ready-to-use 0.0
var x Float
if s := x.Text('f', 1); s != "0.0" {
t.Errorf("zero value = %s; want 0.0", s)
}
// zero value has precision 0
if prec := x.Prec(); prec != 0 {
t.Errorf("prec = %d; want 0", prec)
}
// zero value can be used in any and all positions of binary operations
make := func(x int) *Float {
var f Float
if x != 0 {
f.SetInt64(int64(x))
}
// x == 0 translates into the zero value
return &f
}
for _, test := range []struct {
z, x, y, want int
opname rune
op func(z, x, y *Float) *Float
}{
{0, 0, 0, 0, '+', (*Float).Add},
{0, 1, 2, 3, '+', (*Float).Add},
{1, 2, 0, 2, '+', (*Float).Add},
{2, 0, 1, 1, '+', (*Float).Add},
{0, 0, 0, 0, '-', (*Float).Sub},
{0, 1, 2, -1, '-', (*Float).Sub},
{1, 2, 0, 2, '-', (*Float).Sub},
{2, 0, 1, -1, '-', (*Float).Sub},
{0, 0, 0, 0, '*', (*Float).Mul},
{0, 1, 2, 2, '*', (*Float).Mul},
{1, 2, 0, 0, '*', (*Float).Mul},
{2, 0, 1, 0, '*', (*Float).Mul},
// {0, 0, 0, 0, '/', (*Float).Quo}, // panics
{0, 2, 1, 2, '/', (*Float).Quo},
{1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf
{2, 0, 1, 0, '/', (*Float).Quo},
} {
z := make(test.z)
test.op(z, make(test.x), make(test.y))
got := 0
if !z.IsInf() {
got = int(z.int64())
}
if got != test.want {
t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want)
}
}
// TODO(gri) test how precision is set for zero value results
}
func makeFloat(s string) *Float {
x, _, err := ParseFloat(s, 0, 1000, ToNearestEven)
if err != nil {
panic(err)
}
return x
}
func TestFloatSetPrec(t *testing.T) {
for _, test := range []struct {
x string
prec uint
want string
acc Accuracy
}{
// prec 0
{"0", 0, "0", Exact},
{"-0", 0, "-0", Exact},
{"-Inf", 0, "-Inf", Exact},
{"+Inf", 0, "+Inf", Exact},
{"123", 0, "0", Below},
{"-123", 0, "-0", Above},
// prec at upper limit
{"0", MaxPrec, "0", Exact},
{"-0", MaxPrec, "-0", Exact},
{"-Inf", MaxPrec, "-Inf", Exact},
{"+Inf", MaxPrec, "+Inf", Exact},
// just a few regular cases - general rounding is tested elsewhere
{"1.5", 1, "2", Above},
{"-1.5", 1, "-2", Below},
{"123", 1e6, "123", Exact},
{"-123", 1e6, "-123", Exact},
} {
x := makeFloat(test.x).SetPrec(test.prec)
prec := test.prec
if prec > MaxPrec {
prec = MaxPrec
}
if got := x.Prec(); got != prec {
t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec)
}
if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc {
t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc)
}
}
}
func TestFloatMinPrec(t *testing.T) {
const max = 100
for _, test := range []struct {
x string
want uint
}{
{"0", 0},
{"-0", 0},
{"+Inf", 0},
{"-Inf", 0},
{"1", 1},
{"2", 1},
{"3", 2},
{"0x8001", 16},
{"0x8001p-1000", 16},
{"0x8001p+1000", 16},
{"0.1", max},
} {
x := makeFloat(test.x).SetPrec(max)
if got := x.MinPrec(); got != test.want {
t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want)
}
}
}
func TestFloatSign(t *testing.T) {
for _, test := range []struct {
x string
s int
}{
{"-Inf", -1},
{"-1", -1},
{"-0", 0},
{"+0", 0},
{"+1", +1},
{"+Inf", +1},
} {
x := makeFloat(test.x)
s := x.Sign()
if s != test.s {
t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s)
}
}
}
// alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0).
func alike(x, y *Float) bool {
return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
}
func alike32(x, y float32) bool {
// we can ignore NaNs
return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y))
}
func alike64(x, y float64) bool {
// we can ignore NaNs
return x == y && math.Signbit(x) == math.Signbit(y)
}
func TestFloatMantExp(t *testing.T) {
for _, test := range []struct {
x string
mant string
exp int
}{
{"0", "0", 0},
{"+0", "0", 0},
{"-0", "-0", 0},
{"Inf", "+Inf", 0},
{"+Inf", "+Inf", 0},
{"-Inf", "-Inf", 0},
{"1.5", "0.75", 1},
{"1.024e3", "0.5", 11},
{"-0.125", "-0.5", -2},
} {
x := makeFloat(test.x)
mant := makeFloat(test.mant)
m := new(Float)
e := x.MantExp(m)
if !alike(m, mant) || e != test.exp {
t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Text('g', 10), e, test.mant, test.exp)
}
}
}
func TestFloatMantExpAliasing(t *testing.T) {
x := makeFloat("0.5p10")
if e := x.MantExp(x); e != 10 {
t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e)
}
if want := makeFloat("0.5"); !alike(x, want) {
t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Text('g', 10), want.Text('g', 10))
}
}
func TestFloatSetMantExp(t *testing.T) {
for _, test := range []struct {
frac string
exp int
z string
}{
{"0", 0, "0"},
{"+0", 0, "0"},
{"-0", 0, "-0"},
{"Inf", 1234, "+Inf"},
{"+Inf", -1234, "+Inf"},
{"-Inf", -1234, "-Inf"},
{"0", MinExp, "0"},
{"0.25", MinExp, "+0"}, // exponent underflow
{"-0.25", MinExp, "-0"}, // exponent underflow
{"1", MaxExp, "+Inf"}, // exponent overflow
{"2", MaxExp - 1, "+Inf"}, // exponent overflow
{"0.75", 1, "1.5"},
{"0.5", 11, "1024"},
{"-0.5", -2, "-0.125"},
{"32", 5, "1024"},
{"1024", -10, "1"},
} {
frac := makeFloat(test.frac)
want := makeFloat(test.z)
var z Float
z.SetMantExp(frac, test.exp)
if !alike(&z, want) {
t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Text('g', 10), test.z)
}
// test inverse property
mant := new(Float)
if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 {
t.Errorf("Inverse property not satisfied: got %s; want %s", z.Text('g', 10), test.z)
}
}
}
func TestFloatPredicates(t *testing.T) {
for _, test := range []struct {
x string
sign int
signbit, inf bool
}{
{x: "-Inf", sign: -1, signbit: true, inf: true},
{x: "-1", sign: -1, signbit: true},
{x: "-0", signbit: true},
{x: "0"},
{x: "1", sign: 1},
{x: "+Inf", sign: 1, inf: true},
} {
x := makeFloat(test.x)
if got := x.Signbit(); got != test.signbit {
t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit)
}
if got := x.Sign(); got != test.sign {
t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign)
}
if got := x.IsInf(); got != test.inf {
t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf)
}
}
}
func TestFloatIsInt(t *testing.T) {
for _, test := range []string{
"0 int",
"-0 int",
"1 int",
"-1 int",
"0.5",
"1.23",
"1.23e1",
"1.23e2 int",
"0.000000001e+8",
"0.000000001e+9 int",
"1.2345e200 int",
"Inf",
"+Inf",
"-Inf",
} {
s := strings.TrimSuffix(test, " int")
want := s != test
if got := makeFloat(s).IsInt(); got != want {
t.Errorf("%s.IsInt() == %t", s, got)
}
}
}
func fromBinary(s string) int64 {
x, err := strconv.ParseInt(s, 2, 64)
if err != nil {
panic(err)
}
return x
}
func toBinary(x int64) string {
return strconv.FormatInt(x, 2)
}
func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
// verify test data
var ok bool
switch mode {
case ToNearestEven, ToNearestAway:
ok = true // nothing to do for now
case ToZero:
if x < 0 {
ok = r >= x
} else {
ok = r <= x
}
case AwayFromZero:
if x < 0 {
ok = r <= x
} else {
ok = r >= x
}
case ToNegativeInf:
ok = r <= x
case ToPositiveInf:
ok = r >= x
default:
panic("unreachable")
}
if !ok {
t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r))
}
// compute expected accuracy
a := Exact
switch {
case r < x:
a = Below
case r > x:
a = Above
}
// round
f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec)
// check result
r1 := f.int64()
p1 := f.Prec()
a1 := f.Acc()
if r1 != r || p1 != prec || a1 != a {
t.Errorf("round %s (%d bits, %s) incorrect: got %s (%d bits, %s); want %s (%d bits, %s)",
toBinary(x), prec, mode,
toBinary(r1), p1, a1,
toBinary(r), prec, a)
return
}
// g and f should be the same
// (rounding by SetPrec after SetInt64 using default precision
// should be the same as rounding by SetInt64 after setting the
// precision)
g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x)
if !alike(g, f) {
t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s",
toBinary(x), prec, mode,
toBinary(g.int64()),
toBinary(r1),
toBinary(r),
)
return
}
// h and f should be the same
// (repeated rounding should be idempotent)
h := new(Float).SetMode(mode).SetPrec(prec).Set(f)
if !alike(h, f) {
t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s",
toBinary(x), prec, mode,
toBinary(h.int64()),
toBinary(r1),
toBinary(r),
)
return
}
}
// TestFloatRound tests basic rounding.
func TestFloatRound(t *testing.T) {
for _, test := range []struct {
prec uint
x, zero, neven, naway, away string // input, results rounded to prec bits
}{
{5, "1000", "1000", "1000", "1000", "1000"},
{5, "1001", "1001", "1001", "1001", "1001"},
{5, "1010", "1010", "1010", "1010", "1010"},
{5, "1011", "1011", "1011", "1011", "1011"},
{5, "1100", "1100", "1100", "1100", "1100"},
{5, "1101", "1101", "1101", "1101", "1101"},
{5, "1110", "1110", "1110", "1110", "1110"},
{5, "1111", "1111", "1111", "1111", "1111"},
{4, "1000", "1000", "1000", "1000", "1000"},
{4, "1001", "1001", "1001", "1001", "1001"},
{4, "1010", "1010", "1010", "1010", "1010"},
{4, "1011", "1011", "1011", "1011", "1011"},
{4, "1100", "1100", "1100", "1100", "1100"},
{4, "1101", "1101", "1101", "1101", "1101"},
{4, "1110", "1110", "1110", "1110", "1110"},
{4, "1111", "1111", "1111", "1111", "1111"},
{3, "1000", "1000", "1000", "1000", "1000"},
{3, "1001", "1000", "1000", "1010", "1010"},
{3, "1010", "1010", "1010", "1010", "1010"},
{3, "1011", "1010", "1100", "1100", "1100"},
{3, "1100", "1100", "1100", "1100", "1100"},
{3, "1101", "1100", "1100", "1110", "1110"},
{3, "1110", "1110", "1110", "1110", "1110"},
{3, "1111", "1110", "10000", "10000", "10000"},
{3, "1000001", "1000000", "1000000", "1000000", "1010000"},
{3, "1001001", "1000000", "1010000", "1010000", "1010000"},
{3, "1010001", "1010000", "1010000", "1010000", "1100000"},
{3, "1011001", "1010000", "1100000", "1100000", "1100000"},
{3, "1100001", "1100000", "1100000", "1100000", "1110000"},
{3, "1101001", "1100000", "1110000", "1110000", "1110000"},
{3, "1110001", "1110000", "1110000", "1110000", "10000000"},
{3, "1111001", "1110000", "10000000", "10000000", "10000000"},
{2, "1000", "1000", "1000", "1000", "1000"},
{2, "1001", "1000", "1000", "1000", "1100"},
{2, "1010", "1000", "1000", "1100", "1100"},
{2, "1011", "1000", "1100", "1100", "1100"},
{2, "1100", "1100", "1100", "1100", "1100"},
{2, "1101", "1100", "1100", "1100", "10000"},
{2, "1110", "1100", "10000", "10000", "10000"},
{2, "1111", "1100", "10000", "10000", "10000"},
{2, "1000001", "1000000", "1000000", "1000000", "1100000"},
{2, "1001001", "1000000", "1000000", "1000000", "1100000"},
{2, "1010001", "1000000", "1100000", "1100000", "1100000"},
{2, "1011001", "1000000", "1100000", "1100000", "1100000"},
{2, "1100001", "1100000", "1100000", "1100000", "10000000"},
{2, "1101001", "1100000", "1100000", "1100000", "10000000"},
{2, "1110001", "1100000", "10000000", "10000000", "10000000"},
{2, "1111001", "1100000", "10000000", "10000000", "10000000"},
{1, "1000", "1000", "1000", "1000", "1000"},
{1, "1001", "1000", "1000", "1000", "10000"},
{1, "1010", "1000", "1000", "1000", "10000"},
{1, "1011", "1000", "1000", "1000", "10000"},
{1, "1100", "1000", "10000", "10000", "10000"},
{1, "1101", "1000", "10000", "10000", "10000"},
{1, "1110", "1000", "10000", "10000", "10000"},
{1, "1111", "1000", "10000", "10000", "10000"},
{1, "1000001", "1000000", "1000000", "1000000", "10000000"},
{1, "1001001", "1000000", "1000000", "1000000", "10000000"},
{1, "1010001", "1000000", "1000000", "1000000", "10000000"},
{1, "1011001", "1000000", "1000000", "1000000", "10000000"},
{1, "1100001", "1000000", "10000000", "10000000", "10000000"},
{1, "1101001", "1000000", "10000000", "10000000", "10000000"},
{1, "1110001", "1000000", "10000000", "10000000", "10000000"},
{1, "1111001", "1000000", "10000000", "10000000", "10000000"},
} {
x := fromBinary(test.x)
z := fromBinary(test.zero)
e := fromBinary(test.neven)
n := fromBinary(test.naway)
a := fromBinary(test.away)
prec := test.prec
testFloatRound(t, x, z, prec, ToZero)
testFloatRound(t, x, e, prec, ToNearestEven)
testFloatRound(t, x, n, prec, ToNearestAway)
testFloatRound(t, x, a, prec, AwayFromZero)
testFloatRound(t, x, z, prec, ToNegativeInf)
testFloatRound(t, x, a, prec, ToPositiveInf)
testFloatRound(t, -x, -a, prec, ToNegativeInf)
testFloatRound(t, -x, -z, prec, ToPositiveInf)
}
}
// TestFloatRound24 tests that rounding a float64 to 24 bits
// matches IEEE-754 rounding to nearest when converting a
// float64 to a float32 (excluding denormal numbers).
func TestFloatRound24(t *testing.T) {
const x0 = 1<<26 - 0x10 // 11...110000 (26 bits)
for d := 0; d <= 0x10; d++ {
x := float64(x0 + d)
f := new(Float).SetPrec(24).SetFloat64(x)
got, _ := f.Float32()
want := float32(x)
if got != want {
t.Errorf("Round(%g, 24) = %g; want %g", x, got, want)
}
}
}
func TestFloatSetUint64(t *testing.T) {
for _, want := range []uint64{
0,
1,
2,
10,
100,
1<<32 - 1,
1 << 32,
1<<64 - 1,
} {
var f Float
f.SetUint64(want)
if got := f.uint64(); got != want {
t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
}
}
// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
const x uint64 = 0x8765432187654321 // 64 bits needed
for prec := uint(1); prec <= 64; prec++ {
f := new(Float).SetPrec(prec).SetMode(ToZero).SetUint64(x)
got := f.uint64()
want := x &^ (1<<(64-prec) - 1) // cut off (round to zero) low 64-prec bits
if got != want {
t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
}
}
}
func TestFloatSetInt64(t *testing.T) {
for _, want := range []int64{
0,
1,
2,
10,
100,
1<<32 - 1,
1 << 32,
1<<63 - 1,
} {
for i := range [2]int{} {
if i&1 != 0 {
want = -want
}
var f Float
f.SetInt64(want)
if got := f.int64(); got != want {
t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
}
}
}
// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
const x int64 = 0x7654321076543210 // 63 bits needed
for prec := uint(1); prec <= 63; prec++ {
f := new(Float).SetPrec(prec).SetMode(ToZero).SetInt64(x)
got := f.int64()
want := x &^ (1<<(63-prec) - 1) // cut off (round to zero) low 63-prec bits
if got != want {
t.Errorf("got %#x (%s); want %#x", got, f.Text('p', 0), want)
}
}
}
func TestFloatSetFloat64(t *testing.T) {
for _, want := range []float64{
0,
1,
2,
12345,
1e10,
1e100,
3.14159265e10,
2.718281828e-123,
1.0 / 3,
math.MaxFloat32,
math.MaxFloat64,
math.SmallestNonzeroFloat32,
math.SmallestNonzeroFloat64,
math.Inf(-1),
math.Inf(0),
-math.Inf(1),
} {
for i := range [2]int{} {
if i&1 != 0 {
want = -want
}
var f Float
f.SetFloat64(want)
if got, acc := f.Float64(); got != want || acc != Exact {
t.Errorf("got %g (%s, %s); want %g (Exact)", got, f.Text('p', 0), acc, want)
}
}
}
// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
const x uint64 = 0x8765432143218 // 53 bits needed
for prec := uint(1); prec <= 52; prec++ {
f := new(Float).SetPrec(prec).SetMode(ToZero).SetFloat64(float64(x))
got, _ := f.Float64()
want := float64(x &^ (1<<(52-prec) - 1)) // cut off (round to zero) low 53-prec bits
if got != want {
t.Errorf("got %g (%s); want %g", got, f.Text('p', 0), want)
}
}
// test NaN
defer func() {
if p, ok := recover().(ErrNaN); !ok {
t.Errorf("got %v; want ErrNaN panic", p)
}
}()
var f Float
f.SetFloat64(math.NaN())
// should not reach here
t.Errorf("got %s; want ErrNaN panic", f.Text('p', 0))
}
func TestFloatSetInt(t *testing.T) {
for _, want := range []string{
"0",
"1",
"-1",
"1234567890",
"123456789012345678901234567890",
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
} {
var x Int
_, ok := x.SetString(want, 0)
if !ok {
t.Errorf("invalid integer %s", want)
continue
}
n := x.BitLen()
var f Float
f.SetInt(&x)
// check precision
if n < 64 {
n = 64
}
if prec := f.Prec(); prec != uint(n) {
t.Errorf("got prec = %d; want %d", prec, n)
}
// check value
got := f.Text('g', 100)
if got != want {
t.Errorf("got %s (%s); want %s", got, f.Text('p', 0), want)
}
}
// TODO(gri) test basic rounding behavior
}
func TestFloatSetRat(t *testing.T) {
for _, want := range []string{
"0",
"1",
"-1",
"1234567890",
"123456789012345678901234567890",
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
"1.2",
"3.14159265",
// TODO(gri) expand
} {
var x Rat
_, ok := x.SetString(want)
if !ok {
t.Errorf("invalid fraction %s", want)
continue
}
n := max(x.Num().BitLen(), x.Denom().BitLen())
var f1, f2 Float
f2.SetPrec(1000)
f1.SetRat(&x)
f2.SetRat(&x)
// check precision when set automatically
if n < 64 {
n = 64
}
if prec := f1.Prec(); prec != uint(n) {
t.Errorf("got prec = %d; want %d", prec, n)
}
got := f2.Text('g', 100)
if got != want {
t.Errorf("got %s (%s); want %s", got, f2.Text('p', 0), want)
}
}
}
func TestFloatSetInf(t *testing.T) {
var f Float
for _, test := range []struct {
signbit bool
prec uint
want string
}{
{false, 0, "+Inf"},
{true, 0, "-Inf"},
{false, 10, "+Inf"},
{true, 30, "-Inf"},
} {
x := f.SetPrec(test.prec).SetInf(test.signbit)
if got := x.String(); got != test.want || x.Prec() != test.prec {
t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec)
}
}
}
func TestFloatUint64(t *testing.T) {
for _, test := range []struct {
x string
out uint64
acc Accuracy
}{
{"-Inf", 0, Above},
{"-1", 0, Above},
{"-1e-1000", 0, Above},
{"-0", 0, Exact},
{"0", 0, Exact},
{"1e-1000", 0, Below},
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"18446744073709551615", 18446744073709551615, Exact},
{"18446744073709551615.000000000000000000001", math.MaxUint64, Below},
{"18446744073709551616", math.MaxUint64, Below},
{"1e10000", math.MaxUint64, Below},
{"+Inf", math.MaxUint64, Below},
} {
x := makeFloat(test.x)
out, acc := x.Uint64()
if out != test.out || acc != test.acc {
t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
}
}
}
func TestFloatInt64(t *testing.T) {
for _, test := range []struct {
x string
out int64
acc Accuracy
}{
{"-Inf", math.MinInt64, Above},
{"-1e10000", math.MinInt64, Above},
{"-9223372036854775809", math.MinInt64, Above},
{"-9223372036854775808.000000000000000000001", math.MinInt64, Above},
{"-9223372036854775808", -9223372036854775808, Exact},
{"-9223372036854775807.000000000000000000001", -9223372036854775807, Above},
{"-9223372036854775807", -9223372036854775807, Exact},
{"-12345.000000000000000000001", -12345, Above},
{"-12345.0", -12345, Exact},
{"-1.000000000000000000001", -1, Above},
{"-1.5", -1, Above},
{"-1", -1, Exact},
{"-1e-1000", 0, Above},
{"0", 0, Exact},
{"1e-1000", 0, Below},
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"1.5", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"9223372036854775807", 9223372036854775807, Exact},
{"9223372036854775807.000000000000000000001", math.MaxInt64, Below},
{"9223372036854775808", math.MaxInt64, Below},
{"1e10000", math.MaxInt64, Below},
{"+Inf", math.MaxInt64, Below},
} {
x := makeFloat(test.x)
out, acc := x.Int64()
if out != test.out || acc != test.acc {
t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
}
}
}
func TestFloatFloat32(t *testing.T) {
for _, test := range []struct {
x string
out float32
acc Accuracy
}{
{"0", 0, Exact},
// underflow to zero
{"1e-1000", 0, Below},
{"0x0.000002p-127", 0, Below},
{"0x.0000010p-126", 0, Below},
// denormals
{"1.401298464e-45", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
{"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
{"0x.0000018p-126", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
{"0x.0000020p-126", math.SmallestNonzeroFloat32, Exact},
{"0x.8p-148", math.SmallestNonzeroFloat32, Exact},
{"1p-149", math.SmallestNonzeroFloat32, Exact},
{"0x.fffffep-126", math.Float32frombits(0x7fffff), Exact}, // largest denormal
// special denormal cases (see issues 14553, 14651)
{"0x0.0000001p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero
{"0x0.0000008p-126", math.Float32frombits(0x00000000), Below}, // underflow to zero
{"0x0.0000010p-126", math.Float32frombits(0x00000000), Below}, // rounded down to even
{"0x0.0000011p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal
{"0x0.0000018p-126", math.Float32frombits(0x00000001), Above}, // rounded up to smallest denormal
{"0x1.0000000p-149", math.Float32frombits(0x00000001), Exact}, // smallest denormal
{"0x0.0000020p-126", math.Float32frombits(0x00000001), Exact}, // smallest denormal
{"0x0.fffffe0p-126", math.Float32frombits(0x007fffff), Exact}, // largest denormal
{"0x1.0000000p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal
{"0x0.8p-149", math.Float32frombits(0x000000000), Below}, // rounded down to even
{"0x0.9p-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
{"0x0.ap-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
{"0x0.bp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
{"0x0.cp-149", math.Float32frombits(0x000000001), Above}, // rounded up to smallest denormal
{"0x1.0p-149", math.Float32frombits(0x000000001), Exact}, // smallest denormal
{"0x1.7p-149", math.Float32frombits(0x000000001), Below},
{"0x1.8p-149", math.Float32frombits(0x000000002), Above},
{"0x1.9p-149", math.Float32frombits(0x000000002), Above},
{"0x2.0p-149", math.Float32frombits(0x000000002), Exact},
{"0x2.8p-149", math.Float32frombits(0x000000002), Below}, // rounded down to even
{"0x2.9p-149", math.Float32frombits(0x000000003), Above},
{"0x3.0p-149", math.Float32frombits(0x000000003), Exact},
{"0x3.7p-149", math.Float32frombits(0x000000003), Below},
{"0x3.8p-149", math.Float32frombits(0x000000004), Above}, // rounded up to even
{"0x4.0p-149", math.Float32frombits(0x000000004), Exact},
{"0x4.8p-149", math.Float32frombits(0x000000004), Below}, // rounded down to even
{"0x4.9p-149", math.Float32frombits(0x000000005), Above},
// specific case from issue 14553
{"0x7.7p-149", math.Float32frombits(0x000000007), Below},
{"0x7.8p-149", math.Float32frombits(0x000000008), Above},
{"0x7.9p-149", math.Float32frombits(0x000000008), Above},
// normals
{"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal
{"1p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal
{"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact},
{"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"0x1.fffffe0p127", math.MaxFloat32, Exact},
{"0x1.fffffe8p127", math.MaxFloat32, Below},
// overflow
{"0x1.ffffff0p127", float32(math.Inf(+1)), Above},
{"0x1p128", float32(math.Inf(+1)), Above},
{"1e10000", float32(math.Inf(+1)), Above},
{"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding
// inf
{"Inf", float32(math.Inf(+1)), Exact},
} {
for i := 0; i < 2; i++ {
// test both signs
tx, tout, tacc := test.x, test.out, test.acc
if i != 0 {
tx = "-" + tx
tout = -tout
tacc = -tacc
}
// conversion should match strconv where syntax is agreeable
if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) {
t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
}
x := makeFloat(tx)
out, acc := x.Float32()
if !alike32(out, tout) || acc != tacc {
t.Errorf("%s: got %g (%#08x, %s); want %g (%#08x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc)
}
// test that x.SetFloat64(float64(f)).Float32() == f
var x2 Float
out2, acc2 := x2.SetFloat64(float64(out)).Float32()
if !alike32(out2, out) || acc2 != Exact {
t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
}
}
}
}
func TestFloatFloat64(t *testing.T) {
const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022
for _, test := range []struct {
x string
out float64
acc Accuracy
}{
{"0", 0, Exact},
// underflow to zero
{"1e-1000", 0, Below},
{"0x0.0000000000001p-1023", 0, Below},
{"0x0.00000000000008p-1022", 0, Below},
// denormals
{"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal
{"0x0.00000000000010p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal
{"0x.8p-1073", math.SmallestNonzeroFloat64, Exact},
{"1p-1074", math.SmallestNonzeroFloat64, Exact},
{"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal
// special denormal cases (see issues 14553, 14651)
{"0x0.00000000000001p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero
{"0x0.00000000000004p-1022", math.Float64frombits(0x00000000000000000), Below}, // underflow to zero
{"0x0.00000000000008p-1022", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even
{"0x0.00000000000009p-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x0.0000000000000ap-1022", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x0.8p-1074", math.Float64frombits(0x00000000000000000), Below}, // rounded down to even
{"0x0.9p-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x0.ap-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x0.bp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x0.cp-1074", math.Float64frombits(0x00000000000000001), Above}, // rounded up to smallest denormal
{"0x1.0p-1074", math.Float64frombits(0x00000000000000001), Exact},
{"0x1.7p-1074", math.Float64frombits(0x00000000000000001), Below},
{"0x1.8p-1074", math.Float64frombits(0x00000000000000002), Above},
{"0x1.9p-1074", math.Float64frombits(0x00000000000000002), Above},
{"0x2.0p-1074", math.Float64frombits(0x00000000000000002), Exact},
{"0x2.8p-1074", math.Float64frombits(0x00000000000000002), Below}, // rounded down to even
{"0x2.9p-1074", math.Float64frombits(0x00000000000000003), Above},
{"0x3.0p-1074", math.Float64frombits(0x00000000000000003), Exact},
{"0x3.7p-1074", math.Float64frombits(0x00000000000000003), Below},
{"0x3.8p-1074", math.Float64frombits(0x00000000000000004), Above}, // rounded up to even
{"0x4.0p-1074", math.Float64frombits(0x00000000000000004), Exact},
{"0x4.8p-1074", math.Float64frombits(0x00000000000000004), Below}, // rounded down to even
{"0x4.9p-1074", math.Float64frombits(0x00000000000000005), Above},
// normals
{"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal
{"1p-1022", math.Float64frombits(0x0010000000000000), Exact}, // smallest normal
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact},
{"0x1.fffffffffffff4p1023", math.MaxFloat64, Below},
// overflow
{"0x1.fffffffffffff8p1023", math.Inf(+1), Above},
{"0x1p1024", math.Inf(+1), Above},
{"1e10000", math.Inf(+1), Above},
{"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding
{"Inf", math.Inf(+1), Exact},
// selected denormalized values that were handled incorrectly in the past
{"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
{"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
{"2.2250738585072011e-308", 2.225073858507201e-308, Below},
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
{"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
} {
for i := 0; i < 2; i++ {
// test both signs
tx, tout, tacc := test.x, test.out, test.acc
if i != 0 {
tx = "-" + tx
tout = -tout
tacc = -tacc
}
// conversion should match strconv where syntax is agreeable
if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) {
t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
}
x := makeFloat(tx)
out, acc := x.Float64()
if !alike64(out, tout) || acc != tacc {
t.Errorf("%s: got %g (%#016x, %s); want %g (%#016x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc)
}
// test that x.SetFloat64(f).Float64() == f
var x2 Float
out2, acc2 := x2.SetFloat64(out).Float64()
if !alike64(out2, out) || acc2 != Exact {
t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
}
}
}
}
func TestFloatInt(t *testing.T) {
for _, test := range []struct {
x string
want string
acc Accuracy
}{
{"0", "0", Exact},
{"+0", "0", Exact},
{"-0", "0", Exact},
{"Inf", "nil", Below},
{"+Inf", "nil", Below},
{"-Inf", "nil", Above},
{"1", "1", Exact},
{"-1", "-1", Exact},
{"1.23", "1", Below},
{"-1.23", "-1", Above},
{"123e-2", "1", Below},
{"123e-3", "0", Below},
{"123e-4", "0", Below},
{"1e-1000", "0", Below},
{"-1e-1000", "0", Above},
{"1e+10", "10000000000", Exact},
{"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
} {
x := makeFloat(test.x)
res, acc := x.Int(nil)
got := "nil"
if res != nil {
got = res.String()
}
if got != test.want || acc != test.acc {
t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
}
}
// check that supplied *Int is used
for _, f := range []string{"0", "1", "-1", "1234"} {
x := makeFloat(f)
i := new(Int)
if res, _ := x.Int(i); res != i {
t.Errorf("(%s).Int is not using supplied *Int", f)
}
}
}
func TestFloatRat(t *testing.T) {
for _, test := range []struct {
x, want string
acc Accuracy
}{
{"0", "0/1", Exact},
{"+0", "0/1", Exact},
{"-0", "0/1", Exact},
{"Inf", "nil", Below},
{"+Inf", "nil", Below},
{"-Inf", "nil", Above},
{"1", "1/1", Exact},
{"-1", "-1/1", Exact},
{"1.25", "5/4", Exact},
{"-1.25", "-5/4", Exact},
{"1e10", "10000000000/1", Exact},
{"1p10", "1024/1", Exact},
{"-1p-10", "-1/1024", Exact},
{"3.14159265", "7244019449799623199/2305843009213693952", Exact},
} {
x := makeFloat(test.x).SetPrec(64)
res, acc := x.Rat(nil)
got := "nil"
if res != nil {
got = res.String()
}
if got != test.want {
t.Errorf("%s: got %s; want %s", test.x, got, test.want)
continue
}
if acc != test.acc {
t.Errorf("%s: got %s; want %s", test.x, acc, test.acc)
continue
}
// inverse conversion
if res != nil {
got := new(Float).SetPrec(64).SetRat(res)
if got.Cmp(x) != 0 {
t.Errorf("%s: got %s; want %s", test.x, got, x)
}
}
}
// check that supplied *Rat is used
for _, f := range []string{"0", "1", "-1", "1234"} {
x := makeFloat(f)
r := new(Rat)
if res, _ := x.Rat(r); res != r {
t.Errorf("(%s).Rat is not using supplied *Rat", f)
}
}
}
func TestFloatAbs(t *testing.T) {
for _, test := range []string{
"0",
"1",
"1234",
"1.23e-2",
"1e-1000",
"1e1000",
"Inf",
} {
p := makeFloat(test)
a := new(Float).Abs(p)
if !alike(a, p) {
t.Errorf("%s: got %s; want %s", test, a.Text('g', 10), test)
}
n := makeFloat("-" + test)
a.Abs(n)
if !alike(a, p) {
t.Errorf("-%s: got %s; want %s", test, a.Text('g', 10), test)
}
}
}
func TestFloatNeg(t *testing.T) {
for _, test := range []string{
"0",
"1",
"1234",
"1.23e-2",
"1e-1000",
"1e1000",
"Inf",
} {
p1 := makeFloat(test)
n1 := makeFloat("-" + test)
n2 := new(Float).Neg(p1)
p2 := new(Float).Neg(n2)
if !alike(n2, n1) {
t.Errorf("%s: got %s; want %s", test, n2.Text('g', 10), n1.Text('g', 10))
}
if !alike(p2, p1) {
t.Errorf("%s: got %s; want %s", test, p2.Text('g', 10), p1.Text('g', 10))
}
}
}
func TestFloatInc(t *testing.T) {
const n = 10
for _, prec := range precList {
if 1<<prec < n {
continue // prec must be large enough to hold all numbers from 0 to n
}
var x, one Float
x.SetPrec(prec)
one.SetInt64(1)
for i := 0; i < n; i++ {
x.Add(&x, &one)
}
if x.Cmp(new(Float).SetInt64(n)) != 0 {
t.Errorf("prec = %d: got %s; want %d", prec, &x, n)
}
}
}
// Selected precisions with which to run various tests.
var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
// Selected bits with which to run various tests.
// Each entry is a list of bits representing a floating-point number (see fromBits).
var bitsList = [...]Bits{
{}, // = 0
{0}, // = 1
{1}, // = 2
{-1}, // = 1/2
{10}, // = 2**10 == 1024
{-10}, // = 2**-10 == 1/1024
{100, 10, 1}, // = 2**100 + 2**10 + 2**1
{0, -1, -2, -10},
// TODO(gri) add more test cases
}
// TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual"
// addition/subtraction of arguments represented by Bits values with the
// respective Float addition/subtraction for a variety of precisions
// and rounding modes.
func TestFloatAdd(t *testing.T) {
for _, xbits := range bitsList {
for _, ybits := range bitsList {
// exact values
x := xbits.Float()
y := ybits.Float()
zbits := xbits.add(ybits)
z := zbits.Float()
for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
for _, prec := range precList {
got := new(Float).SetPrec(prec).SetMode(mode)
got.Add(x, y)
want := zbits.round(prec, mode)
if got.Cmp(want) != 0 {
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s",
i, prec, mode, x, xbits, y, ybits, got, want)
}
got.Sub(z, x)
want = ybits.round(prec, mode)
if got.Cmp(want) != 0 {
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s",
i, prec, mode, z, zbits, x, xbits, got, want)
}
}
}
}
}
}
// TestFloatAdd32 tests that Float.Add/Sub of numbers with
// 24bit mantissa behaves like float32 addition/subtraction
// (excluding denormal numbers).
func TestFloatAdd32(t *testing.T) {
// chose base such that we cross the mantissa precision limit
const base = 1<<26 - 0x10 // 11...110000 (26 bits)
for d := 0; d <= 0x10; d++ {
for i := range [2]int{} {
x0, y0 := float64(base), float64(d)
if i&1 != 0 {
x0, y0 = y0, x0
}
x := NewFloat(x0)
y := NewFloat(y0)
z := new(Float).SetPrec(24)
z.Add(x, y)
got, acc := z.Float32()
want := float32(y0) + float32(x0)
if got != want || acc != Exact {
t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
}
z.Sub(z, y)
got, acc = z.Float32()
want = float32(want) - float32(y0)
if got != want || acc != Exact {
t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
}
}
}
}
// TestFloatAdd64 tests that Float.Add/Sub of numbers with
// 53bit mantissa behaves like float64 addition/subtraction.
func TestFloatAdd64(t *testing.T) {
// chose base such that we cross the mantissa precision limit
const base = 1<<55 - 0x10 // 11...110000 (55 bits)
for d := 0; d <= 0x10; d++ {
for i := range [2]int{} {
x0, y0 := float64(base), float64(d)
if i&1 != 0 {
x0, y0 = y0, x0
}
x := NewFloat(x0)
y := NewFloat(y0)
z := new(Float).SetPrec(53)
z.Add(x, y)
got, acc := z.Float64()
want := x0 + y0
if got != want || acc != Exact {
t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
}
z.Sub(z, y)
got, acc = z.Float64()
want -= y0
if got != want || acc != Exact {
t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
}
}
}
}
// TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual"
// multiplication/division of arguments represented by Bits values with the
// respective Float multiplication/division for a variety of precisions
// and rounding modes.
func TestFloatMul(t *testing.T) {
for _, xbits := range bitsList {
for _, ybits := range bitsList {
// exact values
x := xbits.Float()
y := ybits.Float()
zbits := xbits.mul(ybits)
z := zbits.Float()
for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
for _, prec := range precList {
got := new(Float).SetPrec(prec).SetMode(mode)
got.Mul(x, y)
want := zbits.round(prec, mode)
if got.Cmp(want) != 0 {
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s",
i, prec, mode, x, xbits, y, ybits, got, want)
}
if x.Sign() == 0 {
continue // ignore div-0 case (not invertable)
}
got.Quo(z, x)
want = ybits.round(prec, mode)
if got.Cmp(want) != 0 {
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s",
i, prec, mode, z, zbits, x, xbits, got, want)
}
}
}
}
}
}
// TestFloatMul64 tests that Float.Mul/Quo of numbers with
// 53bit mantissa behaves like float64 multiplication/division.
func TestFloatMul64(t *testing.T) {
for _, test := range []struct {
x, y float64
}{
{0, 0},
{0, 1},
{1, 1},
{1, 1.5},
{1.234, 0.5678},
{2.718281828, 3.14159265358979},
{2.718281828e10, 3.14159265358979e-32},
{1.0 / 3, 1e200},
} {
for i := range [8]int{} {
x0, y0 := test.x, test.y
if i&1 != 0 {
x0 = -x0
}
if i&2 != 0 {
y0 = -y0
}
if i&4 != 0 {
x0, y0 = y0, x0
}
x := NewFloat(x0)
y := NewFloat(y0)
z := new(Float).SetPrec(53)
z.Mul(x, y)
got, _ := z.Float64()
want := x0 * y0
if got != want {
t.Errorf("%g * %g = %g; want %g", x0, y0, got, want)
}
if y0 == 0 {
continue // avoid division-by-zero
}
z.Quo(z, y)
got, _ = z.Float64()
want /= y0
if got != want {
t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want)
}
}
}
}
func TestIssue6866(t *testing.T) {
for _, prec := range precList {
two := new(Float).SetPrec(prec).SetInt64(2)
one := new(Float).SetPrec(prec).SetInt64(1)
three := new(Float).SetPrec(prec).SetInt64(3)
msix := new(Float).SetPrec(prec).SetInt64(-6)
psix := new(Float).SetPrec(prec).SetInt64(+6)
p := new(Float).SetPrec(prec)
z1 := new(Float).SetPrec(prec)
z2 := new(Float).SetPrec(prec)
// z1 = 2 + 1.0/3*-6
p.Quo(one, three)
p.Mul(p, msix)
z1.Add(two, p)
// z2 = 2 - 1.0/3*+6
p.Quo(one, three)
p.Mul(p, psix)
z2.Sub(two, p)
if z1.Cmp(z2) != 0 {
t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2)
}
if z1.Sign() != 0 {
t.Errorf("prec %d: got z1 = %s; want 0", prec, z1)
}
if z2.Sign() != 0 {
t.Errorf("prec %d: got z2 = %s; want 0", prec, z2)
}
}
}
func TestFloatQuo(t *testing.T) {
// TODO(gri) make the test vary these precisions
preci := 200 // precision of integer part
precf := 20 // precision of fractional part
for i := 0; i < 8; i++ {
// compute accurate (not rounded) result z
bits := Bits{preci - 1}
if i&3 != 0 {
bits = append(bits, 0)
}
if i&2 != 0 {
bits = append(bits, -1)
}
if i&1 != 0 {
bits = append(bits, -precf)
}
z := bits.Float()
// compute accurate x as z*y
y := NewFloat(3.14159265358979323e123)
x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero)
x.Mul(z, y)
// leave for debugging
// fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z)
if got := x.Acc(); got != Exact {
t.Errorf("got acc = %s; want exact", got)
}
// round accurate z for a variety of precisions and
// modes and compare against result of x / y.
for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
for d := -5; d < 5; d++ {
prec := uint(preci + d)
got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y)
want := bits.round(prec, mode)
if got.Cmp(want) != 0 {
t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s",
i, prec, mode, x, y, got, want)
}
}
}
}
}
// TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
// it serves as a smoke test for basic correctness of division.
func TestFloatQuoSmoke(t *testing.T) {
n := 1000
if testing.Short() {
n = 10
}
const dprec = 3 // max. precision variation
const prec = 10 + dprec // enough bits to hold n precisely
for x := -n; x <= n; x++ {
for y := -n; y < n; y++ {
if y == 0 {
continue
}
a := float64(x)
b := float64(y)
c := a / b
// vary operand precision (only ok as long as a, b can be represented correctly)
for ad := -dprec; ad <= dprec; ad++ {
for bd := -dprec; bd <= dprec; bd++ {
A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a)
B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b)
C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width
cc, acc := C.Float64()
if cc != c {
t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Text('g', 5), c)
continue
}
if acc != Exact {
t.Errorf("%g/%g got %s result; want exact result", a, b, acc)
}
}
}
}
}
}
// TestFloatArithmeticSpecialValues tests that Float operations produce the
// correct results for combinations of zero (±0), finite (±1 and ±2.71828),
// and infinite (±Inf) operands.
func TestFloatArithmeticSpecialValues(t *testing.T) {
zero := 0.0
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
xx := new(Float)
yy := new(Float)
got := new(Float)
want := new(Float)
for i := 0; i < 4; i++ {
for _, x := range args {
xx.SetFloat64(x)
// check conversion is correct
// (no need to do this for y, since we see exactly the
// same values there)
if got, acc := xx.Float64(); got != x || acc != Exact {
t.Errorf("Float(%g) == %g (%s)", x, got, acc)
}
for _, y := range args {
yy.SetFloat64(y)
var (
op string
z float64
f func(z, x, y *Float) *Float
)
switch i {
case 0:
op = "+"
z = x + y
f = (*Float).Add
case 1:
op = "-"
z = x - y
f = (*Float).Sub
case 2:
op = "*"
z = x * y
f = (*Float).Mul
case 3:
op = "/"
z = x / y
f = (*Float).Quo
default:
panic("unreachable")
}
var errnan bool // set if execution of f panicked with ErrNaN
// protect execution of f
func() {
defer func() {
if p := recover(); p != nil {
_ = p.(ErrNaN) // re-panic if not ErrNaN
errnan = true
}
}()
f(got, xx, yy)
}()
if math.IsNaN(z) {
if !errnan {
t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got)
}
continue
}
if errnan {
t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want)
continue
}
want.SetFloat64(z)
if !alike(got, want) {
t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
}
}
}
}
}
func TestFloatArithmeticOverflow(t *testing.T) {
for _, test := range []struct {
prec uint
mode RoundingMode
op byte
x, y, want string
acc Accuracy
}{
{4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test
{4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact}, // smoke test
{4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact},
{4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below}, // rounded to zero
{4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in +
{4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in +
{4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in -
{4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below}, // rounded to zero
{4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding
{4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding
{4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding
{4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding
{4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above}, // rounded to zero
{4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact},
{4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact},
{4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p+2147483647", Exact},
{4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in *
{4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in *
{4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact},
{4, ToNearestEven, '/', "0x.8p+0", "0x.8p2147483647", "0x.8p-2147483646", Exact},
{4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact},
{4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact},
{4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in /
} {
x := makeFloat(test.x)
y := makeFloat(test.y)
z := new(Float).SetPrec(test.prec).SetMode(test.mode)
switch test.op {
case '+':
z.Add(x, y)
case '-':
z.Sub(x, y)
case '*':
z.Mul(x, y)
case '/':
z.Quo(x, y)
default:
panic("unreachable")
}
if got := z.Text('p', 0); got != test.want || z.Acc() != test.acc {
t.Errorf(
"prec = %d (%s): %s %c %s = %s (%s); want %s (%s)",
test.prec, test.mode, x.Text('p', 0), test.op, y.Text('p', 0), got, z.Acc(), test.want, test.acc,
)
}
}
}
// TODO(gri) Add tests that check correctness in the presence of aliasing.
// For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected
// by the sign of the value to be rounded. Test that rounding happens after
// the sign of a result has been set.
// This test uses specific values that are known to fail if rounding is
// "factored" out before setting the result sign.
func TestFloatArithmeticRounding(t *testing.T) {
for _, test := range []struct {
mode RoundingMode
prec uint
x, y, want int64
op byte
}{
{ToZero, 3, -0x8, -0x1, -0x8, '+'},
{AwayFromZero, 3, -0x8, -0x1, -0xa, '+'},
{ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'},
{ToZero, 3, -0x8, 0x1, -0x8, '-'},
{AwayFromZero, 3, -0x8, 0x1, -0xa, '-'},
{ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'},
{ToZero, 3, -0x9, 0x1, -0x8, '*'},
{AwayFromZero, 3, -0x9, 0x1, -0xa, '*'},
{ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'},
{ToZero, 3, -0x9, 0x1, -0x8, '/'},
{AwayFromZero, 3, -0x9, 0x1, -0xa, '/'},
{ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'},
} {
var x, y, z Float
x.SetInt64(test.x)
y.SetInt64(test.y)
z.SetPrec(test.prec).SetMode(test.mode)
switch test.op {
case '+':
z.Add(&x, &y)
case '-':
z.Sub(&x, &y)
case '*':
z.Mul(&x, &y)
case '/':
z.Quo(&x, &y)
default:
panic("unreachable")
}
if got, acc := z.Int64(); got != test.want || acc != Exact {
t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)",
test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want,
)
}
}
}
// TestFloatCmpSpecialValues tests that Cmp produces the correct results for
// combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf)
// operands.
func TestFloatCmpSpecialValues(t *testing.T) {
zero := 0.0
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
xx := new(Float)
yy := new(Float)
for i := 0; i < 4; i++ {
for _, x := range args {
xx.SetFloat64(x)
// check conversion is correct
// (no need to do this for y, since we see exactly the
// same values there)
if got, acc := xx.Float64(); got != x || acc != Exact {
t.Errorf("Float(%g) == %g (%s)", x, got, acc)
}
for _, y := range args {
yy.SetFloat64(y)
got := xx.Cmp(yy)
want := 0
switch {
case x < y:
want = -1
case x > y:
want = +1
}
if got != want {
t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want)
}
}
}
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements string-to-Float conversion functions.
package big
import (
"fmt"
"io"
"strings"
)
// SetString sets z to the value of s and returns z and a boolean indicating
// success. s must be a floating-point number of the same format as accepted
// by Parse, with base argument 0.
func (z *Float) SetString(s string) (*Float, bool) {
if f, _, err := z.Parse(s, 0); err == nil {
return f, true
}
return nil, false
}
// scan is like Parse but reads the longest possible prefix representing a valid
// floating point number from an io.ByteScanner rather than a string. It serves
// as the implementation of Parse. It does not recognize ±Inf and does not expect
// EOF at the end.
func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
prec := z.prec
if prec == 0 {
prec = 64
}
// A reasonable value in case of an error.
z.form = zero
// sign
z.neg, err = scanSign(r)
if err != nil {
return
}
// mantissa
var fcount int // fractional digit count; valid if <= 0
z.mant, b, fcount, err = z.mant.scan(r, base, true)
if err != nil {
return
}
// exponent
var exp int64
var ebase int
exp, ebase, err = scanExponent(r, true)
if err != nil {
return
}
// special-case 0
if len(z.mant) == 0 {
z.prec = prec
z.acc = Exact
z.form = zero
f = z
return
}
// len(z.mant) > 0
// The mantissa may have a decimal point (fcount <= 0) and there
// may be a nonzero exponent exp. The decimal point amounts to a
// division by b**(-fcount). An exponent means multiplication by
// ebase**exp. Finally, mantissa normalization (shift left) requires
// a correcting multiplication by 2**(-shiftcount). Multiplications
// are commutative, so we can apply them in any order as long as there
// is no loss of precision. We only have powers of 2 and 10, and
// we split powers of 10 into the product of the same powers of
// 2 and 5. This reduces the size of the multiplication factor
// needed for base-10 exponents.
// normalize mantissa and determine initial exponent contributions
exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
exp5 := int64(0)
// determine binary or decimal exponent contribution of decimal point
if fcount < 0 {
// The mantissa has a "decimal" point ddd.dddd; and
// -fcount is the number of digits to the right of '.'.
// Adjust relevant exponent accordingly.
d := int64(fcount)
switch b {
case 10:
exp5 = d
fallthrough // 10**e == 5**e * 2**e
case 2:
exp2 += d
case 16:
exp2 += d * 4 // hexadecimal digits are 4 bits each
default:
panic("unexpected mantissa base")
}
// fcount consumed - not needed anymore
}
// take actual exponent into account
switch ebase {
case 10:
exp5 += exp
fallthrough
case 2:
exp2 += exp
default:
panic("unexpected exponent base")
}
// exp consumed - not needed anymore
// apply 2**exp2
if MinExp <= exp2 && exp2 <= MaxExp {
z.prec = prec
z.form = finite
z.exp = int32(exp2)
f = z
} else {
err = fmt.Errorf("exponent overflow")
return
}
if exp5 == 0 {
// no decimal exponent contribution
z.round(0)
return
}
// exp5 != 0
// apply 5**exp5
p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
if exp5 < 0 {
z.Quo(z, p.pow5(uint64(-exp5)))
} else {
z.Mul(z, p.pow5(uint64(exp5)))
}
return
}
// These powers of 5 fit into a uint64.
//
// for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
// fmt.Println(q)
// }
//
var pow5tab = [...]uint64{
1,
5,
25,
125,
625,
3125,
15625,
78125,
390625,
1953125,
9765625,
48828125,
244140625,
1220703125,
6103515625,
30517578125,
152587890625,
762939453125,
3814697265625,
19073486328125,
95367431640625,
476837158203125,
2384185791015625,
11920928955078125,
59604644775390625,
298023223876953125,
1490116119384765625,
7450580596923828125,
}
// pow5 sets z to 5**n and returns z.
// n must not be negative.
func (z *Float) pow5(n uint64) *Float {
const m = uint64(len(pow5tab) - 1)
if n <= m {
return z.SetUint64(pow5tab[n])
}
// n > m
z.SetUint64(pow5tab[m])
n -= m
// use more bits for f than for z
// TODO(gri) what is the right number?
f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
for n > 0 {
if n&1 != 0 {
z.Mul(z, f)
}
f.Mul(f, f)
n >>= 1
}
return z
}
// Parse parses s which must contain a text representation of a floating-
// point number with a mantissa in the given conversion base (the exponent
// is always a decimal number), or a string representing an infinite value.
//
// It sets z to the (possibly rounded) value of the corresponding floating-
// point value, and returns z, the actual base b, and an error err, if any.
// If z's precision is 0, it is changed to 64 before rounding takes effect.
// The number must be of the form:
//
// number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
// sign = "+" | "-" .
// prefix = "0" ( "x" | "X" | "b" | "B" ) .
// mantissa = digits | digits "." [ digits ] | "." digits .
// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
// digits = digit { digit } .
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
// infinity = [ sign ] ( "inf" | "Inf" ) .
//
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
// argument will lead to a run-time panic.
//
// For base 0, the number prefix determines the actual base: A prefix of
// "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
// base 2; otherwise, the actual base is 10 and no prefix is accepted.
// The octal prefix "0" is not supported (a leading "0" is simply
// considered a "0").
//
// A "p" exponent indicates a binary (rather then decimal) exponent;
// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
// maximum float64 value. For hexadecimal mantissae, the exponent must
// be binary, if present (an "e" or "E" exponent indicator cannot be
// distinguished from a mantissa digit).
//
// The returned *Float f is nil and the value of z is valid but not
// defined if an error is reported.
//
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
// scan doesn't handle ±Inf
if len(s) == 3 && (s == "Inf" || s == "inf") {
f = z.SetInf(false)
return
}
if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
f = z.SetInf(s[0] == '-')
return
}
r := strings.NewReader(s)
if f, b, err = z.scan(r, base); err != nil {
return
}
// entire string must have been consumed
if ch, err2 := r.ReadByte(); err2 == nil {
err = fmt.Errorf("expected end of string, found %q", ch)
} else if err2 != io.EOF {
err = err2
}
return
}
// ParseFloat is like f.Parse(s, base) with f set to the given precision
// and rounding mode.
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"fmt"
"math"
"strconv"
"testing"
)
func TestFloatSetFloat64String(t *testing.T) {
inf := math.Inf(0)
nan := math.NaN()
for _, test := range []struct {
s string
x float64 // NaNs represent invalid inputs
}{
// basics
{"0", 0},
{"-0", -0},
{"+0", 0},
{"1", 1},
{"-1", -1},
{"+1", 1},
{"1.234", 1.234},
{"-1.234", -1.234},
{"+1.234", 1.234},
{".1", 0.1},
{"1.", 1},
{"+1.", 1},
// various zeros
{"0e100", 0},
{"-0e+100", 0},
{"+0e-100", 0},
{"0E100", 0},
{"-0E+100", 0},
{"+0E-100", 0},
// various decimal exponent formats
{"1.e10", 1e10},
{"1e+10", 1e10},
{"+1e-10", 1e-10},
{"1E10", 1e10},
{"1.E+10", 1e10},
{"+1E-10", 1e-10},
// infinities
{"Inf", inf},
{"+Inf", inf},
{"-Inf", -inf},
{"inf", inf},
{"+inf", inf},
{"-inf", -inf},
// invalid numbers
{"", nan},
{"-", nan},
{"0x", nan},
{"0e", nan},
{"1.2ef", nan},
{"2..3", nan},
{"123..", nan},
{"infinity", nan},
{"foobar", nan},
// misc decimal values
{"3.14159265", 3.14159265},
{"-687436.79457e-245", -687436.79457e-245},
{"-687436.79457E245", -687436.79457e245},
{".0000000000000000000000000000000000000001", 1e-40},
{"+10000000000000000000000000000000000000000e-0", 1e40},
// decimal mantissa, binary exponent
{"0p0", 0},
{"-0p0", -0},
{"1p10", 1 << 10},
{"1p+10", 1 << 10},
{"+1p-10", 1.0 / (1 << 10)},
{"1024p-12", 0.25},
{"-1p10", -1024},
{"1.5p1", 3},
// binary mantissa, decimal exponent
{"0b0", 0},
{"-0b0", -0},
{"0b0e+10", 0},
{"-0b0e-10", -0},
{"0b1010", 10},
{"0B1010E2", 1000},
{"0b.1", 0.5},
{"0b.001", 0.125},
{"0b.001e3", 125},
// binary mantissa, binary exponent
{"0b0p+10", 0},
{"-0b0p-10", -0},
{"0b.1010p4", 10},
{"0b1p-1", 0.5},
{"0b001p-3", 0.125},
{"0b.001p3", 1},
{"0b0.01p2", 1},
// hexadecimal mantissa and exponent
{"0x0", 0},
{"-0x0", -0},
{"0x0p+10", 0},
{"-0x0p-10", -0},
{"0xff", 255},
{"0X.8p1", 1},
{"-0X0.00008p16", -0.5},
{"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
{"0x1.fffffffffffffp1023", math.MaxFloat64},
} {
var x Float
x.SetPrec(53)
_, ok := x.SetString(test.s)
if math.IsNaN(test.x) {
// test.s is invalid
if ok {
t.Errorf("%s: want parse error", test.s)
}
continue
}
// test.s is valid
if !ok {
t.Errorf("%s: got parse error", test.s)
continue
}
f, _ := x.Float64()
want := new(Float).SetFloat64(test.x)
if x.Cmp(want) != 0 {
t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
}
}
}
func fdiv(a, b float64) float64 { return a / b }
const (
below1e23 = 99999999999999974834176
above1e23 = 100000000000000008388608
)
func TestFloat64Text(t *testing.T) {
for _, test := range []struct {
x float64
format byte
prec int
want string
}{
{0, 'f', 0, "0"},
{math.Copysign(0, -1), 'f', 0, "-0"},
{1, 'f', 0, "1"},
{-1, 'f', 0, "-1"},
{0.001, 'e', 0, "1e-03"},
{0.459, 'e', 0, "5e-01"},
{1.459, 'e', 0, "1e+00"},
{2.459, 'e', 1, "2.5e+00"},
{3.459, 'e', 2, "3.46e+00"},
{4.459, 'e', 3, "4.459e+00"},
{5.459, 'e', 4, "5.4590e+00"},
{0.001, 'f', 0, "0"},
{0.459, 'f', 0, "0"},
{1.459, 'f', 0, "1"},
{2.459, 'f', 1, "2.5"},
{3.459, 'f', 2, "3.46"},
{4.459, 'f', 3, "4.459"},
{5.459, 'f', 4, "5.4590"},
{0, 'b', 0, "0"},
{math.Copysign(0, -1), 'b', 0, "-0"},
{1.0, 'b', 0, "4503599627370496p-52"},
{-1.0, 'b', 0, "-4503599627370496p-52"},
{4503599627370496, 'b', 0, "4503599627370496p+0"},
{0, 'p', 0, "0"},
{math.Copysign(0, -1), 'p', 0, "-0"},
{1024.0, 'p', 0, "0x.8p+11"},
{-1024.0, 'p', 0, "-0x.8p+11"},
// all test cases below from strconv/ftoa_test.go
{1, 'e', 5, "1.00000e+00"},
{1, 'f', 5, "1.00000"},
{1, 'g', 5, "1"},
{1, 'g', -1, "1"},
{20, 'g', -1, "20"},
{1234567.8, 'g', -1, "1.2345678e+06"},
{200000, 'g', -1, "200000"},
{2000000, 'g', -1, "2e+06"},
// g conversion and zero suppression
{400, 'g', 2, "4e+02"},
{40, 'g', 2, "40"},
{4, 'g', 2, "4"},
{.4, 'g', 2, "0.4"},
{.04, 'g', 2, "0.04"},
{.004, 'g', 2, "0.004"},
{.0004, 'g', 2, "0.0004"},
{.00004, 'g', 2, "4e-05"},
{.000004, 'g', 2, "4e-06"},
{0, 'e', 5, "0.00000e+00"},
{0, 'f', 5, "0.00000"},
{0, 'g', 5, "0"},
{0, 'g', -1, "0"},
{-1, 'e', 5, "-1.00000e+00"},
{-1, 'f', 5, "-1.00000"},
{-1, 'g', 5, "-1"},
{-1, 'g', -1, "-1"},
{12, 'e', 5, "1.20000e+01"},
{12, 'f', 5, "12.00000"},
{12, 'g', 5, "12"},
{12, 'g', -1, "12"},
{123456700, 'e', 5, "1.23457e+08"},
{123456700, 'f', 5, "123456700.00000"},
{123456700, 'g', 5, "1.2346e+08"},
{123456700, 'g', -1, "1.234567e+08"},
{1.2345e6, 'e', 5, "1.23450e+06"},
{1.2345e6, 'f', 5, "1234500.00000"},
{1.2345e6, 'g', 5, "1.2345e+06"},
{1e23, 'e', 17, "9.99999999999999916e+22"},
{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
{1e23, 'g', 17, "9.9999999999999992e+22"},
{1e23, 'e', -1, "1e+23"},
{1e23, 'f', -1, "100000000000000000000000"},
{1e23, 'g', -1, "1e+23"},
{below1e23, 'e', 17, "9.99999999999999748e+22"},
{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
{below1e23, 'g', 17, "9.9999999999999975e+22"},
{below1e23, 'e', -1, "9.999999999999997e+22"},
{below1e23, 'f', -1, "99999999999999970000000"},
{below1e23, 'g', -1, "9.999999999999997e+22"},
{above1e23, 'e', 17, "1.00000000000000008e+23"},
{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
{above1e23, 'g', 17, "1.0000000000000001e+23"},
{above1e23, 'e', -1, "1.0000000000000001e+23"},
{above1e23, 'f', -1, "100000000000000010000000"},
{above1e23, 'g', -1, "1.0000000000000001e+23"},
{5e-304 / 1e20, 'g', -1, "5e-324"},
{-5e-304 / 1e20, 'g', -1, "-5e-324"},
{fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic
{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
{32, 'g', -1, "32"},
{32, 'g', 0, "3e+01"},
{100, 'x', -1, "%x"},
// {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
{math.Inf(0), 'g', -1, "+Inf"},
{math.Inf(-1), 'g', -1, "-Inf"},
{-math.Inf(0), 'g', -1, "-Inf"},
{-1, 'b', -1, "-4503599627370496p-52"},
// fixed bugs
{0.9, 'f', 1, "0.9"},
{0.09, 'f', 1, "0.1"},
{0.0999, 'f', 1, "0.1"},
{0.05, 'f', 1, "0.1"},
{0.05, 'f', 0, "0"},
{0.5, 'f', 1, "0.5"},
{0.5, 'f', 0, "0"},
{1.5, 'f', 0, "2"},
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
// Issue 2625.
{383260575764816448, 'f', 0, "383260575764816448"},
{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
// Issue 15918.
{1, 'f', -10, "1"},
{1, 'f', -11, "1"},
{1, 'f', -12, "1"},
} {
// The test cases are from the strconv package which tests float64 values.
// When formatting values with prec = -1 (shortest representation),
// the actually available mantissa precision matters.
// For denormalized values, that precision is < 53 (SetFloat64 default).
// Compute and set the actual precision explicitly.
f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x)
got := f.Text(test.format, test.prec)
if got != test.want {
t.Errorf("%v: got %s; want %s", test, got, test.want)
continue
}
if test.format == 'b' && test.x == 0 {
continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
}
if test.format == 'p' {
continue // 'p' format not supported in strconv.Format
}
// verify that Float format matches strconv format
want := strconv.FormatFloat(test.x, test.format, test.prec, 64)
if got != want {
t.Errorf("%v: got %s; want %s (strconv)", test, got, want)
}
}
}
// actualPrec returns the number of actually used mantissa bits.
func actualPrec(x float64) uint {
if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 {
// x is denormalized
return 64 - nlz64(bits&(1<<52-1))
}
return 53
}
func TestFloatText(t *testing.T) {
for _, test := range []struct {
x string
prec uint
format byte
digits int
want string
}{
{"0", 10, 'f', 0, "0"},
{"-0", 10, 'f', 0, "-0"},
{"1", 10, 'f', 0, "1"},
{"-1", 10, 'f', 0, "-1"},
{"1.459", 100, 'e', 0, "1e+00"},
{"2.459", 100, 'e', 1, "2.5e+00"},
{"3.459", 100, 'e', 2, "3.46e+00"},
{"4.459", 100, 'e', 3, "4.459e+00"},
{"5.459", 100, 'e', 4, "5.4590e+00"},
{"1.459", 100, 'E', 0, "1E+00"},
{"2.459", 100, 'E', 1, "2.5E+00"},
{"3.459", 100, 'E', 2, "3.46E+00"},
{"4.459", 100, 'E', 3, "4.459E+00"},
{"5.459", 100, 'E', 4, "5.4590E+00"},
{"1.459", 100, 'f', 0, "1"},
{"2.459", 100, 'f', 1, "2.5"},
{"3.459", 100, 'f', 2, "3.46"},
{"4.459", 100, 'f', 3, "4.459"},
{"5.459", 100, 'f', 4, "5.4590"},
{"1.459", 100, 'g', 0, "1"},
{"2.459", 100, 'g', 1, "2"},
{"3.459", 100, 'g', 2, "3.5"},
{"4.459", 100, 'g', 3, "4.46"},
{"5.459", 100, 'g', 4, "5.459"},
{"1459", 53, 'g', 0, "1e+03"},
{"2459", 53, 'g', 1, "2e+03"},
{"3459", 53, 'g', 2, "3.5e+03"},
{"4459", 53, 'g', 3, "4.46e+03"},
{"5459", 53, 'g', 4, "5459"},
{"1459", 53, 'G', 0, "1E+03"},
{"2459", 53, 'G', 1, "2E+03"},
{"3459", 53, 'G', 2, "3.5E+03"},
{"4459", 53, 'G', 3, "4.46E+03"},
{"5459", 53, 'G', 4, "5459"},
{"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
{"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
{"3", 10, 'g', 40, "3"},
{"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
{"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
{"3e40", 100, 'g', 40, "3e+40"},
// make sure "stupid" exponents don't stall the machine
{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
{"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
{"1e646456993", 64, 'p', 0, "+Inf"},
{"1e1000000000", 64, 'p', 0, "+Inf"},
{"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
{"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
{"1e-646456994", 64, 'p', 0, "0"},
{"1e-1000000000", 64, 'p', 0, "0"},
// minimum and maximum values
{"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"},
{"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"},
{"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"},
{"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"},
// TODO(gri) need tests for actual large Floats
{"0", 53, 'b', 0, "0"},
{"-0", 53, 'b', 0, "-0"},
{"1.0", 53, 'b', 0, "4503599627370496p-52"},
{"-1.0", 53, 'b', 0, "-4503599627370496p-52"},
{"4503599627370496", 53, 'b', 0, "4503599627370496p+0"},
// issue 9939
{"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3", 350, 'p', 0, "0x.cp+2"},
{"03", 350, 'p', 0, "0x.cp+2"},
{"3.", 350, 'p', 0, "0x.cp+2"},
{"3.0", 350, 'p', 0, "0x.cp+2"},
{"3.00", 350, 'p', 0, "0x.cp+2"},
{"3.000", 350, 'p', 0, "0x.cp+2"},
{"0", 64, 'p', 0, "0"},
{"-0", 64, 'p', 0, "-0"},
{"1024.0", 64, 'p', 0, "0x.8p+11"},
{"-1024.0", 64, 'p', 0, "-0x.8p+11"},
// unsupported format
{"3.14", 64, 'x', 0, "%x"},
{"-3.14", 64, 'x', 0, "%x"},
} {
f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
if err != nil {
t.Errorf("%v: %s", test, err)
continue
}
got := f.Text(test.format, test.digits)
if got != test.want {
t.Errorf("%v: got %s; want %s", test, got, test.want)
}
// compare with strconv.FormatFloat output if possible
// ('p' format is not supported by strconv.FormatFloat,
// and its output for 0.0 prints a biased exponent value
// as in 0p-1074 which makes no sense to emulate here)
if test.prec == 53 && test.format != 'p' && f.Sign() != 0 {
f64, acc := f.Float64()
if acc != Exact {
t.Errorf("%v: expected exact conversion to float64", test)
continue
}
got := strconv.FormatFloat(f64, test.format, test.digits, 64)
if got != test.want {
t.Errorf("%v: got %s; want %s", test, got, test.want)
}
}
}
}
func TestFloatFormat(t *testing.T) {
for _, test := range []struct {
format string
value interface{} // float32, float64, or string (== 512bit *Float)
want string
}{
// from fmt/fmt_test.go
{"%+.3e", 0.0, "+0.000e+00"},
{"%+.3e", 1.0, "+1.000e+00"},
{"%+.3f", -1.0, "-1.000"},
{"%+.3F", -1.0, "-1.000"},
{"%+.3F", float32(-1.0), "-1.000"},
{"%+07.2f", 1.0, "+001.00"},
{"%+07.2f", -1.0, "-001.00"},
{"%+10.2f", +1.0, " +1.00"},
{"%+10.2f", -1.0, " -1.00"},
{"% .3E", -1.0, "-1.000E+00"},
{"% .3e", 1.0, " 1.000e+00"},
{"%+.3g", 0.0, "+0"},
{"%+.3g", 1.0, "+1"},
{"%+.3g", -1.0, "-1"},
{"% .3g", -1.0, "-1"},
{"% .3g", 1.0, " 1"},
{"%b", float32(1.0), "8388608p-23"},
{"%b", 1.0, "4503599627370496p-52"},
// from fmt/fmt_test.go: old test/fmt_test.go
{"%e", 1.0, "1.000000e+00"},
{"%e", 1234.5678e3, "1.234568e+06"},
{"%e", 1234.5678e-8, "1.234568e-05"},
{"%e", -7.0, "-7.000000e+00"},
{"%e", -1e-9, "-1.000000e-09"},
{"%f", 1234.5678e3, "1234567.800000"},
{"%f", 1234.5678e-8, "0.000012"},
{"%f", -7.0, "-7.000000"},
{"%f", -1e-9, "-0.000000"},
{"%g", 1234.5678e3, "1.2345678e+06"},
{"%g", float32(1234.5678e3), "1.2345678e+06"},
{"%g", 1234.5678e-8, "1.2345678e-05"},
{"%g", -7.0, "-7"},
{"%g", -1e-9, "-1e-09"},
{"%g", float32(-1e-9), "-1e-09"},
{"%E", 1.0, "1.000000E+00"},
{"%E", 1234.5678e3, "1.234568E+06"},
{"%E", 1234.5678e-8, "1.234568E-05"},
{"%E", -7.0, "-7.000000E+00"},
{"%E", -1e-9, "-1.000000E-09"},
{"%G", 1234.5678e3, "1.2345678E+06"},
{"%G", float32(1234.5678e3), "1.2345678E+06"},
{"%G", 1234.5678e-8, "1.2345678E-05"},
{"%G", -7.0, "-7"},
{"%G", -1e-9, "-1E-09"},
{"%G", float32(-1e-9), "-1E-09"},
{"%20.6e", 1.2345e3, " 1.234500e+03"},
{"%20.6e", 1.2345e-3, " 1.234500e-03"},
{"%20e", 1.2345e3, " 1.234500e+03"},
{"%20e", 1.2345e-3, " 1.234500e-03"},
{"%20.8e", 1.2345e3, " 1.23450000e+03"},
{"%20f", 1.23456789e3, " 1234.567890"},
{"%20f", 1.23456789e-3, " 0.001235"},
{"%20f", 12345678901.23456789, " 12345678901.234568"},
{"%-20f", 1.23456789e3, "1234.567890 "},
{"%20.8f", 1.23456789e3, " 1234.56789000"},
{"%20.8f", 1.23456789e-3, " 0.00123457"},
{"%g", 1.23456789e3, "1234.56789"},
{"%g", 1.23456789e-3, "0.00123456789"},
{"%g", 1.23456789e20, "1.23456789e+20"},
{"%20e", math.Inf(1), " +Inf"},
{"%-20f", math.Inf(-1), "-Inf "},
// from fmt/fmt_test.go: comparison of padding rules with C printf
{"%.2f", 1.0, "1.00"},
{"%.2f", -1.0, "-1.00"},
{"% .2f", 1.0, " 1.00"},
{"% .2f", -1.0, "-1.00"},
{"%+.2f", 1.0, "+1.00"},
{"%+.2f", -1.0, "-1.00"},
{"%7.2f", 1.0, " 1.00"},
{"%7.2f", -1.0, " -1.00"},
{"% 7.2f", 1.0, " 1.00"},
{"% 7.2f", -1.0, " -1.00"},
{"%+7.2f", 1.0, " +1.00"},
{"%+7.2f", -1.0, " -1.00"},
{"%07.2f", 1.0, "0001.00"},
{"%07.2f", -1.0, "-001.00"},
{"% 07.2f", 1.0, " 001.00"},
{"% 07.2f", -1.0, "-001.00"},
{"%+07.2f", 1.0, "+001.00"},
{"%+07.2f", -1.0, "-001.00"},
// from fmt/fmt_test.go: zero padding does not apply to infinities
{"%020f", math.Inf(-1), " -Inf"},
{"%020f", math.Inf(+1), " +Inf"},
{"% 020f", math.Inf(-1), " -Inf"},
{"% 020f", math.Inf(+1), " Inf"},
{"%+020f", math.Inf(-1), " -Inf"},
{"%+020f", math.Inf(+1), " +Inf"},
{"%20f", -1.0, " -1.000000"},
// handle %v like %g
{"%v", 0.0, "0"},
{"%v", -7.0, "-7"},
{"%v", -1e-9, "-1e-09"},
{"%v", float32(-1e-9), "-1e-09"},
{"%010v", 0.0, "0000000000"},
// *Float cases
{"%.20f", "1e-20", "0.00000000000000000001"},
{"%.20f", "-1e-20", "-0.00000000000000000001"},
{"%30.20f", "-1e-20", " -0.00000000000000000001"},
{"%030.20f", "-1e-20", "-00000000.00000000000000000001"},
{"%030.20f", "+1e-20", "000000000.00000000000000000001"},
{"% 030.20f", "+1e-20", " 00000000.00000000000000000001"},
// erroneous formats
{"%s", 1.0, "%!s(*big.Float=1)"},
} {
value := new(Float)
switch v := test.value.(type) {
case float32:
value.SetPrec(24).SetFloat64(float64(v))
case float64:
value.SetPrec(53).SetFloat64(v)
case string:
value.SetPrec(512).Parse(v, 0)
default:
t.Fatalf("unsupported test value: %v (%T)", v, v)
}
if got := fmt.Sprintf(test.format, value); got != test.want {
t.Errorf("%v: got %q; want %q", test, got, test.want)
}
}
}
func BenchmarkParseFloatSmallExp(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, s := range []string{
"1e0",
"1e-1",
"1e-2",
"1e-3",
"1e-4",
"1e-5",
"1e-10",
"1e-20",
"1e-50",
"1e1",
"1e2",
"1e3",
"1e4",
"1e5",
"1e10",
"1e20",
"1e50",
} {
var x Float
_, _, err := x.Parse(s, 0)
if err != nil {
b.Fatalf("%s: %v", s, err)
}
}
}
}
func BenchmarkParseFloatLargeExp(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, s := range []string{
"1e0",
"1e-10",
"1e-20",
"1e-30",
"1e-40",
"1e-50",
"1e-100",
"1e-500",
"1e-1000",
"1e-5000",
"1e-10000",
"1e10",
"1e20",
"1e30",
"1e40",
"1e50",
"1e100",
"1e500",
"1e1000",
"1e5000",
"1e10000",
} {
var x Float
_, _, err := x.Parse(s, 0)
if err != nil {
b.Fatalf("%s: %v", s, err)
}
}
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big_test
import (
"cmd/compile/internal/big"
"fmt"
"math"
)
func ExampleFloat_Add() {
// Operate on numbers of different precision.
var x, y, z big.Float
x.SetInt64(1000) // x is automatically set to 64bit precision
y.SetFloat64(2.718281828) // y is automatically set to 53bit precision
z.SetPrec(32)
z.Add(&x, &y)
fmt.Printf("x = %.10g (%s, prec = %d, acc = %s)\n", &x, x.Text('p', 0), x.Prec(), x.Acc())
fmt.Printf("y = %.10g (%s, prec = %d, acc = %s)\n", &y, y.Text('p', 0), y.Prec(), y.Acc())
fmt.Printf("z = %.10g (%s, prec = %d, acc = %s)\n", &z, z.Text('p', 0), z.Prec(), z.Acc())
// Output:
// x = 1000 (0x.fap+10, prec = 64, acc = Exact)
// y = 2.718281828 (0x.adf85458248cd8p+2, prec = 53, acc = Exact)
// z = 1002.718282 (0x.faadf854p+10, prec = 32, acc = Below)
}
func ExampleFloat_shift() {
// Implement Float "shift" by modifying the (binary) exponents directly.
for s := -5; s <= 5; s++ {
x := big.NewFloat(0.5)
x.SetMantExp(x, x.MantExp(nil)+s) // shift x by s
fmt.Println(x)
}
// Output:
// 0.015625
// 0.03125
// 0.0625
// 0.125
// 0.25
// 0.5
// 1
// 2
// 4
// 8
// 16
}
func ExampleFloat_Cmp() {
inf := math.Inf(1)
zero := 0.0
operands := []float64{-inf, -1.2, -zero, 0, +1.2, +inf}
fmt.Println(" x y cmp")
fmt.Println("---------------")
for _, x64 := range operands {
x := big.NewFloat(x64)
for _, y64 := range operands {
y := big.NewFloat(y64)
fmt.Printf("%4g %4g %3d\n", x, y, x.Cmp(y))
}
fmt.Println()
}
// Output:
// x y cmp
// ---------------
// -Inf -Inf 0
// -Inf -1.2 -1
// -Inf -0 -1
// -Inf 0 -1
// -Inf 1.2 -1
// -Inf +Inf -1
//
// -1.2 -Inf 1
// -1.2 -1.2 0
// -1.2 -0 -1
// -1.2 0 -1
// -1.2 1.2 -1
// -1.2 +Inf -1
//
// -0 -Inf 1
// -0 -1.2 1
// -0 -0 0
// -0 0 0
// -0 1.2 -1
// -0 +Inf -1
//
// 0 -Inf 1
// 0 -1.2 1
// 0 -0 0
// 0 0 0
// 0 1.2 -1
// 0 +Inf -1
//
// 1.2 -Inf 1
// 1.2 -1.2 1
// 1.2 -0 1
// 1.2 0 1
// 1.2 1.2 0
// 1.2 +Inf -1
//
// +Inf -Inf 1
// +Inf -1.2 1
// +Inf -0 1
// +Inf 0 1
// +Inf 1.2 1
// +Inf +Inf 0
}
func ExampleRoundingMode() {
operands := []float64{2.6, 2.5, 2.1, -2.1, -2.5, -2.6}
fmt.Print(" x")
for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
fmt.Printf(" %s", mode)
}
fmt.Println()
for _, f64 := range operands {
fmt.Printf("%4g", f64)
for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
// sample operands above require 2 bits to represent mantissa
// set binary precision to 2 to round them to integer values
f := new(big.Float).SetPrec(2).SetMode(mode).SetFloat64(f64)
fmt.Printf(" %*g", len(mode.String()), f)
}
fmt.Println()
}
// Output:
// x ToNearestEven ToNearestAway ToZero AwayFromZero ToNegativeInf ToPositiveInf
// 2.6 3 3 2 3 2 3
// 2.5 2 3 2 3 2 3
// 2.1 2 2 2 3 2 3
// -2.1 -2 -2 -2 -3 -3 -2
// -2.5 -2 -3 -2 -3 -3 -2
// -2.6 -3 -3 -2 -3 -3 -2
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements encoding/decoding of Floats.
package big
import (
"encoding/binary"
"fmt"
)
// Gob codec version. Permits backward-compatible changes to the encoding.
const floatGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
// The Float value and all its attributes (precision,
// rounding mode, accuracy) are marshalled.
func (x *Float) GobEncode() ([]byte, error) {
if x == nil {
return nil, nil
}
// determine max. space (bytes) required for encoding
sz := 1 + 1 + 4 // version + mode|acc|form|neg (3+2+2+1bit) + prec
n := 0 // number of mantissa words
if x.form == finite {
// add space for mantissa and exponent
n = int((x.prec + (_W - 1)) / _W) // required mantissa length in words for given precision
// actual mantissa slice could be shorter (trailing 0's) or longer (unused bits):
// - if shorter, only encode the words present
// - if longer, cut off unused words when encoding in bytes
// (in practice, this should never happen since rounding
// takes care of it, but be safe and do it always)
if len(x.mant) < n {
n = len(x.mant)
}
// len(x.mant) >= n
sz += 4 + n*_S // exp + mant
}
buf := make([]byte, sz)
buf[0] = floatGobVersion
b := byte(x.mode&7)<<5 | byte((x.acc+1)&3)<<3 | byte(x.form&3)<<1
if x.neg {
b |= 1
}
buf[1] = b
binary.BigEndian.PutUint32(buf[2:], x.prec)
if x.form == finite {
binary.BigEndian.PutUint32(buf[6:], uint32(x.exp))
x.mant[len(x.mant)-n:].bytes(buf[10:]) // cut off unused trailing words
}
return buf, nil
}
// GobDecode implements the gob.GobDecoder interface.
// The result is rounded per the precision and rounding mode of
// z unless z's precision is 0, in which case z is set exactly
// to the decoded value.
func (z *Float) GobDecode(buf []byte) error {
if len(buf) == 0 {
// Other side sent a nil or default value.
*z = Float{}
return nil
}
if buf[0] != floatGobVersion {
return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0])
}
oldPrec := z.prec
oldMode := z.mode
b := buf[1]
z.mode = RoundingMode((b >> 5) & 7)
z.acc = Accuracy((b>>3)&3) - 1
z.form = form((b >> 1) & 3)
z.neg = b&1 != 0
z.prec = binary.BigEndian.Uint32(buf[2:])
if z.form == finite {
z.exp = int32(binary.BigEndian.Uint32(buf[6:]))
z.mant = z.mant.setBytes(buf[10:])
}
if oldPrec != 0 {
z.mode = oldMode
z.SetPrec(uint(oldPrec))
}
return nil
}
// MarshalText implements the encoding.TextMarshaler interface.
// Only the Float value is marshaled (in full precision), other
// attributes such as precision or accuracy are ignored.
func (x *Float) MarshalText() (text []byte, err error) {
if x == nil {
return []byte("<nil>"), 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
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"bytes"
"encoding/gob"
"encoding/json"
"io"
"testing"
)
var floatVals = []string{
"0",
"1",
"0.1",
"2.71828",
"1234567890",
"3.14e1234",
"3.14e-1234",
"0.738957395793475734757349579759957975985497e100",
"0.73895739579347546656564656573475734957975995797598589749859834759476745986795497e100",
"inf",
"Inf",
}
func TestFloatGobEncoding(t *testing.T) {
var medium bytes.Buffer
enc := gob.NewEncoder(&medium)
dec := gob.NewDecoder(&medium)
for _, test := range floatVals {
for _, sign := range []string{"", "+", "-"} {
for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
for _, mode := range []RoundingMode{ToNearestEven, ToNearestAway, ToZero, AwayFromZero, ToNegativeInf, ToPositiveInf} {
medium.Reset() // empty buffer for each test case (in case of failures)
x := sign + test
var tx Float
_, _, err := tx.SetPrec(prec).SetMode(mode).Parse(x, 0)
if err != nil {
t.Errorf("parsing of %s (%dbits, %v) failed (invalid test case): %v", x, prec, mode, err)
continue
}
// If tx was set to prec == 0, tx.Parse(x, 0) assumes precision 64. Correct it.
if prec == 0 {
tx.SetPrec(0)
}
if err := enc.Encode(&tx); err != nil {
t.Errorf("encoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err)
continue
}
var rx Float
if err := dec.Decode(&rx); err != nil {
t.Errorf("decoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err)
continue
}
if rx.Cmp(&tx) != 0 {
t.Errorf("transmission of %s failed: got %s want %s", x, rx.String(), tx.String())
continue
}
if rx.Prec() != prec {
t.Errorf("transmission of %s's prec failed: got %d want %d", x, rx.Prec(), prec)
}
if rx.Mode() != mode {
t.Errorf("transmission of %s's mode failed: got %s want %s", x, rx.Mode(), mode)
}
if rx.Acc() != tx.Acc() {
t.Errorf("transmission of %s's accuracy failed: got %s want %s", x, rx.Acc(), tx.Acc())
}
}
}
}
}
}
func TestFloatCorruptGob(t *testing.T) {
var buf bytes.Buffer
tx := NewFloat(4 / 3).SetPrec(1000).SetMode(ToPositiveInf)
if err := gob.NewEncoder(&buf).Encode(tx); err != nil {
t.Fatal(err)
}
b := buf.Bytes()
var rx Float
if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err != nil {
t.Fatal(err)
}
if err := gob.NewDecoder(bytes.NewReader(b[:10])).Decode(&rx); err != io.ErrUnexpectedEOF {
t.Errorf("got %v want EOF", err)
}
b[1] = 0
if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err == nil {
t.Fatal("got nil want version error")
}
}
func TestFloatJSONEncoding(t *testing.T) {
for _, test := range floatVals {
for _, sign := range []string{"", "+", "-"} {
for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
x := sign + test
var tx Float
_, _, err := tx.SetPrec(prec).Parse(x, 0)
if err != nil {
t.Errorf("parsing of %s (prec = %d) failed (invalid test case): %v", x, prec, err)
continue
}
b, err := json.Marshal(&tx)
if err != nil {
t.Errorf("marshaling of %v (prec = %d) failed: %v", &tx, prec, err)
continue
}
var rx Float
rx.SetPrec(prec)
if err := json.Unmarshal(b, &rx); err != nil {
t.Errorf("unmarshaling of %v (prec = %d) failed: %v", &tx, prec, err)
continue
}
if rx.Cmp(&tx) != 0 {
t.Errorf("JSON encoding of %v (prec = %d) failed: got %v want %v", &tx, prec, &rx, &tx)
}
}
}
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements Float-to-string conversion functions.
// It is closely following the corresponding implementation
// in strconv/ftoa.go, but modified and simplified for Float.
package big
import (
"bytes"
"fmt"
"strconv"
)
// Text converts the floating-point number x to a string according
// to the given format and precision prec. The format is one of:
//
// 'e' -d.dddde±dd, decimal exponent, at least two (possibly 0) exponent digits
// 'E' -d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
// 'f' -ddddd.dddd, no exponent
// 'g' like 'e' for large exponents, like 'f' otherwise
// 'G' like 'E' for large exponents, like 'f' otherwise
// 'b' -ddddddp±dd, binary exponent
// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
//
// For the binary exponent formats, the mantissa is printed in normalized form:
//
// 'b' decimal integer mantissa using x.Prec() bits, or -0
// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
//
// If format is a different character, Text returns a "%" followed by the
// unrecognized format character.
//
// The precision prec controls the number of digits (excluding the exponent)
// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
// it is the number of digits after the decimal point. For 'g' and 'G' it is
// the total number of digits. A negative precision selects the smallest
// number of decimal digits necessary to identify the value x uniquely using
// x.Prec() mantissa bits.
// The prec value is ignored for the 'b' or 'p' format.
func (x *Float) Text(format byte, prec int) string {
cap := 10 // TODO(gri) determine a good/better value here
if prec > 0 {
cap += prec
}
return string(x.Append(make([]byte, 0, cap), format, prec))
}
// String formats x like x.Text('g', 10).
// (String must be called explicitly, Float.Format does not support %s verb.)
func (x *Float) String() string {
return x.Text('g', 10)
}
// Append appends to buf the string form of the floating-point number x,
// as generated by x.Text, and returns the extended buffer.
func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
// sign
if x.neg {
buf = append(buf, '-')
}
// Inf
if x.form == inf {
if !x.neg {
buf = append(buf, '+')
}
return append(buf, "Inf"...)
}
// pick off easy formats
switch fmt {
case 'b':
return x.fmtB(buf)
case 'p':
return x.fmtP(buf)
}
// Algorithm:
// 1) convert Float to multiprecision decimal
// 2) round to desired precision
// 3) read digits out and format
// 1) convert Float to multiprecision decimal
var d decimal // == 0.0
if x.form == finite {
// x != 0
d.init(x.mant, int(x.exp)-x.mant.bitLen())
}
// 2) round to desired precision
shortest := false
if prec < 0 {
shortest = true
roundShortest(&d, x)
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = len(d.mant) - 1
case 'f':
prec = max(len(d.mant)-d.exp, 0)
case 'g', 'G':
prec = len(d.mant)
}
} else {
// round appropriately
switch fmt {
case 'e', 'E':
// one digit before and number of digits after decimal point
d.round(1 + prec)
case 'f':
// number of digits before and after decimal point
d.round(d.exp + prec)
case 'g', 'G':
if prec == 0 {
prec = 1
}
d.round(prec)
}
}
// 3) read digits out and format
switch fmt {
case 'e', 'E':
return fmtE(buf, fmt, prec, d)
case 'f':
return fmtF(buf, prec, d)
case 'g', 'G':
// trim trailing fractional zeros in %e format
eprec := prec
if eprec > len(d.mant) && len(d.mant) >= d.exp {
eprec = len(d.mant)
}
// %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision.
// If precision was the shortest possible, use eprec = 6 for
// this decision.
if shortest {
eprec = 6
}
exp := d.exp - 1
if exp < -4 || exp >= eprec {
if prec > len(d.mant) {
prec = len(d.mant)
}
return fmtE(buf, fmt+'e'-'g', prec-1, d)
}
if prec > d.exp {
prec = len(d.mant)
}
return fmtF(buf, max(prec-d.exp, 0), d)
}
// unknown format
if x.neg {
buf = buf[:len(buf)-1] // sign was added prematurely - remove it again
}
return append(buf, '%', fmt)
}
func roundShortest(d *decimal, x *Float) {
// if the mantissa is zero, the number is zero - stop now
if len(d.mant) == 0 {
return
}
// Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp]
// (possibly exclusive) round to x for the given precision of x.
// Compute the lower and upper bound in decimal form and find the
// shortest decimal number d such that lower <= d <= upper.
// TODO(gri) strconv/ftoa.do describes a shortcut in some cases.
// See if we can use it (in adjusted form) here as well.
// 1) Compute normalized mantissa mant and exponent exp for x such
// that the lsb of mant corresponds to 1/2 ulp for the precision of
// x (i.e., for mant we want x.prec + 1 bits).
mant := nat(nil).set(x.mant)
exp := int(x.exp) - mant.bitLen()
s := mant.bitLen() - int(x.prec+1)
switch {
case s < 0:
mant = mant.shl(mant, uint(-s))
case s > 0:
mant = mant.shr(mant, uint(+s))
}
exp += s
// x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec
// 2) Compute lower bound by subtracting 1/2 ulp.
var lower decimal
var tmp nat
lower.init(tmp.sub(mant, natOne), exp)
// 3) Compute upper bound by adding 1/2 ulp.
var upper decimal
upper.init(tmp.add(mant, natOne), exp)
// The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that ToNearestEven rounding
// would round to the original mantissa and not the neighbors.
inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1
// Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower.
for i, m := range d.mant {
l := lower.at(i)
u := upper.at(i)
// Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding
// down (i.e., and we have reached the final digit of lower).
okdown := l != m || inclusive && i+1 == len(lower.mant)
// Okay to round up if upper has a different digit and either upper
// is inclusive or upper is bigger than the result of rounding up.
okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
// If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it.
switch {
case okdown && okup:
d.round(i + 1)
return
case okdown:
d.roundDown(i + 1)
return
case okup:
d.roundUp(i + 1)
return
}
}
}
// %e: d.ddddde±dd
func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
// first digit
ch := byte('0')
if len(d.mant) > 0 {
ch = d.mant[0]
}
buf = append(buf, ch)
// .moredigits
if prec > 0 {
buf = append(buf, '.')
i := 1
m := min(len(d.mant), prec+1)
if i < m {
buf = append(buf, d.mant[i:m]...)
i = m
}
for ; i <= prec; i++ {
buf = append(buf, '0')
}
}
// e±
buf = append(buf, fmt)
var exp int64
if len(d.mant) > 0 {
exp = int64(d.exp) - 1 // -1 because first digit was printed before '.'
}
if exp < 0 {
ch = '-'
exp = -exp
} else {
ch = '+'
}
buf = append(buf, ch)
// dd...d
if exp < 10 {
buf = append(buf, '0') // at least 2 exponent digits
}
return strconv.AppendInt(buf, exp, 10)
}
// %f: ddddddd.ddddd
func fmtF(buf []byte, prec int, d decimal) []byte {
// integer, padded with zeros as needed
if d.exp > 0 {
m := min(len(d.mant), d.exp)
buf = append(buf, d.mant[:m]...)
for ; m < d.exp; m++ {
buf = append(buf, '0')
}
} else {
buf = append(buf, '0')
}
// fraction
if prec > 0 {
buf = append(buf, '.')
for i := 0; i < prec; i++ {
buf = append(buf, d.at(d.exp+i))
}
}
return buf
}
// fmtB appends the string of x in the format mantissa "p" exponent
// with a decimal mantissa and a binary exponent, or 0" if x is zero,
// and returns the extended buffer.
// The mantissa is normalized such that is uses x.Prec() bits in binary
// representation.
// The sign of x is ignored, and x must not be an Inf.
func (x *Float) fmtB(buf []byte) []byte {
if x.form == zero {
return append(buf, '0')
}
if debugFloat && x.form != finite {
panic("non-finite float")
}
// x != 0
// adjust mantissa to use exactly x.prec bits
m := x.mant
switch w := uint32(len(x.mant)) * _W; {
case w < x.prec:
m = nat(nil).shl(m, uint(x.prec-w))
case w > x.prec:
m = nat(nil).shr(m, uint(w-x.prec))
}
buf = append(buf, m.utoa(10)...)
buf = append(buf, 'p')
e := int64(x.exp) - int64(x.prec)
if e >= 0 {
buf = append(buf, '+')
}
return strconv.AppendInt(buf, e, 10)
}
// fmtP appends the string of x in the format "0x." mantissa "p" exponent
// with a hexadecimal mantissa and a binary exponent, or "0" if x is zero,
// and returns the extended buffer.
// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
// The sign of x is ignored, and x must not be an Inf.
func (x *Float) fmtP(buf []byte) []byte {
if x.form == zero {
return append(buf, '0')
}
if debugFloat && x.form != finite {
panic("non-finite float")
}
// x != 0
// remove trailing 0 words early
// (no need to convert to hex 0's and trim later)
m := x.mant
i := 0
for i < len(m) && m[i] == 0 {
i++
}
m = m[i:]
buf = append(buf, "0x."...)
buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
buf = append(buf, 'p')
if x.exp >= 0 {
buf = append(buf, '+')
}
return strconv.AppendInt(buf, int64(x.exp), 10)
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
// Format implements fmt.Formatter. It accepts all the regular
// formats for floating-point numbers ('b', 'e', 'E', 'f', 'F',
// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the
// interpretation of 'p'. The 'v' format is handled like 'g'.
// Format also supports specification of the minimum precision
// in digits, the output field width, as well as the format flags
// '+' and ' ' for sign control, '0' for space or zero padding,
// and '-' for left or right justification. See the fmt package
// for details.
func (x *Float) Format(s fmt.State, format rune) {
prec, hasPrec := s.Precision()
if !hasPrec {
prec = 6 // default precision for 'e', 'f'
}
switch format {
case 'e', 'E', 'f', 'b', 'p':
// nothing to do
case 'F':
// (*Float).Text doesn't support 'F'; handle like 'f'
format = 'f'
case 'v':
// handle like 'g'
format = 'g'
fallthrough
case 'g', 'G':
if !hasPrec {
prec = -1 // default precision for 'g', 'G'
}
default:
fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
return
}
var buf []byte
buf = x.Append(buf, byte(format), prec)
if len(buf) == 0 {
buf = []byte("?") // should never happen, but don't crash
}
// len(buf) > 0
var sign string
switch {
case buf[0] == '-':
sign = "-"
buf = buf[1:]
case buf[0] == '+':
// +Inf
sign = "+"
if s.Flag(' ') {
sign = " "
}
buf = buf[1:]
case s.Flag('+'):
sign = "+"
case s.Flag(' '):
sign = " "
}
var padding int
if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
padding = width - len(sign) - len(buf)
}
switch {
case s.Flag('0') && !x.IsInf():
// 0-padding on left
writeMultiple(s, sign, 1)
writeMultiple(s, "0", padding)
s.Write(buf)
case s.Flag('-'):
// padding on right
writeMultiple(s, sign, 1)
s.Write(buf)
writeMultiple(s, " ", padding)
default:
// padding on left
writeMultiple(s, " ", padding)
writeMultiple(s, sign, 1)
s.Write(buf)
}
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements a GCD benchmark.
// Usage: go test math/big -test.bench GCD
package big
import (
"math/rand"
"testing"
)
// randInt returns a pseudo-random Int in the range [1<<(size-1), (1<<size) - 1]
func randInt(r *rand.Rand, size uint) *Int {
n := new(Int).Lsh(intOne, size-1)
x := new(Int).Rand(r, n)
return x.Add(x, n) // make sure result > 1<<(size-1)
}
func runGCD(b *testing.B, aSize, bSize uint) {
b.Run("WithoutXY", func(b *testing.B) {
runGCDExt(b, aSize, bSize, false)
})
b.Run("WithXY", func(b *testing.B) {
runGCDExt(b, aSize, bSize, true)
})
}
func runGCDExt(b *testing.B, aSize, bSize uint, calcXY bool) {
b.StopTimer()
var r = rand.New(rand.NewSource(1234))
aa := randInt(r, aSize)
bb := randInt(r, bSize)
var x, y *Int
if calcXY {
x = new(Int)
y = new(Int)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
new(Int).GCD(x, y, aa, bb)
}
}
func BenchmarkGCD10x10(b *testing.B) { runGCD(b, 10, 10) }
func BenchmarkGCD10x100(b *testing.B) { runGCD(b, 10, 100) }
func BenchmarkGCD10x1000(b *testing.B) { runGCD(b, 10, 1000) }
func BenchmarkGCD10x10000(b *testing.B) { runGCD(b, 10, 10000) }
func BenchmarkGCD10x100000(b *testing.B) { runGCD(b, 10, 100000) }
func BenchmarkGCD100x100(b *testing.B) { runGCD(b, 100, 100) }
func BenchmarkGCD100x1000(b *testing.B) { runGCD(b, 100, 1000) }
func BenchmarkGCD100x10000(b *testing.B) { runGCD(b, 100, 10000) }
func BenchmarkGCD100x100000(b *testing.B) { runGCD(b, 100, 100000) }
func BenchmarkGCD1000x1000(b *testing.B) { runGCD(b, 1000, 1000) }
func BenchmarkGCD1000x10000(b *testing.B) { runGCD(b, 1000, 10000) }
func BenchmarkGCD1000x100000(b *testing.B) { runGCD(b, 1000, 100000) }
func BenchmarkGCD10000x10000(b *testing.B) { runGCD(b, 10000, 10000) }
func BenchmarkGCD10000x100000(b *testing.B) { runGCD(b, 10000, 100000) }
func BenchmarkGCD100000x100000(b *testing.B) { runGCD(b, 100000, 100000) }
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// A little test program and benchmark for rational arithmetics.
// Computes a Hilbert matrix, its inverse, multiplies them
// and verifies that the product is the identity matrix.
package big
import (
"fmt"
"testing"
)
type matrix struct {
n, m int
a []*Rat
}
func (a *matrix) at(i, j int) *Rat {
if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
panic("index out of range")
}
return a.a[i*a.m+j]
}
func (a *matrix) set(i, j int, x *Rat) {
if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
panic("index out of range")
}
a.a[i*a.m+j] = x
}
func newMatrix(n, m int) *matrix {
if !(0 <= n && 0 <= m) {
panic("illegal matrix")
}
a := new(matrix)
a.n = n
a.m = m
a.a = make([]*Rat, n*m)
return a
}
func newUnit(n int) *matrix {
a := newMatrix(n, n)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
x := NewRat(0, 1)
if i == j {
x.SetInt64(1)
}
a.set(i, j, x)
}
}
return a
}
func newHilbert(n int) *matrix {
a := newMatrix(n, n)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
a.set(i, j, NewRat(1, int64(i+j+1)))
}
}
return a
}
func newInverseHilbert(n int) *matrix {
a := newMatrix(n, n)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
x1 := new(Rat).SetInt64(int64(i + j + 1))
x2 := new(Rat).SetInt(new(Int).Binomial(int64(n+i), int64(n-j-1)))
x3 := new(Rat).SetInt(new(Int).Binomial(int64(n+j), int64(n-i-1)))
x4 := new(Rat).SetInt(new(Int).Binomial(int64(i+j), int64(i)))
x1.Mul(x1, x2)
x1.Mul(x1, x3)
x1.Mul(x1, x4)
x1.Mul(x1, x4)
if (i+j)&1 != 0 {
x1.Neg(x1)
}
a.set(i, j, x1)
}
}
return a
}
func (a *matrix) mul(b *matrix) *matrix {
if a.m != b.n {
panic("illegal matrix multiply")
}
c := newMatrix(a.n, b.m)
for i := 0; i < c.n; i++ {
for j := 0; j < c.m; j++ {
x := NewRat(0, 1)
for k := 0; k < a.m; k++ {
x.Add(x, new(Rat).Mul(a.at(i, k), b.at(k, j)))
}
c.set(i, j, x)
}
}
return c
}
func (a *matrix) eql(b *matrix) bool {
if a.n != b.n || a.m != b.m {
return false
}
for i := 0; i < a.n; i++ {
for j := 0; j < a.m; j++ {
if a.at(i, j).Cmp(b.at(i, j)) != 0 {
return false
}
}
}
return true
}
func (a *matrix) String() string {
s := ""
for i := 0; i < a.n; i++ {
for j := 0; j < a.m; j++ {
s += fmt.Sprintf("\t%s", a.at(i, j))
}
s += "\n"
}
return s
}
func doHilbert(t *testing.T, n int) {
a := newHilbert(n)
b := newInverseHilbert(n)
I := newUnit(n)
ab := a.mul(b)
if !ab.eql(I) {
if t == nil {
panic("Hilbert failed")
}
t.Errorf("a = %s\n", a)
t.Errorf("b = %s\n", b)
t.Errorf("a*b = %s\n", ab)
t.Errorf("I = %s\n", I)
}
}
func TestHilbert(t *testing.T) {
doHilbert(t, 10)
}
func BenchmarkHilbert(b *testing.B) {
for i := 0; i < b.N; i++ {
doHilbert(nil, 10)
}
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements signed multi-precision integers.
package big
import (
"fmt"
"io"
"math/rand"
"strings"
)
// An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0.
type Int struct {
neg bool // sign
abs nat // absolute value of the integer
}
var intOne = &Int{false, natOne}
// Sign returns:
//
// -1 if x < 0
// 0 if x == 0
// +1 if x > 0
//
func (x *Int) Sign() int {
if len(x.abs) == 0 {
return 0
}
if x.neg {
return -1
}
return 1
}
// SetInt64 sets z to x and returns z.
func (z *Int) SetInt64(x int64) *Int {
neg := false
if x < 0 {
neg = true
x = -x
}
z.abs = z.abs.setUint64(uint64(x))
z.neg = neg
return z
}
// SetUint64 sets z to x and returns z.
func (z *Int) SetUint64(x uint64) *Int {
z.abs = z.abs.setUint64(x)
z.neg = false
return z
}
// NewInt allocates and returns a new Int set to x.
func NewInt(x int64) *Int {
return new(Int).SetInt64(x)
}
// Set sets z to x and returns z.
func (z *Int) Set(x *Int) *Int {
if z != x {
z.abs = z.abs.set(x.abs)
z.neg = x.neg
}
return z
}
// Bits provides raw (unchecked but fast) access to x by returning its
// absolute value as a little-endian Word slice. The result and x share
// the same underlying array.
// Bits is intended to support implementation of missing low-level Int
// functionality outside this package; it should be avoided otherwise.
func (x *Int) Bits() []Word {
return x.abs
}
// SetBits provides raw (unchecked but fast) access to z by setting its
// value to abs, interpreted as a little-endian Word slice, and returning
// z. The result and abs share the same underlying array.
// SetBits is intended to support implementation of missing low-level Int
// functionality outside this package; it should be avoided otherwise.
func (z *Int) SetBits(abs []Word) *Int {
z.abs = nat(abs).norm()
z.neg = false
return z
}
// Abs sets z to |x| (the absolute value of x) and returns z.
func (z *Int) Abs(x *Int) *Int {
z.Set(x)
z.neg = false
return z
}
// Neg sets z to -x and returns z.
func (z *Int) Neg(x *Int) *Int {
z.Set(x)
z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign
return z
}
// Add sets z to the sum x+y and returns z.
func (z *Int) Add(x, y *Int) *Int {
neg := x.neg
if x.neg == y.neg {
// x + y == x + y
// (-x) + (-y) == -(x + y)
z.abs = z.abs.add(x.abs, y.abs)
} else {
// x + (-y) == x - y == -(y - x)
// (-x) + y == y - x == -(x - y)
if x.abs.cmp(y.abs) >= 0 {
z.abs = z.abs.sub(x.abs, y.abs)
} else {
neg = !neg
z.abs = z.abs.sub(y.abs, x.abs)
}
}
z.neg = len(z.abs) > 0 && neg // 0 has no sign
return z
}
// Sub sets z to the difference x-y and returns z.
func (z *Int) Sub(x, y *Int) *Int {
neg := x.neg
if x.neg != y.neg {
// x - (-y) == x + y
// (-x) - y == -(x + y)
z.abs = z.abs.add(x.abs, y.abs)
} else {
// x - y == x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y)
if x.abs.cmp(y.abs) >= 0 {
z.abs = z.abs.sub(x.abs, y.abs)
} else {
neg = !neg
z.abs = z.abs.sub(y.abs, x.abs)
}
}
z.neg = len(z.abs) > 0 && neg // 0 has no sign
return z
}
// Mul sets z to the product x*y and returns z.
func (z *Int) Mul(x, y *Int) *Int {
// x * y == x * y
// x * (-y) == -(x * y)
// (-x) * y == -(x * y)
// (-x) * (-y) == x * y
z.abs = z.abs.mul(x.abs, y.abs)
z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
return z
}
// MulRange sets z to the product of all integers
// in the range [a, b] inclusively and returns z.
// If a > b (empty range), the result is 1.
func (z *Int) MulRange(a, b int64) *Int {
switch {
case a > b:
return z.SetInt64(1) // empty range
case a <= 0 && b >= 0:
return z.SetInt64(0) // range includes 0
}
// a <= b && (b < 0 || a > 0)
neg := false
if a < 0 {
neg = (b-a)&1 == 0
a, b = -b, -a
}
z.abs = z.abs.mulRange(uint64(a), uint64(b))
z.neg = neg
return z
}
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
func (z *Int) Binomial(n, k int64) *Int {
// reduce the number of multiplications by reducing k
if n/2 < k && k <= n {
k = n - k // Binomial(n, k) == Binomial(n, n-k)
}
var a, b Int
a.MulRange(n-k+1, n)
b.MulRange(1, k)
return z.Quo(&a, &b)
}
// Quo sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Quo implements truncated division (like Go); see QuoRem for more details.
func (z *Int) Quo(x, y *Int) *Int {
z.abs, _ = z.abs.div(nil, x.abs, y.abs)
z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
return z
}
// Rem sets z to the remainder x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Rem implements truncated modulus (like Go); see QuoRem for more details.
func (z *Int) Rem(x, y *Int) *Int {
_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
return z
}
// QuoRem sets z to the quotient x/y and r to the remainder x%y
// and returns the pair (z, r) for y != 0.
// If y == 0, a division-by-zero run-time panic occurs.
//
// QuoRem implements T-division and modulus (like Go):
//
// q = x/y with the result truncated to zero
// r = x - y*q
//
// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
// See DivMod for Euclidean division and modulus (unlike Go).
//
func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs)
z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign
return z, r
}
// Div sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Div implements Euclidean division (unlike Go); see DivMod for more details.
func (z *Int) Div(x, y *Int) *Int {
y_neg := y.neg // z may be an alias for y
var r Int
z.QuoRem(x, y, &r)
if r.neg {
if y_neg {
z.Add(z, intOne)
} else {
z.Sub(z, intOne)
}
}
return z
}
// Mod sets z to the modulus x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
func (z *Int) Mod(x, y *Int) *Int {
y0 := y // save y
if z == y || alias(z.abs, y.abs) {
y0 = new(Int).Set(y)
}
var q Int
q.QuoRem(x, y, z)
if z.neg {
if y0.neg {
z.Sub(z, y0)
} else {
z.Add(z, y0)
}
}
return z
}
// DivMod sets z to the quotient x div y and m to the modulus x mod y
// and returns the pair (z, m) for y != 0.
// If y == 0, a division-by-zero run-time panic occurs.
//
// DivMod implements Euclidean division and modulus (unlike Go):
//
// q = x div y such that
// m = x - y*q with 0 <= m < |y|
//
// (See Raymond T. Boute, ``The Euclidean definition of the functions
// div and mod''. ACM Transactions on Programming Languages and
// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
// ACM press.)
// See QuoRem for T-division and modulus (like Go).
//
func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
y0 := y // save y
if z == y || alias(z.abs, y.abs) {
y0 = new(Int).Set(y)
}
z.QuoRem(x, y, m)
if m.neg {
if y0.neg {
z.Add(z, intOne)
m.Sub(m, y0)
} else {
z.Sub(z, intOne)
m.Add(m, y0)
}
}
return z, m
}
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
func (x *Int) Cmp(y *Int) (r int) {
// x cmp y == x cmp y
// x cmp (-y) == x
// (-x) cmp y == y
// (-x) cmp (-y) == -(x cmp y)
switch {
case x.neg == y.neg:
r = x.abs.cmp(y.abs)
if x.neg {
r = -r
}
case x.neg:
r = -1
default:
r = 1
}
return
}
// low32 returns the least significant 32 bits of z.
func low32(z nat) uint32 {
if len(z) == 0 {
return 0
}
return uint32(z[0])
}
// low64 returns the least significant 64 bits of z.
func low64(z nat) uint64 {
if len(z) == 0 {
return 0
}
v := uint64(z[0])
if _W == 32 && len(z) > 1 {
v |= uint64(z[1]) << 32
}
return v
}
// Int64 returns the int64 representation of x.
// If x cannot be represented in an int64, the result is undefined.
func (x *Int) Int64() int64 {
v := int64(low64(x.abs))
if x.neg {
v = -v
}
return v
}
// Uint64 returns the uint64 representation of x.
// If x cannot be represented in a uint64, the result is undefined.
func (x *Int) Uint64() uint64 {
return low64(x.abs)
}
// SetString sets z to the value of s, interpreted in the given base,
// and returns z and a boolean indicating success. If SetString fails,
// the value of z is undefined but the returned value is nil.
//
// The base argument must be 0 or a value between 2 and MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
//
func (z *Int) SetString(s string, base int) (*Int, bool) {
r := strings.NewReader(s)
_, _, err := z.scan(r, base)
if err != nil {
return nil, false
}
_, err = r.ReadByte()
if err != io.EOF {
return nil, false
}
return z, true // err == io.EOF => scan consumed all of s
}
// SetBytes interprets buf as the bytes of a big-endian unsigned
// integer, sets z to that value, and returns z.
func (z *Int) SetBytes(buf []byte) *Int {
z.abs = z.abs.setBytes(buf)
z.neg = false
return z
}
// Bytes returns the absolute value of x as a big-endian byte slice.
func (x *Int) Bytes() []byte {
buf := make([]byte, len(x.abs)*_S)
return buf[x.abs.bytes(buf):]
}
// BitLen returns the length of the absolute value of x in bits.
// The bit length of 0 is 0.
func (x *Int) BitLen() int {
return x.abs.bitLen()
}
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y.
// See Knuth, volume 2, section 4.6.3.
func (z *Int) Exp(x, y, m *Int) *Int {
var yWords nat
if !y.neg {
yWords = y.abs
}
// y >= 0
var mWords nat
if m != nil {
mWords = m.abs // m.abs may be nil for m == 0
}
z.abs = z.abs.expNN(x.abs, yWords, mWords)
z.neg = len(z.abs) > 0 && x.neg && len(yWords) > 0 && yWords[0]&1 == 1 // 0 has no sign
if z.neg && len(mWords) > 0 {
// make modulus result positive
z.abs = z.abs.sub(mWords, z.abs) // z == x**y mod |m| && 0 <= z < |m|
z.neg = false
}
return z
}
// GCD sets z to the greatest common divisor of a and b, which both must
// be > 0, and returns z.
// If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
// If either a or b is <= 0, GCD sets z = x = y = 0.
func (z *Int) GCD(x, y, a, b *Int) *Int {
if a.Sign() <= 0 || b.Sign() <= 0 {
z.SetInt64(0)
if x != nil {
x.SetInt64(0)
}
if y != nil {
y.SetInt64(0)
}
return z
}
if x == nil && y == nil {
return z.binaryGCD(a, b)
}
A := new(Int).Set(a)
B := new(Int).Set(b)
X := new(Int)
Y := new(Int).SetInt64(1)
lastX := new(Int).SetInt64(1)
lastY := new(Int)
q := new(Int)
temp := new(Int)
r := new(Int)
for len(B.abs) > 0 {
q, r = q.QuoRem(A, B, r)
A, B, r = B, r, A
temp.Set(X)
X.Mul(X, q)
X.neg = !X.neg
X.Add(X, lastX)
lastX.Set(temp)
temp.Set(Y)
Y.Mul(Y, q)
Y.neg = !Y.neg
Y.Add(Y, lastY)
lastY.Set(temp)
}
if x != nil {
*x = *lastX
}
if y != nil {
*y = *lastY
}
*z = *A
return z
}
// binaryGCD sets z to the greatest common divisor of a and b, which both must
// be > 0, and returns z.
// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B.
func (z *Int) binaryGCD(a, b *Int) *Int {
u := z
v := new(Int)
// use one Euclidean iteration to ensure that u and v are approx. the same size
switch {
case len(a.abs) > len(b.abs):
// must set v before u since u may be alias for a or b (was issue #11284)
v.Rem(a, b)
u.Set(b)
case len(a.abs) < len(b.abs):
v.Rem(b, a)
u.Set(a)
default:
v.Set(b)
u.Set(a)
}
// a, b must not be used anymore (may be aliases with u)
// v might be 0 now
if len(v.abs) == 0 {
return u
}
// u > 0 && v > 0
// determine largest k such that u = u' << k, v = v' << k
k := u.abs.trailingZeroBits()
if vk := v.abs.trailingZeroBits(); vk < k {
k = vk
}
u.Rsh(u, k)
v.Rsh(v, k)
// determine t (we know that u > 0)
t := new(Int)
if u.abs[0]&1 != 0 {
// u is odd
t.Neg(v)
} else {
t.Set(u)
}
for len(t.abs) > 0 {
// reduce t
t.Rsh(t, t.abs.trailingZeroBits())
if t.neg {
v, t = t, v
v.neg = len(v.abs) > 0 && !v.neg // 0 has no sign
} else {
u, t = t, u
}
t.Sub(u, v)
}
return z.Lsh(u, k)
}
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
// If x is prime, it returns true.
// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
//
// It is not suitable for judging primes that an adversary may have crafted
// to fool this test.
func (x *Int) ProbablyPrime(n int) bool {
if n <= 0 {
panic("non-positive n for ProbablyPrime")
}
return !x.neg && x.abs.probablyPrime(n)
}
// Rand sets z to a pseudo-random number in [0, n) and returns z.
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
z.neg = false
if n.neg == true || len(n.abs) == 0 {
z.abs = nil
return z
}
z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen())
return z
}
// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ
// and returns z. If g and n are not relatively prime, the result is undefined.
func (z *Int) ModInverse(g, n *Int) *Int {
var d Int
d.GCD(z, nil, g, n)
// x and y are such that g*x + n*y = d. Since g and n are
// relatively prime, d = 1. Taking that modulo n results in
// g*x = 1, therefore x is the inverse element.
if z.neg {
z.Add(z, n)
}
return z
}
// Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0.
// The y argument must be an odd integer.
func Jacobi(x, y *Int) int {
if len(y.abs) == 0 || y.abs[0]&1 == 0 {
panic(fmt.Sprintf("big: invalid 2nd argument to Int.Jacobi: need odd integer but got %s", y))
}
// We use the formulation described in chapter 2, section 2.4,
// "The Yacas Book of Algorithms":
// http://yacas.sourceforge.net/Algo.book.pdf
var a, b, c Int
a.Set(x)
b.Set(y)
j := 1
if b.neg {
if a.neg {
j = -1
}
b.neg = false
}
for {
if b.Cmp(intOne) == 0 {
return j
}
if len(a.abs) == 0 {
return 0
}
a.Mod(&a, &b)
if len(a.abs) == 0 {
return 0
}
// a > 0
// handle factors of 2 in 'a'
s := a.abs.trailingZeroBits()
if s&1 != 0 {
bmod8 := b.abs[0] & 7
if bmod8 == 3 || bmod8 == 5 {
j = -j
}
}
c.Rsh(&a, s) // a = 2^s*c
// swap numerator and denominator
if b.abs[0]&3 == 3 && c.abs[0]&3 == 3 {
j = -j
}
a.Set(&b)
b.Set(&c)
}
}
// modSqrt3Mod4 uses the identity
// (a^((p+1)/4))^2 mod p
// == u^(p+1) mod p
// == u^2 mod p
// to calculate the square root of any quadratic residue mod p quickly for 3
// mod 4 primes.
func (z *Int) modSqrt3Mod4Prime(x, p *Int) *Int {
z.Set(p) // z = p
z.Add(z, intOne) // z = p + 1
z.Rsh(z, 2) // z = (p + 1) / 4
z.Exp(x, z, p) // z = x^z mod p
return z
}
// modSqrtTonelliShanks uses the Tonelli-Shanks algorithm to find the square
// root of a quadratic residue modulo any prime.
func (z *Int) modSqrtTonelliShanks(x, p *Int) *Int {
// Break p-1 into s*2^e such that s is odd.
var s Int
s.Sub(p, intOne)
e := s.abs.trailingZeroBits()
s.Rsh(&s, e)
// find some non-square n
var n Int
n.SetInt64(2)
for Jacobi(&n, p) != -1 {
n.Add(&n, intOne)
}
// Core of the Tonelli-Shanks algorithm. Follows the description in
// section 6 of "Square roots from 1; 24, 51, 10 to Dan Shanks" by Ezra
// Brown:
// https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf
var y, b, g, t Int
y.Add(&s, intOne)
y.Rsh(&y, 1)
y.Exp(x, &y, p) // y = x^((s+1)/2)
b.Exp(x, &s, p) // b = x^s
g.Exp(&n, &s, p) // g = n^s
r := e
for {
// find the least m such that ord_p(b) = 2^m
var m uint
t.Set(&b)
for t.Cmp(intOne) != 0 {
t.Mul(&t, &t).Mod(&t, p)
m++
}
if m == 0 {
return z.Set(&y)
}
t.SetInt64(0).SetBit(&t, int(r-m-1), 1).Exp(&g, &t, p)
// t = g^(2^(r-m-1)) mod p
g.Mul(&t, &t).Mod(&g, p) // g = g^(2^(r-m)) mod p
y.Mul(&y, &t).Mod(&y, p)
b.Mul(&b, &g).Mod(&b, p)
r = m
}
}
// ModSqrt sets z to a square root of x mod p if such a square root exists, and
// returns z. The modulus p must be an odd prime. If x is not a square mod p,
// ModSqrt leaves z unchanged and returns nil. This function panics if p is
// not an odd integer.
func (z *Int) ModSqrt(x, p *Int) *Int {
switch Jacobi(x, p) {
case -1:
return nil // x is not a square mod p
case 0:
return z.SetInt64(0) // sqrt(0) mod p = 0
case 1:
break
}
if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
x = new(Int).Mod(x, p)
}
// Check whether p is 3 mod 4, and if so, use the faster algorithm.
if len(p.abs) > 0 && p.abs[0]%4 == 3 {
return z.modSqrt3Mod4Prime(x, p)
}
// Otherwise, use Tonelli-Shanks.
return z.modSqrtTonelliShanks(x, p)
}
// Lsh sets z = x << n and returns z.
func (z *Int) Lsh(x *Int, n uint) *Int {
z.abs = z.abs.shl(x.abs, n)
z.neg = x.neg
return z
}
// Rsh sets z = x >> n and returns z.
func (z *Int) Rsh(x *Int, n uint) *Int {
if x.neg {
// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0
t = t.shr(t, n)
z.abs = t.add(t, natOne)
z.neg = true // z cannot be zero if x is negative
return z
}
z.abs = z.abs.shr(x.abs, n)
z.neg = false
return z
}
// Bit returns the value of the i'th bit of x. That is, it
// returns (x>>i)&1. The bit index i must be >= 0.
func (x *Int) Bit(i int) uint {
if i == 0 {
// optimization for common case: odd/even test of x
if len(x.abs) > 0 {
return uint(x.abs[0] & 1) // bit 0 is same for -x
}
return 0
}
if i < 0 {
panic("negative bit index")
}
if x.neg {
t := nat(nil).sub(x.abs, natOne)
return t.bit(uint(i)) ^ 1
}
return x.abs.bit(uint(i))
}
// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
// That is, if b is 1 SetBit sets z = x | (1 << i);
// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
// SetBit will panic.
func (z *Int) SetBit(x *Int, i int, b uint) *Int {
if i < 0 {
panic("negative bit index")
}
if x.neg {
t := z.abs.sub(x.abs, natOne)
t = t.setBit(t, uint(i), b^1)
z.abs = t.add(t, natOne)
z.neg = len(z.abs) > 0
return z
}
z.abs = z.abs.setBit(x.abs, uint(i), b)
z.neg = false
return z
}
// And sets z = x & y and returns z.
func (z *Int) And(x, y *Int) *Int {
if x.neg == y.neg {
if x.neg {
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
x1 := nat(nil).sub(x.abs, natOne)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
z.neg = true // z cannot be zero if x and y are negative
return z
}
// x & y == x & y
z.abs = z.abs.and(x.abs, y.abs)
z.neg = false
return z
}
// x.neg != y.neg
if x.neg {
x, y = y, x // & is symmetric
}
// x & (-y) == x & ^(y-1) == x &^ (y-1)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.andNot(x.abs, y1)
z.neg = false
return z
}
// AndNot sets z = x &^ y and returns z.
func (z *Int) AndNot(x, y *Int) *Int {
if x.neg == y.neg {
if x.neg {
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
x1 := nat(nil).sub(x.abs, natOne)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.andNot(y1, x1)
z.neg = false
return z
}
// x &^ y == x &^ y
z.abs = z.abs.andNot(x.abs, y.abs)
z.neg = false
return z
}
if x.neg {
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
x1 := nat(nil).sub(x.abs, natOne)
z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
z.neg = true // z cannot be zero if x is negative and y is positive
return z
}
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.and(x.abs, y1)
z.neg = false
return z
}
// Or sets z = x | y and returns z.
func (z *Int) Or(x, y *Int) *Int {
if x.neg == y.neg {
if x.neg {
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
x1 := nat(nil).sub(x.abs, natOne)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
z.neg = true // z cannot be zero if x and y are negative
return z
}
// x | y == x | y
z.abs = z.abs.or(x.abs, y.abs)
z.neg = false
return z
}
// x.neg != y.neg
if x.neg {
x, y = y, x // | is symmetric
}
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
z.neg = true // z cannot be zero if one of x or y is negative
return z
}
// Xor sets z = x ^ y and returns z.
func (z *Int) Xor(x, y *Int) *Int {
if x.neg == y.neg {
if x.neg {
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
x1 := nat(nil).sub(x.abs, natOne)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.xor(x1, y1)
z.neg = false
return z
}
// x ^ y == x ^ y
z.abs = z.abs.xor(x.abs, y.abs)
z.neg = false
return z
}
// x.neg != y.neg
if x.neg {
x, y = y, x // ^ is symmetric
}
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
z.neg = true // z cannot be zero if only one of x or y is negative
return z
}
// Not sets z = ^x and returns z.
func (z *Int) Not(x *Int) *Int {
if x.neg {
// ^(-x) == ^(^(x-1)) == x-1
z.abs = z.abs.sub(x.abs, natOne)
z.neg = false
return z
}
// ^x == -x-1 == -(x+1)
z.abs = z.abs.add(x.abs, natOne)
z.neg = true // z cannot be zero if x is positive
return z
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"testing"
"testing/quick"
)
func isNormalized(x *Int) bool {
if len(x.abs) == 0 {
return !x.neg
}
// len(x.abs) > 0
return x.abs[len(x.abs)-1] != 0
}
type funZZ func(z, x, y *Int) *Int
type argZZ struct {
z, x, y *Int
}
var sumZZ = []argZZ{
{NewInt(0), NewInt(0), NewInt(0)},
{NewInt(1), NewInt(1), NewInt(0)},
{NewInt(1111111110), NewInt(123456789), NewInt(987654321)},
{NewInt(-1), NewInt(-1), NewInt(0)},
{NewInt(864197532), NewInt(-123456789), NewInt(987654321)},
{NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)},
}
var prodZZ = []argZZ{
{NewInt(0), NewInt(0), NewInt(0)},
{NewInt(0), NewInt(1), NewInt(0)},
{NewInt(1), NewInt(1), NewInt(1)},
{NewInt(-991 * 991), NewInt(991), NewInt(-991)},
// TODO(gri) add larger products
}
func TestSignZ(t *testing.T) {
var zero Int
for _, a := range sumZZ {
s := a.z.Sign()
e := a.z.Cmp(&zero)
if s != e {
t.Errorf("got %d; want %d for z = %v", s, e, a.z)
}
}
}
func TestSetZ(t *testing.T) {
for _, a := range sumZZ {
var z Int
z.Set(a.z)
if !isNormalized(&z) {
t.Errorf("%v is not normalized", z)
}
if (&z).Cmp(a.z) != 0 {
t.Errorf("got z = %v; want %v", z, a.z)
}
}
}
func TestAbsZ(t *testing.T) {
var zero Int
for _, a := range sumZZ {
var z Int
z.Abs(a.z)
var e Int
e.Set(a.z)
if e.Cmp(&zero) < 0 {
e.Sub(&zero, &e)
}
if z.Cmp(&e) != 0 {
t.Errorf("got z = %v; want %v", z, e)
}
}
}
func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
var z Int
f(&z, a.x, a.y)
if !isNormalized(&z) {
t.Errorf("%s%v is not normalized", msg, z)
}
if (&z).Cmp(a.z) != 0 {
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
}
}
func TestSumZZ(t *testing.T) {
AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) }
SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) }
for _, a := range sumZZ {
arg := a
testFunZZ(t, "AddZZ", AddZZ, arg)
arg = argZZ{a.z, a.y, a.x}
testFunZZ(t, "AddZZ symmetric", AddZZ, arg)
arg = argZZ{a.x, a.z, a.y}
testFunZZ(t, "SubZZ", SubZZ, arg)
arg = argZZ{a.y, a.z, a.x}
testFunZZ(t, "SubZZ symmetric", SubZZ, arg)
}
}
func TestProdZZ(t *testing.T) {
MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) }
for _, a := range prodZZ {
arg := a
testFunZZ(t, "MulZZ", MulZZ, arg)
arg = argZZ{a.z, a.y, a.x}
testFunZZ(t, "MulZZ symmetric", MulZZ, arg)
}
}
// mulBytes returns x*y via grade school multiplication. Both inputs
// and the result are assumed to be in big-endian representation (to
// match the semantics of Int.Bytes and Int.SetBytes).
func mulBytes(x, y []byte) []byte {
z := make([]byte, len(x)+len(y))
// multiply
k0 := len(z) - 1
for j := len(y) - 1; j >= 0; j-- {
d := int(y[j])
if d != 0 {
k := k0
carry := 0
for i := len(x) - 1; i >= 0; i-- {
t := int(z[k]) + int(x[i])*d + carry
z[k], carry = byte(t), t>>8
k--
}
z[k] = byte(carry)
}
k0--
}
// normalize (remove leading 0's)
i := 0
for i < len(z) && z[i] == 0 {
i++
}
return z[i:]
}
func checkMul(a, b []byte) bool {
var x, y, z1 Int
x.SetBytes(a)
y.SetBytes(b)
z1.Mul(&x, &y)
var z2 Int
z2.SetBytes(mulBytes(a, b))
return z1.Cmp(&z2) == 0
}
func TestMul(t *testing.T) {
if err := quick.Check(checkMul, nil); err != nil {
t.Error(err)
}
}
var mulRangesZ = []struct {
a, b int64
prod string
}{
// entirely positive ranges are covered by mulRangesN
{-1, 1, "0"},
{-2, -1, "2"},
{-3, -2, "6"},
{-3, -1, "-6"},
{1, 3, "6"},
{-10, -10, "-10"},
{0, -1, "1"}, // empty range
{-1, -100, "1"}, // empty range
{-1, 1, "0"}, // range includes 0
{-1e9, 0, "0"}, // range includes 0
{-1e9, 1e9, "0"}, // range includes 0
{-10, -1, "3628800"}, // 10!
{-20, -2, "-2432902008176640000"}, // -20!
{-99, -1,
"-933262154439441526816992388562667004907159682643816214685929" +
"638952175999932299156089414639761565182862536979208272237582" +
"511852109168640000000000000000000000", // -99!
},
}
func TestMulRangeZ(t *testing.T) {
var tmp Int
// test entirely positive ranges
for i, r := range mulRangesN {
prod := tmp.MulRange(int64(r.a), int64(r.b)).String()
if prod != r.prod {
t.Errorf("#%da: got %s; want %s", i, prod, r.prod)
}
}
// test other ranges
for i, r := range mulRangesZ {
prod := tmp.MulRange(r.a, r.b).String()
if prod != r.prod {
t.Errorf("#%db: got %s; want %s", i, prod, r.prod)
}
}
}
func TestBinomial(t *testing.T) {
var z Int
for _, test := range []struct {
n, k int64
want string
}{
{0, 0, "1"},
{0, 1, "0"},
{1, 0, "1"},
{1, 1, "1"},
{1, 10, "0"},
{4, 0, "1"},
{4, 1, "4"},
{4, 2, "6"},
{4, 3, "4"},
{4, 4, "1"},
{10, 1, "10"},
{10, 9, "10"},
{10, 5, "252"},
{11, 5, "462"},
{11, 6, "462"},
{100, 10, "17310309456440"},
{100, 90, "17310309456440"},
{1000, 10, "263409560461970212832400"},
{1000, 990, "263409560461970212832400"},
} {
if got := z.Binomial(test.n, test.k).String(); got != test.want {
t.Errorf("Binomial(%d, %d) = %s; want %s", test.n, test.k, got, test.want)
}
}
}
func BenchmarkBinomial(b *testing.B) {
var z Int
for i := b.N - 1; i >= 0; i-- {
z.Binomial(1000, 990)
}
}
// Examples from the Go Language Spec, section "Arithmetic operators"
var divisionSignsTests = []struct {
x, y int64
q, r int64 // T-division
d, m int64 // Euclidian division
}{
{5, 3, 1, 2, 1, 2},
{-5, 3, -1, -2, -2, 1},
{5, -3, -1, 2, -1, 2},
{-5, -3, 1, -2, 2, 1},
{1, 2, 0, 1, 0, 1},
{8, 4, 2, 0, 2, 0},
}
func TestDivisionSigns(t *testing.T) {
for i, test := range divisionSignsTests {
x := NewInt(test.x)
y := NewInt(test.y)
q := NewInt(test.q)
r := NewInt(test.r)
d := NewInt(test.d)
m := NewInt(test.m)
q1 := new(Int).Quo(x, y)
r1 := new(Int).Rem(x, y)
if !isNormalized(q1) {
t.Errorf("#%d Quo: %v is not normalized", i, *q1)
}
if !isNormalized(r1) {
t.Errorf("#%d Rem: %v is not normalized", i, *r1)
}
if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 {
t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r)
}
q2, r2 := new(Int).QuoRem(x, y, new(Int))
if !isNormalized(q2) {
t.Errorf("#%d Quo: %v is not normalized", i, *q2)
}
if !isNormalized(r2) {
t.Errorf("#%d Rem: %v is not normalized", i, *r2)
}
if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 {
t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r)
}
d1 := new(Int).Div(x, y)
m1 := new(Int).Mod(x, y)
if !isNormalized(d1) {
t.Errorf("#%d Div: %v is not normalized", i, *d1)
}
if !isNormalized(m1) {
t.Errorf("#%d Mod: %v is not normalized", i, *m1)
}
if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 {
t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m)
}
d2, m2 := new(Int).DivMod(x, y, new(Int))
if !isNormalized(d2) {
t.Errorf("#%d Div: %v is not normalized", i, *d2)
}
if !isNormalized(m2) {
t.Errorf("#%d Mod: %v is not normalized", i, *m2)
}
if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 {
t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m)
}
}
}
func norm(x nat) nat {
i := len(x)
for i > 0 && x[i-1] == 0 {
i--
}
return x[:i]
}
func TestBits(t *testing.T) {
for _, test := range []nat{
nil,
{0},
{1},
{0, 1, 2, 3, 4},
{4, 3, 2, 1, 0},
{4, 3, 2, 1, 0, 0, 0, 0},
} {
var z Int
z.neg = true
got := z.SetBits(test)
want := norm(test)
if got.abs.cmp(want) != 0 {
t.Errorf("SetBits(%v) = %v; want %v", test, got.abs, want)
}
if got.neg {
t.Errorf("SetBits(%v): got negative result", test)
}
bits := nat(z.Bits())
if bits.cmp(want) != 0 {
t.Errorf("%v.Bits() = %v; want %v", z.abs, bits, want)
}
}
}
func checkSetBytes(b []byte) bool {
hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
hex2 := hex.EncodeToString(b)
for len(hex1) < len(hex2) {
hex1 = "0" + hex1
}
for len(hex1) > len(hex2) {
hex2 = "0" + hex2
}
return hex1 == hex2
}
func TestSetBytes(t *testing.T) {
if err := quick.Check(checkSetBytes, nil); err != nil {
t.Error(err)
}
}
func checkBytes(b []byte) bool {
// trim leading zero bytes since Bytes() won't return them
// (was issue 12231)
for len(b) > 0 && b[0] == 0 {
b = b[1:]
}
b2 := new(Int).SetBytes(b).Bytes()
return bytes.Equal(b, b2)
}
func TestBytes(t *testing.T) {
if err := quick.Check(checkBytes, nil); err != nil {
t.Error(err)
}
}
func checkQuo(x, y []byte) bool {
u := new(Int).SetBytes(x)
v := new(Int).SetBytes(y)
if len(v.abs) == 0 {
return true
}
r := new(Int)
q, r := new(Int).QuoRem(u, v, r)
if r.Cmp(v) >= 0 {
return false
}
uprime := new(Int).Set(q)
uprime.Mul(uprime, v)
uprime.Add(uprime, r)
return uprime.Cmp(u) == 0
}
var quoTests = []struct {
x, y string
q, r string
}{
{
"476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357",
"9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996",
"50911",
"1",
},
{
"11510768301994997771168",
"1328165573307167369775",
"8",
"885443715537658812968",
},
}
func TestQuo(t *testing.T) {
if err := quick.Check(checkQuo, nil); err != nil {
t.Error(err)
}
for i, test := range quoTests {
x, _ := new(Int).SetString(test.x, 10)
y, _ := new(Int).SetString(test.y, 10)
expectedQ, _ := new(Int).SetString(test.q, 10)
expectedR, _ := new(Int).SetString(test.r, 10)
r := new(Int)
q, r := new(Int).QuoRem(x, y, r)
if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 {
t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
}
}
}
func TestQuoStepD6(t *testing.T) {
// See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises
// a code path which only triggers 1 in 10^{-19} cases.
u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}}
v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}}
r := new(Int)
q, r := new(Int).QuoRem(u, v, r)
const expectedQ64 = "18446744073709551613"
const expectedR64 = "3138550867693340382088035895064302439801311770021610913807"
const expectedQ32 = "4294967293"
const expectedR32 = "39614081266355540837921718287"
if q.String() != expectedQ64 && q.String() != expectedQ32 ||
r.String() != expectedR64 && r.String() != expectedR32 {
t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32)
}
}
var bitLenTests = []struct {
in string
out int
}{
{"-1", 1},
{"0", 0},
{"1", 1},
{"2", 2},
{"4", 3},
{"0xabc", 12},
{"0x8000", 16},
{"0x80000000", 32},
{"0x800000000000", 48},
{"0x8000000000000000", 64},
{"0x80000000000000000000", 80},
{"-0x4000000000000000000000", 87},
}
func TestBitLen(t *testing.T) {
for i, test := range bitLenTests {
x, ok := new(Int).SetString(test.in, 0)
if !ok {
t.Errorf("#%d test input invalid: %s", i, test.in)
continue
}
if n := x.BitLen(); n != test.out {
t.Errorf("#%d got %d want %d", i, n, test.out)
}
}
}
var expTests = []struct {
x, y, m string
out string
}{
// y <= 0
{"0", "0", "", "1"},
{"1", "0", "", "1"},
{"-10", "0", "", "1"},
{"1234", "-1", "", "1"},
// m == 1
{"0", "0", "1", "0"},
{"1", "0", "1", "0"},
{"-10", "0", "1", "0"},
{"1234", "-1", "1", "0"},
// misc
{"5", "1", "3", "2"},
{"5", "-7", "", "1"},
{"-5", "-7", "", "1"},
{"5", "0", "", "1"},
{"-5", "0", "", "1"},
{"5", "1", "", "5"},
{"-5", "1", "", "-5"},
{"-5", "1", "7", "2"},
{"-2", "3", "2", "0"},
{"5", "2", "", "25"},
{"1", "65537", "2", "1"},
{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
{"0x8000000000000000", "2", "6719", "4944"},
{"0x8000000000000000", "3", "6719", "5447"},
{"0x8000000000000000", "1000", "6719", "1603"},
{"0x8000000000000000", "1000000", "6719", "3199"},
{"0x8000000000000000", "-1000000", "6719", "1"},
{"0xffffffffffffffffffffffffffffffff", "0x12345678123456781234567812345678123456789", "0x01112222333344445555666677778889", "0x36168FA1DB3AAE6C8CE647E137F97A"},
{
"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
"298472983472983471903246121093472394872319615612417471234712061",
"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
},
// test case for issue 8822
{
"11001289118363089646017359372117963499250546375269047542777928006103246876688756735760905680604646624353196869572752623285140408755420374049317646428185270079555372763503115646054602867593662923894140940837479507194934267532831694565516466765025434902348314525627418515646588160955862839022051353653052947073136084780742729727874803457643848197499548297570026926927502505634297079527299004267769780768565695459945235586892627059178884998772989397505061206395455591503771677500931269477503508150175717121828518985901959919560700853226255420793148986854391552859459511723547532575574664944815966793196961286234040892865",
"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
"21484252197776302499639938883777710321993113097987201050501182909581359357618579566746556372589385361683610524730509041328855066514963385522570894839035884713051640171474186548713546686476761306436434146475140156284389181808675016576845833340494848283681088886584219750554408060556769486628029028720727393293111678826356480455433909233520504112074401376133077150471237549474149190242010469539006449596611576612573955754349042329130631128234637924786466585703488460540228477440853493392086251021228087076124706778899179648655221663765993962724699135217212118535057766739392069738618682722216712319320435674779146070442",
},
{
"-0x1BCE04427D8032319A89E5C4136456671AC620883F2C4139E57F91307C485AD2D6204F4F87A58262652DB5DBBAC72B0613E51B835E7153BEC6068F5C8D696B74DBD18FEC316AEF73985CF0475663208EB46B4F17DD9DA55367B03323E5491A70997B90C059FB34809E6EE55BCFBD5F2F52233BFE62E6AA9E4E26A1D4C2439883D14F2633D55D8AA66A1ACD5595E778AC3A280517F1157989E70C1A437B849F1877B779CC3CDDEDE2DAA6594A6C66D181A00A5F777EE60596D8773998F6E988DEAE4CCA60E4DDCF9590543C89F74F603259FCAD71660D30294FBBE6490300F78A9D63FA660DC9417B8B9DDA28BEB3977B621B988E23D4D954F322C3540541BC649ABD504C50FADFD9F0987D58A2BF689313A285E773FF02899A6EF887D1D4A0D2",
"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
"21484252197776302499639938883777710321993113097987201050501182909581359357618579566746556372589385361683610524730509041328855066514963385522570894839035884713051640171474186548713546686476761306436434146475140156284389181808675016576845833340494848283681088886584219750554408060556769486628029028720727393293111678826356480455433909233520504112074401376133077150471237549474149190242010469539006449596611576612573955754349042329130631128234637924786466585703488460540228477440853493392086251021228087076124706778899179648655221663765993962724699135217212118535057766739392069738618682722216712319320435674779146070442",
},
// test cases for issue 13907
{"0xffffffff00000001", "0xffffffff00000001", "0xffffffff00000001", "0"},
{"0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0"},
{"0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0"},
{"0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0"},
}
func TestExp(t *testing.T) {
for i, test := range expTests {
x, ok1 := new(Int).SetString(test.x, 0)
y, ok2 := new(Int).SetString(test.y, 0)
out, ok3 := new(Int).SetString(test.out, 0)
var ok4 bool
var m *Int
if len(test.m) == 0 {
m, ok4 = nil, true
} else {
m, ok4 = new(Int).SetString(test.m, 0)
}
if !ok1 || !ok2 || !ok3 || !ok4 {
t.Errorf("#%d: error in input", i)
continue
}
z1 := new(Int).Exp(x, y, m)
if !isNormalized(z1) {
t.Errorf("#%d: %v is not normalized", i, *z1)
}
if z1.Cmp(out) != 0 {
t.Errorf("#%d: got %x want %x", i, z1, out)
}
if m == nil {
// The result should be the same as for m == 0;
// specifically, there should be no div-zero panic.
m = &Int{abs: nat{}} // m != nil && len(m.abs) == 0
z2 := new(Int).Exp(x, y, m)
if z2.Cmp(z1) != 0 {
t.Errorf("#%d: got %x want %x", i, z2, z1)
}
}
}
}
func checkGcd(aBytes, bBytes []byte) bool {
x := new(Int)
y := new(Int)
a := new(Int).SetBytes(aBytes)
b := new(Int).SetBytes(bBytes)
d := new(Int).GCD(x, y, a, b)
x.Mul(x, a)
y.Mul(y, b)
x.Add(x, y)
return x.Cmp(d) == 0
}
var gcdTests = []struct {
d, x, y, a, b string
}{
// a <= 0 || b <= 0
{"0", "0", "0", "0", "0"},
{"0", "0", "0", "0", "7"},
{"0", "0", "0", "11", "0"},
{"0", "0", "0", "-77", "35"},
{"0", "0", "0", "64515", "-24310"},
{"0", "0", "0", "-64515", "-24310"},
{"1", "-9", "47", "120", "23"},
{"7", "1", "-2", "77", "35"},
{"935", "-3", "8", "64515", "24310"},
{"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"},
{"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"},
// test early exit (after one Euclidean iteration) in binaryGCD
{"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"},
}
func testGcd(t *testing.T, d, x, y, a, b *Int) {
var X *Int
if x != nil {
X = new(Int)
}
var Y *Int
if y != nil {
Y = new(Int)
}
D := new(Int).GCD(X, Y, a, b)
if D.Cmp(d) != 0 {
t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d)
}
if x != nil && X.Cmp(x) != 0 {
t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x)
}
if y != nil && Y.Cmp(y) != 0 {
t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y)
}
// binaryGCD requires a > 0 && b > 0
if a.Sign() <= 0 || b.Sign() <= 0 {
return
}
D.binaryGCD(a, b)
if D.Cmp(d) != 0 {
t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
}
// check results in presence of aliasing (issue #11284)
a2 := new(Int).Set(a)
b2 := new(Int).Set(b)
a2.binaryGCD(a2, b2) // result is same as 1st argument
if a2.Cmp(d) != 0 {
t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, a2, d)
}
a2 = new(Int).Set(a)
b2 = new(Int).Set(b)
b2.binaryGCD(a2, b2) // result is same as 2nd argument
if b2.Cmp(d) != 0 {
t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, b2, d)
}
}
func TestGcd(t *testing.T) {
for _, test := range gcdTests {
d, _ := new(Int).SetString(test.d, 0)
x, _ := new(Int).SetString(test.x, 0)
y, _ := new(Int).SetString(test.y, 0)
a, _ := new(Int).SetString(test.a, 0)
b, _ := new(Int).SetString(test.b, 0)
testGcd(t, d, nil, nil, a, b)
testGcd(t, d, x, nil, a, b)
testGcd(t, d, nil, y, a, b)
testGcd(t, d, x, y, a, b)
}
if err := quick.Check(checkGcd, nil); err != nil {
t.Error(err)
}
}
var primes = []string{
"2",
"3",
"5",
"7",
"11",
"13756265695458089029",
"13496181268022124907",
"10953742525620032441",
"17908251027575790097",
// https://golang.org/issue/638
"18699199384836356663",
"98920366548084643601728869055592650835572950932266967461790948584315647051443",
"94560208308847015747498523884063394671606671904944666360068158221458669711639",
// http://primes.utm.edu/lists/small/small3.html
"449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
// ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02
"3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9
"57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19
"9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105
"42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17
"6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1
}
var composites = []string{
"0",
"1",
"21284175091214687912771199898307297748211672914763848041968395774954376176754",
"6084766654921918907427900243509372380954290099172559290432744450051395395951",
"84594350493221918389213352992032324280367711247940675652888030554255915464401",
"82793403787388584738507275144194252681",
}
func TestProbablyPrime(t *testing.T) {
nreps := 20
if testing.Short() {
nreps = 1
}
for i, s := range primes {
p, _ := new(Int).SetString(s, 10)
if !p.ProbablyPrime(nreps) {
t.Errorf("#%d prime found to be non-prime (%s)", i, s)
}
}
for i, s := range composites {
c, _ := new(Int).SetString(s, 10)
if c.ProbablyPrime(nreps) {
t.Errorf("#%d composite found to be prime (%s)", i, s)
}
if testing.Short() {
break
}
}
// check that ProbablyPrime panics if n <= 0
c := NewInt(11) // a prime
for _, n := range []int{-1, 0, 1} {
func() {
defer func() {
if n <= 0 && recover() == nil {
t.Fatalf("expected panic from ProbablyPrime(%d)", n)
}
}()
if !c.ProbablyPrime(n) {
t.Fatalf("%v should be a prime", c)
}
}()
}
}
type intShiftTest struct {
in string
shift uint
out string
}
var rshTests = []intShiftTest{
{"0", 0, "0"},
{"-0", 0, "0"},
{"0", 1, "0"},
{"0", 2, "0"},
{"1", 0, "1"},
{"1", 1, "0"},
{"1", 2, "0"},
{"2", 0, "2"},
{"2", 1, "1"},
{"-1", 0, "-1"},
{"-1", 1, "-1"},
{"-1", 10, "-1"},
{"-100", 2, "-25"},
{"-100", 3, "-13"},
{"-100", 100, "-1"},
{"4294967296", 0, "4294967296"},
{"4294967296", 1, "2147483648"},
{"4294967296", 2, "1073741824"},
{"18446744073709551616", 0, "18446744073709551616"},
{"18446744073709551616", 1, "9223372036854775808"},
{"18446744073709551616", 2, "4611686018427387904"},
{"18446744073709551616", 64, "1"},
{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
{"340282366920938463463374607431768211456", 128, "1"},
}
func TestRsh(t *testing.T) {
for i, test := range rshTests {
in, _ := new(Int).SetString(test.in, 10)
expected, _ := new(Int).SetString(test.out, 10)
out := new(Int).Rsh(in, test.shift)
if !isNormalized(out) {
t.Errorf("#%d: %v is not normalized", i, *out)
}
if out.Cmp(expected) != 0 {
t.Errorf("#%d: got %s want %s", i, out, expected)
}
}
}
func TestRshSelf(t *testing.T) {
for i, test := range rshTests {
z, _ := new(Int).SetString(test.in, 10)
expected, _ := new(Int).SetString(test.out, 10)
z.Rsh(z, test.shift)
if !isNormalized(z) {
t.Errorf("#%d: %v is not normalized", i, *z)
}
if z.Cmp(expected) != 0 {
t.Errorf("#%d: got %s want %s", i, z, expected)
}
}
}
var lshTests = []intShiftTest{
{"0", 0, "0"},
{"0", 1, "0"},
{"0", 2, "0"},
{"1", 0, "1"},
{"1", 1, "2"},
{"1", 2, "4"},
{"2", 0, "2"},
{"2", 1, "4"},
{"2", 2, "8"},
{"-87", 1, "-174"},
{"4294967296", 0, "4294967296"},
{"4294967296", 1, "8589934592"},
{"4294967296", 2, "17179869184"},
{"18446744073709551616", 0, "18446744073709551616"},
{"9223372036854775808", 1, "18446744073709551616"},
{"4611686018427387904", 2, "18446744073709551616"},
{"1", 64, "18446744073709551616"},
{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
{"1", 128, "340282366920938463463374607431768211456"},
}
func TestLsh(t *testing.T) {
for i, test := range lshTests {
in, _ := new(Int).SetString(test.in, 10)
expected, _ := new(Int).SetString(test.out, 10)
out := new(Int).Lsh(in, test.shift)
if !isNormalized(out) {
t.Errorf("#%d: %v is not normalized", i, *out)
}
if out.Cmp(expected) != 0 {
t.Errorf("#%d: got %s want %s", i, out, expected)
}
}
}
func TestLshSelf(t *testing.T) {
for i, test := range lshTests {
z, _ := new(Int).SetString(test.in, 10)
expected, _ := new(Int).SetString(test.out, 10)
z.Lsh(z, test.shift)
if !isNormalized(z) {
t.Errorf("#%d: %v is not normalized", i, *z)
}
if z.Cmp(expected) != 0 {
t.Errorf("#%d: got %s want %s", i, z, expected)
}
}
}
func TestLshRsh(t *testing.T) {
for i, test := range rshTests {
in, _ := new(Int).SetString(test.in, 10)
out := new(Int).Lsh(in, test.shift)
out = out.Rsh(out, test.shift)
if !isNormalized(out) {
t.Errorf("#%d: %v is not normalized", i, *out)
}
if in.Cmp(out) != 0 {
t.Errorf("#%d: got %s want %s", i, out, in)
}
}
for i, test := range lshTests {
in, _ := new(Int).SetString(test.in, 10)
out := new(Int).Lsh(in, test.shift)
out.Rsh(out, test.shift)
if !isNormalized(out) {
t.Errorf("#%d: %v is not normalized", i, *out)
}
if in.Cmp(out) != 0 {
t.Errorf("#%d: got %s want %s", i, out, in)
}
}
}
var int64Tests = []int64{
0,
1,
-1,
4294967295,
-4294967295,
4294967296,
-4294967296,
9223372036854775807,
-9223372036854775807,
-9223372036854775808,
}
func TestInt64(t *testing.T) {
for i, testVal := range int64Tests {
in := NewInt(testVal)
out := in.Int64()
if out != testVal {
t.Errorf("#%d got %d want %d", i, out, testVal)
}
}
}
var uint64Tests = []uint64{
0,
1,
4294967295,
4294967296,
8589934591,
8589934592,
9223372036854775807,
9223372036854775808,
18446744073709551615, // 1<<64 - 1
}
func TestUint64(t *testing.T) {
in := new(Int)
for i, testVal := range uint64Tests {
in.SetUint64(testVal)
out := in.Uint64()
if out != testVal {
t.Errorf("#%d got %d want %d", i, out, testVal)
}
str := fmt.Sprint(testVal)
strOut := in.String()
if strOut != str {
t.Errorf("#%d.String got %s want %s", i, strOut, str)
}
}
}
var bitwiseTests = []struct {
x, y string
and, or, xor, andNot string
}{
{"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"},
{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"},
{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"},
{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"},
{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"},
{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"},
{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"},
{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
{"0xff", "-0x0a", "0xf6", "-0x01", "-0xf7", "0x09"},
{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},
{
"0x1000009dc6e3d9822cba04129bcbe3401",
"0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
"0x1000001186210100001000009048c2001",
"0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
"0x8c40c2d8822caa04120b8321400",
},
{
"0x1000009dc6e3d9822cba04129bcbe3401",
"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
"0x8c40c2d8822caa04120b8321401",
"-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd",
"-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe",
"0x1000001186210100001000009048c2000",
},
{
"-0x1000009dc6e3d9822cba04129bcbe3401",
"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
"-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
"-0x1000001186210100001000009048c2001",
"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
"0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc",
},
}
type bitFun func(z, x, y *Int) *Int
func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
expected := new(Int)
expected.SetString(exp, 0)
out := f(new(Int), x, y)
if out.Cmp(expected) != 0 {
t.Errorf("%s: got %s want %s", msg, out, expected)
}
}
func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
self := new(Int)
self.Set(x)
expected := new(Int)
expected.SetString(exp, 0)
self = f(self, self, y)
if self.Cmp(expected) != 0 {
t.Errorf("%s: got %s want %s", msg, self, expected)
}
}
func altBit(x *Int, i int) uint {
z := new(Int).Rsh(x, uint(i))
z = z.And(z, NewInt(1))
if z.Cmp(new(Int)) != 0 {
return 1
}
return 0
}
func altSetBit(z *Int, x *Int, i int, b uint) *Int {
one := NewInt(1)
m := one.Lsh(one, uint(i))
switch b {
case 1:
return z.Or(x, m)
case 0:
return z.AndNot(x, m)
}
panic("set bit is not 0 or 1")
}
func testBitset(t *testing.T, x *Int) {
n := x.BitLen()
z := new(Int).Set(x)
z1 := new(Int).Set(x)
for i := 0; i < n+10; i++ {
old := z.Bit(i)
old1 := altBit(z1, i)
if old != old1 {
t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1)
}
z := new(Int).SetBit(z, i, 1)
z1 := altSetBit(new(Int), z1, i, 1)
if z.Bit(i) == 0 {
t.Errorf("bitset: bit %d of %s got 0 want 1", i, x)
}
if z.Cmp(z1) != 0 {
t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1)
}
z.SetBit(z, i, 0)
altSetBit(z1, z1, i, 0)
if z.Bit(i) != 0 {
t.Errorf("bitset: bit %d of %s got 1 want 0", i, x)
}
if z.Cmp(z1) != 0 {
t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1)
}
altSetBit(z1, z1, i, old)
z.SetBit(z, i, old)
if z.Cmp(z1) != 0 {
t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1)
}
}
if z.Cmp(x) != 0 {
t.Errorf("bitset: got %s want %s", z, x)
}
}
var bitsetTests = []struct {
x string
i int
b uint
}{
{"0", 0, 0},
{"0", 200, 0},
{"1", 0, 1},
{"1", 1, 0},
{"-1", 0, 1},
{"-1", 200, 1},
{"0x2000000000000000000000000000", 108, 0},
{"0x2000000000000000000000000000", 109, 1},
{"0x2000000000000000000000000000", 110, 0},
{"-0x2000000000000000000000000001", 108, 1},
{"-0x2000000000000000000000000001", 109, 0},
{"-0x2000000000000000000000000001", 110, 1},
}
func TestBitSet(t *testing.T) {
for _, test := range bitwiseTests {
x := new(Int)
x.SetString(test.x, 0)
testBitset(t, x)
x = new(Int)
x.SetString(test.y, 0)
testBitset(t, x)
}
for i, test := range bitsetTests {
x := new(Int)
x.SetString(test.x, 0)
b := x.Bit(test.i)
if b != test.b {
t.Errorf("#%d got %v want %v", i, b, test.b)
}
}
z := NewInt(1)
z.SetBit(NewInt(0), 2, 1)
if z.Cmp(NewInt(4)) != 0 {
t.Errorf("destination leaked into result; got %s want 4", z)
}
}
func BenchmarkBitset(b *testing.B) {
z := new(Int)
z.SetBit(z, 512, 1)
b.ResetTimer()
b.StartTimer()
for i := b.N - 1; i >= 0; i-- {
z.SetBit(z, i&512, 1)
}
}
func BenchmarkBitsetNeg(b *testing.B) {
z := NewInt(-1)
z.SetBit(z, 512, 0)
b.ResetTimer()
b.StartTimer()
for i := b.N - 1; i >= 0; i-- {
z.SetBit(z, i&512, 0)
}
}
func BenchmarkBitsetOrig(b *testing.B) {
z := new(Int)
altSetBit(z, z, 512, 1)
b.ResetTimer()
b.StartTimer()
for i := b.N - 1; i >= 0; i-- {
altSetBit(z, z, i&512, 1)
}
}
func BenchmarkBitsetNegOrig(b *testing.B) {
z := NewInt(-1)
altSetBit(z, z, 512, 0)
b.ResetTimer()
b.StartTimer()
for i := b.N - 1; i >= 0; i-- {
altSetBit(z, z, i&512, 0)
}
}
// tri generates the trinomial 2**(n*2) - 2**n - 1, which is always 3 mod 4 and
// 7 mod 8, so that 2 is always a quadratic residue.
func tri(n uint) *Int {
x := NewInt(1)
x.Lsh(x, n)
x2 := new(Int).Lsh(x, n)
x2.Sub(x2, x)
x2.Sub(x2, intOne)
return x2
}
func BenchmarkModSqrt225_Tonelli(b *testing.B) {
p := tri(225)
x := NewInt(2)
for i := 0; i < b.N; i++ {
x.SetUint64(2)
x.modSqrtTonelliShanks(x, p)
}
}
func BenchmarkModSqrt224_3Mod4(b *testing.B) {
p := tri(225)
x := new(Int).SetUint64(2)
for i := 0; i < b.N; i++ {
x.SetUint64(2)
x.modSqrt3Mod4Prime(x, p)
}
}
func BenchmarkModSqrt5430_Tonelli(b *testing.B) {
p := tri(5430)
x := new(Int).SetUint64(2)
for i := 0; i < b.N; i++ {
x.SetUint64(2)
x.modSqrtTonelliShanks(x, p)
}
}
func BenchmarkModSqrt5430_3Mod4(b *testing.B) {
p := tri(5430)
x := new(Int).SetUint64(2)
for i := 0; i < b.N; i++ {
x.SetUint64(2)
x.modSqrt3Mod4Prime(x, p)
}
}
func TestBitwise(t *testing.T) {
x := new(Int)
y := new(Int)
for _, test := range bitwiseTests {
x.SetString(test.x, 0)
y.SetString(test.y, 0)
testBitFun(t, "and", (*Int).And, x, y, test.and)
testBitFunSelf(t, "and", (*Int).And, x, y, test.and)
testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot)
testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot)
testBitFun(t, "or", (*Int).Or, x, y, test.or)
testBitFunSelf(t, "or", (*Int).Or, x, y, test.or)
testBitFun(t, "xor", (*Int).Xor, x, y, test.xor)
testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor)
}
}
var notTests = []struct {
in string
out string
}{
{"0", "-1"},
{"1", "-2"},
{"7", "-8"},
{"0", "-1"},
{"-81910", "81909"},
{
"298472983472983471903246121093472394872319615612417471234712061",
"-298472983472983471903246121093472394872319615612417471234712062",
},
}
func TestNot(t *testing.T) {
in := new(Int)
out := new(Int)
expected := new(Int)
for i, test := range notTests {
in.SetString(test.in, 10)
expected.SetString(test.out, 10)
out = out.Not(in)
if out.Cmp(expected) != 0 {
t.Errorf("#%d: got %s want %s", i, out, expected)
}
out = out.Not(out)
if out.Cmp(in) != 0 {
t.Errorf("#%d: got %s want %s", i, out, in)
}
}
}
var modInverseTests = []struct {
element string
modulus string
}{
{"1234567", "458948883992"},
{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
}
func TestModInverse(t *testing.T) {
var element, modulus, gcd, inverse Int
one := NewInt(1)
for i, test := range modInverseTests {
(&element).SetString(test.element, 10)
(&modulus).SetString(test.modulus, 10)
(&inverse).ModInverse(&element, &modulus)
(&inverse).Mul(&inverse, &element)
(&inverse).Mod(&inverse, &modulus)
if (&inverse).Cmp(one) != 0 {
t.Errorf("#%d: failed (e·e^(-1)=%s)", i, &inverse)
}
}
// exhaustive test for small values
for n := 2; n < 100; n++ {
(&modulus).SetInt64(int64(n))
for x := 1; x < n; x++ {
(&element).SetInt64(int64(x))
(&gcd).GCD(nil, nil, &element, &modulus)
if (&gcd).Cmp(one) != 0 {
continue
}
(&inverse).ModInverse(&element, &modulus)
(&inverse).Mul(&inverse, &element)
(&inverse).Mod(&inverse, &modulus)
if (&inverse).Cmp(one) != 0 {
t.Errorf("ModInverse(%d,%d)*%d%%%d=%d, not 1", &element, &modulus, &element, &modulus, &inverse)
}
}
}
}
// testModSqrt is a helper for TestModSqrt,
// which checks that ModSqrt can compute a square-root of elt^2.
func testModSqrt(t *testing.T, elt, mod, sq, sqrt *Int) bool {
var sqChk, sqrtChk, sqrtsq Int
sq.Mul(elt, elt)
sq.Mod(sq, mod)
z := sqrt.ModSqrt(sq, mod)
if z != sqrt {
t.Errorf("ModSqrt returned wrong value %s", z)
}
// test ModSqrt arguments outside the range [0,mod)
sqChk.Add(sq, mod)
z = sqrtChk.ModSqrt(&sqChk, mod)
if z != &sqrtChk || z.Cmp(sqrt) != 0 {
t.Errorf("ModSqrt returned inconsistent value %s", z)
}
sqChk.Sub(sq, mod)
z = sqrtChk.ModSqrt(&sqChk, mod)
if z != &sqrtChk || z.Cmp(sqrt) != 0 {
t.Errorf("ModSqrt returned inconsistent value %s", z)
}
// make sure we actually got a square root
if sqrt.Cmp(elt) == 0 {
return true // we found the "desired" square root
}
sqrtsq.Mul(sqrt, sqrt) // make sure we found the "other" one
sqrtsq.Mod(&sqrtsq, mod)
return sq.Cmp(&sqrtsq) == 0
}
func TestModSqrt(t *testing.T) {
var elt, mod, modx4, sq, sqrt Int
r := rand.New(rand.NewSource(9))
for i, s := range primes[1:] { // skip 2, use only odd primes
mod.SetString(s, 10)
modx4.Lsh(&mod, 2)
// test a few random elements per prime
for x := 1; x < 5; x++ {
elt.Rand(r, &modx4)
elt.Sub(&elt, &mod) // test range [-mod, 3*mod)
if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
}
}
if testing.Short() && i > 2 {
break
}
}
if testing.Short() {
return
}
// exhaustive test for small values
for n := 3; n < 100; n++ {
mod.SetInt64(int64(n))
if !mod.ProbablyPrime(10) {
continue
}
isSquare := make([]bool, n)
// test all the squares
for x := 1; x < n; x++ {
elt.SetInt64(int64(x))
if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
t.Errorf("#%d: failed (sqrt(%d,%d) = %s)", x, &elt, &mod, &sqrt)
}
isSquare[sq.Uint64()] = true
}
// test all non-squares
for x := 1; x < n; x++ {
sq.SetInt64(int64(x))
z := sqrt.ModSqrt(&sq, &mod)
if !isSquare[x] && z != nil {
t.Errorf("#%d: failed (sqrt(%d,%d) = nil)", x, &sqrt, &mod)
}
}
}
}
func TestJacobi(t *testing.T) {
testCases := []struct {
x, y int64
result int
}{
{0, 1, 1},
{0, -1, 1},
{1, 1, 1},
{1, -1, 1},
{0, 5, 0},
{1, 5, 1},
{2, 5, -1},
{-2, 5, -1},
{2, -5, -1},
{-2, -5, 1},
{3, 5, -1},
{5, 5, 0},
{-5, 5, 0},
{6, 5, 1},
{6, -5, 1},
{-6, 5, 1},
{-6, -5, -1},
}
var x, y Int
for i, test := range testCases {
x.SetInt64(test.x)
y.SetInt64(test.y)
expected := test.result
actual := Jacobi(&x, &y)
if actual != expected {
t.Errorf("#%d: Jacobi(%d, %d) = %d, but expected %d", i, test.x, test.y, actual, expected)
}
}
}
func TestJacobiPanic(t *testing.T) {
const failureMsg = "test failure"
defer func() {
msg := recover()
if msg == nil || msg == failureMsg {
panic(msg)
}
t.Log(msg)
}()
x := NewInt(1)
y := NewInt(2)
// Jacobi should panic when the second argument is even.
Jacobi(x, y)
panic(failureMsg)
}
func TestIssue2607(t *testing.T) {
// This code sequence used to hang.
n := NewInt(10)
n.Rand(rand.New(rand.NewSource(9)), n)
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements int-to-string conversion functions.
package big
import (
"errors"
"fmt"
"io"
)
// TODO(gri) Should rename itoa to utoa (there's no sign). That
// would permit the introduction of itoa which is like utoa but
// reserves a byte for a possible sign that's passed in. That
// would permit Int.Text to be implemented w/o the need for
// string copy if the number is negative.
// Text returns the string representation of x in the given base.
// Base must be between 2 and 36, inclusive. The result uses the
// lower-case letters 'a' to 'z' for digit values >= 10. No base
// prefix (such as "0x") is added to the string.
func (x *Int) Text(base int) string {
if x == nil {
return "<nil>"
}
return string(x.abs.itoa(x.neg, base))
}
// Append appends the string representation of x, as generated by
// x.Text(base), to buf and returns the extended buffer.
func (x *Int) Append(buf []byte, base int) []byte {
if x == nil {
return append(buf, "<nil>"...)
}
return append(buf, x.abs.itoa(x.neg, base)...)
}
func (x *Int) String() string {
return x.Text(10)
}
// write count copies of text to s
func writeMultiple(s fmt.State, text string, count int) {
if len(text) > 0 {
b := []byte(text)
for ; count > 0; count-- {
s.Write(b)
}
}
}
// Format implements fmt.Formatter. It accepts the formats
// 'b' (binary), 'o' (octal), 'd' (decimal), 'x' (lowercase
// hexadecimal), and 'X' (uppercase hexadecimal).
// Also supported are the full suite of package fmt's format
// flags for integral types, including '+' and ' ' for sign
// control, '#' for leading zero in octal and for hexadecimal,
// a leading "0x" or "0X" for "%#x" and "%#X" respectively,
// specification of minimum digits precision, output field
// width, space or zero padding, and '-' for left or right
// justification.
//
func (x *Int) Format(s fmt.State, ch rune) {
// determine base
var base int
switch ch {
case 'b':
base = 2
case 'o':
base = 8
case 'd', 's', 'v':
base = 10
case 'x', 'X':
base = 16
default:
// unknown format
fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
return
}
if x == nil {
fmt.Fprint(s, "<nil>")
return
}
// determine sign character
sign := ""
switch {
case x.neg:
sign = "-"
case s.Flag('+'): // supersedes ' ' when both specified
sign = "+"
case s.Flag(' '):
sign = " "
}
// determine prefix characters for indicating output base
prefix := ""
if s.Flag('#') {
switch ch {
case 'o': // octal
prefix = "0"
case 'x': // hexadecimal
prefix = "0x"
case 'X':
prefix = "0X"
}
}
digits := x.abs.utoa(base)
if ch == 'X' {
// faster than bytes.ToUpper
for i, d := range digits {
if 'a' <= d && d <= 'z' {
digits[i] = 'A' + (d - 'a')
}
}
}
// number of characters for the three classes of number padding
var left int // space characters to left of digits for right justification ("%8d")
var zeros int // zero characters (actually cs[0]) as left-most digits ("%.8d")
var right int // space characters to right of digits for left justification ("%-8d")
// determine number padding from precision: the least number of digits to output
precision, precisionSet := s.Precision()
if precisionSet {
switch {
case len(digits) < precision:
zeros = precision - len(digits) // count of zero padding
case len(digits) == 1 && digits[0] == '0' && precision == 0:
return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
}
}
// determine field pad from width: the least number of characters to output
length := len(sign) + len(prefix) + zeros + len(digits)
if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
switch d := width - length; {
case s.Flag('-'):
// pad on the right with spaces; supersedes '0' when both specified
right = d
case s.Flag('0') && !precisionSet:
// pad with zeros unless precision also specified
zeros = d
default:
// pad on the left with spaces
left = d
}
}
// print number as [left pad][sign][prefix][zero pad][digits][right pad]
writeMultiple(s, " ", left)
writeMultiple(s, sign, 1)
writeMultiple(s, prefix, 1)
writeMultiple(s, "0", zeros)
s.Write(digits)
writeMultiple(s, " ", right)
}
// scan sets z to the integer value corresponding to the longest possible prefix
// read from r representing a signed integer number in a given conversion base.
// It returns z, the actual conversion base used, and an error, if any. In the
// error case, the value of z is undefined but the returned value is nil. The
// syntax follows the syntax of integer literals in Go.
//
// The base argument must be 0 or a value from 2 through MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
//
func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
// determine sign
neg, err := scanSign(r)
if err != nil {
return nil, 0, err
}
// determine mantissa
z.abs, base, _, err = z.abs.scan(r, base, false)
if err != nil {
return nil, base, err
}
z.neg = len(z.abs) > 0 && neg // 0 has no sign
return z, base, nil
}
func scanSign(r io.ByteScanner) (neg bool, err error) {
var ch byte
if ch, err = r.ReadByte(); err != nil {
return false, err
}
switch ch {
case '-':
neg = true
case '+':
// nothing to do
default:
r.UnreadByte()
}
return
}
// byteReader is a local wrapper around fmt.ScanState;
// it implements the ByteReader interface.
type byteReader struct {
fmt.ScanState
}
func (r byteReader) ReadByte() (byte, error) {
ch, size, err := r.ReadRune()
if size != 1 && err == nil {
err = fmt.Errorf("invalid rune %#U", ch)
}
return byte(ch), err
}
func (r byteReader) UnreadByte() error {
return r.UnreadRune()
}
// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
func (z *Int) Scan(s fmt.ScanState, ch rune) error {
s.SkipSpace() // skip leading space characters
base := 0
switch ch {
case 'b':
base = 2
case 'o':
base = 8
case 'd':
base = 10
case 'x', 'X':
base = 16
case 's', 'v':
// let scan determine the base
default:
return errors.New("Int.Scan: invalid verb")
}
_, _, err := z.scan(byteReader{s}, base)
return err
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"bytes"
"fmt"
"testing"
)
var stringTests = []struct {
in string
out string
base int
val int64
ok bool
}{
{in: ""},
{in: "a"},
{in: "z"},
{in: "+"},
{in: "-"},
{in: "0b"},
{in: "0x"},
{in: "2", base: 2},
{in: "0b2", base: 0},
{in: "08"},
{in: "8", base: 8},
{in: "0xg", base: 0},
{in: "g", base: 16},
{"0", "0", 0, 0, true},
{"0", "0", 10, 0, true},
{"0", "0", 16, 0, true},
{"+0", "0", 0, 0, true},
{"-0", "0", 0, 0, true},
{"10", "10", 0, 10, true},
{"10", "10", 10, 10, true},
{"10", "10", 16, 16, true},
{"-10", "-10", 16, -16, true},
{"+10", "10", 16, 16, true},
{"0x10", "16", 0, 16, true},
{in: "0x10", base: 16},
{"-0x10", "-16", 0, -16, true},
{"+0x10", "16", 0, 16, true},
{"00", "0", 0, 0, true},
{"0", "0", 8, 0, true},
{"07", "7", 0, 7, true},
{"7", "7", 8, 7, true},
{"023", "19", 0, 19, true},
{"23", "23", 8, 19, true},
{"cafebabe", "cafebabe", 16, 0xcafebabe, true},
{"0b0", "0", 0, 0, true},
{"-111", "-111", 2, -7, true},
{"-0b111", "-7", 0, -7, true},
{"0b1001010111", "599", 0, 0x257, true},
{"1001010111", "1001010111", 2, 0x257, true},
}
func TestIntText(t *testing.T) {
z := new(Int)
for _, test := range stringTests {
if !test.ok {
continue
}
_, ok := z.SetString(test.in, test.base)
if !ok {
t.Errorf("%v: failed to parse", test)
continue
}
base := test.base
if base == 0 {
base = 10
}
if got := z.Text(base); got != test.out {
t.Errorf("%v: got %s; want %s", test, got, test.out)
}
}
}
func TestAppendText(t *testing.T) {
z := new(Int)
var buf []byte
for _, test := range stringTests {
if !test.ok {
continue
}
_, ok := z.SetString(test.in, test.base)
if !ok {
t.Errorf("%v: failed to parse", test)
continue
}
base := test.base
if base == 0 {
base = 10
}
i := len(buf)
buf = z.Append(buf, base)
if got := string(buf[i:]); got != test.out {
t.Errorf("%v: got %s; want %s", test, got, test.out)
}
}
}
func format(base int) string {
switch base {
case 2:
return "%b"
case 8:
return "%o"
case 16:
return "%x"
}
return "%d"
}
func TestGetString(t *testing.T) {
z := new(Int)
for i, test := range stringTests {
if !test.ok {
continue
}
z.SetInt64(test.val)
if test.base == 10 {
if got := z.String(); got != test.out {
t.Errorf("#%da got %s; want %s", i, got, test.out)
}
}
if got := fmt.Sprintf(format(test.base), z); got != test.out {
t.Errorf("#%db got %s; want %s", i, got, test.out)
}
}
}
func TestSetString(t *testing.T) {
tmp := new(Int)
for i, test := range stringTests {
// initialize to a non-zero value so that issues with parsing
// 0 are detected
tmp.SetInt64(1234567890)
n1, ok1 := new(Int).SetString(test.in, test.base)
n2, ok2 := tmp.SetString(test.in, test.base)
expected := NewInt(test.val)
if ok1 != test.ok || ok2 != test.ok {
t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
continue
}
if !ok1 {
if n1 != nil {
t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
}
continue
}
if !ok2 {
if n2 != nil {
t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
}
continue
}
if ok1 && !isNormalized(n1) {
t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
}
if ok2 && !isNormalized(n2) {
t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
}
if n1.Cmp(expected) != 0 {
t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
}
if n2.Cmp(expected) != 0 {
t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
}
}
}
var formatTests = []struct {
input string
format string
output string
}{
{"<nil>", "%x", "<nil>"},
{"<nil>", "%#x", "<nil>"},
{"<nil>", "%#y", "%!y(big.Int=<nil>)"},
{"10", "%b", "1010"},
{"10", "%o", "12"},
{"10", "%d", "10"},
{"10", "%v", "10"},
{"10", "%x", "a"},
{"10", "%X", "A"},
{"-10", "%X", "-A"},
{"10", "%y", "%!y(big.Int=10)"},
{"-10", "%y", "%!y(big.Int=-10)"},
{"10", "%#b", "1010"},
{"10", "%#o", "012"},
{"10", "%#d", "10"},
{"10", "%#v", "10"},
{"10", "%#x", "0xa"},
{"10", "%#X", "0XA"},
{"-10", "%#X", "-0XA"},
{"10", "%#y", "%!y(big.Int=10)"},
{"-10", "%#y", "%!y(big.Int=-10)"},
{"1234", "%d", "1234"},
{"1234", "%3d", "1234"},
{"1234", "%4d", "1234"},
{"-1234", "%d", "-1234"},
{"1234", "% 5d", " 1234"},
{"1234", "%+5d", "+1234"},
{"1234", "%-5d", "1234 "},
{"1234", "%x", "4d2"},
{"1234", "%X", "4D2"},
{"-1234", "%3x", "-4d2"},
{"-1234", "%4x", "-4d2"},
{"-1234", "%5x", " -4d2"},
{"-1234", "%-5x", "-4d2 "},
{"1234", "%03d", "1234"},
{"1234", "%04d", "1234"},
{"1234", "%05d", "01234"},
{"1234", "%06d", "001234"},
{"-1234", "%06d", "-01234"},
{"1234", "%+06d", "+01234"},
{"1234", "% 06d", " 01234"},
{"1234", "%-6d", "1234 "},
{"1234", "%-06d", "1234 "},
{"-1234", "%-06d", "-1234 "},
{"1234", "%.3d", "1234"},
{"1234", "%.4d", "1234"},
{"1234", "%.5d", "01234"},
{"1234", "%.6d", "001234"},
{"-1234", "%.3d", "-1234"},
{"-1234", "%.4d", "-1234"},
{"-1234", "%.5d", "-01234"},
{"-1234", "%.6d", "-001234"},
{"1234", "%8.3d", " 1234"},
{"1234", "%8.4d", " 1234"},
{"1234", "%8.5d", " 01234"},
{"1234", "%8.6d", " 001234"},
{"-1234", "%8.3d", " -1234"},
{"-1234", "%8.4d", " -1234"},
{"-1234", "%8.5d", " -01234"},
{"-1234", "%8.6d", " -001234"},
{"1234", "%+8.3d", " +1234"},
{"1234", "%+8.4d", " +1234"},
{"1234", "%+8.5d", " +01234"},
{"1234", "%+8.6d", " +001234"},
{"-1234", "%+8.3d", " -1234"},
{"-1234", "%+8.4d", " -1234"},
{"-1234", "%+8.5d", " -01234"},
{"-1234", "%+8.6d", " -001234"},
{"1234", "% 8.3d", " 1234"},
{"1234", "% 8.4d", " 1234"},
{"1234", "% 8.5d", " 01234"},
{"1234", "% 8.6d", " 001234"},
{"-1234", "% 8.3d", " -1234"},
{"-1234", "% 8.4d", " -1234"},
{"-1234", "% 8.5d", " -01234"},
{"-1234", "% 8.6d", " -001234"},
{"1234", "%.3x", "4d2"},
{"1234", "%.4x", "04d2"},
{"1234", "%.5x", "004d2"},
{"1234", "%.6x", "0004d2"},
{"-1234", "%.3x", "-4d2"},
{"-1234", "%.4x", "-04d2"},
{"-1234", "%.5x", "-004d2"},
{"-1234", "%.6x", "-0004d2"},
{"1234", "%8.3x", " 4d2"},
{"1234", "%8.4x", " 04d2"},
{"1234", "%8.5x", " 004d2"},
{"1234", "%8.6x", " 0004d2"},
{"-1234", "%8.3x", " -4d2"},
{"-1234", "%8.4x", " -04d2"},
{"-1234", "%8.5x", " -004d2"},
{"-1234", "%8.6x", " -0004d2"},
{"1234", "%+8.3x", " +4d2"},
{"1234", "%+8.4x", " +04d2"},
{"1234", "%+8.5x", " +004d2"},
{"1234", "%+8.6x", " +0004d2"},
{"-1234", "%+8.3x", " -4d2"},
{"-1234", "%+8.4x", " -04d2"},
{"-1234", "%+8.5x", " -004d2"},
{"-1234", "%+8.6x", " -0004d2"},
{"1234", "% 8.3x", " 4d2"},
{"1234", "% 8.4x", " 04d2"},
{"1234", "% 8.5x", " 004d2"},
{"1234", "% 8.6x", " 0004d2"},
{"1234", "% 8.7x", " 00004d2"},
{"1234", "% 8.8x", " 000004d2"},
{"-1234", "% 8.3x", " -4d2"},
{"-1234", "% 8.4x", " -04d2"},
{"-1234", "% 8.5x", " -004d2"},
{"-1234", "% 8.6x", " -0004d2"},
{"-1234", "% 8.7x", "-00004d2"},
{"-1234", "% 8.8x", "-000004d2"},
{"1234", "%-8.3d", "1234 "},
{"1234", "%-8.4d", "1234 "},
{"1234", "%-8.5d", "01234 "},
{"1234", "%-8.6d", "001234 "},
{"1234", "%-8.7d", "0001234 "},
{"1234", "%-8.8d", "00001234"},
{"-1234", "%-8.3d", "-1234 "},
{"-1234", "%-8.4d", "-1234 "},
{"-1234", "%-8.5d", "-01234 "},
{"-1234", "%-8.6d", "-001234 "},
{"-1234", "%-8.7d", "-0001234"},
{"-1234", "%-8.8d", "-00001234"},
{"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
{"0", "%.d", ""},
{"0", "%.0d", ""},
{"0", "%3.d", ""},
}
func TestFormat(t *testing.T) {
for i, test := range formatTests {
var x *Int
if test.input != "<nil>" {
var ok bool
x, ok = new(Int).SetString(test.input, 0)
if !ok {
t.Errorf("#%d failed reading input %s", i, test.input)
}
}
output := fmt.Sprintf(test.format, x)
if output != test.output {
t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
}
}
}
var scanTests = []struct {
input string
format string
output string
remaining int
}{
{"1010", "%b", "10", 0},
{"0b1010", "%v", "10", 0},
{"12", "%o", "10", 0},
{"012", "%v", "10", 0},
{"10", "%d", "10", 0},
{"10", "%v", "10", 0},
{"a", "%x", "10", 0},
{"0xa", "%v", "10", 0},
{"A", "%X", "10", 0},
{"-A", "%X", "-10", 0},
{"+0b1011001", "%v", "89", 0},
{"0xA", "%v", "10", 0},
{"0 ", "%v", "0", 1},
{"2+3", "%v", "2", 2},
{"0XABC 12", "%v", "2748", 3},
}
func TestScan(t *testing.T) {
var buf bytes.Buffer
for i, test := range scanTests {
x := new(Int)
buf.Reset()
buf.WriteString(test.input)
if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
t.Errorf("#%d error: %s", i, err)
}
if x.String() != test.output {
t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
}
if buf.Len() != test.remaining {
t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
}
}
}
// 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 {
// Ignore null, like in the main JSON package.
if string(text) == "null" {
return nil
}
return z.UnmarshalText(text)
}
// 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)
}
}
}
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements unsigned multi-precision integers (natural
// numbers). They are the building blocks for the implementation
// of signed integers, rationals, and floating-point numbers.
package big
import (
"math/rand"
"sync"
)
// An unsigned integer x of the form
//
// x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]
//
// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,
// with the digits x[i] as the slice elements.
//
// A number is normalized if the slice contains no leading 0 digits.
// During arithmetic operations, denormalized values may occur but are
// always normalized before returning the final result. The normalized
// representation of 0 is the empty or nil slice (length = 0).
//
type nat []Word
var (
natOne = nat{1}
natTwo = nat{2}
natTen = nat{10}
)
func (z nat) clear() {
for i := range z {
z[i] = 0
}
}
func (z nat) norm() nat {
i := len(z)
for i > 0 && z[i-1] == 0 {
i--
}
return z[0:i]
}
func (z nat) make(n int) nat {
if n <= cap(z) {
return z[:n] // reuse z
}
// Choosing a good value for e has significant performance impact
// because it increases the chance that a value can be reused.
const e = 4 // extra capacity
return make(nat, n, n+e)
}
func (z nat) setWord(x Word) nat {
if x == 0 {
return z[:0]
}
z = z.make(1)
z[0] = x
return z
}
func (z nat) setUint64(x uint64) nat {
// single-digit values
if w := Word(x); uint64(w) == x {
return z.setWord(w)
}
// compute number of words n required to represent x
n := 0
for t := x; t > 0; t >>= _W {
n++
}
// split x into n words
z = z.make(n)
for i := range z {
z[i] = Word(x & _M)
x >>= _W
}
return z
}
func (z nat) set(x nat) nat {
z = z.make(len(x))
copy(z, x)
return z
}
func (z nat) add(x, y nat) nat {
m := len(x)
n := len(y)
switch {
case m < n:
return z.add(y, x)
case m == 0:
// n == 0 because m >= n; result is 0
return z[:0]
case n == 0:
// result is x
return z.set(x)
}
// m > 0
z = z.make(m + 1)
c := addVV(z[0:n], x, y)
if m > n {
c = addVW(z[n:m], x[n:], c)
}
z[m] = c
return z.norm()
}
func (z nat) sub(x, y nat) nat {
m := len(x)
n := len(y)
switch {
case m < n:
panic("underflow")
case m == 0:
// n == 0 because m >= n; result is 0
return z[:0]
case n == 0:
// result is x
return z.set(x)
}
// m > 0
z = z.make(m)
c := subVV(z[0:n], x, y)
if m > n {
c = subVW(z[n:], x[n:], c)
}
if c != 0 {
panic("underflow")
}
return z.norm()
}
func (x nat) cmp(y nat) (r int) {
m := len(x)
n := len(y)
if m != n || m == 0 {
switch {
case m < n:
r = -1
case m > n:
r = 1
}
return
}
i := m - 1
for i > 0 && x[i] == y[i] {
i--
}
switch {
case x[i] < y[i]:
r = -1
case x[i] > y[i]:
r = 1
}
return
}
func (z nat) mulAddWW(x nat, y, r Word) nat {
m := len(x)
if m == 0 || y == 0 {
return z.setWord(r) // result is r
}
// m > 0
z = z.make(m + 1)
z[m] = mulAddVWW(z[0:m], x, y, r)
return z.norm()
}
// basicMul multiplies x and y and leaves the result in z.
// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
func basicMul(z, x, y nat) {
z[0 : len(x)+len(y)].clear() // initialize z
for i, d := range y {
if d != 0 {
z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
}
}
}
// montgomery computes z mod m = x*y*2**(-n*_W) mod m,
// assuming k = -1/m mod 2**_W.
// z is used for storing the result which is returned;
// z must not alias x, y or m.
// See Gueron, "Efficient Software Implementations of Modular Exponentiation".
// https://eprint.iacr.org/2011/239.pdf
// In the terminology of that paper, this is an "Almost Montgomery Multiplication":
// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result
// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.
func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
// This code assumes x, y, m are all the same length, n.
// (required by addMulVVW and the for loop).
// It also assumes that x, y are already reduced mod m,
// or else the result will not be properly reduced.
if len(x) != n || len(y) != n || len(m) != n {
panic("math/big: mismatched montgomery number lengths")
}
z = z.make(n)
z.clear()
var c Word
for i := 0; i < n; i++ {
d := y[i]
c2 := addMulVVW(z, x, d)
t := z[0] * k
c3 := addMulVVW(z, m, t)
copy(z, z[1:])
cx := c + c2
cy := cx + c3
z[n-1] = cy
if cx < c2 || cy < c3 {
c = 1
} else {
c = 0
}
}
if c != 0 {
subVV(z, z, m)
}
return z
}
// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
// Factored out for readability - do not use outside karatsuba.
func karatsubaAdd(z, x nat, n int) {
if c := addVV(z[0:n], z, x); c != 0 {
addVW(z[n:n+n>>1], z[n:], c)
}
}
// Like karatsubaAdd, but does subtract.
func karatsubaSub(z, x nat, n int) {
if c := subVV(z[0:n], z, x); c != 0 {
subVW(z[n:n+n>>1], z[n:], c)
}
}
// Operands that are shorter than karatsubaThreshold are multiplied using
// "grade school" multiplication; for longer operands the Karatsuba algorithm
// is used.
var karatsubaThreshold int = 40 // computed by calibrate.go
// karatsuba multiplies x and y and leaves the result in z.
// Both x and y must have the same length n and n must be a
// power of 2. The result vector z must have len(z) >= 6*n.
// The (non-normalized) result is placed in z[0 : 2*n].
func karatsuba(z, x, y nat) {
n := len(y)
// Switch to basic multiplication if numbers are odd or small.
// (n is always even if karatsubaThreshold is even, but be
// conservative)
if n&1 != 0 || n < karatsubaThreshold || n < 2 {
basicMul(z, x, y)
return
}
// n&1 == 0 && n >= karatsubaThreshold && n >= 2
// Karatsuba multiplication is based on the observation that
// for two numbers x and y with:
//
// x = x1*b + x0
// y = y1*b + y0
//
// the product x*y can be obtained with 3 products z2, z1, z0
// instead of 4:
//
// x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0
// = z2*b*b + z1*b + z0
//
// with:
//
// xd = x1 - x0
// yd = y0 - y1
//
// z1 = xd*yd + z2 + z0
// = (x1-x0)*(y0 - y1) + z2 + z0
// = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0
// = x1*y0 - z2 - z0 + x0*y1 + z2 + z0
// = x1*y0 + x0*y1
// split x, y into "digits"
n2 := n >> 1 // n2 >= 1
x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0
y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0
// z is used for the result and temporary storage:
//
// 6*n 5*n 4*n 3*n 2*n 1*n 0*n
// z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ]
//
// For each recursive call of karatsuba, an unused slice of
// z is passed in that has (at least) half the length of the
// caller's z.
// compute z0 and z2 with the result "in place" in z
karatsuba(z, x0, y0) // z0 = x0*y0
karatsuba(z[n:], x1, y1) // z2 = x1*y1
// compute xd (or the negative value if underflow occurs)
s := 1 // sign of product xd*yd
xd := z[2*n : 2*n+n2]
if subVV(xd, x1, x0) != 0 { // x1-x0
s = -s
subVV(xd, x0, x1) // x0-x1
}
// compute yd (or the negative value if underflow occurs)
yd := z[2*n+n2 : 3*n]
if subVV(yd, y0, y1) != 0 { // y0-y1
s = -s
subVV(yd, y1, y0) // y1-y0
}
// p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0
// p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0
p := z[n*3:]
karatsuba(p, xd, yd)
// save original z2:z0
// (ok to use upper half of z since we're done recursing)
r := z[n*4:]
copy(r, z[:n*2])
// add up all partial products
//
// 2*n n 0
// z = [ z2 | z0 ]
// + [ z0 ]
// + [ z2 ]
// + [ p ]
//
karatsubaAdd(z[n2:], r, n)
karatsubaAdd(z[n2:], r[n:], n)
if s > 0 {
karatsubaAdd(z[n2:], p, n)
} else {
karatsubaSub(z[n2:], p, n)
}
}
// alias reports whether x and y share the same base array.
func alias(x, y nat) bool {
return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
}
// addAt implements z += x<<(_W*i); z must be long enough.
// (we don't use nat.add because we need z to stay the same
// slice, and we don't need to normalize z after each addition)
func addAt(z, x nat, i int) {
if n := len(x); n > 0 {
if c := addVV(z[i:i+n], z[i:], x); c != 0 {
j := i + n
if j < len(z) {
addVW(z[j:], z[j:], c)
}
}
}
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
// karatsubaLen computes an approximation to the maximum k <= n such that
// k = p<<i for a number p <= karatsubaThreshold and an i >= 0. Thus, the
// result is the largest number that can be divided repeatedly by 2 before
// becoming about the value of karatsubaThreshold.
func karatsubaLen(n int) int {
i := uint(0)
for n > karatsubaThreshold {
n >>= 1
i++
}
return n << i
}
func (z nat) mul(x, y nat) nat {
m := len(x)
n := len(y)
switch {
case m < n:
return z.mul(y, x)
case m == 0 || n == 0:
return z[:0]
case n == 1:
return z.mulAddWW(x, y[0], 0)
}
// m >= n > 1
// determine if z can be reused
if alias(z, x) || alias(z, y) {
z = nil // z is an alias for x or y - cannot reuse
}
// use basic multiplication if the numbers are small
if n < karatsubaThreshold {
z = z.make(m + n)
basicMul(z, x, y)
return z.norm()
}
// m >= n && n >= karatsubaThreshold && n >= 2
// determine Karatsuba length k such that
//
// x = xh*b + x0 (0 <= x0 < b)
// y = yh*b + y0 (0 <= y0 < b)
// b = 1<<(_W*k) ("base" of digits xi, yi)
//
k := karatsubaLen(n)
// k <= n
// multiply x0 and y0 via Karatsuba
x0 := x[0:k] // x0 is not normalized
y0 := y[0:k] // y0 is not normalized
z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
karatsuba(z, x0, y0)
z = z[0 : m+n] // z has final length but may be incomplete
z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)
// If xh != 0 or yh != 0, add the missing terms to z. For
//
// xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b)
// yh = y1*b (0 <= y1 < b)
//
// the missing terms are
//
// x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0
//
// since all the yi for i > 1 are 0 by choice of k: If any of them
// were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would
// be a larger valid threshold contradicting the assumption about k.
//
if k < n || m != n {
var t nat
// add x0*y1*b
x0 := x0.norm()
y1 := y[k:] // y1 is normalized because y is
t = t.mul(x0, y1) // update t so we don't lose t's underlying array
addAt(z, t, k)
// add xi*y0<<i, xi*y1*b<<(i+k)
y0 := y0.norm()
for i := k; i < len(x); i += k {
xi := x[i:]
if len(xi) > k {
xi = xi[:k]
}
xi = xi.norm()
t = t.mul(xi, y0)
addAt(z, t, i)
t = t.mul(xi, y1)
addAt(z, t, i+k)
}
}
return z.norm()
}
// mulRange computes the product of all the unsigned integers in the
// range [a, b] inclusively. If a > b (empty range), the result is 1.
func (z nat) mulRange(a, b uint64) nat {
switch {
case a == 0:
// cut long ranges short (optimization)
return z.setUint64(0)
case a > b:
return z.setUint64(1)
case a == b:
return z.setUint64(a)
case a+1 == b:
return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
}
m := (a + b) / 2
return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
}
// q = (x-r)/y, with 0 <= r < y
func (z nat) divW(x nat, y Word) (q nat, r Word) {
m := len(x)
switch {
case y == 0:
panic("division by zero")
case y == 1:
q = z.set(x) // result is x
return
case m == 0:
q = z[:0] // result is 0
return
}
// m > 0
z = z.make(m)
r = divWVW(z, 0, x, y)
q = z.norm()
return
}
func (z nat) div(z2, u, v nat) (q, r nat) {
if len(v) == 0 {
panic("division by zero")
}
if u.cmp(v) < 0 {
q = z[:0]
r = z2.set(u)
return
}
if len(v) == 1 {
var r2 Word
q, r2 = z.divW(u, v[0])
r = z2.setWord(r2)
return
}
q, r = z.divLarge(z2, u, v)
return
}
// getNat returns a nat of len n. The contents may not be zero.
func getNat(n int) nat {
var z nat
if v := natPool.Get(); v != nil {
z = v.(nat)
}
return z.make(n)
}
func putNat(x nat) {
natPool.Put(x)
}
var natPool sync.Pool
// q = (uIn-r)/v, with 0 <= r < y
// Uses z as storage for q, and u as storage for r if possible.
// See Knuth, Volume 2, section 4.3.1, Algorithm D.
// Preconditions:
// len(v) >= 2
// len(uIn) >= len(v)
func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
n := len(v)
m := len(uIn) - n
// determine if z can be reused
// TODO(gri) should find a better solution - this if statement
// is very costly (see e.g. time pidigits -s -n 10000)
if alias(z, uIn) || alias(z, v) {
z = nil // z is an alias for uIn or v - cannot reuse
}
q = z.make(m + 1)
qhatv := getNat(n + 1)
if alias(u, uIn) || alias(u, v) {
u = nil // u is an alias for uIn or v - cannot reuse
}
u = u.make(len(uIn) + 1)
u.clear() // TODO(gri) no need to clear if we allocated a new u
// D1.
var v1 nat
shift := nlz(v[n-1])
if shift > 0 {
// do not modify v, it may be used by another goroutine simultaneously
v1 = getNat(n)
shlVU(v1, v, shift)
v = v1
}
u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
// D2.
for j := m; j >= 0; j-- {
// D3.
qhat := Word(_M)
if u[j+n] != v[n-1] {
var rhat Word
qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
// x1 | x2 = q̂v_{n-2}
x1, x2 := mulWW(qhat, v[n-2])
// test if q̂v_{n-2} > br̂ + u_{j+n-2}
for greaterThan(x1, x2, rhat, u[j+n-2]) {
qhat--
prevRhat := rhat
rhat += v[n-1]
// v[n-1] >= 0, so this tests for overflow.
if rhat < prevRhat {
break
}
x1, x2 = mulWW(qhat, v[n-2])
}
}
// D4.
qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
c := subVV(u[j:j+len(qhatv)], u[j:], qhatv)
if c != 0 {
c := addVV(u[j:j+n], u[j:], v)
u[j+n] += c
qhat--
}
q[j] = qhat
}
if v1 != nil {
putNat(v1)
}
putNat(qhatv)
q = q.norm()
shrVU(u, u, shift)
r = u.norm()
return q, r
}
// Length of x in bits. x must be normalized.
func (x nat) bitLen() int {
if i := len(x) - 1; i >= 0 {
return i*_W + bitLen(x[i])
}
return 0
}
const deBruijn32 = 0x077CB531
var deBruijn32Lookup = []byte{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
}
const deBruijn64 = 0x03f79d71b4ca8b09
var deBruijn64Lookup = []byte{
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
}
// trailingZeroBits returns the number of consecutive least significant zero
// bits of x.
func trailingZeroBits(x Word) uint {
// x & -x leaves only the right-most bit set in the word. Let k be the
// index of that bit. Since only a single bit is set, the value is two
// to the power of k. Multiplying by a power of two is equivalent to
// left shifting, in this case by k bits. The de Bruijn constant is
// such that all six bit, consecutive substrings are distinct.
// Therefore, if we have a left shifted version of this constant we can
// find by how many bits it was shifted by looking at which six bit
// substring ended up at the top of the word.
// (Knuth, volume 4, section 7.3.1)
switch _W {
case 32:
return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
case 64:
return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
default:
panic("unknown word size")
}
}
// trailingZeroBits returns the number of consecutive least significant zero
// bits of x.
func (x nat) trailingZeroBits() uint {
if len(x) == 0 {
return 0
}
var i uint
for x[i] == 0 {
i++
}
// x[i] != 0
return i*_W + trailingZeroBits(x[i])
}
// z = x << s
func (z nat) shl(x nat, s uint) nat {
m := len(x)
if m == 0 {
return z[:0]
}
// m > 0
n := m + int(s/_W)
z = z.make(n + 1)
z[n] = shlVU(z[n-m:n], x, s%_W)
z[0 : n-m].clear()
return z.norm()
}
// z = x >> s
func (z nat) shr(x nat, s uint) nat {
m := len(x)
n := m - int(s/_W)
if n <= 0 {
return z[:0]
}
// n > 0
z = z.make(n)
shrVU(z, x[m-n:], s%_W)
return z.norm()
}
func (z nat) setBit(x nat, i uint, b uint) nat {
j := int(i / _W)
m := Word(1) << (i % _W)
n := len(x)
switch b {
case 0:
z = z.make(n)
copy(z, x)
if j >= n {
// no need to grow
return z
}
z[j] &^= m
return z.norm()
case 1:
if j >= n {
z = z.make(j + 1)
z[n:].clear()
} else {
z = z.make(n)
}
copy(z, x)
z[j] |= m
// no need to normalize
return z
}
panic("set bit is not 0 or 1")
}
// bit returns the value of the i'th bit, with lsb == bit 0.
func (x nat) bit(i uint) uint {
j := i / _W
if j >= uint(len(x)) {
return 0
}
// 0 <= j < len(x)
return uint(x[j] >> (i % _W) & 1)
}
// sticky returns 1 if there's a 1 bit within the
// i least significant bits, otherwise it returns 0.
func (x nat) sticky(i uint) uint {
j := i / _W
if j >= uint(len(x)) {
if len(x) == 0 {
return 0
}
return 1
}
// 0 <= j < len(x)
for _, x := range x[:j] {
if x != 0 {
return 1
}
}
if x[j]<<(_W-i%_W) != 0 {
return 1
}
return 0
}
func (z nat) and(x, y nat) nat {
m := len(x)
n := len(y)
if m > n {
m = n
}
// m <= n
z = z.make(m)
for i := 0; i < m; i++ {
z[i] = x[i] & y[i]
}
return z.norm()
}
func (z nat) andNot(x, y nat) nat {
m := len(x)
n := len(y)
if n > m {
n = m
}
// m >= n
z = z.make(m)
for i := 0; i < n; i++ {
z[i] = x[i] &^ y[i]
}
copy(z[n:m], x[n:m])
return z.norm()
}
func (z nat) or(x, y nat) nat {
m := len(x)
n := len(y)
s := x
if m < n {
n, m = m, n
s = y
}
// m >= n
z = z.make(m)
for i := 0; i < n; i++ {
z[i] = x[i] | y[i]
}
copy(z[n:m], s[n:m])
return z.norm()
}
func (z nat) xor(x, y nat) nat {
m := len(x)
n := len(y)
s := x
if m < n {
n, m = m, n
s = y
}
// m >= n
z = z.make(m)
for i := 0; i < n; i++ {
z[i] = x[i] ^ y[i]
}
copy(z[n:m], s[n:m])
return z.norm()
}
// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2)
func greaterThan(x1, x2, y1, y2 Word) bool {
return x1 > y1 || x1 == y1 && x2 > y2
}
// modW returns x % d.
func (x nat) modW(d Word) (r Word) {
// TODO(agl): we don't actually need to store the q value.
var q nat
q = q.make(len(x))
return divWVW(q, 0, x, d)
}
// random creates a random integer in [0..limit), using the space in z if
// possible. n is the bit length of limit.
func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
if alias(z, limit) {
z = nil // z is an alias for limit - cannot reuse
}
z = z.make(len(limit))
bitLengthOfMSW := uint(n % _W)
if bitLengthOfMSW == 0 {
bitLengthOfMSW = _W
}
mask := Word((1 << bitLengthOfMSW) - 1)
for {
switch _W {
case 32:
for i := range z {
z[i] = Word(rand.Uint32())
}
case 64:
for i := range z {
z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
}
default:
panic("unknown word size")
}
z[len(limit)-1] &= mask
if z.cmp(limit) < 0 {
break
}
}
return z.norm()
}
// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m;
// otherwise it sets z to x**y. The result is the value of z.
func (z nat) expNN(x, y, m nat) nat {
if alias(z, x) || alias(z, y) {
// We cannot allow in-place modification of x or y.
z = nil
}
// x**y mod 1 == 0
if len(m) == 1 && m[0] == 1 {
return z.setWord(0)
}
// m == 0 || m > 1
// x**0 == 1
if len(y) == 0 {
return z.setWord(1)
}
// y > 0
// x**1 mod m == x mod m
if len(y) == 1 && y[0] == 1 && len(m) != 0 {
_, z = z.div(z, x, m)
return z
}
// y > 1
if len(m) != 0 {
// We likely end up being as long as the modulus.
z = z.make(len(m))
}
z = z.set(x)
// If the base is non-trivial and the exponent is large, we use
// 4-bit, windowed exponentiation. This involves precomputing 14 values
// (x^2...x^15) but then reduces the number of multiply-reduces by a
// third. Even for a 32-bit exponent, this reduces the number of
// operations. Uses Montgomery method for odd moduli.
if len(x) > 1 && len(y) > 1 && len(m) > 0 {
if m[0]&1 == 1 {
return z.expNNMontgomery(x, y, m)
}
return z.expNNWindowed(x, y, m)
}
v := y[len(y)-1] // v > 0 because y is normalized and y > 0
shift := nlz(v) + 1
v <<= shift
var q nat
const mask = 1 << (_W - 1)
// We walk through the bits of the exponent one by one. Each time we
// see a bit, we square, thus doubling the power. If the bit is a one,
// we also multiply by x, thus adding one to the power.
w := _W - int(shift)
// zz and r are used to avoid allocating in mul and div as
// otherwise the arguments would alias.
var zz, r nat
for j := 0; j < w; j++ {
zz = zz.mul(z, z)
zz, z = z, zz
if v&mask != 0 {
zz = zz.mul(z, x)
zz, z = z, zz
}
if len(m) != 0 {
zz, r = zz.div(r, z, m)
zz, r, q, z = q, z, zz, r
}
v <<= 1
}
for i := len(y) - 2; i >= 0; i-- {
v = y[i]
for j := 0; j < _W; j++ {
zz = zz.mul(z, z)
zz, z = z, zz
if v&mask != 0 {
zz = zz.mul(z, x)
zz, z = z, zz
}
if len(m) != 0 {
zz, r = zz.div(r, z, m)
zz, r, q, z = q, z, zz, r
}
v <<= 1
}
}
return z.norm()
}
// expNNWindowed calculates x**y mod m using a fixed, 4-bit window.
func (z nat) expNNWindowed(x, y, m nat) nat {
// zz and r are used to avoid allocating in mul and div as otherwise
// the arguments would alias.
var zz, r nat
const n = 4
// powers[i] contains x^i.
var powers [1 << n]nat
powers[0] = natOne
powers[1] = x
for i := 2; i < 1<<n; i += 2 {
p2, p, p1 := &powers[i/2], &powers[i], &powers[i+1]
*p = p.mul(*p2, *p2)
zz, r = zz.div(r, *p, m)
*p, r = r, *p
*p1 = p1.mul(*p, x)
zz, r = zz.div(r, *p1, m)
*p1, r = r, *p1
}
z = z.setWord(1)
for i := len(y) - 1; i >= 0; i-- {
yi := y[i]
for j := 0; j < _W; j += n {
if i != len(y)-1 || j != 0 {
// Unrolled loop for significant performance
// gain. Use go test -bench=".*" in crypto/rsa
// to check performance before making changes.
zz = zz.mul(z, z)
zz, z = z, zz
zz, r = zz.div(r, z, m)
z, r = r, z
zz = zz.mul(z, z)
zz, z = z, zz
zz, r = zz.div(r, z, m)
z, r = r, z
zz = zz.mul(z, z)
zz, z = z, zz
zz, r = zz.div(r, z, m)
z, r = r, z
zz = zz.mul(z, z)
zz, z = z, zz
zz, r = zz.div(r, z, m)
z, r = r, z
}
zz = zz.mul(z, powers[yi>>(_W-n)])
zz, z = z, zz
zz, r = zz.div(r, z, m)
z, r = r, z
yi <<= n
}
}
return z.norm()
}
// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
// Uses Montgomery representation.
func (z nat) expNNMontgomery(x, y, m nat) nat {
numWords := len(m)
// We want the lengths of x and m to be equal.
// It is OK if x >= m as long as len(x) == len(m).
if len(x) > numWords {
_, x = nat(nil).div(nil, x, m)
// Note: now len(x) <= numWords, not guaranteed ==.
}
if len(x) < numWords {
rr := make(nat, numWords)
copy(rr, x)
x = rr
}
// Ideally the precomputations would be performed outside, and reused
// k0 = -m**-1 mod 2**_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
// Iteration for Multiplicative Inverses Modulo Prime Powers".
k0 := 2 - m[0]
t := m[0] - 1
for i := 1; i < _W; i <<= 1 {
t *= t
k0 *= (t + 1)
}
k0 = -k0
// RR = 2**(2*_W*len(m)) mod m
RR := nat(nil).setWord(1)
zz := nat(nil).shl(RR, uint(2*numWords*_W))
_, RR = RR.div(RR, zz, m)
if len(RR) < numWords {
zz = zz.make(numWords)
copy(zz, RR)
RR = zz
}
// one = 1, with equal length to that of m
one := make(nat, numWords)
one[0] = 1
const n = 4
// powers[i] contains x^i
var powers [1 << n]nat
powers[0] = powers[0].montgomery(one, RR, m, k0, numWords)
powers[1] = powers[1].montgomery(x, RR, m, k0, numWords)
for i := 2; i < 1<<n; i++ {
powers[i] = powers[i].montgomery(powers[i-1], powers[1], m, k0, numWords)
}
// initialize z = 1 (Montgomery 1)
z = z.make(numWords)
copy(z, powers[0])
zz = zz.make(numWords)
// same windowed exponent, but with Montgomery multiplications
for i := len(y) - 1; i >= 0; i-- {
yi := y[i]
for j := 0; j < _W; j += n {
if i != len(y)-1 || j != 0 {
zz = zz.montgomery(z, z, m, k0, numWords)
z = z.montgomery(zz, zz, m, k0, numWords)
zz = zz.montgomery(z, z, m, k0, numWords)
z = z.montgomery(zz, zz, m, k0, numWords)
}
zz = zz.montgomery(z, powers[yi>>(_W-n)], m, k0, numWords)
z, zz = zz, z
yi <<= n
}
}
// convert to regular number
zz = zz.montgomery(z, one, m, k0, numWords)
// One last reduction, just in case.
// See golang.org/issue/13907.
if zz.cmp(m) >= 0 {
// Common case is m has high bit set; in that case,
// since zz is the same length as m, there can be just
// one multiple of m to remove. Just subtract.
// We think that the subtract should be sufficient in general,
// so do that unconditionally, but double-check,
// in case our beliefs are wrong.
// The div is not expected to be reached.
zz = zz.sub(zz, m)
if zz.cmp(m) >= 0 {
_, zz = nat(nil).div(nil, zz, m)
}
}
return zz.norm()
}
// probablyPrime performs n Miller-Rabin tests to check whether x is prime.
// If x is prime, it returns true.
// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
//
// It is not suitable for judging primes that an adversary may have crafted
// to fool this test.
func (n nat) probablyPrime(reps int) bool {
if len(n) == 0 {
return false
}
if len(n) == 1 {
if n[0] < 2 {
return false
}
if n[0]%2 == 0 {
return n[0] == 2
}
// We have to exclude these cases because we reject all
// multiples of these numbers below.
switch n[0] {
case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53:
return true
}
}
if n[0]&1 == 0 {
return false // n is even
}
const primesProduct32 = 0xC0CFD797 // Π {p ∈ primes, 2 < p <= 29}
const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
var r Word
switch _W {
case 32:
r = n.modW(primesProduct32)
case 64:
r = n.modW(primesProduct64 & _M)
default:
panic("Unknown word size")
}
if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 ||
r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 {
return false
}
if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 ||
r%43 == 0 || r%47 == 0 || r%53 == 0) {
return false
}
nm1 := nat(nil).sub(n, natOne)
// determine q, k such that nm1 = q << k
k := nm1.trailingZeroBits()
q := nat(nil).shr(nm1, k)
nm3 := nat(nil).sub(nm1, natTwo)
rand := rand.New(rand.NewSource(int64(n[0])))
var x, y, quotient nat
nm3Len := nm3.bitLen()
NextRandom:
for i := 0; i < reps; i++ {
x = x.random(rand, nm3, nm3Len)
x = x.add(x, natTwo)
y = y.expNN(x, q, n)
if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
continue
}
for j := uint(1); j < k; j++ {
y = y.mul(y, y)
quotient, y = quotient.div(y, y, n)
if y.cmp(nm1) == 0 {
continue NextRandom
}
if y.cmp(natOne) == 0 {
return false
}
}
return false
}
return true
}
// bytes writes the value of z into buf using big-endian encoding.
// len(buf) must be >= len(z)*_S. The value of z is encoded in the
// slice buf[i:]. The number i of unused bytes at the beginning of
// buf is returned as result.
func (z nat) bytes(buf []byte) (i int) {
i = len(buf)
for _, d := range z {
for j := 0; j < _S; j++ {
i--
buf[i] = byte(d)
d >>= 8
}
}
for i < len(buf) && buf[i] == 0 {
i++
}
return
}
// setBytes interprets buf as the bytes of a big-endian unsigned
// integer, sets z to that value, and returns z.
func (z nat) setBytes(buf []byte) nat {
z = z.make((len(buf) + _S - 1) / _S)
k := 0
s := uint(0)
var d Word
for i := len(buf); i > 0; i-- {
d |= Word(buf[i-1]) << s
if s += 8; s == _S*8 {
z[k] = d
k++
s = 0
d = 0
}
}
if k < len(z) {
z[k] = d
}
return z.norm()
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"fmt"
"runtime"
"strings"
"testing"
)
var cmpTests = []struct {
x, y nat
r int
}{
{nil, nil, 0},
{nil, nat(nil), 0},
{nat(nil), nil, 0},
{nat(nil), nat(nil), 0},
{nat{0}, nat{0}, 0},
{nat{0}, nat{1}, -1},
{nat{1}, nat{0}, 1},
{nat{1}, nat{1}, 0},
{nat{0, _M}, nat{1}, 1},
{nat{1}, nat{0, _M}, -1},
{nat{1, _M}, nat{0, _M}, 1},
{nat{0, _M}, nat{1, _M}, -1},
{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
}
func TestCmp(t *testing.T) {
for i, a := range cmpTests {
r := a.x.cmp(a.y)
if r != a.r {
t.Errorf("#%d got r = %v; want %v", i, r, a.r)
}
}
}
type funNN func(z, x, y nat) nat
type argNN struct {
z, x, y nat
}
var sumNN = []argNN{
{},
{nat{1}, nil, nat{1}},
{nat{1111111110}, nat{123456789}, nat{987654321}},
{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
}
var prodNN = []argNN{
{},
{nil, nil, nil},
{nil, nat{991}, nil},
{nat{991}, nat{991}, nat{1}},
{nat{991 * 991}, nat{991}, nat{991}},
{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
// 3^100 * 3^28 = 3^128
{
natFromString("11790184577738583171520872861412518665678211592275841109096961"),
natFromString("515377520732011331036461129765621272702107522001"),
natFromString("22876792454961"),
},
// z = 111....1 (70000 digits)
// x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
// y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
{
natFromString(strings.Repeat("1", 70000)),
natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
natFromString(strings.Repeat("1", 700)),
},
// z = 111....1 (20000 digits)
// x = 10^10000 + 1
// y = 111....1 (10000 digits)
{
natFromString(strings.Repeat("1", 20000)),
natFromString("1" + strings.Repeat("0", 9999) + "1"),
natFromString(strings.Repeat("1", 10000)),
},
}
func natFromString(s string) nat {
x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false)
if err != nil {
panic(err)
}
return x
}
func TestSet(t *testing.T) {
for _, a := range sumNN {
z := nat(nil).set(a.z)
if z.cmp(a.z) != 0 {
t.Errorf("got z = %v; want %v", z, a.z)
}
}
}
func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
z := f(nil, a.x, a.y)
if z.cmp(a.z) != 0 {
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
}
}
func TestFunNN(t *testing.T) {
for _, a := range sumNN {
arg := a
testFunNN(t, "add", nat.add, arg)
arg = argNN{a.z, a.y, a.x}
testFunNN(t, "add symmetric", nat.add, arg)
arg = argNN{a.x, a.z, a.y}
testFunNN(t, "sub", nat.sub, arg)
arg = argNN{a.y, a.z, a.x}
testFunNN(t, "sub symmetric", nat.sub, arg)
}
for _, a := range prodNN {
arg := a
testFunNN(t, "mul", nat.mul, arg)
arg = argNN{a.z, a.y, a.x}
testFunNN(t, "mul symmetric", nat.mul, arg)
}
}
var mulRangesN = []struct {
a, b uint64
prod string
}{
{0, 0, "0"},
{1, 1, "1"},
{1, 2, "2"},
{1, 3, "6"},
{10, 10, "10"},
{0, 100, "0"},
{0, 1e9, "0"},
{1, 0, "1"}, // empty range
{100, 1, "1"}, // empty range
{1, 10, "3628800"}, // 10!
{1, 20, "2432902008176640000"}, // 20!
{1, 100,
"933262154439441526816992388562667004907159682643816214685929" +
"638952175999932299156089414639761565182862536979208272237582" +
"51185210916864000000000000000000000000", // 100!
},
}
func TestMulRangeN(t *testing.T) {
for i, r := range mulRangesN {
prod := string(nat(nil).mulRange(r.a, r.b).utoa(10))
if prod != r.prod {
t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
}
}
}
// allocBytes returns the number of bytes allocated by invoking f.
func allocBytes(f func()) uint64 {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
t := stats.TotalAlloc
f()
runtime.ReadMemStats(&stats)
return stats.TotalAlloc - t
}
// TestMulUnbalanced tests that multiplying numbers of different lengths
// does not cause deep recursion and in turn allocate too much memory.
// Test case for issue 3807.
func TestMulUnbalanced(t *testing.T) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
x := rndNat(50000)
y := rndNat(40)
allocSize := allocBytes(func() {
nat(nil).mul(x, y)
})
inputSize := uint64(len(x)+len(y)) * _S
if ratio := allocSize / uint64(inputSize); ratio > 10 {
t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
}
}
func rndNat(n int) nat {
return nat(rndV(n)).norm()
}
func BenchmarkMul(b *testing.B) {
mulx := rndNat(1e4)
muly := rndNat(1e4)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var z nat
z.mul(mulx, muly)
}
}
func TestNLZ(t *testing.T) {
var x Word = _B >> 1
for i := 0; i <= _W; i++ {
if int(nlz(x)) != i {
t.Errorf("failed at %x: got %d want %d", x, nlz(x), i)
}
x >>= 1
}
}
type shiftTest struct {
in nat
shift uint
out nat
}
var leftShiftTests = []shiftTest{
{nil, 0, nil},
{nil, 1, nil},
{natOne, 0, natOne},
{natOne, 1, natTwo},
{nat{1 << (_W - 1)}, 1, nat{0}},
{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
}
func TestShiftLeft(t *testing.T) {
for i, test := range leftShiftTests {
var z nat
z = z.shl(test.in, test.shift)
for j, d := range test.out {
if j >= len(z) || z[j] != d {
t.Errorf("#%d: got: %v want: %v", i, z, test.out)
break
}
}
}
}
var rightShiftTests = []shiftTest{
{nil, 0, nil},
{nil, 1, nil},
{natOne, 0, natOne},
{natOne, 1, nil},
{natTwo, 1, natOne},
{nat{0, 1}, 1, nat{1 << (_W - 1)}},
{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
}
func TestShiftRight(t *testing.T) {
for i, test := range rightShiftTests {
var z nat
z = z.shr(test.in, test.shift)
for j, d := range test.out {
if j >= len(z) || z[j] != d {
t.Errorf("#%d: got: %v want: %v", i, z, test.out)
break
}
}
}
}
type modWTest struct {
in string
dividend string
out string
}
var modWTests32 = []modWTest{
{"23492635982634928349238759823742", "252341", "220170"},
}
var modWTests64 = []modWTest{
{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
}
func runModWTests(t *testing.T, tests []modWTest) {
for i, test := range tests {
in, _ := new(Int).SetString(test.in, 10)
d, _ := new(Int).SetString(test.dividend, 10)
out, _ := new(Int).SetString(test.out, 10)
r := in.abs.modW(d.abs[0])
if r != out.abs[0] {
t.Errorf("#%d failed: got %d want %s", i, r, out)
}
}
}
func TestModW(t *testing.T) {
if _W >= 32 {
runModWTests(t, modWTests32)
}
if _W >= 64 {
runModWTests(t, modWTests64)
}
}
func TestTrailingZeroBits(t *testing.T) {
// test 0 case explicitly
if n := trailingZeroBits(0); n != 0 {
t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
}
x := Word(1)
for i := uint(0); i < _W; i++ {
n := trailingZeroBits(x)
if n != i {
t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
}
x <<= 1
}
// test 0 case explicitly
if n := nat(nil).trailingZeroBits(); n != 0 {
t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
}
y := nat(nil).set(natOne)
for i := uint(0); i <= 3*_W; i++ {
n := y.trailingZeroBits()
if n != i {
t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
}
y = y.shl(y, 1)
}
}
var montgomeryTests = []struct {
x, y, m string
k0 uint64
out32, out64 string
}{
{
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
"0xfffffffffffffffffffffffffffffffffffffffffffffffff",
1,
"0x1000000000000000000000000000000000000000000",
"0x10000000000000000000000000000000000",
},
{
"0x000000000ffffff5",
"0x000000000ffffff0",
"0x0000000010000001",
0xff0000000fffffff,
"0x000000000bfffff4",
"0x0000000003400001",
},
{
"0x0000000080000000",
"0x00000000ffffffff",
"0x1000000000000001",
0xfffffffffffffff,
"0x0800000008000001",
"0x0800000008000001",
},
{
"0x0000000080000000",
"0x0000000080000000",
"0xffffffff00000001",
0xfffffffeffffffff,
"0xbfffffff40000001",
"0xbfffffff40000001",
},
{
"0x0000000080000000",
"0x0000000080000000",
"0x00ffffff00000001",
0xfffffeffffffff,
"0xbfffff40000001",
"0xbfffff40000001",
},
{
"0x0000000080000000",
"0x0000000080000000",
"0x0000ffff00000001",
0xfffeffffffff,
"0xbfff40000001",
"0xbfff40000001",
},
{
"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
"0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
0xdecc8f1249812adf,
"0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5",
"0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0",
},
{
"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
0xdecc8f1249812adf,
"0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715",
"0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6",
},
}
func TestMontgomery(t *testing.T) {
one := NewInt(1)
_B := new(Int).Lsh(one, _W)
for i, test := range montgomeryTests {
x := natFromString(test.x)
y := natFromString(test.y)
m := natFromString(test.m)
for len(x) < len(m) {
x = append(x, 0)
}
for len(y) < len(m) {
y = append(y, 0)
}
if x.cmp(m) > 0 {
_, r := nat(nil).div(nil, x, m)
t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16))
}
if y.cmp(m) > 0 {
_, r := nat(nil).div(nil, x, m)
t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16))
}
var out nat
if _W == 32 {
out = natFromString(test.out32)
} else {
out = natFromString(test.out64)
}
// t.Logf("#%d: len=%d\n", i, len(m))
// check output in table
xi := &Int{abs: x}
yi := &Int{abs: y}
mi := &Int{abs: m}
p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi)
if out.cmp(p.abs.norm()) != 0 {
t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16))
}
// check k0 in table
k := new(Int).Mod(&Int{abs: m}, _B)
k = new(Int).Sub(_B, k)
k = new(Int).Mod(k, _B)
k0 := Word(new(Int).ModInverse(k, _B).Uint64())
if k0 != Word(test.k0) {
t.Errorf("#%d: k0 in table=%#x, computed=%#x\n", i, test.k0, k0)
}
// check montgomery with correct k0 produces correct output
z := nat(nil).montgomery(x, y, m, k0, len(m))
z = z.norm()
if z.cmp(out) != 0 {
t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
}
}
}
var expNNTests = []struct {
x, y, m string
out string
}{
{"0", "0", "0", "1"},
{"0", "0", "1", "0"},
{"1", "1", "1", "0"},
{"2", "1", "1", "0"},
{"2", "2", "1", "0"},
{"10", "100000000000", "1", "0"},
{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
{"0x8000000000000000", "2", "6719", "4944"},
{"0x8000000000000000", "3", "6719", "5447"},
{"0x8000000000000000", "1000", "6719", "1603"},
{"0x8000000000000000", "1000000", "6719", "3199"},
{
"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
"298472983472983471903246121093472394872319615612417471234712061",
"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
},
{
"11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
"426343618817810911523",
"444747819283133684179",
"42",
},
}
func TestExpNN(t *testing.T) {
for i, test := range expNNTests {
x := natFromString(test.x)
y := natFromString(test.y)
out := natFromString(test.out)
var m nat
if len(test.m) > 0 {
m = natFromString(test.m)
}
z := nat(nil).expNN(x, y, m)
if z.cmp(out) != 0 {
t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
}
}
}
func BenchmarkExp3Power(b *testing.B) {
const x = 3
for _, y := range []Word{
0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000,
} {
b.Run(fmt.Sprintf("%#x", y), func(b *testing.B) {
var z nat
for i := 0; i < b.N; i++ {
z.expWW(x, y)
}
})
}
}
func fibo(n int) nat {
switch n {
case 0:
return nil
case 1:
return nat{1}
}
f0 := fibo(0)
f1 := fibo(1)
var f2 nat
for i := 1; i < n; i++ {
f2 = f2.add(f0, f1)
f0, f1, f2 = f1, f2, f0
}
return f1
}
var fiboNums = []string{
"0",
"55",
"6765",
"832040",
"102334155",
"12586269025",
"1548008755920",
"190392490709135",
"23416728348467685",
"2880067194370816120",
"354224848179261915075",
}
func TestFibo(t *testing.T) {
for i, want := range fiboNums {
n := i * 10
got := string(fibo(n).utoa(10))
if got != want {
t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
}
}
}
func BenchmarkFibo(b *testing.B) {
for i := 0; i < b.N; i++ {
fibo(1e0)
fibo(1e1)
fibo(1e2)
fibo(1e3)
fibo(1e4)
fibo(1e5)
}
}
var bitTests = []struct {
x string
i uint
want uint
}{
{"0", 0, 0},
{"0", 1, 0},
{"0", 1000, 0},
{"0x1", 0, 1},
{"0x10", 0, 0},
{"0x10", 3, 0},
{"0x10", 4, 1},
{"0x10", 5, 0},
{"0x8000000000000000", 62, 0},
{"0x8000000000000000", 63, 1},
{"0x8000000000000000", 64, 0},
{"0x3" + strings.Repeat("0", 32), 127, 0},
{"0x3" + strings.Repeat("0", 32), 128, 1},
{"0x3" + strings.Repeat("0", 32), 129, 1},
{"0x3" + strings.Repeat("0", 32), 130, 0},
}
func TestBit(t *testing.T) {
for i, test := range bitTests {
x := natFromString(test.x)
if got := x.bit(test.i); got != test.want {
t.Errorf("#%d: %s.bit(%d) = %v; want %v", i, test.x, test.i, got, test.want)
}
}
}
var stickyTests = []struct {
x string
i uint
want uint
}{
{"0", 0, 0},
{"0", 1, 0},
{"0", 1000, 0},
{"0x1", 0, 0},
{"0x1", 1, 1},
{"0x1350", 0, 0},
{"0x1350", 4, 0},
{"0x1350", 5, 1},
{"0x8000000000000000", 63, 0},
{"0x8000000000000000", 64, 1},
{"0x1" + strings.Repeat("0", 100), 400, 0},
{"0x1" + strings.Repeat("0", 100), 401, 1},
}
func TestSticky(t *testing.T) {
for i, test := range stickyTests {
x := natFromString(test.x)
if got := x.sticky(test.i); got != test.want {
t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i, got, test.want)
}
if test.want == 1 {
// all subsequent i's should also return 1
for d := uint(1); d <= 3; d++ {
if got := x.sticky(test.i + d); got != 1 {
t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i+d, got, 1)
}
}
}
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements nat-to-string conversion functions.
package big
import (
"errors"
"fmt"
"io"
"math"
"sync"
)
const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
// Note: MaxBase = len(digits), but it must remain a rune constant
// for API compatibility.
// MaxBase is the largest number base accepted for string conversions.
const MaxBase = 'z' - 'a' + 10 + 1
// maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
// For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
// In other words, at most n digits in base b fit into a Word.
// TODO(gri) replace this with a table, generated at build time.
func maxPow(b Word) (p Word, n int) {
p, n = b, 1 // assuming b <= _M
for max := _M / b; p <= max; {
// p == b**n && p <= max
p *= b
n++
}
// p == b**n && p <= _M
return
}
// pow returns x**n for n > 0, and 1 otherwise.
func pow(x Word, n int) (p Word) {
// n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
// thus x**n == product of x**(2**i) for all i where bi == 1
// (Russian Peasant Method for exponentiation)
p = 1
for n > 0 {
if n&1 != 0 {
p *= x
}
x *= x
n >>= 1
}
return
}
// scan scans the number corresponding to the longest possible prefix
// from r representing an unsigned number in a given conversion base.
// It returns the corresponding natural number res, the actual base b,
// a digit count, and a read or syntax error err, if any.
//
// number = [ prefix ] mantissa .
// prefix = "0" [ "x" | "X" | "b" | "B" ] .
// mantissa = digits | digits "." [ digits ] | "." digits .
// digits = digit { digit } .
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
//
// Unless fracOk is set, the base argument must be 0 or a value between
// 2 and MaxBase. If fracOk is set, the base argument must be one of
// 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
// time panic.
//
// For base 0, the number prefix determines the actual base: A prefix of
// ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
// selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
// the selected base is 10 and no prefix is accepted.
//
// If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
// stands for a zero digit), and a period followed by a fractional part
// is permitted. The result value is computed as if there were no period
// present; and the count value is used to determine the fractional part.
//
// A result digit count > 0 corresponds to the number of (non-prefix) digits
// parsed. A digit count <= 0 indicates the presence of a period (if fracOk
// is set, only), and -count is the number of fractional digits found.
// In this case, the actual value of the scanned number is res * b**count.
//
func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count int, err error) {
// reject illegal bases
baseOk := base == 0 ||
!fracOk && 2 <= base && base <= MaxBase ||
fracOk && (base == 2 || base == 10 || base == 16)
if !baseOk {
panic(fmt.Sprintf("illegal number base %d", base))
}
// one char look-ahead
ch, err := r.ReadByte()
if err != nil {
return
}
// determine actual base
b = base
if base == 0 {
// actual base is 10 unless there's a base prefix
b = 10
if ch == '0' {
count = 1
switch ch, err = r.ReadByte(); err {
case nil:
// possibly one of 0x, 0X, 0b, 0B
if !fracOk {
b = 8
}
switch ch {
case 'x', 'X':
b = 16
case 'b', 'B':
b = 2
}
switch b {
case 16, 2:
count = 0 // prefix is not counted
if ch, err = r.ReadByte(); err != nil {
// io.EOF is also an error in this case
return
}
case 8:
count = 0 // prefix is not counted
}
case io.EOF:
// input is "0"
res = z[:0]
err = nil
return
default:
// read error
return
}
}
}
// convert string
// Algorithm: Collect digits in groups of at most n digits in di
// and then use mulAddWW for every such group to add them to the
// result.
z = z[:0]
b1 := Word(b)
bn, n := maxPow(b1) // at most n digits in base b1 fit into Word
di := Word(0) // 0 <= di < b1**i < bn
i := 0 // 0 <= i < n
dp := -1 // position of decimal point
for {
if fracOk && ch == '.' {
fracOk = false
dp = count
// advance
if ch, err = r.ReadByte(); err != nil {
if err == io.EOF {
err = nil
break
}
return
}
}
// convert rune into digit value d1
var d1 Word
switch {
case '0' <= ch && ch <= '9':
d1 = Word(ch - '0')
case 'a' <= ch && ch <= 'z':
d1 = Word(ch - 'a' + 10)
case 'A' <= ch && ch <= 'Z':
d1 = Word(ch - 'A' + 10)
default:
d1 = MaxBase + 1
}
if d1 >= b1 {
r.UnreadByte() // ch does not belong to number anymore
break
}
count++
// collect d1 in di
di = di*b1 + d1
i++
// if di is "full", add it to the result
if i == n {
z = z.mulAddWW(z, bn, di)
di = 0
i = 0
}
// advance
if ch, err = r.ReadByte(); err != nil {
if err == io.EOF {
err = nil
break
}
return
}
}
if count == 0 {
// no digits found
switch {
case base == 0 && b == 8:
// there was only the octal prefix 0 (possibly followed by digits > 7);
// count as one digit and return base 10, not 8
count = 1
b = 10
case base != 0 || b != 8:
// there was neither a mantissa digit nor the octal prefix 0
err = errors.New("syntax error scanning number")
}
return
}
// count > 0
// add remaining digits to result
if i > 0 {
z = z.mulAddWW(z, pow(b1, i), di)
}
res = z.norm()
// adjust for fraction, if any
if dp >= 0 {
// 0 <= dp <= count > 0
count = dp - count
}
return
}
// utoa converts x to an ASCII representation in the given base;
// base must be between 2 and MaxBase, inclusive.
func (x nat) utoa(base int) []byte {
return x.itoa(false, base)
}
// itoa is like utoa but it prepends a '-' if neg && x != 0.
func (x nat) itoa(neg bool, base int) []byte {
if base < 2 || base > MaxBase {
panic("invalid base")
}
// x == 0
if len(x) == 0 {
return []byte("0")
}
// len(x) > 0
// allocate buffer for conversion
i := int(float64(x.bitLen())/math.Log2(float64(base))) + 1 // off by 1 at most
if neg {
i++
}
s := make([]byte, i)
// convert power of two and non power of two bases separately
if b := Word(base); b == b&-b {
// shift is base b digit size in bits
shift := trailingZeroBits(b) // shift > 0 because b >= 2
mask := Word(1<<shift - 1)
w := x[0] // current word
nbits := uint(_W) // number of unprocessed bits in w
// convert less-significant words (include leading zeros)
for k := 1; k < len(x); k++ {
// convert full digits
for nbits >= shift {
i--
s[i] = digits[w&mask]
w >>= shift
nbits -= shift
}
// convert any partial leading digit and advance to next word
if nbits == 0 {
// no partial digit remaining, just advance
w = x[k]
nbits = _W
} else {
// partial digit in current word w (== x[k-1]) and next word x[k]
w |= x[k] << nbits
i--
s[i] = digits[w&mask]
// advance
w = x[k] >> (shift - nbits)
nbits = _W - (shift - nbits)
}
}
// convert digits of most-significant word w (omit leading zeros)
for w != 0 {
i--
s[i] = digits[w&mask]
w >>= shift
}
} else {
bb, ndigits := maxPow(b)
// construct table of successive squares of bb*leafSize to use in subdivisions
// result (table != nil) <=> (len(x) > leafSize > 0)
table := divisors(len(x), b, ndigits, bb)
// preserve x, create local copy for use by convertWords
q := nat(nil).set(x)
// convert q to string s in base b
q.convertWords(s, b, ndigits, bb, table)
// strip leading zeros
// (x != 0; thus s must contain at least one non-zero digit
// and the loop will terminate)
i = 0
for s[i] == '0' {
i++
}
}
if neg {
i--
s[i] = '-'
}
return s[i:]
}
// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
// repeated nat/Word division.
//
// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
// Recursive conversion divides q by its approximate square root, yielding two parts, each half
// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
// is made better by splitting the subblocks recursively. Best is to split blocks until one more
// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
// specific hardware.
//
func (q nat) convertWords(s []byte, b Word, ndigits int, bb Word, table []divisor) {
// split larger blocks recursively
if table != nil {
// len(q) > leafSize > 0
var r nat
index := len(table) - 1
for len(q) > leafSize {
// find divisor close to sqrt(q) if possible, but in any case < q
maxLength := q.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
minLength := maxLength >> 1 // ~= log2 sqrt(q)
for index > 0 && table[index-1].nbits > minLength {
index-- // desired
}
if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
index--
if index < 0 {
panic("internal inconsistency")
}
}
// split q into the two digit number (q'*bbb + r) to form independent subblocks
q, r = q.div(r, q, table[index].bbb)
// convert subblocks and collect results in s[:h] and s[h:]
h := len(s) - table[index].ndigits
r.convertWords(s[h:], b, ndigits, bb, table[0:index])
s = s[:h] // == q.convertWords(s, b, ndigits, bb, table[0:index+1])
}
}
// having split any large blocks now process the remaining (small) block iteratively
i := len(s)
var r Word
if b == 10 {
// hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
for len(q) > 0 {
// extract least significant, base bb "digit"
q, r = q.divW(q, bb)
for j := 0; j < ndigits && i > 0; j++ {
i--
// avoid % computation since r%10 == r - int(r/10)*10;
// this appears to be faster for BenchmarkString10000Base10
// and smaller strings (but a bit slower for larger ones)
t := r / 10
s[i] = '0' + byte(r-t*10)
r = t
}
}
} else {
for len(q) > 0 {
// extract least significant, base bb "digit"
q, r = q.divW(q, bb)
for j := 0; j < ndigits && i > 0; j++ {
i--
s[i] = digits[r%b]
r /= b
}
}
}
// prepend high-order zeros
for i > 0 { // while need more leading zeros
i--
s[i] = '0'
}
}
// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
// Benchmark and configure leafSize using: go test -bench="Leaf"
// 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
// 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
type divisor struct {
bbb nat // divisor
nbits int // bit length of divisor (discounting leading zeros) ~= log2(bbb)
ndigits int // digit length of divisor in terms of output base digits
}
var cacheBase10 struct {
sync.Mutex
table [64]divisor // cached divisors for base 10
}
// expWW computes x**y
func (z nat) expWW(x, y Word) nat {
return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
}
// construct table of powers of bb*leafSize to use in subdivisions
func divisors(m int, b Word, ndigits int, bb Word) []divisor {
// only compute table when recursive conversion is enabled and x is large
if leafSize == 0 || m <= leafSize {
return nil
}
// determine k where (bb**leafSize)**(2**k) >= sqrt(x)
k := 1
for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
k++
}
// reuse and extend existing table of divisors or create new table as appropriate
var table []divisor // for b == 10, table overlaps with cacheBase10.table
if b == 10 {
cacheBase10.Lock()
table = cacheBase10.table[0:k] // reuse old table for this conversion
} else {
table = make([]divisor, k) // create new table for this conversion
}
// extend table
if table[k-1].ndigits == 0 {
// add new entries as needed
var larger nat
for i := 0; i < k; i++ {
if table[i].ndigits == 0 {
if i == 0 {
table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
table[0].ndigits = ndigits * leafSize
} else {
table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
table[i].ndigits = 2 * table[i-1].ndigits
}
// optimization: exploit aggregated extra bits in macro blocks
larger = nat(nil).set(table[i].bbb)
for mulAddVWW(larger, larger, b, 0) == 0 {
table[i].bbb = table[i].bbb.set(larger)
table[i].ndigits++
}
table[i].nbits = table[i].bbb.bitLen()
}
}
}
if b == 10 {
cacheBase10.Unlock()
}
return table
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"bytes"
"fmt"
"io"
"strings"
"testing"
)
func itoa(x nat, base int) []byte {
// special cases
switch {
case base < 2:
panic("illegal base")
case len(x) == 0:
return []byte("0")
}
// allocate buffer for conversion
i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
s := make([]byte, i)
// don't destroy x
q := nat(nil).set(x)
// convert
for len(q) > 0 {
i--
var r Word
q, r = q.divW(q, Word(base))
s[i] = digits[r]
}
return s[i:]
}
var strTests = []struct {
x nat // nat value to be converted
b int // conversion base
s string // expected result
}{
{nil, 2, "0"},
{nat{1}, 2, "1"},
{nat{0xc5}, 2, "11000101"},
{nat{03271}, 8, "3271"},
{nat{10}, 10, "10"},
{nat{1234567890}, 10, "1234567890"},
{nat{0xdeadbeef}, 16, "deadbeef"},
{nat{0x229be7}, 17, "1a2b3c"},
{nat{0x309663e6}, 32, "o9cov6"},
}
func TestString(t *testing.T) {
// test invalid base explicitly
var panicStr string
func() {
defer func() {
panicStr = recover().(string)
}()
natOne.utoa(1)
}()
if panicStr != "invalid base" {
t.Errorf("expected panic for invalid base")
}
for _, a := range strTests {
s := string(a.x.utoa(a.b))
if s != a.s {
t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
}
x, b, _, err := nat(nil).scan(strings.NewReader(a.s), a.b, false)
if x.cmp(a.x) != 0 {
t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
}
if b != a.b {
t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.b)
}
if err != nil {
t.Errorf("scan%+v\n\tgot error = %s", a, err)
}
}
}
var natScanTests = []struct {
s string // string to be scanned
base int // input base
frac bool // fraction ok
x nat // expected nat
b int // expected base
count int // expected digit count
ok bool // expected success
next rune // next character (or 0, if at EOF)
}{
// error: no mantissa
{},
{s: "?"},
{base: 10},
{base: 36},
{s: "?", base: 10},
{s: "0x"},
{s: "345", base: 2},
// error: incorrect use of decimal point
{s: ".0"},
{s: ".0", base: 10},
{s: ".", base: 0},
{s: "0x.0"},
// no errors
{"0", 0, false, nil, 10, 1, true, 0},
{"0", 10, false, nil, 10, 1, true, 0},
{"0", 36, false, nil, 36, 1, true, 0},
{"1", 0, false, nat{1}, 10, 1, true, 0},
{"1", 10, false, nat{1}, 10, 1, true, 0},
{"0 ", 0, false, nil, 10, 1, true, ' '},
{"08", 0, false, nil, 10, 1, true, '8'},
{"08", 10, false, nat{8}, 10, 2, true, 0},
{"018", 0, false, nat{1}, 8, 1, true, '8'},
{"0b1", 0, false, nat{1}, 2, 1, true, 0},
{"0b11000101", 0, false, nat{0xc5}, 2, 8, true, 0},
{"03271", 0, false, nat{03271}, 8, 4, true, 0},
{"10ab", 0, false, nat{10}, 10, 2, true, 'a'},
{"1234567890", 0, false, nat{1234567890}, 10, 10, true, 0},
{"xyz", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, 0},
{"xyz?", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, '?'},
{"0x", 16, false, nil, 16, 1, true, 'x'},
{"0xdeadbeef", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
{"0XDEADBEEF", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
// no errors, decimal point
{"0.", 0, false, nil, 10, 1, true, '.'},
{"0.", 10, true, nil, 10, 0, true, 0},
{"0.1.2", 10, true, nat{1}, 10, -1, true, '.'},
{".000", 10, true, nil, 10, -3, true, 0},
{"12.3", 10, true, nat{123}, 10, -1, true, 0},
{"012.345", 10, true, nat{12345}, 10, -3, true, 0},
}
func TestScanBase(t *testing.T) {
for _, a := range natScanTests {
r := strings.NewReader(a.s)
x, b, count, err := nat(nil).scan(r, a.base, a.frac)
if err == nil && !a.ok {
t.Errorf("scan%+v\n\texpected error", a)
}
if err != nil {
if a.ok {
t.Errorf("scan%+v\n\tgot error = %s", a, err)
}
continue
}
if x.cmp(a.x) != 0 {
t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
}
if b != a.b {
t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
}
if count != a.count {
t.Errorf("scan%+v\n\tgot count = %d; want %d", a, count, a.count)
}
next, _, err := r.ReadRune()
if err == io.EOF {
next = 0
err = nil
}
if err == nil && next != a.next {
t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
}
}
}
var pi = "3" +
"14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
"32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
"28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
"96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
"31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
"60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
"22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
"29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
"81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
"21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
"55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
"63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
"75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
"45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
"34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
"16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
"04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
"26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
"99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
"53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
"68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
"13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
"88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
"79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
"68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
"21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
"06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
"14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
"21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
"05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
"23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
"90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
"31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
"20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
"97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
"44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
"44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
"85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
"58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
"27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
"09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
"79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
"06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
"91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
"94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
"78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
"24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
"59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
"34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
"88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
"94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
// Test case for BenchmarkScanPi.
func TestScanPi(t *testing.T) {
var x nat
z, _, _, err := x.scan(strings.NewReader(pi), 10, false)
if err != nil {
t.Errorf("scanning pi: %s", err)
}
if s := string(z.utoa(10)); s != pi {
t.Errorf("scanning pi: got %s", s)
}
}
func TestScanPiParallel(t *testing.T) {
const n = 2
c := make(chan int)
for i := 0; i < n; i++ {
go func() {
TestScanPi(t)
c <- 0
}()
}
for i := 0; i < n; i++ {
<-c
}
}
func BenchmarkScanPi(b *testing.B) {
for i := 0; i < b.N; i++ {
var x nat
x.scan(strings.NewReader(pi), 10, false)
}
}
func BenchmarkStringPiParallel(b *testing.B) {
var x nat
x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
if string(x.utoa(10)) != pi {
panic("benchmark incorrect: conversion failed")
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
x.utoa(10)
}
})
}
func BenchmarkScan(b *testing.B) {
const x = 10
for _, base := range []int{2, 8, 10, 16} {
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
b.StopTimer()
var z nat
z = z.expWW(x, y)
s := z.utoa(base)
if t := itoa(z, base); !bytes.Equal(s, t) {
b.Fatalf("scanning: got %s; want %s", s, t)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
z.scan(bytes.NewReader(s), base, false)
}
})
}
}
}
func BenchmarkString(b *testing.B) {
const x = 10
for _, base := range []int{2, 8, 10, 16} {
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
b.StopTimer()
var z nat
z = z.expWW(x, y)
z.utoa(base) // warm divisor cache
b.StartTimer()
for i := 0; i < b.N; i++ {
_ = z.utoa(base)
}
})
}
}
}
func BenchmarkLeafSize(b *testing.B) {
for n := 0; n <= 16; n++ {
b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) })
}
// Try some large lengths
for _, n := range []int{32, 64} {
b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) })
}
}
func LeafSizeHelper(b *testing.B, base, size int) {
b.StopTimer()
originalLeafSize := leafSize
resetTable(cacheBase10.table[:])
leafSize = size
b.StartTimer()
for d := 1; d <= 10000; d *= 10 {
b.StopTimer()
var z nat
z = z.expWW(Word(base), Word(d)) // build target number
_ = z.utoa(base) // warm divisor cache
b.StartTimer()
for i := 0; i < b.N; i++ {
_ = z.utoa(base)
}
}
b.StopTimer()
resetTable(cacheBase10.table[:])
leafSize = originalLeafSize
b.StartTimer()
}
func resetTable(table []divisor) {
if table != nil && table[0].bbb != nil {
for i := 0; i < len(table); i++ {
table[i].bbb = nil
table[i].nbits = 0
table[i].ndigits = 0
}
}
}
func TestStringPowers(t *testing.T) {
var p Word
for b := 2; b <= 16; b++ {
for p = 0; p <= 512; p++ {
x := nat(nil).expWW(Word(b), p)
xs := x.utoa(b)
xs2 := itoa(x, b)
if !bytes.Equal(xs, xs2) {
t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
}
}
if b >= 3 && testing.Short() {
break
}
}
}
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements multi-precision rational numbers.
package big
import (
"fmt"
"math"
)
// A Rat represents a quotient a/b of arbitrary precision.
// The zero value for a Rat represents the value 0.
type Rat struct {
// To make zero values for Rat work w/o initialization,
// a zero value of b (len(b) == 0) acts like b == 1.
// a.neg determines the sign of the Rat, b.neg is ignored.
a, b Int
}
// NewRat creates a new Rat with numerator a and denominator b.
func NewRat(a, b int64) *Rat {
return new(Rat).SetFrac64(a, b)
}
// SetFloat64 sets z to exactly f and returns z.
// If f is not finite, SetFloat returns nil.
func (z *Rat) SetFloat64(f float64) *Rat {
const expMask = 1<<11 - 1
bits := math.Float64bits(f)
mantissa := bits & (1<<52 - 1)
exp := int((bits >> 52) & expMask)
switch exp {
case expMask: // non-finite
return nil
case 0: // denormal
exp -= 1022
default: // normal
mantissa |= 1 << 52
exp -= 1023
}
shift := 52 - exp
// Optimization (?): partially pre-normalise.
for mantissa&1 == 0 && shift > 0 {
mantissa >>= 1
shift--
}
z.a.SetUint64(mantissa)
z.a.neg = f < 0
z.b.Set(intOne)
if shift > 0 {
z.b.Lsh(&z.b, uint(shift))
} else {
z.a.Lsh(&z.a, uint(-shift))
}
return z.norm()
}
// quotToFloat32 returns the non-negative float32 value
// nearest to the quotient a/b, using round-to-even in
// halfway cases. It does not mutate its arguments.
// Preconditions: b is non-zero; a and b have no common factors.
func quotToFloat32(a, b nat) (f float32, exact bool) {
const (
// float size in bits
Fsize = 32
// mantissa
Msize = 23
Msize1 = Msize + 1 // incl. implicit 1
Msize2 = Msize1 + 1
// exponent
Esize = Fsize - Msize1
Ebias = 1<<(Esize-1) - 1
Emin = 1 - Ebias
Emax = Ebias
)
// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
alen := a.bitLen()
if alen == 0 {
return 0, true
}
blen := b.bitLen()
if blen == 0 {
panic("division by zero")
}
// 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
// (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
// This is 2 or 3 more than the float32 mantissa field width of Msize:
// - the optional extra bit is shifted away in step 3 below.
// - the high-order 1 is omitted in "normal" representation;
// - the low-order 1 will be used during rounding then discarded.
exp := alen - blen
var a2, b2 nat
a2 = a2.set(a)
b2 = b2.set(b)
if shift := Msize2 - exp; shift > 0 {
a2 = a2.shl(a2, uint(shift))
} else if shift < 0 {
b2 = b2.shl(b2, uint(-shift))
}
// 2. Compute quotient and remainder (q, r). NB: due to the
// extra shift, the low-order bit of q is logically the
// high-order bit of r.
var q nat
q, r := q.div(a2, a2, b2) // (recycle a2)
mantissa := low32(q)
haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
// 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
// (in effect---we accomplish this incrementally).
if mantissa>>Msize2 == 1 {
if mantissa&1 == 1 {
haveRem = true
}
mantissa >>= 1
exp++
}
if mantissa>>Msize1 != 1 {
panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
}
// 4. Rounding.
if Emin-Msize <= exp && exp <= Emin {
// Denormal case; lose 'shift' bits of precision.
shift := uint(Emin - (exp - 1)) // [1..Esize1)
lostbits := mantissa & (1<<shift - 1)
haveRem = haveRem || lostbits != 0
mantissa >>= shift
exp = 2 - Ebias // == exp + shift
}
// Round q using round-half-to-even.
exact = !haveRem
if mantissa&1 != 0 {
exact = false
if haveRem || mantissa&2 != 0 {
if mantissa++; mantissa >= 1<<Msize2 {
// Complete rollover 11...1 => 100...0, so shift is safe
mantissa >>= 1
exp++
}
}
}
mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1<<Msize1.
f = float32(math.Ldexp(float64(mantissa), exp-Msize1))
if math.IsInf(float64(f), 0) {
exact = false
}
return
}
// quotToFloat64 returns the non-negative float64 value
// nearest to the quotient a/b, using round-to-even in
// halfway cases. It does not mutate its arguments.
// Preconditions: b is non-zero; a and b have no common factors.
func quotToFloat64(a, b nat) (f float64, exact bool) {
const (
// float size in bits
Fsize = 64
// mantissa
Msize = 52
Msize1 = Msize + 1 // incl. implicit 1
Msize2 = Msize1 + 1
// exponent
Esize = Fsize - Msize1
Ebias = 1<<(Esize-1) - 1
Emin = 1 - Ebias
Emax = Ebias
)
// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
alen := a.bitLen()
if alen == 0 {
return 0, true
}
blen := b.bitLen()
if blen == 0 {
panic("division by zero")
}
// 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
// (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
// This is 2 or 3 more than the float64 mantissa field width of Msize:
// - the optional extra bit is shifted away in step 3 below.
// - the high-order 1 is omitted in "normal" representation;
// - the low-order 1 will be used during rounding then discarded.
exp := alen - blen
var a2, b2 nat
a2 = a2.set(a)
b2 = b2.set(b)
if shift := Msize2 - exp; shift > 0 {
a2 = a2.shl(a2, uint(shift))
} else if shift < 0 {
b2 = b2.shl(b2, uint(-shift))
}
// 2. Compute quotient and remainder (q, r). NB: due to the
// extra shift, the low-order bit of q is logically the
// high-order bit of r.
var q nat
q, r := q.div(a2, a2, b2) // (recycle a2)
mantissa := low64(q)
haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
// 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
// (in effect---we accomplish this incrementally).
if mantissa>>Msize2 == 1 {
if mantissa&1 == 1 {
haveRem = true
}
mantissa >>= 1
exp++
}
if mantissa>>Msize1 != 1 {
panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
}
// 4. Rounding.
if Emin-Msize <= exp && exp <= Emin {
// Denormal case; lose 'shift' bits of precision.
shift := uint(Emin - (exp - 1)) // [1..Esize1)
lostbits := mantissa & (1<<shift - 1)
haveRem = haveRem || lostbits != 0
mantissa >>= shift
exp = 2 - Ebias // == exp + shift
}
// Round q using round-half-to-even.
exact = !haveRem
if mantissa&1 != 0 {
exact = false
if haveRem || mantissa&2 != 0 {
if mantissa++; mantissa >= 1<<Msize2 {
// Complete rollover 11...1 => 100...0, so shift is safe
mantissa >>= 1
exp++
}
}
}
mantissa >>= 1 // discard rounding bit. Mantissa now scaled by 1<<Msize1.
f = math.Ldexp(float64(mantissa), exp-Msize1)
if math.IsInf(f, 0) {
exact = false
}
return
}
// Float32 returns the nearest float32 value for x and a bool indicating
// whether f represents x exactly. If the magnitude of x is too large to
// be represented by a float32, f is an infinity and exact is false.
// The sign of f always matches the sign of x, even if f == 0.
func (x *Rat) Float32() (f float32, exact bool) {
b := x.b.abs
if len(b) == 0 {
b = b.set(natOne) // materialize denominator
}
f, exact = quotToFloat32(x.a.abs, b)
if x.a.neg {
f = -f
}
return
}
// Float64 returns the nearest float64 value for x and a bool indicating
// whether f represents x exactly. If the magnitude of x is too large to
// be represented by a float64, f is an infinity and exact is false.
// The sign of f always matches the sign of x, even if f == 0.
func (x *Rat) Float64() (f float64, exact bool) {
b := x.b.abs
if len(b) == 0 {
b = b.set(natOne) // materialize denominator
}
f, exact = quotToFloat64(x.a.abs, b)
if x.a.neg {
f = -f
}
return
}
// SetFrac sets z to a/b and returns z.
func (z *Rat) SetFrac(a, b *Int) *Rat {
z.a.neg = a.neg != b.neg
babs := b.abs
if len(babs) == 0 {
panic("division by zero")
}
if &z.a == b || alias(z.a.abs, babs) {
babs = nat(nil).set(babs) // make a copy
}
z.a.abs = z.a.abs.set(a.abs)
z.b.abs = z.b.abs.set(babs)
return z.norm()
}
// SetFrac64 sets z to a/b and returns z.
func (z *Rat) SetFrac64(a, b int64) *Rat {
z.a.SetInt64(a)
if b == 0 {
panic("division by zero")
}
if b < 0 {
b = -b
z.a.neg = !z.a.neg
}
z.b.abs = z.b.abs.setUint64(uint64(b))
return z.norm()
}
// SetInt sets z to x (by making a copy of x) and returns z.
func (z *Rat) SetInt(x *Int) *Rat {
z.a.Set(x)
z.b.abs = z.b.abs[:0]
return z
}
// SetInt64 sets z to x and returns z.
func (z *Rat) SetInt64(x int64) *Rat {
z.a.SetInt64(x)
z.b.abs = z.b.abs[:0]
return z
}
// Set sets z to x (by making a copy of x) and returns z.
func (z *Rat) Set(x *Rat) *Rat {
if z != x {
z.a.Set(&x.a)
z.b.Set(&x.b)
}
return z
}
// Abs sets z to |x| (the absolute value of x) and returns z.
func (z *Rat) Abs(x *Rat) *Rat {
z.Set(x)
z.a.neg = false
return z
}
// Neg sets z to -x and returns z.
func (z *Rat) Neg(x *Rat) *Rat {
z.Set(x)
z.a.neg = len(z.a.abs) > 0 && !z.a.neg // 0 has no sign
return z
}
// Inv sets z to 1/x and returns z.
func (z *Rat) Inv(x *Rat) *Rat {
if len(x.a.abs) == 0 {
panic("division by zero")
}
z.Set(x)
a := z.b.abs
if len(a) == 0 {
a = a.set(natOne) // materialize numerator
}
b := z.a.abs
if b.cmp(natOne) == 0 {
b = b[:0] // normalize denominator
}
z.a.abs, z.b.abs = a, b // sign doesn't change
return z
}
// Sign returns:
//
// -1 if x < 0
// 0 if x == 0
// +1 if x > 0
//
func (x *Rat) Sign() int {
return x.a.Sign()
}
// IsInt reports whether the denominator of x is 1.
func (x *Rat) IsInt() bool {
return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
}
// Num returns the numerator of x; it may be <= 0.
// The result is a reference to x's numerator; it
// may change if a new value is assigned to x, and vice versa.
// The sign of the numerator corresponds to the sign of x.
func (x *Rat) Num() *Int {
return &x.a
}
// Denom returns the denominator of x; it is always > 0.
// The result is a reference to x's denominator; it
// may change if a new value is assigned to x, and vice versa.
func (x *Rat) Denom() *Int {
x.b.neg = false // the result is always >= 0
if len(x.b.abs) == 0 {
x.b.abs = x.b.abs.set(natOne) // materialize denominator
}
return &x.b
}
func (z *Rat) norm() *Rat {
switch {
case len(z.a.abs) == 0:
// z == 0 - normalize sign and denominator
z.a.neg = false
z.b.abs = z.b.abs[:0]
case len(z.b.abs) == 0:
// z is normalized int - nothing to do
case z.b.abs.cmp(natOne) == 0:
// z is int - normalize denominator
z.b.abs = z.b.abs[:0]
default:
neg := z.a.neg
z.a.neg = false
z.b.neg = false
if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
if z.b.abs.cmp(natOne) == 0 {
// z is int - normalize denominator
z.b.abs = z.b.abs[:0]
}
}
z.a.neg = neg
}
return z
}
// mulDenom sets z to the denominator product x*y (by taking into
// account that 0 values for x or y must be interpreted as 1) and
// returns z.
func mulDenom(z, x, y nat) nat {
switch {
case len(x) == 0:
return z.set(y)
case len(y) == 0:
return z.set(x)
}
return z.mul(x, y)
}
// scaleDenom computes x*f.
// If f == 0 (zero value of denominator), the result is (a copy of) x.
func scaleDenom(x *Int, f nat) *Int {
var z Int
if len(f) == 0 {
return z.Set(x)
}
z.abs = z.abs.mul(x.abs, f)
z.neg = x.neg
return &z
}
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
func (x *Rat) Cmp(y *Rat) int {
return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
}
// Add sets z to the sum x+y and returns z.
func (z *Rat) Add(x, y *Rat) *Rat {
a1 := scaleDenom(&x.a, y.b.abs)
a2 := scaleDenom(&y.a, x.b.abs)
z.a.Add(a1, a2)
z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
// Sub sets z to the difference x-y and returns z.
func (z *Rat) Sub(x, y *Rat) *Rat {
a1 := scaleDenom(&x.a, y.b.abs)
a2 := scaleDenom(&y.a, x.b.abs)
z.a.Sub(a1, a2)
z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
// Mul sets z to the product x*y and returns z.
func (z *Rat) Mul(x, y *Rat) *Rat {
z.a.Mul(&x.a, &y.a)
z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
return z.norm()
}
// Quo sets z to the quotient x/y and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
func (z *Rat) Quo(x, y *Rat) *Rat {
if len(y.a.abs) == 0 {
panic("division by zero")
}
a := scaleDenom(&x.a, y.b.abs)
b := scaleDenom(&y.a, x.b.abs)
z.a.abs = a.abs
z.b.abs = b.abs
z.a.neg = a.neg != b.neg
return z.norm()
}
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"math"
"testing"
)
func TestZeroRat(t *testing.T) {
var x, y, z Rat
y.SetFrac64(0, 42)
if x.Cmp(&y) != 0 {
t.Errorf("x and y should be both equal and zero")
}
if s := x.String(); s != "0/1" {
t.Errorf("got x = %s, want 0/1", s)
}
if s := x.RatString(); s != "0" {
t.Errorf("got x = %s, want 0", s)
}
z.Add(&x, &y)
if s := z.RatString(); s != "0" {
t.Errorf("got x+y = %s, want 0", s)
}
z.Sub(&x, &y)
if s := z.RatString(); s != "0" {
t.Errorf("got x-y = %s, want 0", s)
}
z.Mul(&x, &y)
if s := z.RatString(); s != "0" {
t.Errorf("got x*y = %s, want 0", s)
}
// check for division by zero
defer func() {
if s := recover(); s == nil || s.(string) != "division by zero" {
panic(s)
}
}()
z.Quo(&x, &y)
}
func TestRatSign(t *testing.T) {
zero := NewRat(0, 1)
for _, a := range setStringTests {
x, ok := new(Rat).SetString(a.in)
if !ok {
continue
}
s := x.Sign()
e := x.Cmp(zero)
if s != e {
t.Errorf("got %d; want %d for z = %v", s, e, &x)
}
}
}
var ratCmpTests = []struct {
rat1, rat2 string
out int
}{
{"0", "0/1", 0},
{"1/1", "1", 0},
{"-1", "-2/2", 0},
{"1", "0", 1},
{"0/1", "1/1", -1},
{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
}
func TestRatCmp(t *testing.T) {
for i, test := range ratCmpTests {
x, _ := new(Rat).SetString(test.rat1)
y, _ := new(Rat).SetString(test.rat2)
out := x.Cmp(y)
if out != test.out {
t.Errorf("#%d got out = %v; want %v", i, out, test.out)
}
}
}
func TestIsInt(t *testing.T) {
one := NewInt(1)
for _, a := range setStringTests {
x, ok := new(Rat).SetString(a.in)
if !ok {
continue
}
i := x.IsInt()
e := x.Denom().Cmp(one) == 0
if i != e {
t.Errorf("got IsInt(%v) == %v; want %v", x, i, e)
}
}
}
func TestRatAbs(t *testing.T) {
zero := new(Rat)
for _, a := range setStringTests {
x, ok := new(Rat).SetString(a.in)
if !ok {
continue
}
e := new(Rat).Set(x)
if e.Cmp(zero) < 0 {
e.Sub(zero, e)
}
z := new(Rat).Abs(x)
if z.Cmp(e) != 0 {
t.Errorf("got Abs(%v) = %v; want %v", x, z, e)
}
}
}
func TestRatNeg(t *testing.T) {
zero := new(Rat)
for _, a := range setStringTests {
x, ok := new(Rat).SetString(a.in)
if !ok {
continue
}
e := new(Rat).Sub(zero, x)
z := new(Rat).Neg(x)
if z.Cmp(e) != 0 {
t.Errorf("got Neg(%v) = %v; want %v", x, z, e)
}
}
}
func TestRatInv(t *testing.T) {
zero := new(Rat)
for _, a := range setStringTests {
x, ok := new(Rat).SetString(a.in)
if !ok {
continue
}
if x.Cmp(zero) == 0 {
continue // avoid division by zero
}
e := new(Rat).SetFrac(x.Denom(), x.Num())
z := new(Rat).Inv(x)
if z.Cmp(e) != 0 {
t.Errorf("got Inv(%v) = %v; want %v", x, z, e)
}
}
}
type ratBinFun func(z, x, y *Rat) *Rat
type ratBinArg struct {
x, y, z string
}
func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
x, _ := new(Rat).SetString(a.x)
y, _ := new(Rat).SetString(a.y)
z, _ := new(Rat).SetString(a.z)
out := f(new(Rat), x, y)
if out.Cmp(z) != 0 {
t.Errorf("%s #%d got %s want %s", name, i, out, z)
}
}
var ratBinTests = []struct {
x, y string
sum, prod string
}{
{"0", "0", "0", "0"},
{"0", "1", "1", "0"},
{"-1", "0", "-1", "0"},
{"-1", "1", "0", "-1"},
{"1", "1", "2", "1"},
{"1/2", "1/2", "1", "1/4"},
{"1/4", "1/3", "7/12", "1/12"},
{"2/5", "-14/3", "-64/15", "-28/15"},
{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
}
func TestRatBin(t *testing.T) {
for i, test := range ratBinTests {
arg := ratBinArg{test.x, test.y, test.sum}
testRatBin(t, i, "Add", (*Rat).Add, arg)
arg = ratBinArg{test.y, test.x, test.sum}
testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
arg = ratBinArg{test.sum, test.x, test.y}
testRatBin(t, i, "Sub", (*Rat).Sub, arg)
arg = ratBinArg{test.sum, test.y, test.x}
testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
arg = ratBinArg{test.x, test.y, test.prod}
testRatBin(t, i, "Mul", (*Rat).Mul, arg)
arg = ratBinArg{test.y, test.x, test.prod}
testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
if test.x != "0" {
arg = ratBinArg{test.prod, test.x, test.y}
testRatBin(t, i, "Quo", (*Rat).Quo, arg)
}
if test.y != "0" {
arg = ratBinArg{test.prod, test.y, test.x}
testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
}
}
}
func TestIssue820(t *testing.T) {
x := NewRat(3, 1)
y := NewRat(2, 1)
z := y.Quo(x, y)
q := NewRat(3, 2)
if z.Cmp(q) != 0 {
t.Errorf("got %s want %s", z, q)
}
y = NewRat(3, 1)
x = NewRat(2, 1)
z = y.Quo(x, y)
q = NewRat(2, 3)
if z.Cmp(q) != 0 {
t.Errorf("got %s want %s", z, q)
}
x = NewRat(3, 1)
z = x.Quo(x, x)
q = NewRat(3, 3)
if z.Cmp(q) != 0 {
t.Errorf("got %s want %s", z, q)
}
}
var setFrac64Tests = []struct {
a, b int64
out string
}{
{0, 1, "0"},
{0, -1, "0"},
{1, 1, "1"},
{-1, 1, "-1"},
{1, -1, "-1"},
{-1, -1, "1"},
{-9223372036854775808, -9223372036854775808, "1"},
}
func TestRatSetFrac64Rat(t *testing.T) {
for i, test := range setFrac64Tests {
x := new(Rat).SetFrac64(test.a, test.b)
if x.RatString() != test.out {
t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
}
}
}
func TestIssue2379(t *testing.T) {
// 1) no aliasing
q := NewRat(3, 2)
x := new(Rat)
x.SetFrac(NewInt(3), NewInt(2))
if x.Cmp(q) != 0 {
t.Errorf("1) got %s want %s", x, q)
}
// 2) aliasing of numerator
x = NewRat(2, 3)
x.SetFrac(NewInt(3), x.Num())
if x.Cmp(q) != 0 {
t.Errorf("2) got %s want %s", x, q)
}
// 3) aliasing of denominator
x = NewRat(2, 3)
x.SetFrac(x.Denom(), NewInt(2))
if x.Cmp(q) != 0 {
t.Errorf("3) got %s want %s", x, q)
}
// 4) aliasing of numerator and denominator
x = NewRat(2, 3)
x.SetFrac(x.Denom(), x.Num())
if x.Cmp(q) != 0 {
t.Errorf("4) got %s want %s", x, q)
}
// 5) numerator and denominator are the same
q = NewRat(1, 1)
x = new(Rat)
n := NewInt(7)
x.SetFrac(n, n)
if x.Cmp(q) != 0 {
t.Errorf("5) got %s want %s", x, q)
}
}
func TestIssue3521(t *testing.T) {
a := new(Int)
b := new(Int)
a.SetString("64375784358435883458348587", 0)
b.SetString("4789759874531", 0)
// 0) a raw zero value has 1 as denominator
zero := new(Rat)
one := NewInt(1)
if zero.Denom().Cmp(one) != 0 {
t.Errorf("0) got %s want %s", zero.Denom(), one)
}
// 1a) a zero value remains zero independent of denominator
x := new(Rat)
x.Denom().Set(new(Int).Neg(b))
if x.Cmp(zero) != 0 {
t.Errorf("1a) got %s want %s", x, zero)
}
// 1b) a zero value may have a denominator != 0 and != 1
x.Num().Set(a)
qab := new(Rat).SetFrac(a, b)
if x.Cmp(qab) != 0 {
t.Errorf("1b) got %s want %s", x, qab)
}
// 2a) an integral value becomes a fraction depending on denominator
x.SetFrac64(10, 2)
x.Denom().SetInt64(3)
q53 := NewRat(5, 3)
if x.Cmp(q53) != 0 {
t.Errorf("2a) got %s want %s", x, q53)
}
// 2b) an integral value becomes a fraction depending on denominator
x = NewRat(10, 2)
x.Denom().SetInt64(3)
if x.Cmp(q53) != 0 {
t.Errorf("2b) got %s want %s", x, q53)
}
// 3) changing the numerator/denominator of a Rat changes the Rat
x.SetFrac(a, b)
a = x.Num()
b = x.Denom()
a.SetInt64(5)
b.SetInt64(3)
if x.Cmp(q53) != 0 {
t.Errorf("3) got %s want %s", x, q53)
}
}
func TestFloat32Distribution(t *testing.T) {
// Generate a distribution of (sign, mantissa, exp) values
// broader than the float32 range, and check Rat.Float32()
// always picks the closest float32 approximation.
var add = []int64{
0,
1,
3,
5,
7,
9,
11,
}
var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64)
if testing.Short() {
winc, einc = 5, 15 // quick test (~60ms on x86-64)
}
for _, sign := range "+-" {
for _, a := range add {
for wid := uint64(0); wid < 30; wid += winc {
b := 1<<wid + a
if sign == '-' {
b = -b
}
for exp := -150; exp < 150; exp += einc {
num, den := NewInt(b), NewInt(1)
if exp > 0 {
num.Lsh(num, uint(exp))
} else {
den.Lsh(den, uint(-exp))
}
r := new(Rat).SetFrac(num, den)
f, _ := r.Float32()
if !checkIsBestApprox32(t, f, r) {
// Append context information.
t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
b, exp, f, f, math.Ldexp(float64(b), exp), r)
}
checkNonLossyRoundtrip32(t, f)
}
}
}
}
}
func TestFloat64Distribution(t *testing.T) {
// Generate a distribution of (sign, mantissa, exp) values
// broader than the float64 range, and check Rat.Float64()
// always picks the closest float64 approximation.
var add = []int64{
0,
1,
3,
5,
7,
9,
11,
}
var winc, einc = uint64(1), 1 // soak test (~75s on x86-64)
if testing.Short() {
winc, einc = 10, 500 // quick test (~12ms on x86-64)
}
for _, sign := range "+-" {
for _, a := range add {
for wid := uint64(0); wid < 60; wid += winc {
b := 1<<wid + a
if sign == '-' {
b = -b
}
for exp := -1100; exp < 1100; exp += einc {
num, den := NewInt(b), NewInt(1)
if exp > 0 {
num.Lsh(num, uint(exp))
} else {
den.Lsh(den, uint(-exp))
}
r := new(Rat).SetFrac(num, den)
f, _ := r.Float64()
if !checkIsBestApprox64(t, f, r) {
// Append context information.
t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
b, exp, f, f, math.Ldexp(float64(b), exp), r)
}
checkNonLossyRoundtrip64(t, f)
}
}
}
}
}
// TestSetFloat64NonFinite checks that SetFloat64 of a non-finite value
// returns nil.
func TestSetFloat64NonFinite(t *testing.T) {
for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} {
var r Rat
if r2 := r.SetFloat64(f); r2 != nil {
t.Errorf("SetFloat64(%g) was %v, want nil", f, r2)
}
}
}
// checkNonLossyRoundtrip32 checks that a float->Rat->float roundtrip is
// non-lossy for finite f.
func checkNonLossyRoundtrip32(t *testing.T, f float32) {
if !isFinite(float64(f)) {
return
}
r := new(Rat).SetFloat64(float64(f))
if r == nil {
t.Errorf("Rat.SetFloat64(float64(%g) (%b)) == nil", f, f)
return
}
f2, exact := r.Float32()
if f != f2 || !exact {
t.Errorf("Rat.SetFloat64(float64(%g)).Float32() = %g (%b), %v, want %g (%b), %v; delta = %b",
f, f2, f2, exact, f, f, true, f2-f)
}
}
// checkNonLossyRoundtrip64 checks that a float->Rat->float roundtrip is
// non-lossy for finite f.
func checkNonLossyRoundtrip64(t *testing.T, f float64) {
if !isFinite(f) {
return
}
r := new(Rat).SetFloat64(f)
if r == nil {
t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f)
return
}
f2, exact := r.Float64()
if f != f2 || !exact {
t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b",
f, f2, f2, exact, f, f, true, f2-f)
}
}
// delta returns the absolute difference between r and f.
func delta(r *Rat, f float64) *Rat {
d := new(Rat).Sub(r, new(Rat).SetFloat64(f))
return d.Abs(d)
}
// checkIsBestApprox32 checks that f is the best possible float32
// approximation of r.
// Returns true on success.
func checkIsBestApprox32(t *testing.T, f float32, r *Rat) bool {
if math.Abs(float64(f)) >= math.MaxFloat32 {
// Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32).
// But we have tests for these special cases.
return true
}
// r must be strictly between f0 and f1, the floats bracketing f.
f0 := math.Nextafter32(f, float32(math.Inf(-1)))
f1 := math.Nextafter32(f, float32(math.Inf(+1)))
// For f to be correct, r must be closer to f than to f0 or f1.
df := delta(r, float64(f))
df0 := delta(r, float64(f0))
df1 := delta(r, float64(f1))
if df.Cmp(df0) > 0 {
t.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r, f, f, f0, f0)
return false
}
if df.Cmp(df1) > 0 {
t.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r, f, f, f1, f1)
return false
}
if df.Cmp(df0) == 0 && !isEven32(f) {
t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
return false
}
if df.Cmp(df1) == 0 && !isEven32(f) {
t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
return false
}
return true
}
// checkIsBestApprox64 checks that f is the best possible float64
// approximation of r.
// Returns true on success.
func checkIsBestApprox64(t *testing.T, f float64, r *Rat) bool {
if math.Abs(f) >= math.MaxFloat64 {
// Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64).
// But we have tests for these special cases.
return true
}
// r must be strictly between f0 and f1, the floats bracketing f.
f0 := math.Nextafter(f, math.Inf(-1))
f1 := math.Nextafter(f, math.Inf(+1))
// For f to be correct, r must be closer to f than to f0 or f1.
df := delta(r, f)
df0 := delta(r, f0)
df1 := delta(r, f1)
if df.Cmp(df0) > 0 {
t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0)
return false
}
if df.Cmp(df1) > 0 {
t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1)
return false
}
if df.Cmp(df0) == 0 && !isEven64(f) {
t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
return false
}
if df.Cmp(df1) == 0 && !isEven64(f) {
t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
return false
}
return true
}
func isEven32(f float32) bool { return math.Float32bits(f)&1 == 0 }
func isEven64(f float64) bool { return math.Float64bits(f)&1 == 0 }
func TestIsFinite(t *testing.T) {
finites := []float64{
1.0 / 3,
4891559871276714924261e+222,
math.MaxFloat64,
math.SmallestNonzeroFloat64,
-math.MaxFloat64,
-math.SmallestNonzeroFloat64,
}
for _, f := range finites {
if !isFinite(f) {
t.Errorf("!IsFinite(%g (%b))", f, f)
}
}
nonfinites := []float64{
math.NaN(),
math.Inf(-1),
math.Inf(+1),
}
for _, f := range nonfinites {
if isFinite(f) {
t.Errorf("IsFinite(%g, (%b))", f, f)
}
}
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements rat-to-string conversion functions.
package big
import (
"errors"
"fmt"
"io"
"strconv"
"strings"
)
func ratTok(ch rune) bool {
return strings.ContainsRune("+-/0123456789.eE", ch)
}
// Scan is a support routine for fmt.Scanner. It accepts the formats
// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
tok, err := s.Token(true, ratTok)
if err != nil {
return err
}
if !strings.ContainsRune("efgEFGv", ch) {
return errors.New("Rat.Scan: invalid verb")
}
if _, ok := z.SetString(string(tok)); !ok {
return errors.New("Rat.Scan: invalid syntax")
}
return nil
}
// SetString sets z to the value of s and returns z and a boolean indicating
// success. s can be given as a fraction "a/b" or as a floating-point number
// optionally followed by an exponent. If the operation failed, the value of
// z is undefined but the returned value is nil.
func (z *Rat) SetString(s string) (*Rat, bool) {
if len(s) == 0 {
return nil, false
}
// len(s) > 0
// parse fraction a/b, if any
if sep := strings.Index(s, "/"); sep >= 0 {
if _, ok := z.a.SetString(s[:sep], 0); !ok {
return nil, false
}
s = s[sep+1:]
var err error
if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
return nil, false
}
if len(z.b.abs) == 0 {
return nil, false
}
return z.norm(), true
}
// parse floating-point number
r := strings.NewReader(s)
// sign
neg, err := scanSign(r)
if err != nil {
return nil, false
}
// mantissa
var ecorr int
z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
if err != nil {
return nil, false
}
// exponent
var exp int64
exp, _, err = scanExponent(r, false)
if err != nil {
return nil, false
}
// there should be no unread characters left
if _, err = r.ReadByte(); err != io.EOF {
return nil, false
}
// special-case 0 (see also issue #16176)
if len(z.a.abs) == 0 {
return z, true
}
// len(z.a.abs) > 0
// correct exponent
if ecorr < 0 {
exp += int64(ecorr)
}
// compute exponent power
expabs := exp
if expabs < 0 {
expabs = -expabs
}
powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
// complete fraction
if exp < 0 {
z.b.abs = powTen
z.norm()
} else {
z.a.abs = z.a.abs.mul(z.a.abs, powTen)
z.b.abs = z.b.abs[:0]
}
z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
return z, true
}
// scanExponent scans the longest possible prefix of r representing a decimal
// ('e', 'E') or binary ('p') exponent, if any. It returns the exponent, the
// exponent base (10 or 2), or a read or syntax error, if any.
//
// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
// sign = "+" | "-" .
// digits = digit { digit } .
// digit = "0" ... "9" .
//
// A binary exponent is only permitted if binExpOk is set.
func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err error) {
base = 10
var ch byte
if ch, err = r.ReadByte(); err != nil {
if err == io.EOF {
err = nil // no exponent; same as e0
}
return
}
switch ch {
case 'e', 'E':
// ok
case 'p':
if binExpOk {
base = 2
break // ok
}
fallthrough // binary exponent not permitted
default:
r.UnreadByte()
return // no exponent; same as e0
}
var neg bool
if neg, err = scanSign(r); err != nil {
return
}
var digits []byte
if neg {
digits = append(digits, '-')
}
// no need to use nat.scan for exponent digits
// since we only care about int64 values - the
// from-scratch scan is easy enough and faster
for i := 0; ; i++ {
if ch, err = r.ReadByte(); err != nil {
if err != io.EOF || i == 0 {
return
}
err = nil
break // i > 0
}
if ch < '0' || '9' < ch {
if i == 0 {
r.UnreadByte()
err = fmt.Errorf("invalid exponent (missing digits)")
return
}
break // i > 0
}
digits = append(digits, ch)
}
// i > 0 => we have at least one digit
exp, err = strconv.ParseInt(string(digits), 10, 64)
return
}
// String returns a string representation of x in the form "a/b" (even if b == 1).
func (x *Rat) String() string {
var buf []byte
buf = x.a.Append(buf, 10)
buf = append(buf, '/')
if len(x.b.abs) != 0 {
buf = x.b.Append(buf, 10)
} else {
buf = append(buf, '1')
}
return string(buf)
}
// RatString returns a string representation of x in the form "a/b" if b != 1,
// and in the form "a" if b == 1.
func (x *Rat) RatString() string {
if x.IsInt() {
return x.a.String()
}
return x.String()
}
// FloatString returns a string representation of x in decimal form with prec
// digits of precision after the decimal point. The last digit is rounded to
// nearest, with halves rounded away from zero.
func (x *Rat) FloatString(prec int) string {
var buf []byte
if x.IsInt() {
buf = x.a.Append(buf, 10)
if prec > 0 {
buf = append(buf, '.')
for i := prec; i > 0; i-- {
buf = append(buf, '0')
}
}
return string(buf)
}
// x.b.abs != 0
q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
p := natOne
if prec > 0 {
p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
}
r = r.mul(r, p)
r, r2 := r.div(nat(nil), r, x.b.abs)
// see if we need to round up
r2 = r2.add(r2, r2)
if x.b.abs.cmp(r2) <= 0 {
r = r.add(r, natOne)
if r.cmp(p) >= 0 {
q = nat(nil).add(q, natOne)
r = nat(nil).sub(r, p)
}
}
if x.a.neg {
buf = append(buf, '-')
}
buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
if prec > 0 {
buf = append(buf, '.')
rs := r.utoa(10)
for i := prec - len(rs); i > 0; i-- {
buf = append(buf, '0')
}
buf = append(buf, rs...)
}
return string(buf)
}
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package big
import (
"bytes"
"fmt"
"math"
"strconv"
"strings"
"testing"
)
type StringTest struct {
in, out string
ok bool
}
var setStringTests = []StringTest{
{"0", "0", true},
{"-0", "0", true},
{"1", "1", true},
{"-1", "-1", true},
{"1.", "1", true},
{"1e0", "1", true},
{"1.e1", "10", true},
{in: "1e"},
{in: "1.e"},
{in: "1e+14e-5"},
{in: "1e4.5"},
{in: "r"},
{in: "a/b"},
{in: "a.b"},
{"-0.1", "-1/10", true},
{"-.1", "-1/10", true},
{"2/4", "1/2", true},
{".25", "1/4", true},
{"-1/5", "-1/5", true},
{"8129567.7690E14", "812956776900000000000", true},
{"78189e+4", "781890000", true},
{"553019.8935e+8", "55301989350000", true},
{"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
{"9877861857500000E-7", "3951144743/4", true},
{"2169378.417e-3", "2169378417/1000000", true},
{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
{"53/70893980658822810696", "53/70893980658822810696", true},
{"106/141787961317645621392", "53/70893980658822810696", true},
{"204211327800791583.81095", "4084226556015831676219/20000", true},
{"0e9999999999", "0", true}, // issue #16176
{in: "1/0"},
}
// These are not supported by fmt.Fscanf.
var setStringTests2 = []StringTest{
{"0x10", "16", true},
{"-010/1", "-8", true}, // TODO(gri) should we even permit octal here?
{"-010.", "-10", true},
{"0x10/0x20", "1/2", true},
{"0b1000/3", "8/3", true},
// TODO(gri) add more tests
}
func TestRatSetString(t *testing.T) {
var tests []StringTest
tests = append(tests, setStringTests...)
tests = append(tests, setStringTests2...)
for i, test := range tests {
x, ok := new(Rat).SetString(test.in)
if ok {
if !test.ok {
t.Errorf("#%d SetString(%q) expected failure", i, test.in)
} else if x.RatString() != test.out {
t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
}
} else if x != nil {
t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
}
}
}
func TestRatScan(t *testing.T) {
var buf bytes.Buffer
for i, test := range setStringTests {
x := new(Rat)
buf.Reset()
buf.WriteString(test.in)
_, err := fmt.Fscanf(&buf, "%v", x)
if err == nil != test.ok {
if test.ok {
t.Errorf("#%d (%s) error: %s", i, test.in, err)
} else {
t.Errorf("#%d (%s) expected error", i, test.in)
}
continue
}
if err == nil && x.RatString() != test.out {
t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
}
}
}
var floatStringTests = []struct {
in string
prec int
out string
}{
{"0", 0, "0"},
{"0", 4, "0.0000"},
{"1", 0, "1"},
{"1", 2, "1.00"},
{"-1", 0, "-1"},
{"0.05", 1, "0.1"},
{"-0.05", 1, "-0.1"},
{".25", 2, "0.25"},
{".25", 1, "0.3"},
{".25", 3, "0.250"},
{"-1/3", 3, "-0.333"},
{"-2/3", 4, "-0.6667"},
{"0.96", 1, "1.0"},
{"0.999", 2, "1.00"},
{"0.9", 0, "1"},
{".25", -1, "0"},
{".55", -1, "1"},
}
func TestFloatString(t *testing.T) {
for i, test := range floatStringTests {
x, _ := new(Rat).SetString(test.in)
if x.FloatString(test.prec) != test.out {
t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
}
}
}
// Test inputs to Rat.SetString. The prefix "long:" causes the test
// to be skipped in --test.short mode. (The threshold is about 500us.)
var float64inputs = []string{
// Constants plundered from strconv/testfp.txt.
// Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
"5e+125",
"69e+267",
"999e-026",
"7861e-034",
"75569e-254",
"928609e-261",
"9210917e+080",
"84863171e+114",
"653777767e+273",
"5232604057e-298",
"27235667517e-109",
"653532977297e-123",
"3142213164987e-294",
"46202199371337e-072",
"231010996856685e-073",
"9324754620109615e+212",
"78459735791271921e+049",
"272104041512242479e+200",
"6802601037806061975e+198",
"20505426358836677347e-221",
"836168422905420598437e-234",
"4891559871276714924261e+222",
// Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
"9e-265",
"85e-037",
"623e+100",
"3571e+263",
"81661e+153",
"920657e-023",
"4603285e-024",
"87575437e-309",
"245540327e+122",
"6138508175e+120",
"83356057653e+193",
"619534293513e+124",
"2335141086879e+218",
"36167929443327e-159",
"609610927149051e-255",
"3743626360493413e-165",
"94080055902682397e-242",
"899810892172646163e+283",
"7120190517612959703e+120",
"25188282901709339043e-252",
"308984926168550152811e-052",
"6372891218502368041059e+064",
// Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
"5e-20",
"67e+14",
"985e+15",
"7693e-42",
"55895e-16",
"996622e-44",
"7038531e-32",
"60419369e-46",
"702990899e-20",
"6930161142e-48",
"25933168707e+13",
"596428896559e+20",
// Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
"3e-23",
"57e+18",
"789e-35",
"2539e-18",
"76173e+28",
"887745e-11",
"5382571e-37",
"82381273e-35",
"750486563e-38",
"3752432815e-39",
"75224575729e-45",
"459926601011e+15",
// Constants plundered from strconv/atof_test.go.
"0",
"1",
"+1",
"1e23",
"1E23",
"100000000000000000000000",
"1e-100",
"123456700",
"99999999999999974834176",
"100000000000000000000001",
"100000000000000008388608",
"100000000000000016777215",
"100000000000000016777216",
"-1",
"-0.1",
"-0", // NB: exception made for this input
"1e-20",
"625e-3",
// largest float64
"1.7976931348623157e308",
"-1.7976931348623157e308",
// next float64 - too large
"1.7976931348623159e308",
"-1.7976931348623159e308",
// the border is ...158079
// borderline - okay
"1.7976931348623158e308",
"-1.7976931348623158e308",
// borderline - too large
"1.797693134862315808e308",
"-1.797693134862315808e308",
// a little too large
"1e308",
"2e308",
"1e309",
// way too large
"1e310",
"-1e310",
"1e400",
"-1e400",
"long:1e400000",
"long:-1e400000",
// denormalized
"1e-305",
"1e-306",
"1e-307",
"1e-308",
"1e-309",
"1e-310",
"1e-322",
// smallest denormal
"5e-324",
"4e-324",
"3e-324",
// too small
"2e-324",
// way too small
"1e-350",
"long:1e-400000",
// way too small, negative
"-1e-350",
"long:-1e-400000",
// try to overflow exponent
// [Disabled: too slow and memory-hungry with rationals.]
// "1e-4294967296",
// "1e+4294967296",
// "1e-18446744073709551616",
// "1e+18446744073709551616",
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
"2.2250738585072012e-308",
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
"2.2250738585072011e-308",
// A very large number (initially wrongly parsed by the fast algorithm).
"4.630813248087435e+307",
// A different kind of very large number.
"22.222222222222222",
"long:2." + strings.Repeat("2", 4000) + "e+1",
// Exactly halfway between 1 and math.Nextafter(1, 2).
// Round to even (down).
"1.00000000000000011102230246251565404236316680908203125",
// Slightly lower; still round down.
"1.00000000000000011102230246251565404236316680908203124",
// Slightly higher; round up.
"1.00000000000000011102230246251565404236316680908203126",
// Slightly higher, but you have to read all the way to the end.
"long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
// Smallest denormal, 2^(-1022-52)
"4.940656458412465441765687928682213723651e-324",
// Half of smallest denormal, 2^(-1022-53)
"2.470328229206232720882843964341106861825e-324",
// A little more than the exact half of smallest denormal
// 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
"2.470328302827751011111470718709768633275e-324",
// The exact halfway between smallest normal and largest denormal:
// 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
"2.225073858507201136057409796709131975935e-308",
"1152921504606846975", // 1<<60 - 1
"-1152921504606846975", // -(1<<60 - 1)
"1152921504606846977", // 1<<60 + 1
"-1152921504606846977", // -(1<<60 + 1)
"1/3",
}
// isFinite reports whether f represents a finite rational value.
// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
func isFinite(f float64) bool {
return math.Abs(f) <= math.MaxFloat64
}
func TestFloat32SpecialCases(t *testing.T) {
for _, input := range float64inputs {
if strings.HasPrefix(input, "long:") {
if testing.Short() {
continue
}
input = input[len("long:"):]
}
r, ok := new(Rat).SetString(input)
if !ok {
t.Errorf("Rat.SetString(%q) failed", input)
continue
}
f, exact := r.Float32()
// 1. Check string -> Rat -> float32 conversions are
// consistent with strconv.ParseFloat.
// Skip this check if the input uses "a/b" rational syntax.
if !strings.Contains(input, "/") {
e64, _ := strconv.ParseFloat(input, 32)
e := float32(e64)
// Careful: negative Rats too small for
// float64 become -0, but Rat obviously cannot
// preserve the sign from SetString("-0").
switch {
case math.Float32bits(e) == math.Float32bits(f):
// Ok: bitwise equal.
case f == 0 && r.Num().BitLen() == 0:
// Ok: Rat(0) is equivalent to both +/- float64(0).
default:
t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
}
}
if !isFinite(float64(f)) {
continue
}
// 2. Check f is best approximation to r.
if !checkIsBestApprox32(t, f, r) {
// Append context information.
t.Errorf("(input was %q)", input)
}
// 3. Check f->R->f roundtrip is non-lossy.
checkNonLossyRoundtrip32(t, f)
// 4. Check exactness using slow algorithm.
if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
}
}
}
func TestFloat64SpecialCases(t *testing.T) {
for _, input := range float64inputs {
if strings.HasPrefix(input, "long:") {
if testing.Short() {
continue
}
input = input[len("long:"):]
}
r, ok := new(Rat).SetString(input)
if !ok {
t.Errorf("Rat.SetString(%q) failed", input)
continue
}
f, exact := r.Float64()
// 1. Check string -> Rat -> float64 conversions are
// consistent with strconv.ParseFloat.
// Skip this check if the input uses "a/b" rational syntax.
if !strings.Contains(input, "/") {
e, _ := strconv.ParseFloat(input, 64)
// Careful: negative Rats too small for
// float64 become -0, but Rat obviously cannot
// preserve the sign from SetString("-0").
switch {
case math.Float64bits(e) == math.Float64bits(f):
// Ok: bitwise equal.
case f == 0 && r.Num().BitLen() == 0:
// Ok: Rat(0) is equivalent to both +/- float64(0).
default:
t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
}
}
if !isFinite(f) {
continue
}
// 2. Check f is best approximation to r.
if !checkIsBestApprox64(t, f, r) {
// Append context information.
t.Errorf("(input was %q)", input)
}
// 3. Check f->R->f roundtrip is non-lossy.
checkNonLossyRoundtrip64(t, f)
// 4. Check exactness using slow algorithm.
if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
}
}
}
// 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
}
// 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)
}
}
}
}
// generated by stringer -type=RoundingMode; DO NOT EDIT
package big
import "fmt"
const _RoundingMode_name = "ToNearestEvenToNearestAwayToZeroAwayFromZeroToNegativeInfToPositiveInf"
var _RoundingMode_index = [...]uint8{0, 13, 26, 32, 44, 57, 70}
func (i RoundingMode) String() string {
if i+1 >= RoundingMode(len(_RoundingMode_index)) {
return fmt.Sprintf("RoundingMode(%d)", i)
}
return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
}
#!/usr/bin/env bash
# Copyright 2015 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Run this script to obtain an up-to-date vendored version of math/big.
BIGDIR=../../../../math/big
# Start from scratch.
rm *.go
# We don't want any assembly files.
cp $BIGDIR/*.go .
# Use pure Go arith ops w/o build tag.
sed 's|^// \+build math_big_pure_go$||' arith_decl_pure.go > arith_decl.go
rm arith_decl_pure.go
# Import vendored math/big in external tests (e.g., floatexample_test.go).
for f in *_test.go; do
sed 's|"math/big"|"cmd/compile/internal/big"|' $f > foo.go
mv foo.go $f
done
# gofmt to clean up after sed
gofmt -w .
# Test that it works
go test -short
...@@ -132,7 +132,7 @@ package gc ...@@ -132,7 +132,7 @@ package gc
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"cmd/compile/internal/big" "math/big"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"sort" "sort"
......
...@@ -10,7 +10,7 @@ package gc ...@@ -10,7 +10,7 @@ package gc
import ( import (
"bufio" "bufio"
"cmd/compile/internal/big" "math/big"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"strconv" "strconv"
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
package gc package gc
import ( import (
"cmd/compile/internal/big"
"fmt" "fmt"
"math" "math"
"math/big"
) )
// implements float arithmetic // implements float arithmetic
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
package gc package gc
import ( import (
"cmd/compile/internal/big"
"fmt" "fmt"
"math/big"
) )
// implements integer arithmetic // implements integer arithmetic
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package gc package gc
import ( import (
"cmd/compile/internal/big" "math/big"
"testing" "testing"
) )
......
...@@ -18,49 +18,60 @@ import ( ...@@ -18,49 +18,60 @@ import (
// bootstrapDirs is a list of directories holding code that must be // bootstrapDirs is a list of directories holding code that must be
// compiled with a Go 1.4 toolchain to produce the bootstrapTargets. // compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
// All directories in this list are relative to and must be below $GOROOT/src/cmd. // All directories in this list are relative to and must be below $GOROOT/src.
// The list is assumed to have two kinds of entries: names without slashes, //
// which are commands, and entries beginning with internal/, which are // The list has have two kinds of entries: names beginning with cmd/ with
// packages supporting the commands. // no other slashes, which are commands, and other paths, which are packages
// supporting the commands. Packages in the standard library can be listed
// if a newer copy needs to be substituted for the Go 1.4 copy when used
// by the command packages.
// These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big.
var bootstrapDirs = []string{ var bootstrapDirs = []string{
"asm", "cmd/asm",
"asm/internal/arch", "cmd/asm/internal/arch",
"asm/internal/asm", "cmd/asm/internal/asm",
"asm/internal/flags", "cmd/asm/internal/flags",
"asm/internal/lex", "cmd/asm/internal/lex",
"compile", "cmd/compile",
"compile/internal/amd64", "cmd/compile/internal/amd64",
"compile/internal/arm", "cmd/compile/internal/arm",
"compile/internal/arm64", "cmd/compile/internal/arm64",
"compile/internal/big", "cmd/compile/internal/gc",
"compile/internal/gc", "cmd/compile/internal/mips64",
"compile/internal/mips64", "cmd/compile/internal/ppc64",
"compile/internal/ppc64", "cmd/compile/internal/s390x",
"compile/internal/s390x", "cmd/compile/internal/ssa",
"compile/internal/ssa", "cmd/compile/internal/syntax",
"compile/internal/syntax", "cmd/compile/internal/x86",
"compile/internal/x86", "cmd/internal/bio",
"internal/bio", "cmd/internal/gcprog",
"internal/gcprog", "cmd/internal/dwarf",
"internal/dwarf", "cmd/internal/obj",
"internal/obj", "cmd/internal/obj/arm",
"internal/obj/arm", "cmd/internal/obj/arm64",
"internal/obj/arm64", "cmd/internal/obj/mips",
"internal/obj/mips", "cmd/internal/obj/ppc64",
"internal/obj/ppc64", "cmd/internal/obj/s390x",
"internal/obj/s390x", "cmd/internal/obj/x86",
"internal/obj/x86", "cmd/internal/sys",
"internal/sys", "cmd/link",
"link", "cmd/link/internal/amd64",
"link/internal/amd64", "cmd/link/internal/arm",
"link/internal/arm", "cmd/link/internal/arm64",
"link/internal/arm64", "cmd/link/internal/ld",
"link/internal/pe", "cmd/link/internal/mips64",
"link/internal/ld", "cmd/link/internal/pe",
"link/internal/mips64", "cmd/link/internal/ppc64",
"link/internal/ppc64", "cmd/link/internal/s390x",
"link/internal/s390x", "cmd/link/internal/x86",
"link/internal/x86", "math/big",
}
// File suffixes that use build tags introduced since Go 1.4.
// These must not be copied into the bootstrap build directory.
var ignoreSuffixes = []string{
"_arm64.s",
"_arm64.go",
} }
func bootstrapBuildTools() { func bootstrapBuildTools() {
...@@ -84,10 +95,16 @@ func bootstrapBuildTools() { ...@@ -84,10 +95,16 @@ func bootstrapBuildTools() {
// Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths. // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
for _, dir := range bootstrapDirs { for _, dir := range bootstrapDirs {
src := pathf("%s/src/cmd/%s", goroot, dir) src := pathf("%s/src/%s", goroot, dir)
dst := pathf("%s/%s", base, dir) dst := pathf("%s/%s", base, dir)
xmkdirall(dst) xmkdirall(dst)
Dir:
for _, name := range xreaddirfiles(src) { for _, name := range xreaddirfiles(src) {
for _, suf := range ignoreSuffixes {
if strings.HasSuffix(name, suf) {
continue Dir
}
}
srcFile := pathf("%s/%s", src, name) srcFile := pathf("%s/%s", src, name)
text := readfile(srcFile) text := readfile(srcFile)
text = bootstrapFixImports(text, srcFile) text = bootstrapFixImports(text, srcFile)
...@@ -122,10 +139,14 @@ func bootstrapBuildTools() { ...@@ -122,10 +139,14 @@ func bootstrapBuildTools() {
// Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to // Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to
// workaround bugs in Go 1.4's compiler. See discussion thread: // workaround bugs in Go 1.4's compiler. See discussion thread:
// https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ // https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ
run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/...") run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/cmd/...")
// Copy binaries into tool binary directory. // Copy binaries into tool binary directory.
for _, name := range bootstrapDirs { for _, name := range bootstrapDirs {
if !strings.HasPrefix(name, "cmd/") {
continue
}
name = name[len("cmd/"):]
if !strings.Contains(name, "/") { if !strings.Contains(name, "/") {
copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
} }
...@@ -148,7 +169,14 @@ func bootstrapFixImports(text, srcFile string) string { ...@@ -148,7 +169,14 @@ func bootstrapFixImports(text, srcFile string) string {
} }
if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) || if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) { inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
lines[i] = strings.Replace(line, `"cmd/`, `"bootstrap/`, -1) line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
for _, dir := range bootstrapDirs {
if strings.HasPrefix(dir, "cmd/") {
continue
}
line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
}
lines[i] = line
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment