mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/dist: copy needed packages from standard library during bootstrap
This allows use of newer math/big (and later debug/pe) without maintaining a vendored copy somewhere in cmd. Use for math/big, deleting cmd/compile/internal/big. Change-Id: I2bffa7a9ef115015be29fafdb02acc3e7a665d11 Reviewed-on: https://go-review.googlesource.com/31010 Reviewed-by: Minux Ma <minux@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
f444b48fe4
commit
15040c11b9
46 changed files with 80 additions and 15478 deletions
|
|
@ -506,9 +506,7 @@ func formatReplace(in string, f func(i int, s string) string) string {
|
|||
|
||||
// blacklistedPackages is the set of packages which can
|
||||
// be ignored.
|
||||
var blacklistedPackages = map[string]bool{
|
||||
"cmd/compile/internal/big": true,
|
||||
}
|
||||
var blacklistedPackages = map[string]bool{}
|
||||
|
||||
// blacklistedFunctions is the set of functions which may have
|
||||
// format-like arguments but which don't do any formatting and
|
||||
|
|
@ -537,7 +535,7 @@ func init() {
|
|||
// To print out a new table, run: go test -run Formats -v.
|
||||
var knownFormats = map[string]string{
|
||||
"*bytes.Buffer %s": "",
|
||||
"*cmd/compile/internal/big.Int %#x": "",
|
||||
"*math/big.Int %#x": "",
|
||||
"*cmd/compile/internal/gc.Bits %v": "",
|
||||
"*cmd/compile/internal/gc.Field %p": "",
|
||||
"*cmd/compile/internal/gc.Field %v": "",
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
// generated by stringer -type=Accuracy; DO NOT EDIT
|
||||
|
||||
package big
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _Accuracy_name = "BelowExactAbove"
|
||||
|
||||
var _Accuracy_index = [...]uint8{0, 5, 10, 15}
|
||||
|
||||
func (i Accuracy) String() string {
|
||||
i -= -1
|
||||
if i < 0 || i+1 >= Accuracy(len(_Accuracy_index)) {
|
||||
return fmt.Sprintf("Accuracy(%d)", i+-1)
|
||||
}
|
||||
return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]]
|
||||
}
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file provides Go implementations of elementary multi-precision
|
||||
// arithmetic operations on word vectors. Needed for platforms without
|
||||
// assembly implementations of these routines.
|
||||
|
||||
package big
|
||||
|
||||
// A Word represents a single digit of a multi-precision unsigned integer.
|
||||
type Word uintptr
|
||||
|
||||
const (
|
||||
// Compute the size _S of a Word in bytes.
|
||||
_m = ^Word(0)
|
||||
_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
|
||||
_S = 1 << _logS
|
||||
|
||||
_W = _S << 3 // word size in bits
|
||||
_B = 1 << _W // digit base
|
||||
_M = _B - 1 // digit mask
|
||||
|
||||
_W2 = _W / 2 // half word size in bits
|
||||
_B2 = 1 << _W2 // half digit base
|
||||
_M2 = _B2 - 1 // half digit mask
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Elementary operations on words
|
||||
//
|
||||
// These operations are used by the vector operations below.
|
||||
|
||||
// z1<<_W + z0 = x+y+c, with c == 0 or 1
|
||||
func addWW_g(x, y, c Word) (z1, z0 Word) {
|
||||
yc := y + c
|
||||
z0 = x + yc
|
||||
if z0 < x || yc < y {
|
||||
z1 = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// z1<<_W + z0 = x-y-c, with c == 0 or 1
|
||||
func subWW_g(x, y, c Word) (z1, z0 Word) {
|
||||
yc := y + c
|
||||
z0 = x - yc
|
||||
if z0 > x || yc < y {
|
||||
z1 = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// z1<<_W + z0 = x*y
|
||||
// Adapted from Warren, Hacker's Delight, p. 132.
|
||||
func mulWW_g(x, y Word) (z1, z0 Word) {
|
||||
x0 := x & _M2
|
||||
x1 := x >> _W2
|
||||
y0 := y & _M2
|
||||
y1 := y >> _W2
|
||||
w0 := x0 * y0
|
||||
t := x1*y0 + w0>>_W2
|
||||
w1 := t & _M2
|
||||
w2 := t >> _W2
|
||||
w1 += x0 * y1
|
||||
z1 = x1*y1 + w2 + w1>>_W2
|
||||
z0 = x * y
|
||||
return
|
||||
}
|
||||
|
||||
// z1<<_W + z0 = x*y + c
|
||||
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
|
||||
z1, zz0 := mulWW_g(x, y)
|
||||
if z0 = zz0 + c; z0 < zz0 {
|
||||
z1++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Length of x in bits.
|
||||
func bitLen_g(x Word) (n int) {
|
||||
for ; x >= 0x8000; x >>= 16 {
|
||||
n += 16
|
||||
}
|
||||
if x >= 0x80 {
|
||||
x >>= 8
|
||||
n += 8
|
||||
}
|
||||
if x >= 0x8 {
|
||||
x >>= 4
|
||||
n += 4
|
||||
}
|
||||
if x >= 0x2 {
|
||||
x >>= 2
|
||||
n += 2
|
||||
}
|
||||
if x >= 0x1 {
|
||||
n++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// log2 computes the integer binary logarithm of x.
|
||||
// The result is the integer n for which 2^n <= x < 2^(n+1).
|
||||
// If x == 0, the result is -1.
|
||||
func log2(x Word) int {
|
||||
return bitLen(x) - 1
|
||||
}
|
||||
|
||||
// nlz returns the number of leading zeros in x.
|
||||
func nlz(x Word) uint {
|
||||
return uint(_W - bitLen(x))
|
||||
}
|
||||
|
||||
// nlz64 returns the number of leading zeros in x.
|
||||
func nlz64(x uint64) uint {
|
||||
switch _W {
|
||||
case 32:
|
||||
w := x >> 32
|
||||
if w == 0 {
|
||||
return 32 + nlz(Word(x))
|
||||
}
|
||||
return nlz(Word(w))
|
||||
case 64:
|
||||
return nlz(Word(x))
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// q = (u1<<_W + u0 - r)/y
|
||||
// Adapted from Warren, Hacker's Delight, p. 152.
|
||||
func divWW_g(u1, u0, v Word) (q, r Word) {
|
||||
if u1 >= v {
|
||||
return 1<<_W - 1, 1<<_W - 1
|
||||
}
|
||||
|
||||
s := nlz(v)
|
||||
v <<= s
|
||||
|
||||
vn1 := v >> _W2
|
||||
vn0 := v & _M2
|
||||
un32 := u1<<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
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
func mulWW(x, y Word) (z1, z0 Word) {
|
||||
return mulWW_g(x, y)
|
||||
}
|
||||
|
||||
func divWW(x1, x0, y Word) (q, r Word) {
|
||||
return divWW_g(x1, x0, y)
|
||||
}
|
||||
|
||||
func addVV(z, x, y []Word) (c Word) {
|
||||
return addVV_g(z, x, y)
|
||||
}
|
||||
|
||||
func subVV(z, x, y []Word) (c Word) {
|
||||
return subVV_g(z, x, y)
|
||||
}
|
||||
|
||||
func addVW(z, x []Word, y Word) (c Word) {
|
||||
return addVW_g(z, x, y)
|
||||
}
|
||||
|
||||
func subVW(z, x []Word, y Word) (c Word) {
|
||||
return subVW_g(z, x, y)
|
||||
}
|
||||
|
||||
func shlVU(z, x []Word, s uint) (c Word) {
|
||||
return shlVU_g(z, x, s)
|
||||
}
|
||||
|
||||
func shrVU(z, x []Word, s uint) (c Word) {
|
||||
return shrVU_g(z, x, s)
|
||||
}
|
||||
|
||||
func mulAddVWW(z, x []Word, y, r Word) (c Word) {
|
||||
return mulAddVWW_g(z, x, y, r)
|
||||
}
|
||||
|
||||
func addMulVVW(z, x []Word, y Word) (c Word) {
|
||||
return addMulVVW_g(z, x, y)
|
||||
}
|
||||
|
||||
func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
|
||||
return divWVW_g(z, xn, x, y)
|
||||
}
|
||||
|
||||
func bitLen(x Word) (n int) {
|
||||
return bitLen_g(x)
|
||||
}
|
||||
|
|
@ -1,413 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type funWW func(x, y, c Word) (z1, z0 Word)
|
||||
type argWW struct {
|
||||
x, y, c, z1, z0 Word
|
||||
}
|
||||
|
||||
var sumWW = []argWW{
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 1, 0, 0, 1},
|
||||
{0, 0, 1, 0, 1},
|
||||
{0, 1, 1, 0, 2},
|
||||
{12345, 67890, 0, 0, 80235},
|
||||
{12345, 67890, 1, 0, 80236},
|
||||
{_M, 1, 0, 1, 0},
|
||||
{_M, 0, 1, 1, 0},
|
||||
{_M, 1, 1, 1, 1},
|
||||
{_M, _M, 0, 1, _M - 1},
|
||||
{_M, _M, 1, 1, _M},
|
||||
}
|
||||
|
||||
func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
|
||||
z1, z0 := f(a.x, a.y, a.c)
|
||||
if z1 != a.z1 || z0 != a.z0 {
|
||||
t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunWW(t *testing.T) {
|
||||
for _, a := range sumWW {
|
||||
arg := a
|
||||
testFunWW(t, "addWW_g", addWW_g, arg)
|
||||
|
||||
arg = argWW{a.y, a.x, a.c, a.z1, a.z0}
|
||||
testFunWW(t, "addWW_g symmetric", addWW_g, arg)
|
||||
|
||||
arg = argWW{a.z0, a.x, a.c, a.z1, a.y}
|
||||
testFunWW(t, "subWW_g", subWW_g, arg)
|
||||
|
||||
arg = argWW{a.z0, a.y, a.c, a.z1, a.x}
|
||||
testFunWW(t, "subWW_g symmetric", subWW_g, arg)
|
||||
}
|
||||
}
|
||||
|
||||
type funVV func(z, x, y []Word) (c Word)
|
||||
type argVV struct {
|
||||
z, x, y nat
|
||||
c Word
|
||||
}
|
||||
|
||||
var sumVV = []argVV{
|
||||
{},
|
||||
{nat{0}, nat{0}, nat{0}, 0},
|
||||
{nat{1}, nat{1}, nat{0}, 0},
|
||||
{nat{0}, nat{_M}, nat{1}, 1},
|
||||
{nat{80235}, nat{12345}, nat{67890}, 0},
|
||||
{nat{_M - 1}, nat{_M}, nat{_M}, 1},
|
||||
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1},
|
||||
{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0},
|
||||
{nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1},
|
||||
}
|
||||
|
||||
func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
|
||||
z := make(nat, len(a.z))
|
||||
c := f(z, a.x, a.y)
|
||||
for i, zi := range z {
|
||||
if zi != a.z[i] {
|
||||
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if c != a.c {
|
||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunVV(t *testing.T) {
|
||||
for _, a := range sumVV {
|
||||
arg := a
|
||||
testFunVV(t, "addVV_g", addVV_g, arg)
|
||||
testFunVV(t, "addVV", addVV, arg)
|
||||
|
||||
arg = argVV{a.z, a.y, a.x, a.c}
|
||||
testFunVV(t, "addVV_g symmetric", addVV_g, arg)
|
||||
testFunVV(t, "addVV symmetric", addVV, arg)
|
||||
|
||||
arg = argVV{a.x, a.z, a.y, a.c}
|
||||
testFunVV(t, "subVV_g", subVV_g, arg)
|
||||
testFunVV(t, "subVV", subVV, arg)
|
||||
|
||||
arg = argVV{a.y, a.z, a.x, a.c}
|
||||
testFunVV(t, "subVV_g symmetric", subVV_g, arg)
|
||||
testFunVV(t, "subVV symmetric", subVV, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// Always the same seed for reproducible results.
|
||||
var rnd = rand.New(rand.NewSource(0))
|
||||
|
||||
func rndW() Word {
|
||||
return Word(rnd.Int63()<<1 | rnd.Int63n(2))
|
||||
}
|
||||
|
||||
func rndV(n int) []Word {
|
||||
v := make([]Word, n)
|
||||
for i := range v {
|
||||
v[i] = rndW()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
var benchSizes = []int{1, 2, 3, 4, 5, 1e1, 1e2, 1e3, 1e4, 1e5}
|
||||
|
||||
func BenchmarkAddVV(b *testing.B) {
|
||||
for _, n := range benchSizes {
|
||||
x := rndV(n)
|
||||
y := rndV(n)
|
||||
z := make([]Word, n)
|
||||
b.Run(fmt.Sprint(n), func(b *testing.B) {
|
||||
b.SetBytes(int64(n * _W))
|
||||
for i := 0; i < b.N; i++ {
|
||||
addVV(z, x, y)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type funVW func(z, x []Word, y Word) (c Word)
|
||||
type argVW struct {
|
||||
z, x nat
|
||||
y Word
|
||||
c Word
|
||||
}
|
||||
|
||||
var sumVW = []argVW{
|
||||
{},
|
||||
{nil, nil, 2, 2},
|
||||
{nat{0}, nat{0}, 0, 0},
|
||||
{nat{1}, nat{0}, 1, 0},
|
||||
{nat{1}, nat{1}, 0, 0},
|
||||
{nat{0}, nat{_M}, 1, 1},
|
||||
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
|
||||
{nat{585}, nat{314}, 271, 0},
|
||||
}
|
||||
|
||||
var lshVW = []argVW{
|
||||
{},
|
||||
{nat{0}, nat{0}, 0, 0},
|
||||
{nat{0}, nat{0}, 1, 0},
|
||||
{nat{0}, nat{0}, 20, 0},
|
||||
|
||||
{nat{_M}, nat{_M}, 0, 0},
|
||||
{nat{_M << 1 & _M}, nat{_M}, 1, 1},
|
||||
{nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)},
|
||||
|
||||
{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
|
||||
{nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1},
|
||||
{nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)},
|
||||
}
|
||||
|
||||
var rshVW = []argVW{
|
||||
{},
|
||||
{nat{0}, nat{0}, 0, 0},
|
||||
{nat{0}, nat{0}, 1, 0},
|
||||
{nat{0}, nat{0}, 20, 0},
|
||||
|
||||
{nat{_M}, nat{_M}, 0, 0},
|
||||
{nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M},
|
||||
{nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M},
|
||||
|
||||
{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
|
||||
{nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M},
|
||||
{nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M},
|
||||
}
|
||||
|
||||
func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
|
||||
z := make(nat, len(a.z))
|
||||
c := f(z, a.x, a.y)
|
||||
for i, zi := range z {
|
||||
if zi != a.z[i] {
|
||||
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if c != a.c {
|
||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||
}
|
||||
}
|
||||
|
||||
func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW {
|
||||
return func(z, x []Word, s Word) (c Word) {
|
||||
return f(z, x, uint(s))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunVW(t *testing.T) {
|
||||
for _, a := range sumVW {
|
||||
arg := a
|
||||
testFunVW(t, "addVW_g", addVW_g, arg)
|
||||
testFunVW(t, "addVW", addVW, arg)
|
||||
|
||||
arg = argVW{a.x, a.z, a.y, a.c}
|
||||
testFunVW(t, "subVW_g", subVW_g, arg)
|
||||
testFunVW(t, "subVW", subVW, arg)
|
||||
}
|
||||
|
||||
shlVW_g := makeFunVW(shlVU_g)
|
||||
shlVW := makeFunVW(shlVU)
|
||||
for _, a := range lshVW {
|
||||
arg := a
|
||||
testFunVW(t, "shlVU_g", shlVW_g, arg)
|
||||
testFunVW(t, "shlVU", shlVW, arg)
|
||||
}
|
||||
|
||||
shrVW_g := makeFunVW(shrVU_g)
|
||||
shrVW := makeFunVW(shrVU)
|
||||
for _, a := range rshVW {
|
||||
arg := a
|
||||
testFunVW(t, "shrVU_g", shrVW_g, arg)
|
||||
testFunVW(t, "shrVU", shrVW, arg)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAddVW(b *testing.B) {
|
||||
for _, n := range benchSizes {
|
||||
x := rndV(n)
|
||||
y := rndW()
|
||||
z := make([]Word, n)
|
||||
b.Run(fmt.Sprint(n), func(b *testing.B) {
|
||||
b.SetBytes(int64(n * _S))
|
||||
for i := 0; i < b.N; i++ {
|
||||
addVW(z, x, y)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type funVWW func(z, x []Word, y, r Word) (c Word)
|
||||
type argVWW struct {
|
||||
z, x nat
|
||||
y, r Word
|
||||
c Word
|
||||
}
|
||||
|
||||
var prodVWW = []argVWW{
|
||||
{},
|
||||
{nat{0}, nat{0}, 0, 0, 0},
|
||||
{nat{991}, nat{0}, 0, 991, 0},
|
||||
{nat{0}, nat{_M}, 0, 0, 0},
|
||||
{nat{991}, nat{_M}, 0, 991, 0},
|
||||
{nat{0}, nat{0}, _M, 0, 0},
|
||||
{nat{991}, nat{0}, _M, 991, 0},
|
||||
{nat{1}, nat{1}, 1, 0, 0},
|
||||
{nat{992}, nat{1}, 1, 991, 0},
|
||||
{nat{22793}, nat{991}, 23, 0, 0},
|
||||
{nat{22800}, nat{991}, 23, 7, 0},
|
||||
{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0},
|
||||
{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0},
|
||||
{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
|
||||
{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
|
||||
{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0},
|
||||
{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0},
|
||||
{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)},
|
||||
{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)},
|
||||
{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)},
|
||||
{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
|
||||
{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)},
|
||||
{nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
|
||||
}
|
||||
|
||||
func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
|
||||
z := make(nat, len(a.z))
|
||||
c := f(z, a.x, a.y, a.r)
|
||||
for i, zi := range z {
|
||||
if zi != a.z[i] {
|
||||
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if c != a.c {
|
||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gri) mulAddVWW and divWVW are symmetric operations but
|
||||
// their signature is not symmetric. Try to unify.
|
||||
|
||||
type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word)
|
||||
type argWVW struct {
|
||||
z nat
|
||||
xn Word
|
||||
x nat
|
||||
y Word
|
||||
r Word
|
||||
}
|
||||
|
||||
func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
|
||||
z := make(nat, len(a.z))
|
||||
r := f(z, a.xn, a.x, a.y)
|
||||
for i, zi := range z {
|
||||
if zi != a.z[i] {
|
||||
t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if r != a.r {
|
||||
t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunVWW(t *testing.T) {
|
||||
for _, a := range prodVWW {
|
||||
arg := a
|
||||
testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg)
|
||||
testFunVWW(t, "mulAddVWW", mulAddVWW, arg)
|
||||
|
||||
if a.y != 0 && a.r < a.y {
|
||||
arg := argWVW{a.x, a.c, a.z, a.y, a.r}
|
||||
testFunWVW(t, "divWVW_g", divWVW_g, arg)
|
||||
testFunWVW(t, "divWVW", divWVW, arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mulWWTests = []struct {
|
||||
x, y Word
|
||||
q, r Word
|
||||
}{
|
||||
{_M, _M, _M - 1, 1},
|
||||
// 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
|
||||
}
|
||||
|
||||
func TestMulWW(t *testing.T) {
|
||||
for i, test := range mulWWTests {
|
||||
q, r := mulWW_g(test.x, test.y)
|
||||
if q != test.q || r != test.r {
|
||||
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mulAddWWWTests = []struct {
|
||||
x, y, c Word
|
||||
q, r Word
|
||||
}{
|
||||
// TODO(agl): These will only work on 64-bit platforms.
|
||||
// {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
|
||||
// {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
|
||||
{_M, _M, 0, _M - 1, 1},
|
||||
{_M, _M, _M, _M, 0},
|
||||
}
|
||||
|
||||
func TestMulAddWWW(t *testing.T) {
|
||||
for i, test := range mulAddWWWTests {
|
||||
q, r := mulAddWWW_g(test.x, test.y, test.c)
|
||||
if q != test.q || r != test.r {
|
||||
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAddMulVVW(b *testing.B) {
|
||||
for _, n := range benchSizes {
|
||||
x := rndV(n)
|
||||
y := rndW()
|
||||
z := make([]Word, n)
|
||||
b.Run(fmt.Sprint(n), func(b *testing.B) {
|
||||
b.SetBytes(int64(n * _W))
|
||||
for i := 0; i < b.N; i++ {
|
||||
addMulVVW(z, x, y)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
|
||||
for i := 0; i <= _W; i++ {
|
||||
x := Word(1) << uint(i-1) // i == 0 => x == 0
|
||||
n := f(x)
|
||||
if n != i {
|
||||
t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWordBitLen(t *testing.T) {
|
||||
testWordBitLen(t, "bitLen", bitLen)
|
||||
testWordBitLen(t, "bitLen_g", bitLen_g)
|
||||
}
|
||||
|
||||
// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
|
||||
func BenchmarkBitLen(b *testing.B) {
|
||||
// Individual bitLen tests. Numbers chosen to examine both sides
|
||||
// of powers-of-two boundaries.
|
||||
for _, nbits := range []uint{0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 31} {
|
||||
testword := Word((uint64(1) << nbits) - 1)
|
||||
b.Run(fmt.Sprint(nbits), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
bitLen(testword)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements the Bits type used for testing Float operations
|
||||
// via an independent (albeit slower) representations for floating-point
|
||||
// numbers.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A Bits value b represents a finite floating-point number x of the form
|
||||
//
|
||||
// x = 2**b[0] + 2**b[1] + ... 2**b[len(b)-1]
|
||||
//
|
||||
// The order of slice elements is not significant. Negative elements may be
|
||||
// used to form fractions. A Bits value is normalized if each b[i] occurs at
|
||||
// most once. For instance Bits{0, 0, 1} is not normalized but represents the
|
||||
// same floating-point number as Bits{2}, which is normalized. The zero (nil)
|
||||
// value of Bits is a ready to use Bits value and represents the value 0.
|
||||
type Bits []int
|
||||
|
||||
func (x Bits) add(y Bits) Bits {
|
||||
return append(x, y...)
|
||||
}
|
||||
|
||||
func (x Bits) mul(y Bits) Bits {
|
||||
var p Bits
|
||||
for _, x := range x {
|
||||
for _, y := range y {
|
||||
p = append(p, x+y)
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func TestMulBits(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x, y, want Bits
|
||||
}{
|
||||
{nil, nil, nil},
|
||||
{Bits{}, Bits{}, nil},
|
||||
{Bits{0}, Bits{0}, Bits{0}},
|
||||
{Bits{0}, Bits{1}, Bits{1}},
|
||||
{Bits{1}, Bits{1, 2, 3}, Bits{2, 3, 4}},
|
||||
{Bits{-1}, Bits{1}, Bits{0}},
|
||||
{Bits{-10, -1, 0, 1, 10}, Bits{1, 2, 3}, Bits{-9, -8, -7, 0, 1, 2, 1, 2, 3, 2, 3, 4, 11, 12, 13}},
|
||||
} {
|
||||
got := fmt.Sprintf("%v", test.x.mul(test.y))
|
||||
want := fmt.Sprintf("%v", test.want)
|
||||
if got != want {
|
||||
t.Errorf("%v * %v = %s; want %s", test.x, test.y, got, want)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// norm returns the normalized bits for x: It removes multiple equal entries
|
||||
// by treating them as an addition (e.g., Bits{5, 5} => Bits{6}), and it sorts
|
||||
// the result list for reproducible results.
|
||||
func (x Bits) norm() Bits {
|
||||
m := make(map[int]bool)
|
||||
for _, b := range x {
|
||||
for m[b] {
|
||||
m[b] = false
|
||||
b++
|
||||
}
|
||||
m[b] = true
|
||||
}
|
||||
var z Bits
|
||||
for b, set := range m {
|
||||
if set {
|
||||
z = append(z, b)
|
||||
}
|
||||
}
|
||||
sort.Ints([]int(z))
|
||||
return z
|
||||
}
|
||||
|
||||
func TestNormBits(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x, want Bits
|
||||
}{
|
||||
{nil, nil},
|
||||
{Bits{}, Bits{}},
|
||||
{Bits{0}, Bits{0}},
|
||||
{Bits{0, 0}, Bits{1}},
|
||||
{Bits{3, 1, 1}, Bits{2, 3}},
|
||||
{Bits{10, 9, 8, 7, 6, 6}, Bits{11}},
|
||||
} {
|
||||
got := fmt.Sprintf("%v", test.x.norm())
|
||||
want := fmt.Sprintf("%v", test.want)
|
||||
if got != want {
|
||||
t.Errorf("normBits(%v) = %s; want %s", test.x, got, want)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// round returns the Float value corresponding to x after rounding x
|
||||
// to prec bits according to mode.
|
||||
func (x Bits) round(prec uint, mode RoundingMode) *Float {
|
||||
x = x.norm()
|
||||
|
||||
// determine range
|
||||
var min, max int
|
||||
for i, b := range x {
|
||||
if i == 0 || b < min {
|
||||
min = b
|
||||
}
|
||||
if i == 0 || b > max {
|
||||
max = b
|
||||
}
|
||||
}
|
||||
prec0 := uint(max + 1 - min)
|
||||
if prec >= prec0 {
|
||||
return x.Float()
|
||||
}
|
||||
// prec < prec0
|
||||
|
||||
// determine bit 0, rounding, and sticky bit, and result bits z
|
||||
var bit0, rbit, sbit uint
|
||||
var z Bits
|
||||
r := max - int(prec)
|
||||
for _, b := range x {
|
||||
switch {
|
||||
case b == r:
|
||||
rbit = 1
|
||||
case b < r:
|
||||
sbit = 1
|
||||
default:
|
||||
// b > r
|
||||
if b == r+1 {
|
||||
bit0 = 1
|
||||
}
|
||||
z = append(z, b)
|
||||
}
|
||||
}
|
||||
|
||||
// round
|
||||
f := z.Float() // rounded to zero
|
||||
if mode == ToNearestAway {
|
||||
panic("not yet implemented")
|
||||
}
|
||||
if mode == ToNearestEven && rbit == 1 && (sbit == 1 || sbit == 0 && bit0 != 0) || mode == AwayFromZero {
|
||||
// round away from zero
|
||||
f.SetMode(ToZero).SetPrec(prec)
|
||||
f.Add(f, Bits{int(r) + 1}.Float())
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Float returns the *Float z of the smallest possible precision such that
|
||||
// z = sum(2**bits[i]), with i = range bits. If multiple bits[i] are equal,
|
||||
// they are added: Bits{0, 1, 0}.Float() == 2**0 + 2**1 + 2**0 = 4.
|
||||
func (bits Bits) Float() *Float {
|
||||
// handle 0
|
||||
if len(bits) == 0 {
|
||||
return new(Float)
|
||||
}
|
||||
// len(bits) > 0
|
||||
|
||||
// determine lsb exponent
|
||||
var min int
|
||||
for i, b := range bits {
|
||||
if i == 0 || b < min {
|
||||
min = b
|
||||
}
|
||||
}
|
||||
|
||||
// create bit pattern
|
||||
x := NewInt(0)
|
||||
for _, b := range bits {
|
||||
badj := b - min
|
||||
// propagate carry if necessary
|
||||
for x.Bit(badj) != 0 {
|
||||
x.SetBit(x, badj, 0)
|
||||
badj++
|
||||
}
|
||||
x.SetBit(x, badj, 1)
|
||||
}
|
||||
|
||||
// create corresponding float
|
||||
z := new(Float).SetInt(x) // normalized
|
||||
if e := int64(z.exp) + int64(min); MinExp <= e && e <= MaxExp {
|
||||
z.exp = int32(e)
|
||||
} else {
|
||||
// this should never happen for our test cases
|
||||
panic("exponent out of range")
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
func TestFromBits(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
bits Bits
|
||||
want string
|
||||
}{
|
||||
// all different bit numbers
|
||||
{nil, "0"},
|
||||
{Bits{0}, "0x.8p+1"},
|
||||
{Bits{1}, "0x.8p+2"},
|
||||
{Bits{-1}, "0x.8p+0"},
|
||||
{Bits{63}, "0x.8p+64"},
|
||||
{Bits{33, -30}, "0x.8000000000000001p+34"},
|
||||
{Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p+256"},
|
||||
|
||||
// multiple equal bit numbers
|
||||
{Bits{0, 0}, "0x.8p+2"},
|
||||
{Bits{0, 0, 0, 0}, "0x.8p+3"},
|
||||
{Bits{0, 1, 0}, "0x.8p+3"},
|
||||
{append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p+5" /* 17 */},
|
||||
} {
|
||||
f := test.bits.Float()
|
||||
if got := f.Text('p', 0); got != test.want {
|
||||
t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file prints execution times for the Mul benchmark
|
||||
// given different Karatsuba thresholds. The result may be
|
||||
// used to manually fine-tune the threshold constant. The
|
||||
// results are somewhat fragile; use repeated runs to get
|
||||
// a clear picture.
|
||||
|
||||
// Usage: go test -run=TestCalibrate -calibrate
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var calibrate = flag.Bool("calibrate", false, "run calibration test")
|
||||
|
||||
func karatsubaLoad(b *testing.B) {
|
||||
BenchmarkMul(b)
|
||||
}
|
||||
|
||||
// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
|
||||
// given Karatsuba threshold th.
|
||||
func measureKaratsuba(th int) time.Duration {
|
||||
th, karatsubaThreshold = karatsubaThreshold, th
|
||||
res := testing.Benchmark(karatsubaLoad)
|
||||
karatsubaThreshold = th
|
||||
return time.Duration(res.NsPerOp())
|
||||
}
|
||||
|
||||
func computeThresholds() {
|
||||
fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
|
||||
fmt.Printf("(run repeatedly for good results)\n")
|
||||
|
||||
// determine Tk, the work load execution time using basic multiplication
|
||||
Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
|
||||
fmt.Printf("Tb = %10s\n", Tb)
|
||||
|
||||
// thresholds
|
||||
th := 4
|
||||
th1 := -1
|
||||
th2 := -1
|
||||
|
||||
var deltaOld time.Duration
|
||||
for count := -1; count != 0 && th < 128; count-- {
|
||||
// determine Tk, the work load execution time using Karatsuba multiplication
|
||||
Tk := measureKaratsuba(th)
|
||||
|
||||
// improvement over Tb
|
||||
delta := (Tb - Tk) * 100 / Tb
|
||||
|
||||
fmt.Printf("th = %3d Tk = %10s %4d%%", th, Tk, delta)
|
||||
|
||||
// determine break-even point
|
||||
if Tk < Tb && th1 < 0 {
|
||||
th1 = th
|
||||
fmt.Print(" break-even point")
|
||||
}
|
||||
|
||||
// determine diminishing return
|
||||
if 0 < delta && delta < deltaOld && th2 < 0 {
|
||||
th2 = th
|
||||
fmt.Print(" diminishing return")
|
||||
}
|
||||
deltaOld = delta
|
||||
|
||||
fmt.Println()
|
||||
|
||||
// trigger counter
|
||||
if th1 >= 0 && th2 >= 0 && count < 0 {
|
||||
count = 10 // this many extra measurements after we got both thresholds
|
||||
}
|
||||
|
||||
th++
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalibrate(t *testing.T) {
|
||||
if *calibrate {
|
||||
computeThresholds()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements multi-precision decimal numbers.
|
||||
// The implementation is for float to decimal conversion only;
|
||||
// not general purpose use.
|
||||
// The only operations are precise conversion from binary to
|
||||
// decimal and rounding.
|
||||
//
|
||||
// The key observation and some code (shr) is borrowed from
|
||||
// strconv/decimal.go: conversion of binary fractional values can be done
|
||||
// precisely in multi-precision decimal because 2 divides 10 (required for
|
||||
// >> of mantissa); but conversion of decimal floating-point values cannot
|
||||
// be done precisely in binary representation.
|
||||
//
|
||||
// In contrast to strconv/decimal.go, only right shift is implemented in
|
||||
// decimal format - left shift can be done precisely in binary format.
|
||||
|
||||
package big
|
||||
|
||||
// A decimal represents an unsigned floating-point number in decimal representation.
|
||||
// The value of a non-zero decimal d is d.mant * 10**d.exp with 0.5 <= d.mant < 1,
|
||||
// with the most-significant mantissa digit at index 0. For the zero decimal, the
|
||||
// mantissa length and exponent are 0.
|
||||
// The zero value for decimal represents a ready-to-use 0.0.
|
||||
type decimal struct {
|
||||
mant []byte // mantissa ASCII digits, big-endian
|
||||
exp int // exponent
|
||||
}
|
||||
|
||||
// at returns the i'th mantissa digit, starting with the most significant digit at 0.
|
||||
func (d *decimal) at(i int) byte {
|
||||
if 0 <= i && i < len(d.mant) {
|
||||
return d.mant[i]
|
||||
}
|
||||
return '0'
|
||||
}
|
||||
|
||||
// Maximum shift amount that can be done in one pass without overflow.
|
||||
// A Word has _W bits and (1<<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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDecimalString(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x decimal
|
||||
want string
|
||||
}{
|
||||
{want: "0"},
|
||||
{decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
|
||||
{decimal{[]byte("12345"), 0}, "0.12345"},
|
||||
{decimal{[]byte("12345"), -3}, "0.00012345"},
|
||||
{decimal{[]byte("12345"), +3}, "123.45"},
|
||||
{decimal{[]byte("12345"), +10}, "1234500000"},
|
||||
} {
|
||||
if got := test.x.String(); got != test.want {
|
||||
t.Errorf("%v == %s; want %s", test.x, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecimalInit(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x Word
|
||||
shift int
|
||||
want string
|
||||
}{
|
||||
{0, 0, "0"},
|
||||
{0, -100, "0"},
|
||||
{0, 100, "0"},
|
||||
{1, 0, "1"},
|
||||
{1, 10, "1024"},
|
||||
{1, 100, "1267650600228229401496703205376"},
|
||||
{1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
|
||||
{12345678, 8, "3160493568"},
|
||||
{12345678, -8, "48225.3046875"},
|
||||
{195312, 9, "99999744"},
|
||||
{1953125, 9, "1000000000"},
|
||||
} {
|
||||
var d decimal
|
||||
d.init(nat{test.x}.norm(), test.shift)
|
||||
if got := d.String(); got != test.want {
|
||||
t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecimalRounding(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x uint64
|
||||
n int
|
||||
down, even, up string
|
||||
}{
|
||||
{0, 0, "0", "0", "0"},
|
||||
{0, 1, "0", "0", "0"},
|
||||
|
||||
{1, 0, "0", "0", "10"},
|
||||
{5, 0, "0", "0", "10"},
|
||||
{9, 0, "0", "10", "10"},
|
||||
|
||||
{15, 1, "10", "20", "20"},
|
||||
{45, 1, "40", "40", "50"},
|
||||
{95, 1, "90", "100", "100"},
|
||||
|
||||
{12344999, 4, "12340000", "12340000", "12350000"},
|
||||
{12345000, 4, "12340000", "12340000", "12350000"},
|
||||
{12345001, 4, "12340000", "12350000", "12350000"},
|
||||
{23454999, 4, "23450000", "23450000", "23460000"},
|
||||
{23455000, 4, "23450000", "23460000", "23460000"},
|
||||
{23455001, 4, "23450000", "23460000", "23460000"},
|
||||
|
||||
{99994999, 4, "99990000", "99990000", "100000000"},
|
||||
{99995000, 4, "99990000", "100000000", "100000000"},
|
||||
{99999999, 4, "99990000", "100000000", "100000000"},
|
||||
|
||||
{12994999, 4, "12990000", "12990000", "13000000"},
|
||||
{12995000, 4, "12990000", "13000000", "13000000"},
|
||||
{12999999, 4, "12990000", "13000000", "13000000"},
|
||||
} {
|
||||
x := nat(nil).setUint64(test.x)
|
||||
|
||||
var d decimal
|
||||
d.init(x, 0)
|
||||
d.roundDown(test.n)
|
||||
if got := d.String(); got != test.down {
|
||||
t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
|
||||
}
|
||||
|
||||
d.init(x, 0)
|
||||
d.round(test.n)
|
||||
if got := d.String(); got != test.even {
|
||||
t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
|
||||
}
|
||||
|
||||
d.init(x, 0)
|
||||
d.roundUp(test.n)
|
||||
if got := d.String(); got != test.up {
|
||||
t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sink string
|
||||
|
||||
func BenchmarkDecimalConversion(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for shift := -100; shift <= +100; shift++ {
|
||||
var d decimal
|
||||
d.init(natOne, shift)
|
||||
sink = d.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package big implements arbitrary-precision arithmetic (big numbers).
|
||||
The following numeric types are supported:
|
||||
|
||||
Int signed integers
|
||||
Rat rational numbers
|
||||
Float floating-point numbers
|
||||
|
||||
The zero value for an Int, Rat, or Float correspond to 0. Thus, new
|
||||
values can be declared in the usual ways and denote 0 without further
|
||||
initialization:
|
||||
|
||||
var x Int // &x is an *Int of value 0
|
||||
var r = &Rat{} // r is a *Rat of value 0
|
||||
y := new(Float) // y is a *Float of value 0
|
||||
|
||||
Alternatively, new values can be allocated and initialized with factory
|
||||
functions of the form:
|
||||
|
||||
func NewT(v V) *T
|
||||
|
||||
For instance, NewInt(x) returns an *Int set to the value of the int64
|
||||
argument x, NewRat(a, b) returns a *Rat set to the fraction a/b where
|
||||
a and b are int64 values, and NewFloat(f) returns a *Float initialized
|
||||
to the float64 argument f. More flexibility is provided with explicit
|
||||
setters, for instance:
|
||||
|
||||
var z1 Int
|
||||
z1.SetUint64(123) // z1 := 123
|
||||
z2 := new(Rat).SetFloat64(1.2) // z2 := 6/5
|
||||
z3 := new(Float).SetInt(z1) // z3 := 123.0
|
||||
|
||||
Setters, numeric operations and predicates are represented as methods of
|
||||
the form:
|
||||
|
||||
func (z *T) SetV(v V) *T // z = v
|
||||
func (z *T) Unary(x *T) *T // z = unary x
|
||||
func (z *T) Binary(x, y *T) *T // z = x binary y
|
||||
func (x *T) Pred() P // p = pred(x)
|
||||
|
||||
with T one of Int, Rat, or Float. For unary and binary operations, the
|
||||
result is the receiver (usually named z in that case; see below); if it
|
||||
is one of the operands x or y it may be safely overwritten (and its memory
|
||||
reused).
|
||||
|
||||
Arithmetic expressions are typically written as a sequence of individual
|
||||
method calls, with each call corresponding to an operation. The receiver
|
||||
denotes the result and the method arguments are the operation's operands.
|
||||
For instance, given three *Int values a, b and c, the invocation
|
||||
|
||||
c.Add(a, b)
|
||||
|
||||
computes the sum a + b and stores the result in c, overwriting whatever
|
||||
value was held in c before. Unless specified otherwise, operations permit
|
||||
aliasing of parameters, so it is perfectly ok to write
|
||||
|
||||
sum.Add(sum, x)
|
||||
|
||||
to accumulate values x in a sum.
|
||||
|
||||
(By always passing in a result value via the receiver, memory use can be
|
||||
much better controlled. Instead of having to allocate new memory for each
|
||||
result, an operation can reuse the space allocated for the result value,
|
||||
and overwrite that value with the new result in the process.)
|
||||
|
||||
Notational convention: Incoming method parameters (including the receiver)
|
||||
are named consistently in the API to clarify their use. Incoming operands
|
||||
are usually named x, y, a, b, and so on, but never z. A parameter specifying
|
||||
the result is named z (typically the receiver).
|
||||
|
||||
For instance, the arguments for (*Int).Add are named x and y, and because
|
||||
the receiver specifies the result destination, it is called z:
|
||||
|
||||
func (z *Int) Add(x, y *Int) *Int
|
||||
|
||||
Methods of this form typically return the incoming receiver as well, to
|
||||
enable simple call chaining.
|
||||
|
||||
Methods which don't require a result value to be passed in (for instance,
|
||||
Int.Sign), simply return the result. In this case, the receiver is typically
|
||||
the first operand, named x:
|
||||
|
||||
func (x *Int) Sign() int
|
||||
|
||||
Various methods support conversions between strings and corresponding
|
||||
numeric values, and vice versa: *Int, *Rat, and *Float values implement
|
||||
the Stringer interface for a (default) string representation of the value,
|
||||
but also provide SetString methods to initialize a value from a string in
|
||||
a variety of supported formats (see the respective SetString documentation).
|
||||
|
||||
Finally, *Int, *Rat, and *Float satisfy the fmt package's Scanner interface
|
||||
for scanning and (except for *Rat) the Formatter interface for formatted
|
||||
printing.
|
||||
*/
|
||||
package big
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big_test
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Use the classic continued fraction for e
|
||||
// e = [1; 0, 1, 1, 2, 1, 1, ... 2n, 1, 1, ...]
|
||||
// i.e., for the nth term, use
|
||||
// 1 if n mod 3 != 1
|
||||
// (n-1)/3 * 2 if n mod 3 == 1
|
||||
func recur(n, lim int64) *big.Rat {
|
||||
term := new(big.Rat)
|
||||
if n%3 != 1 {
|
||||
term.SetInt64(1)
|
||||
} else {
|
||||
term.SetInt64((n - 1) / 3 * 2)
|
||||
}
|
||||
|
||||
if n > lim {
|
||||
return term
|
||||
}
|
||||
|
||||
// Directly initialize frac as the fractional
|
||||
// inverse of the result of recur.
|
||||
frac := new(big.Rat).Inv(recur(n+1, lim))
|
||||
|
||||
return term.Add(term, frac)
|
||||
}
|
||||
|
||||
// This example demonstrates how to use big.Rat to compute the
|
||||
// first 15 terms in the sequence of rational convergents for
|
||||
// the constant e (base of natural logarithm).
|
||||
func Example_eConvergents() {
|
||||
for i := 1; i <= 15; i++ {
|
||||
r := recur(0, int64(i))
|
||||
|
||||
// Print r both as a fraction and as a floating-point number.
|
||||
// Since big.Rat implements fmt.Formatter, we can use %-13s to
|
||||
// get a left-aligned string representation of the fraction.
|
||||
fmt.Printf("%-13s = %s\n", r, r.FloatString(8))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 2/1 = 2.00000000
|
||||
// 3/1 = 3.00000000
|
||||
// 8/3 = 2.66666667
|
||||
// 11/4 = 2.75000000
|
||||
// 19/7 = 2.71428571
|
||||
// 87/32 = 2.71875000
|
||||
// 106/39 = 2.71794872
|
||||
// 193/71 = 2.71830986
|
||||
// 1264/465 = 2.71827957
|
||||
// 1457/536 = 2.71828358
|
||||
// 2721/1001 = 2.71828172
|
||||
// 23225/8544 = 2.71828184
|
||||
// 25946/9545 = 2.71828182
|
||||
// 49171/18089 = 2.71828183
|
||||
// 517656/190435 = 2.71828183
|
||||
}
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big_test
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
)
|
||||
|
||||
func ExampleRat_SetString() {
|
||||
r := new(big.Rat)
|
||||
r.SetString("355/113")
|
||||
fmt.Println(r.FloatString(3))
|
||||
// Output: 3.142
|
||||
}
|
||||
|
||||
func ExampleInt_SetString() {
|
||||
i := new(big.Int)
|
||||
i.SetString("644", 8) // octal
|
||||
fmt.Println(i)
|
||||
// Output: 420
|
||||
}
|
||||
|
||||
func ExampleRat_Scan() {
|
||||
// The Scan function is rarely used directly;
|
||||
// the fmt package recognizes it as an implementation of fmt.Scanner.
|
||||
r := new(big.Rat)
|
||||
_, err := fmt.Sscan("1.5000", r)
|
||||
if err != nil {
|
||||
log.Println("error scanning value:", err)
|
||||
} else {
|
||||
fmt.Println(r)
|
||||
}
|
||||
// Output: 3/2
|
||||
}
|
||||
|
||||
func ExampleInt_Scan() {
|
||||
// The Scan function is rarely used directly;
|
||||
// the fmt package recognizes it as an implementation of fmt.Scanner.
|
||||
i := new(big.Int)
|
||||
_, err := fmt.Sscan("18446744073709551617", i)
|
||||
if err != nil {
|
||||
log.Println("error scanning value:", err)
|
||||
} else {
|
||||
fmt.Println(i)
|
||||
}
|
||||
// Output: 18446744073709551617
|
||||
}
|
||||
|
||||
// This example demonstrates how to use big.Int to compute the smallest
|
||||
// Fibonacci number with 100 decimal digits and to test whether it is prime.
|
||||
func Example_fibonacci() {
|
||||
// Initialize two big ints with the first two numbers in the sequence.
|
||||
a := big.NewInt(0)
|
||||
b := big.NewInt(1)
|
||||
|
||||
// Initialize limit as 10^99, the smallest integer with 100 digits.
|
||||
var limit big.Int
|
||||
limit.Exp(big.NewInt(10), big.NewInt(99), nil)
|
||||
|
||||
// Loop while a is smaller than 1e100.
|
||||
for a.Cmp(&limit) < 0 {
|
||||
// Compute the next Fibonacci number, storing it in a.
|
||||
a.Add(a, b)
|
||||
// Swap a and b so that b is the next number in the sequence.
|
||||
a, b = b, a
|
||||
}
|
||||
fmt.Println(a) // 100-digit Fibonacci number
|
||||
|
||||
// Test a for primality.
|
||||
// (ProbablyPrimes' argument sets the number of Miller-Rabin
|
||||
// rounds to be performed. 20 is a good value.)
|
||||
fmt.Println(a.ProbablyPrime(20))
|
||||
|
||||
// Output:
|
||||
// 1344719667586153181419716641724567886890850696275767987106294472017884974410332069524504824747437757
|
||||
// false
|
||||
}
|
||||
|
||||
// This example shows how to use big.Float to compute the square root of 2 with
|
||||
// a precision of 200 bits, and how to print the result as a decimal number.
|
||||
func Example_sqrt2() {
|
||||
// We'll do computations with 200 bits of precision in the mantissa.
|
||||
const prec = 200
|
||||
|
||||
// Compute the square root of 2 using Newton's Method. We start with
|
||||
// an initial estimate for sqrt(2), and then iterate:
|
||||
// x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) )
|
||||
|
||||
// Since Newton's Method doubles the number of correct digits at each
|
||||
// iteration, we need at least log_2(prec) steps.
|
||||
steps := int(math.Log2(prec))
|
||||
|
||||
// Initialize values we need for the computation.
|
||||
two := new(big.Float).SetPrec(prec).SetInt64(2)
|
||||
half := new(big.Float).SetPrec(prec).SetFloat64(0.5)
|
||||
|
||||
// Use 1 as the initial estimate.
|
||||
x := new(big.Float).SetPrec(prec).SetInt64(1)
|
||||
|
||||
// We use t as a temporary variable. There's no need to set its precision
|
||||
// since big.Float values with unset (== 0) precision automatically assume
|
||||
// the largest precision of the arguments when used as the result (receiver)
|
||||
// of a big.Float operation.
|
||||
t := new(big.Float)
|
||||
|
||||
// Iterate.
|
||||
for i := 0; i <= steps; i++ {
|
||||
t.Quo(two, x) // t = 2.0 / x_n
|
||||
t.Add(x, t) // t = x_n + (2.0 / x_n)
|
||||
x.Mul(half, t) // x_{n+1} = 0.5 * t
|
||||
}
|
||||
|
||||
// We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter
|
||||
fmt.Printf("sqrt(2) = %.50f\n", x)
|
||||
|
||||
// Print the error between 2 and x*x.
|
||||
t.Mul(x, x) // t = x*x
|
||||
fmt.Printf("error = %e\n", t.Sub(two, t))
|
||||
|
||||
// Output:
|
||||
// sqrt(2) = 1.41421356237309504880168872420969807856967187537695
|
||||
// error = 0.000000e+00
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,275 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements string-to-Float conversion functions.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SetString sets z to the value of s and returns z and a boolean indicating
|
||||
// success. s must be a floating-point number of the same format as accepted
|
||||
// by Parse, with base argument 0.
|
||||
func (z *Float) SetString(s string) (*Float, bool) {
|
||||
if f, _, err := z.Parse(s, 0); err == nil {
|
||||
return f, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// scan is like Parse but reads the longest possible prefix representing a valid
|
||||
// floating point number from an io.ByteScanner rather than a string. It serves
|
||||
// as the implementation of Parse. It does not recognize ±Inf and does not expect
|
||||
// EOF at the end.
|
||||
func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
|
||||
prec := z.prec
|
||||
if prec == 0 {
|
||||
prec = 64
|
||||
}
|
||||
|
||||
// A reasonable value in case of an error.
|
||||
z.form = zero
|
||||
|
||||
// sign
|
||||
z.neg, err = scanSign(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// mantissa
|
||||
var fcount int // fractional digit count; valid if <= 0
|
||||
z.mant, b, fcount, err = z.mant.scan(r, base, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// exponent
|
||||
var exp int64
|
||||
var ebase int
|
||||
exp, ebase, err = scanExponent(r, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// special-case 0
|
||||
if len(z.mant) == 0 {
|
||||
z.prec = prec
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
f = z
|
||||
return
|
||||
}
|
||||
// len(z.mant) > 0
|
||||
|
||||
// The mantissa may have a decimal point (fcount <= 0) and there
|
||||
// may be a nonzero exponent exp. The decimal point amounts to a
|
||||
// division by b**(-fcount). An exponent means multiplication by
|
||||
// ebase**exp. Finally, mantissa normalization (shift left) requires
|
||||
// a correcting multiplication by 2**(-shiftcount). Multiplications
|
||||
// are commutative, so we can apply them in any order as long as there
|
||||
// is no loss of precision. We only have powers of 2 and 10, and
|
||||
// we split powers of 10 into the product of the same powers of
|
||||
// 2 and 5. This reduces the size of the multiplication factor
|
||||
// needed for base-10 exponents.
|
||||
|
||||
// normalize mantissa and determine initial exponent contributions
|
||||
exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
|
||||
exp5 := int64(0)
|
||||
|
||||
// determine binary or decimal exponent contribution of decimal point
|
||||
if fcount < 0 {
|
||||
// The mantissa has a "decimal" point ddd.dddd; and
|
||||
// -fcount is the number of digits to the right of '.'.
|
||||
// Adjust relevant exponent accordingly.
|
||||
d := int64(fcount)
|
||||
switch b {
|
||||
case 10:
|
||||
exp5 = d
|
||||
fallthrough // 10**e == 5**e * 2**e
|
||||
case 2:
|
||||
exp2 += d
|
||||
case 16:
|
||||
exp2 += d * 4 // hexadecimal digits are 4 bits each
|
||||
default:
|
||||
panic("unexpected mantissa base")
|
||||
}
|
||||
// fcount consumed - not needed anymore
|
||||
}
|
||||
|
||||
// take actual exponent into account
|
||||
switch ebase {
|
||||
case 10:
|
||||
exp5 += exp
|
||||
fallthrough
|
||||
case 2:
|
||||
exp2 += exp
|
||||
default:
|
||||
panic("unexpected exponent base")
|
||||
}
|
||||
// exp consumed - not needed anymore
|
||||
|
||||
// apply 2**exp2
|
||||
if MinExp <= exp2 && exp2 <= MaxExp {
|
||||
z.prec = prec
|
||||
z.form = finite
|
||||
z.exp = int32(exp2)
|
||||
f = z
|
||||
} else {
|
||||
err = fmt.Errorf("exponent overflow")
|
||||
return
|
||||
}
|
||||
|
||||
if exp5 == 0 {
|
||||
// no decimal exponent contribution
|
||||
z.round(0)
|
||||
return
|
||||
}
|
||||
// exp5 != 0
|
||||
|
||||
// apply 5**exp5
|
||||
p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
|
||||
if exp5 < 0 {
|
||||
z.Quo(z, p.pow5(uint64(-exp5)))
|
||||
} else {
|
||||
z.Mul(z, p.pow5(uint64(exp5)))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// These powers of 5 fit into a uint64.
|
||||
//
|
||||
// for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
|
||||
// fmt.Println(q)
|
||||
// }
|
||||
//
|
||||
var pow5tab = [...]uint64{
|
||||
1,
|
||||
5,
|
||||
25,
|
||||
125,
|
||||
625,
|
||||
3125,
|
||||
15625,
|
||||
78125,
|
||||
390625,
|
||||
1953125,
|
||||
9765625,
|
||||
48828125,
|
||||
244140625,
|
||||
1220703125,
|
||||
6103515625,
|
||||
30517578125,
|
||||
152587890625,
|
||||
762939453125,
|
||||
3814697265625,
|
||||
19073486328125,
|
||||
95367431640625,
|
||||
476837158203125,
|
||||
2384185791015625,
|
||||
11920928955078125,
|
||||
59604644775390625,
|
||||
298023223876953125,
|
||||
1490116119384765625,
|
||||
7450580596923828125,
|
||||
}
|
||||
|
||||
// pow5 sets z to 5**n and returns z.
|
||||
// n must not be negative.
|
||||
func (z *Float) pow5(n uint64) *Float {
|
||||
const m = uint64(len(pow5tab) - 1)
|
||||
if n <= m {
|
||||
return z.SetUint64(pow5tab[n])
|
||||
}
|
||||
// n > m
|
||||
|
||||
z.SetUint64(pow5tab[m])
|
||||
n -= m
|
||||
|
||||
// use more bits for f than for z
|
||||
// TODO(gri) what is the right number?
|
||||
f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
|
||||
|
||||
for n > 0 {
|
||||
if n&1 != 0 {
|
||||
z.Mul(z, f)
|
||||
}
|
||||
f.Mul(f, f)
|
||||
n >>= 1
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// Parse parses s which must contain a text representation of a floating-
|
||||
// point number with a mantissa in the given conversion base (the exponent
|
||||
// is always a decimal number), or a string representing an infinite value.
|
||||
//
|
||||
// It sets z to the (possibly rounded) value of the corresponding floating-
|
||||
// point value, and returns z, the actual base b, and an error err, if any.
|
||||
// If z's precision is 0, it is changed to 64 before rounding takes effect.
|
||||
// The number must be of the form:
|
||||
//
|
||||
// number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
|
||||
// sign = "+" | "-" .
|
||||
// prefix = "0" ( "x" | "X" | "b" | "B" ) .
|
||||
// mantissa = digits | digits "." [ digits ] | "." digits .
|
||||
// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
|
||||
// digits = digit { digit } .
|
||||
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
|
||||
// infinity = [ sign ] ( "inf" | "Inf" ) .
|
||||
//
|
||||
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
|
||||
// argument will lead to a run-time panic.
|
||||
//
|
||||
// For base 0, the number prefix determines the actual base: A prefix of
|
||||
// "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
|
||||
// base 2; otherwise, the actual base is 10 and no prefix is accepted.
|
||||
// The octal prefix "0" is not supported (a leading "0" is simply
|
||||
// considered a "0").
|
||||
//
|
||||
// A "p" exponent indicates a binary (rather then decimal) exponent;
|
||||
// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
|
||||
// maximum float64 value. For hexadecimal mantissae, the exponent must
|
||||
// be binary, if present (an "e" or "E" exponent indicator cannot be
|
||||
// distinguished from a mantissa digit).
|
||||
//
|
||||
// The returned *Float f is nil and the value of z is valid but not
|
||||
// defined if an error is reported.
|
||||
//
|
||||
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
|
||||
// scan doesn't handle ±Inf
|
||||
if len(s) == 3 && (s == "Inf" || s == "inf") {
|
||||
f = z.SetInf(false)
|
||||
return
|
||||
}
|
||||
if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
|
||||
f = z.SetInf(s[0] == '-')
|
||||
return
|
||||
}
|
||||
|
||||
r := strings.NewReader(s)
|
||||
if f, b, err = z.scan(r, base); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// entire string must have been consumed
|
||||
if ch, err2 := r.ReadByte(); err2 == nil {
|
||||
err = fmt.Errorf("expected end of string, found %q", ch)
|
||||
} else if err2 != io.EOF {
|
||||
err = err2
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ParseFloat is like f.Parse(s, base) with f set to the given precision
|
||||
// and rounding mode.
|
||||
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
|
||||
return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
|
||||
}
|
||||
|
|
@ -1,667 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFloatSetFloat64String(t *testing.T) {
|
||||
inf := math.Inf(0)
|
||||
nan := math.NaN()
|
||||
|
||||
for _, test := range []struct {
|
||||
s string
|
||||
x float64 // NaNs represent invalid inputs
|
||||
}{
|
||||
// basics
|
||||
{"0", 0},
|
||||
{"-0", -0},
|
||||
{"+0", 0},
|
||||
{"1", 1},
|
||||
{"-1", -1},
|
||||
{"+1", 1},
|
||||
{"1.234", 1.234},
|
||||
{"-1.234", -1.234},
|
||||
{"+1.234", 1.234},
|
||||
{".1", 0.1},
|
||||
{"1.", 1},
|
||||
{"+1.", 1},
|
||||
|
||||
// various zeros
|
||||
{"0e100", 0},
|
||||
{"-0e+100", 0},
|
||||
{"+0e-100", 0},
|
||||
{"0E100", 0},
|
||||
{"-0E+100", 0},
|
||||
{"+0E-100", 0},
|
||||
|
||||
// various decimal exponent formats
|
||||
{"1.e10", 1e10},
|
||||
{"1e+10", 1e10},
|
||||
{"+1e-10", 1e-10},
|
||||
{"1E10", 1e10},
|
||||
{"1.E+10", 1e10},
|
||||
{"+1E-10", 1e-10},
|
||||
|
||||
// infinities
|
||||
{"Inf", inf},
|
||||
{"+Inf", inf},
|
||||
{"-Inf", -inf},
|
||||
{"inf", inf},
|
||||
{"+inf", inf},
|
||||
{"-inf", -inf},
|
||||
|
||||
// invalid numbers
|
||||
{"", nan},
|
||||
{"-", nan},
|
||||
{"0x", nan},
|
||||
{"0e", nan},
|
||||
{"1.2ef", nan},
|
||||
{"2..3", nan},
|
||||
{"123..", nan},
|
||||
{"infinity", nan},
|
||||
{"foobar", nan},
|
||||
|
||||
// misc decimal values
|
||||
{"3.14159265", 3.14159265},
|
||||
{"-687436.79457e-245", -687436.79457e-245},
|
||||
{"-687436.79457E245", -687436.79457e245},
|
||||
{".0000000000000000000000000000000000000001", 1e-40},
|
||||
{"+10000000000000000000000000000000000000000e-0", 1e40},
|
||||
|
||||
// decimal mantissa, binary exponent
|
||||
{"0p0", 0},
|
||||
{"-0p0", -0},
|
||||
{"1p10", 1 << 10},
|
||||
{"1p+10", 1 << 10},
|
||||
{"+1p-10", 1.0 / (1 << 10)},
|
||||
{"1024p-12", 0.25},
|
||||
{"-1p10", -1024},
|
||||
{"1.5p1", 3},
|
||||
|
||||
// binary mantissa, decimal exponent
|
||||
{"0b0", 0},
|
||||
{"-0b0", -0},
|
||||
{"0b0e+10", 0},
|
||||
{"-0b0e-10", -0},
|
||||
{"0b1010", 10},
|
||||
{"0B1010E2", 1000},
|
||||
{"0b.1", 0.5},
|
||||
{"0b.001", 0.125},
|
||||
{"0b.001e3", 125},
|
||||
|
||||
// binary mantissa, binary exponent
|
||||
{"0b0p+10", 0},
|
||||
{"-0b0p-10", -0},
|
||||
{"0b.1010p4", 10},
|
||||
{"0b1p-1", 0.5},
|
||||
{"0b001p-3", 0.125},
|
||||
{"0b.001p3", 1},
|
||||
{"0b0.01p2", 1},
|
||||
|
||||
// hexadecimal mantissa and exponent
|
||||
{"0x0", 0},
|
||||
{"-0x0", -0},
|
||||
{"0x0p+10", 0},
|
||||
{"-0x0p-10", -0},
|
||||
{"0xff", 255},
|
||||
{"0X.8p1", 1},
|
||||
{"-0X0.00008p16", -0.5},
|
||||
{"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
|
||||
{"0x1.fffffffffffffp1023", math.MaxFloat64},
|
||||
} {
|
||||
var x Float
|
||||
x.SetPrec(53)
|
||||
_, ok := x.SetString(test.s)
|
||||
if math.IsNaN(test.x) {
|
||||
// test.s is invalid
|
||||
if ok {
|
||||
t.Errorf("%s: want parse error", test.s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// test.s is valid
|
||||
if !ok {
|
||||
t.Errorf("%s: got parse error", test.s)
|
||||
continue
|
||||
}
|
||||
f, _ := x.Float64()
|
||||
want := new(Float).SetFloat64(test.x)
|
||||
if x.Cmp(want) != 0 {
|
||||
t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fdiv(a, b float64) float64 { return a / b }
|
||||
|
||||
const (
|
||||
below1e23 = 99999999999999974834176
|
||||
above1e23 = 100000000000000008388608
|
||||
)
|
||||
|
||||
func TestFloat64Text(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x float64
|
||||
format byte
|
||||
prec int
|
||||
want string
|
||||
}{
|
||||
{0, 'f', 0, "0"},
|
||||
{math.Copysign(0, -1), 'f', 0, "-0"},
|
||||
{1, 'f', 0, "1"},
|
||||
{-1, 'f', 0, "-1"},
|
||||
|
||||
{0.001, 'e', 0, "1e-03"},
|
||||
{0.459, 'e', 0, "5e-01"},
|
||||
{1.459, 'e', 0, "1e+00"},
|
||||
{2.459, 'e', 1, "2.5e+00"},
|
||||
{3.459, 'e', 2, "3.46e+00"},
|
||||
{4.459, 'e', 3, "4.459e+00"},
|
||||
{5.459, 'e', 4, "5.4590e+00"},
|
||||
|
||||
{0.001, 'f', 0, "0"},
|
||||
{0.459, 'f', 0, "0"},
|
||||
{1.459, 'f', 0, "1"},
|
||||
{2.459, 'f', 1, "2.5"},
|
||||
{3.459, 'f', 2, "3.46"},
|
||||
{4.459, 'f', 3, "4.459"},
|
||||
{5.459, 'f', 4, "5.4590"},
|
||||
|
||||
{0, 'b', 0, "0"},
|
||||
{math.Copysign(0, -1), 'b', 0, "-0"},
|
||||
{1.0, 'b', 0, "4503599627370496p-52"},
|
||||
{-1.0, 'b', 0, "-4503599627370496p-52"},
|
||||
{4503599627370496, 'b', 0, "4503599627370496p+0"},
|
||||
|
||||
{0, 'p', 0, "0"},
|
||||
{math.Copysign(0, -1), 'p', 0, "-0"},
|
||||
{1024.0, 'p', 0, "0x.8p+11"},
|
||||
{-1024.0, 'p', 0, "-0x.8p+11"},
|
||||
|
||||
// all test cases below from strconv/ftoa_test.go
|
||||
{1, 'e', 5, "1.00000e+00"},
|
||||
{1, 'f', 5, "1.00000"},
|
||||
{1, 'g', 5, "1"},
|
||||
{1, 'g', -1, "1"},
|
||||
{20, 'g', -1, "20"},
|
||||
{1234567.8, 'g', -1, "1.2345678e+06"},
|
||||
{200000, 'g', -1, "200000"},
|
||||
{2000000, 'g', -1, "2e+06"},
|
||||
|
||||
// g conversion and zero suppression
|
||||
{400, 'g', 2, "4e+02"},
|
||||
{40, 'g', 2, "40"},
|
||||
{4, 'g', 2, "4"},
|
||||
{.4, 'g', 2, "0.4"},
|
||||
{.04, 'g', 2, "0.04"},
|
||||
{.004, 'g', 2, "0.004"},
|
||||
{.0004, 'g', 2, "0.0004"},
|
||||
{.00004, 'g', 2, "4e-05"},
|
||||
{.000004, 'g', 2, "4e-06"},
|
||||
|
||||
{0, 'e', 5, "0.00000e+00"},
|
||||
{0, 'f', 5, "0.00000"},
|
||||
{0, 'g', 5, "0"},
|
||||
{0, 'g', -1, "0"},
|
||||
|
||||
{-1, 'e', 5, "-1.00000e+00"},
|
||||
{-1, 'f', 5, "-1.00000"},
|
||||
{-1, 'g', 5, "-1"},
|
||||
{-1, 'g', -1, "-1"},
|
||||
|
||||
{12, 'e', 5, "1.20000e+01"},
|
||||
{12, 'f', 5, "12.00000"},
|
||||
{12, 'g', 5, "12"},
|
||||
{12, 'g', -1, "12"},
|
||||
|
||||
{123456700, 'e', 5, "1.23457e+08"},
|
||||
{123456700, 'f', 5, "123456700.00000"},
|
||||
{123456700, 'g', 5, "1.2346e+08"},
|
||||
{123456700, 'g', -1, "1.234567e+08"},
|
||||
|
||||
{1.2345e6, 'e', 5, "1.23450e+06"},
|
||||
{1.2345e6, 'f', 5, "1234500.00000"},
|
||||
{1.2345e6, 'g', 5, "1.2345e+06"},
|
||||
|
||||
{1e23, 'e', 17, "9.99999999999999916e+22"},
|
||||
{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
|
||||
{1e23, 'g', 17, "9.9999999999999992e+22"},
|
||||
|
||||
{1e23, 'e', -1, "1e+23"},
|
||||
{1e23, 'f', -1, "100000000000000000000000"},
|
||||
{1e23, 'g', -1, "1e+23"},
|
||||
|
||||
{below1e23, 'e', 17, "9.99999999999999748e+22"},
|
||||
{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
|
||||
{below1e23, 'g', 17, "9.9999999999999975e+22"},
|
||||
|
||||
{below1e23, 'e', -1, "9.999999999999997e+22"},
|
||||
{below1e23, 'f', -1, "99999999999999970000000"},
|
||||
{below1e23, 'g', -1, "9.999999999999997e+22"},
|
||||
|
||||
{above1e23, 'e', 17, "1.00000000000000008e+23"},
|
||||
{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
|
||||
{above1e23, 'g', 17, "1.0000000000000001e+23"},
|
||||
|
||||
{above1e23, 'e', -1, "1.0000000000000001e+23"},
|
||||
{above1e23, 'f', -1, "100000000000000010000000"},
|
||||
{above1e23, 'g', -1, "1.0000000000000001e+23"},
|
||||
|
||||
{5e-304 / 1e20, 'g', -1, "5e-324"},
|
||||
{-5e-304 / 1e20, 'g', -1, "-5e-324"},
|
||||
{fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic
|
||||
{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
|
||||
|
||||
{32, 'g', -1, "32"},
|
||||
{32, 'g', 0, "3e+01"},
|
||||
|
||||
{100, 'x', -1, "%x"},
|
||||
|
||||
// {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
|
||||
// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
|
||||
{math.Inf(0), 'g', -1, "+Inf"},
|
||||
{math.Inf(-1), 'g', -1, "-Inf"},
|
||||
{-math.Inf(0), 'g', -1, "-Inf"},
|
||||
|
||||
{-1, 'b', -1, "-4503599627370496p-52"},
|
||||
|
||||
// fixed bugs
|
||||
{0.9, 'f', 1, "0.9"},
|
||||
{0.09, 'f', 1, "0.1"},
|
||||
{0.0999, 'f', 1, "0.1"},
|
||||
{0.05, 'f', 1, "0.1"},
|
||||
{0.05, 'f', 0, "0"},
|
||||
{0.5, 'f', 1, "0.5"},
|
||||
{0.5, 'f', 0, "0"},
|
||||
{1.5, 'f', 0, "2"},
|
||||
|
||||
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
||||
{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
|
||||
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
|
||||
{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
|
||||
|
||||
// Issue 2625.
|
||||
{383260575764816448, 'f', 0, "383260575764816448"},
|
||||
{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
|
||||
|
||||
// Issue 15918.
|
||||
{1, 'f', -10, "1"},
|
||||
{1, 'f', -11, "1"},
|
||||
{1, 'f', -12, "1"},
|
||||
} {
|
||||
// The test cases are from the strconv package which tests float64 values.
|
||||
// When formatting values with prec = -1 (shortest representation),
|
||||
// the actually available mantissa precision matters.
|
||||
// For denormalized values, that precision is < 53 (SetFloat64 default).
|
||||
// Compute and set the actual precision explicitly.
|
||||
f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x)
|
||||
got := f.Text(test.format, test.prec)
|
||||
if got != test.want {
|
||||
t.Errorf("%v: got %s; want %s", test, got, test.want)
|
||||
continue
|
||||
}
|
||||
|
||||
if test.format == 'b' && test.x == 0 {
|
||||
continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
|
||||
}
|
||||
if test.format == 'p' {
|
||||
continue // 'p' format not supported in strconv.Format
|
||||
}
|
||||
|
||||
// verify that Float format matches strconv format
|
||||
want := strconv.FormatFloat(test.x, test.format, test.prec, 64)
|
||||
if got != want {
|
||||
t.Errorf("%v: got %s; want %s (strconv)", test, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actualPrec returns the number of actually used mantissa bits.
|
||||
func actualPrec(x float64) uint {
|
||||
if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 {
|
||||
// x is denormalized
|
||||
return 64 - nlz64(bits&(1<<52-1))
|
||||
}
|
||||
return 53
|
||||
}
|
||||
|
||||
func TestFloatText(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x string
|
||||
prec uint
|
||||
format byte
|
||||
digits int
|
||||
want string
|
||||
}{
|
||||
{"0", 10, 'f', 0, "0"},
|
||||
{"-0", 10, 'f', 0, "-0"},
|
||||
{"1", 10, 'f', 0, "1"},
|
||||
{"-1", 10, 'f', 0, "-1"},
|
||||
|
||||
{"1.459", 100, 'e', 0, "1e+00"},
|
||||
{"2.459", 100, 'e', 1, "2.5e+00"},
|
||||
{"3.459", 100, 'e', 2, "3.46e+00"},
|
||||
{"4.459", 100, 'e', 3, "4.459e+00"},
|
||||
{"5.459", 100, 'e', 4, "5.4590e+00"},
|
||||
|
||||
{"1.459", 100, 'E', 0, "1E+00"},
|
||||
{"2.459", 100, 'E', 1, "2.5E+00"},
|
||||
{"3.459", 100, 'E', 2, "3.46E+00"},
|
||||
{"4.459", 100, 'E', 3, "4.459E+00"},
|
||||
{"5.459", 100, 'E', 4, "5.4590E+00"},
|
||||
|
||||
{"1.459", 100, 'f', 0, "1"},
|
||||
{"2.459", 100, 'f', 1, "2.5"},
|
||||
{"3.459", 100, 'f', 2, "3.46"},
|
||||
{"4.459", 100, 'f', 3, "4.459"},
|
||||
{"5.459", 100, 'f', 4, "5.4590"},
|
||||
|
||||
{"1.459", 100, 'g', 0, "1"},
|
||||
{"2.459", 100, 'g', 1, "2"},
|
||||
{"3.459", 100, 'g', 2, "3.5"},
|
||||
{"4.459", 100, 'g', 3, "4.46"},
|
||||
{"5.459", 100, 'g', 4, "5.459"},
|
||||
|
||||
{"1459", 53, 'g', 0, "1e+03"},
|
||||
{"2459", 53, 'g', 1, "2e+03"},
|
||||
{"3459", 53, 'g', 2, "3.5e+03"},
|
||||
{"4459", 53, 'g', 3, "4.46e+03"},
|
||||
{"5459", 53, 'g', 4, "5459"},
|
||||
|
||||
{"1459", 53, 'G', 0, "1E+03"},
|
||||
{"2459", 53, 'G', 1, "2E+03"},
|
||||
{"3459", 53, 'G', 2, "3.5E+03"},
|
||||
{"4459", 53, 'G', 3, "4.46E+03"},
|
||||
{"5459", 53, 'G', 4, "5459"},
|
||||
|
||||
{"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
|
||||
{"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
|
||||
{"3", 10, 'g', 40, "3"},
|
||||
|
||||
{"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
|
||||
{"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
|
||||
{"3e40", 100, 'g', 40, "3e+40"},
|
||||
|
||||
// make sure "stupid" exponents don't stall the machine
|
||||
{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
|
||||
{"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
|
||||
{"1e646456993", 64, 'p', 0, "+Inf"},
|
||||
{"1e1000000000", 64, 'p', 0, "+Inf"},
|
||||
{"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
|
||||
{"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
|
||||
{"1e-646456994", 64, 'p', 0, "0"},
|
||||
{"1e-1000000000", 64, 'p', 0, "0"},
|
||||
|
||||
// minimum and maximum values
|
||||
{"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"},
|
||||
{"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"},
|
||||
{"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"},
|
||||
{"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"},
|
||||
|
||||
// TODO(gri) need tests for actual large Floats
|
||||
|
||||
{"0", 53, 'b', 0, "0"},
|
||||
{"-0", 53, 'b', 0, "-0"},
|
||||
{"1.0", 53, 'b', 0, "4503599627370496p-52"},
|
||||
{"-1.0", 53, 'b', 0, "-4503599627370496p-52"},
|
||||
{"4503599627370496", 53, 'b', 0, "4503599627370496p+0"},
|
||||
|
||||
// issue 9939
|
||||
{"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
{"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
{"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
{"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
{"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
{"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
|
||||
|
||||
{"3", 350, 'p', 0, "0x.cp+2"},
|
||||
{"03", 350, 'p', 0, "0x.cp+2"},
|
||||
{"3.", 350, 'p', 0, "0x.cp+2"},
|
||||
{"3.0", 350, 'p', 0, "0x.cp+2"},
|
||||
{"3.00", 350, 'p', 0, "0x.cp+2"},
|
||||
{"3.000", 350, 'p', 0, "0x.cp+2"},
|
||||
|
||||
{"0", 64, 'p', 0, "0"},
|
||||
{"-0", 64, 'p', 0, "-0"},
|
||||
{"1024.0", 64, 'p', 0, "0x.8p+11"},
|
||||
{"-1024.0", 64, 'p', 0, "-0x.8p+11"},
|
||||
|
||||
// unsupported format
|
||||
{"3.14", 64, 'x', 0, "%x"},
|
||||
{"-3.14", 64, 'x', 0, "%x"},
|
||||
} {
|
||||
f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
|
||||
if err != nil {
|
||||
t.Errorf("%v: %s", test, err)
|
||||
continue
|
||||
}
|
||||
|
||||
got := f.Text(test.format, test.digits)
|
||||
if got != test.want {
|
||||
t.Errorf("%v: got %s; want %s", test, got, test.want)
|
||||
}
|
||||
|
||||
// compare with strconv.FormatFloat output if possible
|
||||
// ('p' format is not supported by strconv.FormatFloat,
|
||||
// and its output for 0.0 prints a biased exponent value
|
||||
// as in 0p-1074 which makes no sense to emulate here)
|
||||
if test.prec == 53 && test.format != 'p' && f.Sign() != 0 {
|
||||
f64, acc := f.Float64()
|
||||
if acc != Exact {
|
||||
t.Errorf("%v: expected exact conversion to float64", test)
|
||||
continue
|
||||
}
|
||||
got := strconv.FormatFloat(f64, test.format, test.digits, 64)
|
||||
if got != test.want {
|
||||
t.Errorf("%v: got %s; want %s", test, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatFormat(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
format string
|
||||
value interface{} // float32, float64, or string (== 512bit *Float)
|
||||
want string
|
||||
}{
|
||||
// from fmt/fmt_test.go
|
||||
{"%+.3e", 0.0, "+0.000e+00"},
|
||||
{"%+.3e", 1.0, "+1.000e+00"},
|
||||
{"%+.3f", -1.0, "-1.000"},
|
||||
{"%+.3F", -1.0, "-1.000"},
|
||||
{"%+.3F", float32(-1.0), "-1.000"},
|
||||
{"%+07.2f", 1.0, "+001.00"},
|
||||
{"%+07.2f", -1.0, "-001.00"},
|
||||
{"%+10.2f", +1.0, " +1.00"},
|
||||
{"%+10.2f", -1.0, " -1.00"},
|
||||
{"% .3E", -1.0, "-1.000E+00"},
|
||||
{"% .3e", 1.0, " 1.000e+00"},
|
||||
{"%+.3g", 0.0, "+0"},
|
||||
{"%+.3g", 1.0, "+1"},
|
||||
{"%+.3g", -1.0, "-1"},
|
||||
{"% .3g", -1.0, "-1"},
|
||||
{"% .3g", 1.0, " 1"},
|
||||
{"%b", float32(1.0), "8388608p-23"},
|
||||
{"%b", 1.0, "4503599627370496p-52"},
|
||||
|
||||
// from fmt/fmt_test.go: old test/fmt_test.go
|
||||
{"%e", 1.0, "1.000000e+00"},
|
||||
{"%e", 1234.5678e3, "1.234568e+06"},
|
||||
{"%e", 1234.5678e-8, "1.234568e-05"},
|
||||
{"%e", -7.0, "-7.000000e+00"},
|
||||
{"%e", -1e-9, "-1.000000e-09"},
|
||||
{"%f", 1234.5678e3, "1234567.800000"},
|
||||
{"%f", 1234.5678e-8, "0.000012"},
|
||||
{"%f", -7.0, "-7.000000"},
|
||||
{"%f", -1e-9, "-0.000000"},
|
||||
{"%g", 1234.5678e3, "1.2345678e+06"},
|
||||
{"%g", float32(1234.5678e3), "1.2345678e+06"},
|
||||
{"%g", 1234.5678e-8, "1.2345678e-05"},
|
||||
{"%g", -7.0, "-7"},
|
||||
{"%g", -1e-9, "-1e-09"},
|
||||
{"%g", float32(-1e-9), "-1e-09"},
|
||||
{"%E", 1.0, "1.000000E+00"},
|
||||
{"%E", 1234.5678e3, "1.234568E+06"},
|
||||
{"%E", 1234.5678e-8, "1.234568E-05"},
|
||||
{"%E", -7.0, "-7.000000E+00"},
|
||||
{"%E", -1e-9, "-1.000000E-09"},
|
||||
{"%G", 1234.5678e3, "1.2345678E+06"},
|
||||
{"%G", float32(1234.5678e3), "1.2345678E+06"},
|
||||
{"%G", 1234.5678e-8, "1.2345678E-05"},
|
||||
{"%G", -7.0, "-7"},
|
||||
{"%G", -1e-9, "-1E-09"},
|
||||
{"%G", float32(-1e-9), "-1E-09"},
|
||||
|
||||
{"%20.6e", 1.2345e3, " 1.234500e+03"},
|
||||
{"%20.6e", 1.2345e-3, " 1.234500e-03"},
|
||||
{"%20e", 1.2345e3, " 1.234500e+03"},
|
||||
{"%20e", 1.2345e-3, " 1.234500e-03"},
|
||||
{"%20.8e", 1.2345e3, " 1.23450000e+03"},
|
||||
{"%20f", 1.23456789e3, " 1234.567890"},
|
||||
{"%20f", 1.23456789e-3, " 0.001235"},
|
||||
{"%20f", 12345678901.23456789, " 12345678901.234568"},
|
||||
{"%-20f", 1.23456789e3, "1234.567890 "},
|
||||
{"%20.8f", 1.23456789e3, " 1234.56789000"},
|
||||
{"%20.8f", 1.23456789e-3, " 0.00123457"},
|
||||
{"%g", 1.23456789e3, "1234.56789"},
|
||||
{"%g", 1.23456789e-3, "0.00123456789"},
|
||||
{"%g", 1.23456789e20, "1.23456789e+20"},
|
||||
{"%20e", math.Inf(1), " +Inf"},
|
||||
{"%-20f", math.Inf(-1), "-Inf "},
|
||||
|
||||
// from fmt/fmt_test.go: comparison of padding rules with C printf
|
||||
{"%.2f", 1.0, "1.00"},
|
||||
{"%.2f", -1.0, "-1.00"},
|
||||
{"% .2f", 1.0, " 1.00"},
|
||||
{"% .2f", -1.0, "-1.00"},
|
||||
{"%+.2f", 1.0, "+1.00"},
|
||||
{"%+.2f", -1.0, "-1.00"},
|
||||
{"%7.2f", 1.0, " 1.00"},
|
||||
{"%7.2f", -1.0, " -1.00"},
|
||||
{"% 7.2f", 1.0, " 1.00"},
|
||||
{"% 7.2f", -1.0, " -1.00"},
|
||||
{"%+7.2f", 1.0, " +1.00"},
|
||||
{"%+7.2f", -1.0, " -1.00"},
|
||||
{"%07.2f", 1.0, "0001.00"},
|
||||
{"%07.2f", -1.0, "-001.00"},
|
||||
{"% 07.2f", 1.0, " 001.00"},
|
||||
{"% 07.2f", -1.0, "-001.00"},
|
||||
{"%+07.2f", 1.0, "+001.00"},
|
||||
{"%+07.2f", -1.0, "-001.00"},
|
||||
|
||||
// from fmt/fmt_test.go: zero padding does not apply to infinities
|
||||
{"%020f", math.Inf(-1), " -Inf"},
|
||||
{"%020f", math.Inf(+1), " +Inf"},
|
||||
{"% 020f", math.Inf(-1), " -Inf"},
|
||||
{"% 020f", math.Inf(+1), " Inf"},
|
||||
{"%+020f", math.Inf(-1), " -Inf"},
|
||||
{"%+020f", math.Inf(+1), " +Inf"},
|
||||
{"%20f", -1.0, " -1.000000"},
|
||||
|
||||
// handle %v like %g
|
||||
{"%v", 0.0, "0"},
|
||||
{"%v", -7.0, "-7"},
|
||||
{"%v", -1e-9, "-1e-09"},
|
||||
{"%v", float32(-1e-9), "-1e-09"},
|
||||
{"%010v", 0.0, "0000000000"},
|
||||
|
||||
// *Float cases
|
||||
{"%.20f", "1e-20", "0.00000000000000000001"},
|
||||
{"%.20f", "-1e-20", "-0.00000000000000000001"},
|
||||
{"%30.20f", "-1e-20", " -0.00000000000000000001"},
|
||||
{"%030.20f", "-1e-20", "-00000000.00000000000000000001"},
|
||||
{"%030.20f", "+1e-20", "000000000.00000000000000000001"},
|
||||
{"% 030.20f", "+1e-20", " 00000000.00000000000000000001"},
|
||||
|
||||
// erroneous formats
|
||||
{"%s", 1.0, "%!s(*big.Float=1)"},
|
||||
} {
|
||||
value := new(Float)
|
||||
switch v := test.value.(type) {
|
||||
case float32:
|
||||
value.SetPrec(24).SetFloat64(float64(v))
|
||||
case float64:
|
||||
value.SetPrec(53).SetFloat64(v)
|
||||
case string:
|
||||
value.SetPrec(512).Parse(v, 0)
|
||||
default:
|
||||
t.Fatalf("unsupported test value: %v (%T)", v, v)
|
||||
}
|
||||
|
||||
if got := fmt.Sprintf(test.format, value); got != test.want {
|
||||
t.Errorf("%v: got %q; want %q", test, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseFloatSmallExp(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, s := range []string{
|
||||
"1e0",
|
||||
"1e-1",
|
||||
"1e-2",
|
||||
"1e-3",
|
||||
"1e-4",
|
||||
"1e-5",
|
||||
"1e-10",
|
||||
"1e-20",
|
||||
"1e-50",
|
||||
"1e1",
|
||||
"1e2",
|
||||
"1e3",
|
||||
"1e4",
|
||||
"1e5",
|
||||
"1e10",
|
||||
"1e20",
|
||||
"1e50",
|
||||
} {
|
||||
var x Float
|
||||
_, _, err := x.Parse(s, 0)
|
||||
if err != nil {
|
||||
b.Fatalf("%s: %v", s, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseFloatLargeExp(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, s := range []string{
|
||||
"1e0",
|
||||
"1e-10",
|
||||
"1e-20",
|
||||
"1e-30",
|
||||
"1e-40",
|
||||
"1e-50",
|
||||
"1e-100",
|
||||
"1e-500",
|
||||
"1e-1000",
|
||||
"1e-5000",
|
||||
"1e-10000",
|
||||
"1e10",
|
||||
"1e20",
|
||||
"1e30",
|
||||
"1e40",
|
||||
"1e50",
|
||||
"1e100",
|
||||
"1e500",
|
||||
"1e1000",
|
||||
"1e5000",
|
||||
"1e10000",
|
||||
} {
|
||||
var x Float
|
||||
_, _, err := x.Parse(s, 0)
|
||||
if err != nil {
|
||||
b.Fatalf("%s: %v", s, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big_test
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func ExampleFloat_Add() {
|
||||
// Operate on numbers of different precision.
|
||||
var x, y, z big.Float
|
||||
x.SetInt64(1000) // x is automatically set to 64bit precision
|
||||
y.SetFloat64(2.718281828) // y is automatically set to 53bit precision
|
||||
z.SetPrec(32)
|
||||
z.Add(&x, &y)
|
||||
fmt.Printf("x = %.10g (%s, prec = %d, acc = %s)\n", &x, x.Text('p', 0), x.Prec(), x.Acc())
|
||||
fmt.Printf("y = %.10g (%s, prec = %d, acc = %s)\n", &y, y.Text('p', 0), y.Prec(), y.Acc())
|
||||
fmt.Printf("z = %.10g (%s, prec = %d, acc = %s)\n", &z, z.Text('p', 0), z.Prec(), z.Acc())
|
||||
// Output:
|
||||
// x = 1000 (0x.fap+10, prec = 64, acc = Exact)
|
||||
// y = 2.718281828 (0x.adf85458248cd8p+2, prec = 53, acc = Exact)
|
||||
// z = 1002.718282 (0x.faadf854p+10, prec = 32, acc = Below)
|
||||
}
|
||||
|
||||
func ExampleFloat_shift() {
|
||||
// Implement Float "shift" by modifying the (binary) exponents directly.
|
||||
for s := -5; s <= 5; s++ {
|
||||
x := big.NewFloat(0.5)
|
||||
x.SetMantExp(x, x.MantExp(nil)+s) // shift x by s
|
||||
fmt.Println(x)
|
||||
}
|
||||
// Output:
|
||||
// 0.015625
|
||||
// 0.03125
|
||||
// 0.0625
|
||||
// 0.125
|
||||
// 0.25
|
||||
// 0.5
|
||||
// 1
|
||||
// 2
|
||||
// 4
|
||||
// 8
|
||||
// 16
|
||||
}
|
||||
|
||||
func ExampleFloat_Cmp() {
|
||||
inf := math.Inf(1)
|
||||
zero := 0.0
|
||||
|
||||
operands := []float64{-inf, -1.2, -zero, 0, +1.2, +inf}
|
||||
|
||||
fmt.Println(" x y cmp")
|
||||
fmt.Println("---------------")
|
||||
for _, x64 := range operands {
|
||||
x := big.NewFloat(x64)
|
||||
for _, y64 := range operands {
|
||||
y := big.NewFloat(y64)
|
||||
fmt.Printf("%4g %4g %3d\n", x, y, x.Cmp(y))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// x y cmp
|
||||
// ---------------
|
||||
// -Inf -Inf 0
|
||||
// -Inf -1.2 -1
|
||||
// -Inf -0 -1
|
||||
// -Inf 0 -1
|
||||
// -Inf 1.2 -1
|
||||
// -Inf +Inf -1
|
||||
//
|
||||
// -1.2 -Inf 1
|
||||
// -1.2 -1.2 0
|
||||
// -1.2 -0 -1
|
||||
// -1.2 0 -1
|
||||
// -1.2 1.2 -1
|
||||
// -1.2 +Inf -1
|
||||
//
|
||||
// -0 -Inf 1
|
||||
// -0 -1.2 1
|
||||
// -0 -0 0
|
||||
// -0 0 0
|
||||
// -0 1.2 -1
|
||||
// -0 +Inf -1
|
||||
//
|
||||
// 0 -Inf 1
|
||||
// 0 -1.2 1
|
||||
// 0 -0 0
|
||||
// 0 0 0
|
||||
// 0 1.2 -1
|
||||
// 0 +Inf -1
|
||||
//
|
||||
// 1.2 -Inf 1
|
||||
// 1.2 -1.2 1
|
||||
// 1.2 -0 1
|
||||
// 1.2 0 1
|
||||
// 1.2 1.2 0
|
||||
// 1.2 +Inf -1
|
||||
//
|
||||
// +Inf -Inf 1
|
||||
// +Inf -1.2 1
|
||||
// +Inf -0 1
|
||||
// +Inf 0 1
|
||||
// +Inf 1.2 1
|
||||
// +Inf +Inf 0
|
||||
}
|
||||
|
||||
func ExampleRoundingMode() {
|
||||
operands := []float64{2.6, 2.5, 2.1, -2.1, -2.5, -2.6}
|
||||
|
||||
fmt.Print(" x")
|
||||
for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
|
||||
fmt.Printf(" %s", mode)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
for _, f64 := range operands {
|
||||
fmt.Printf("%4g", f64)
|
||||
for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
|
||||
// sample operands above require 2 bits to represent mantissa
|
||||
// set binary precision to 2 to round them to integer values
|
||||
f := new(big.Float).SetPrec(2).SetMode(mode).SetFloat64(f64)
|
||||
fmt.Printf(" %*g", len(mode.String()), f)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// x ToNearestEven ToNearestAway ToZero AwayFromZero ToNegativeInf ToPositiveInf
|
||||
// 2.6 3 3 2 3 2 3
|
||||
// 2.5 2 3 2 3 2 3
|
||||
// 2.1 2 2 2 3 2 3
|
||||
// -2.1 -2 -2 -2 -3 -3 -2
|
||||
// -2.5 -2 -3 -2 -3 -3 -2
|
||||
// -2.6 -3 -3 -2 -3 -3 -2
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements encoding/decoding of Floats.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||
const floatGobVersion byte = 1
|
||||
|
||||
// GobEncode implements the gob.GobEncoder interface.
|
||||
// The Float value and all its attributes (precision,
|
||||
// rounding mode, accuracy) are marshalled.
|
||||
func (x *Float) GobEncode() ([]byte, error) {
|
||||
if x == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// determine max. space (bytes) required for encoding
|
||||
sz := 1 + 1 + 4 // version + mode|acc|form|neg (3+2+2+1bit) + prec
|
||||
n := 0 // number of mantissa words
|
||||
if x.form == finite {
|
||||
// add space for mantissa and exponent
|
||||
n = int((x.prec + (_W - 1)) / _W) // required mantissa length in words for given precision
|
||||
// actual mantissa slice could be shorter (trailing 0's) or longer (unused bits):
|
||||
// - if shorter, only encode the words present
|
||||
// - if longer, cut off unused words when encoding in bytes
|
||||
// (in practice, this should never happen since rounding
|
||||
// takes care of it, but be safe and do it always)
|
||||
if len(x.mant) < n {
|
||||
n = len(x.mant)
|
||||
}
|
||||
// len(x.mant) >= n
|
||||
sz += 4 + n*_S // exp + mant
|
||||
}
|
||||
buf := make([]byte, sz)
|
||||
|
||||
buf[0] = floatGobVersion
|
||||
b := byte(x.mode&7)<<5 | byte((x.acc+1)&3)<<3 | byte(x.form&3)<<1
|
||||
if x.neg {
|
||||
b |= 1
|
||||
}
|
||||
buf[1] = b
|
||||
binary.BigEndian.PutUint32(buf[2:], x.prec)
|
||||
|
||||
if x.form == finite {
|
||||
binary.BigEndian.PutUint32(buf[6:], uint32(x.exp))
|
||||
x.mant[len(x.mant)-n:].bytes(buf[10:]) // cut off unused trailing words
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// GobDecode implements the gob.GobDecoder interface.
|
||||
// The result is rounded per the precision and rounding mode of
|
||||
// z unless z's precision is 0, in which case z is set exactly
|
||||
// to the decoded value.
|
||||
func (z *Float) GobDecode(buf []byte) error {
|
||||
if len(buf) == 0 {
|
||||
// Other side sent a nil or default value.
|
||||
*z = Float{}
|
||||
return nil
|
||||
}
|
||||
|
||||
if buf[0] != floatGobVersion {
|
||||
return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0])
|
||||
}
|
||||
|
||||
oldPrec := z.prec
|
||||
oldMode := z.mode
|
||||
|
||||
b := buf[1]
|
||||
z.mode = RoundingMode((b >> 5) & 7)
|
||||
z.acc = Accuracy((b>>3)&3) - 1
|
||||
z.form = form((b >> 1) & 3)
|
||||
z.neg = b&1 != 0
|
||||
z.prec = binary.BigEndian.Uint32(buf[2:])
|
||||
|
||||
if z.form == finite {
|
||||
z.exp = int32(binary.BigEndian.Uint32(buf[6:]))
|
||||
z.mant = z.mant.setBytes(buf[10:])
|
||||
}
|
||||
|
||||
if oldPrec != 0 {
|
||||
z.mode = oldMode
|
||||
z.SetPrec(uint(oldPrec))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface.
|
||||
// Only the Float value is marshaled (in full precision), other
|
||||
// attributes such as precision or accuracy are ignored.
|
||||
func (x *Float) MarshalText() (text []byte, err error) {
|
||||
if x == nil {
|
||||
return []byte("<nil>"), 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
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var floatVals = []string{
|
||||
"0",
|
||||
"1",
|
||||
"0.1",
|
||||
"2.71828",
|
||||
"1234567890",
|
||||
"3.14e1234",
|
||||
"3.14e-1234",
|
||||
"0.738957395793475734757349579759957975985497e100",
|
||||
"0.73895739579347546656564656573475734957975995797598589749859834759476745986795497e100",
|
||||
"inf",
|
||||
"Inf",
|
||||
}
|
||||
|
||||
func TestFloatGobEncoding(t *testing.T) {
|
||||
var medium bytes.Buffer
|
||||
enc := gob.NewEncoder(&medium)
|
||||
dec := gob.NewDecoder(&medium)
|
||||
for _, test := range floatVals {
|
||||
for _, sign := range []string{"", "+", "-"} {
|
||||
for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
|
||||
for _, mode := range []RoundingMode{ToNearestEven, ToNearestAway, ToZero, AwayFromZero, ToNegativeInf, ToPositiveInf} {
|
||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||
x := sign + test
|
||||
|
||||
var tx Float
|
||||
_, _, err := tx.SetPrec(prec).SetMode(mode).Parse(x, 0)
|
||||
if err != nil {
|
||||
t.Errorf("parsing of %s (%dbits, %v) failed (invalid test case): %v", x, prec, mode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// If tx was set to prec == 0, tx.Parse(x, 0) assumes precision 64. Correct it.
|
||||
if prec == 0 {
|
||||
tx.SetPrec(0)
|
||||
}
|
||||
|
||||
if err := enc.Encode(&tx); err != nil {
|
||||
t.Errorf("encoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var rx Float
|
||||
if err := dec.Decode(&rx); err != nil {
|
||||
t.Errorf("decoding of %v (%dbits, %v) failed: %v", &tx, prec, mode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("transmission of %s failed: got %s want %s", x, rx.String(), tx.String())
|
||||
continue
|
||||
}
|
||||
|
||||
if rx.Prec() != prec {
|
||||
t.Errorf("transmission of %s's prec failed: got %d want %d", x, rx.Prec(), prec)
|
||||
}
|
||||
|
||||
if rx.Mode() != mode {
|
||||
t.Errorf("transmission of %s's mode failed: got %s want %s", x, rx.Mode(), mode)
|
||||
}
|
||||
|
||||
if rx.Acc() != tx.Acc() {
|
||||
t.Errorf("transmission of %s's accuracy failed: got %s want %s", x, rx.Acc(), tx.Acc())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatCorruptGob(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
tx := NewFloat(4 / 3).SetPrec(1000).SetMode(ToPositiveInf)
|
||||
if err := gob.NewEncoder(&buf).Encode(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := buf.Bytes()
|
||||
|
||||
var rx Float
|
||||
if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := gob.NewDecoder(bytes.NewReader(b[:10])).Decode(&rx); err != io.ErrUnexpectedEOF {
|
||||
t.Errorf("got %v want EOF", err)
|
||||
}
|
||||
|
||||
b[1] = 0
|
||||
if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&rx); err == nil {
|
||||
t.Fatal("got nil want version error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatJSONEncoding(t *testing.T) {
|
||||
for _, test := range floatVals {
|
||||
for _, sign := range []string{"", "+", "-"} {
|
||||
for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
|
||||
x := sign + test
|
||||
var tx Float
|
||||
_, _, err := tx.SetPrec(prec).Parse(x, 0)
|
||||
if err != nil {
|
||||
t.Errorf("parsing of %s (prec = %d) failed (invalid test case): %v", x, prec, err)
|
||||
continue
|
||||
}
|
||||
b, err := json.Marshal(&tx)
|
||||
if err != nil {
|
||||
t.Errorf("marshaling of %v (prec = %d) failed: %v", &tx, prec, err)
|
||||
continue
|
||||
}
|
||||
var rx Float
|
||||
rx.SetPrec(prec)
|
||||
if err := json.Unmarshal(b, &rx); err != nil {
|
||||
t.Errorf("unmarshaling of %v (prec = %d) failed: %v", &tx, prec, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("JSON encoding of %v (prec = %d) failed: got %v want %v", &tx, prec, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,459 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements Float-to-string conversion functions.
|
||||
// It is closely following the corresponding implementation
|
||||
// in strconv/ftoa.go, but modified and simplified for Float.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Text converts the floating-point number x to a string according
|
||||
// to the given format and precision prec. The format is one of:
|
||||
//
|
||||
// 'e' -d.dddde±dd, decimal exponent, at least two (possibly 0) exponent digits
|
||||
// 'E' -d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
|
||||
// 'f' -ddddd.dddd, no exponent
|
||||
// 'g' like 'e' for large exponents, like 'f' otherwise
|
||||
// 'G' like 'E' for large exponents, like 'f' otherwise
|
||||
// 'b' -ddddddp±dd, binary exponent
|
||||
// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
|
||||
//
|
||||
// For the binary exponent formats, the mantissa is printed in normalized form:
|
||||
//
|
||||
// 'b' decimal integer mantissa using x.Prec() bits, or -0
|
||||
// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
|
||||
//
|
||||
// If format is a different character, Text returns a "%" followed by the
|
||||
// unrecognized format character.
|
||||
//
|
||||
// The precision prec controls the number of digits (excluding the exponent)
|
||||
// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
|
||||
// it is the number of digits after the decimal point. For 'g' and 'G' it is
|
||||
// the total number of digits. A negative precision selects the smallest
|
||||
// number of decimal digits necessary to identify the value x uniquely using
|
||||
// x.Prec() mantissa bits.
|
||||
// The prec value is ignored for the 'b' or 'p' format.
|
||||
func (x *Float) Text(format byte, prec int) string {
|
||||
cap := 10 // TODO(gri) determine a good/better value here
|
||||
if prec > 0 {
|
||||
cap += prec
|
||||
}
|
||||
return string(x.Append(make([]byte, 0, cap), format, prec))
|
||||
}
|
||||
|
||||
// String formats x like x.Text('g', 10).
|
||||
// (String must be called explicitly, Float.Format does not support %s verb.)
|
||||
func (x *Float) String() string {
|
||||
return x.Text('g', 10)
|
||||
}
|
||||
|
||||
// Append appends to buf the string form of the floating-point number x,
|
||||
// as generated by x.Text, and returns the extended buffer.
|
||||
func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
|
||||
// sign
|
||||
if x.neg {
|
||||
buf = append(buf, '-')
|
||||
}
|
||||
|
||||
// Inf
|
||||
if x.form == inf {
|
||||
if !x.neg {
|
||||
buf = append(buf, '+')
|
||||
}
|
||||
return append(buf, "Inf"...)
|
||||
}
|
||||
|
||||
// pick off easy formats
|
||||
switch fmt {
|
||||
case 'b':
|
||||
return x.fmtB(buf)
|
||||
case 'p':
|
||||
return x.fmtP(buf)
|
||||
}
|
||||
|
||||
// Algorithm:
|
||||
// 1) convert Float to multiprecision decimal
|
||||
// 2) round to desired precision
|
||||
// 3) read digits out and format
|
||||
|
||||
// 1) convert Float to multiprecision decimal
|
||||
var d decimal // == 0.0
|
||||
if x.form == finite {
|
||||
// x != 0
|
||||
d.init(x.mant, int(x.exp)-x.mant.bitLen())
|
||||
}
|
||||
|
||||
// 2) round to desired precision
|
||||
shortest := false
|
||||
if prec < 0 {
|
||||
shortest = true
|
||||
roundShortest(&d, x)
|
||||
// Precision for shortest representation mode.
|
||||
switch fmt {
|
||||
case 'e', 'E':
|
||||
prec = len(d.mant) - 1
|
||||
case 'f':
|
||||
prec = max(len(d.mant)-d.exp, 0)
|
||||
case 'g', 'G':
|
||||
prec = len(d.mant)
|
||||
}
|
||||
} else {
|
||||
// round appropriately
|
||||
switch fmt {
|
||||
case 'e', 'E':
|
||||
// one digit before and number of digits after decimal point
|
||||
d.round(1 + prec)
|
||||
case 'f':
|
||||
// number of digits before and after decimal point
|
||||
d.round(d.exp + prec)
|
||||
case 'g', 'G':
|
||||
if prec == 0 {
|
||||
prec = 1
|
||||
}
|
||||
d.round(prec)
|
||||
}
|
||||
}
|
||||
|
||||
// 3) read digits out and format
|
||||
switch fmt {
|
||||
case 'e', 'E':
|
||||
return fmtE(buf, fmt, prec, d)
|
||||
case 'f':
|
||||
return fmtF(buf, prec, d)
|
||||
case 'g', 'G':
|
||||
// trim trailing fractional zeros in %e format
|
||||
eprec := prec
|
||||
if eprec > len(d.mant) && len(d.mant) >= d.exp {
|
||||
eprec = len(d.mant)
|
||||
}
|
||||
// %e is used if the exponent from the conversion
|
||||
// is less than -4 or greater than or equal to the precision.
|
||||
// If precision was the shortest possible, use eprec = 6 for
|
||||
// this decision.
|
||||
if shortest {
|
||||
eprec = 6
|
||||
}
|
||||
exp := d.exp - 1
|
||||
if exp < -4 || exp >= eprec {
|
||||
if prec > len(d.mant) {
|
||||
prec = len(d.mant)
|
||||
}
|
||||
return fmtE(buf, fmt+'e'-'g', prec-1, d)
|
||||
}
|
||||
if prec > d.exp {
|
||||
prec = len(d.mant)
|
||||
}
|
||||
return fmtF(buf, max(prec-d.exp, 0), d)
|
||||
}
|
||||
|
||||
// unknown format
|
||||
if x.neg {
|
||||
buf = buf[:len(buf)-1] // sign was added prematurely - remove it again
|
||||
}
|
||||
return append(buf, '%', fmt)
|
||||
}
|
||||
|
||||
func roundShortest(d *decimal, x *Float) {
|
||||
// if the mantissa is zero, the number is zero - stop now
|
||||
if len(d.mant) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp]
|
||||
// (possibly exclusive) round to x for the given precision of x.
|
||||
// Compute the lower and upper bound in decimal form and find the
|
||||
// shortest decimal number d such that lower <= d <= upper.
|
||||
|
||||
// TODO(gri) strconv/ftoa.do describes a shortcut in some cases.
|
||||
// See if we can use it (in adjusted form) here as well.
|
||||
|
||||
// 1) Compute normalized mantissa mant and exponent exp for x such
|
||||
// that the lsb of mant corresponds to 1/2 ulp for the precision of
|
||||
// x (i.e., for mant we want x.prec + 1 bits).
|
||||
mant := nat(nil).set(x.mant)
|
||||
exp := int(x.exp) - mant.bitLen()
|
||||
s := mant.bitLen() - int(x.prec+1)
|
||||
switch {
|
||||
case s < 0:
|
||||
mant = mant.shl(mant, uint(-s))
|
||||
case s > 0:
|
||||
mant = mant.shr(mant, uint(+s))
|
||||
}
|
||||
exp += s
|
||||
// x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec
|
||||
|
||||
// 2) Compute lower bound by subtracting 1/2 ulp.
|
||||
var lower decimal
|
||||
var tmp nat
|
||||
lower.init(tmp.sub(mant, natOne), exp)
|
||||
|
||||
// 3) Compute upper bound by adding 1/2 ulp.
|
||||
var upper decimal
|
||||
upper.init(tmp.add(mant, natOne), exp)
|
||||
|
||||
// The upper and lower bounds are possible outputs only if
|
||||
// the original mantissa is even, so that ToNearestEven rounding
|
||||
// would round to the original mantissa and not the neighbors.
|
||||
inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1
|
||||
|
||||
// Now we can figure out the minimum number of digits required.
|
||||
// Walk along until d has distinguished itself from upper and lower.
|
||||
for i, m := range d.mant {
|
||||
l := lower.at(i)
|
||||
u := upper.at(i)
|
||||
|
||||
// Okay to round down (truncate) if lower has a different digit
|
||||
// or if lower is inclusive and is exactly the result of rounding
|
||||
// down (i.e., and we have reached the final digit of lower).
|
||||
okdown := l != m || inclusive && i+1 == len(lower.mant)
|
||||
|
||||
// Okay to round up if upper has a different digit and either upper
|
||||
// is inclusive or upper is bigger than the result of rounding up.
|
||||
okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
|
||||
|
||||
// If it's okay to do either, then round to the nearest one.
|
||||
// If it's okay to do only one, do it.
|
||||
switch {
|
||||
case okdown && okup:
|
||||
d.round(i + 1)
|
||||
return
|
||||
case okdown:
|
||||
d.roundDown(i + 1)
|
||||
return
|
||||
case okup:
|
||||
d.roundUp(i + 1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// %e: d.ddddde±dd
|
||||
func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
|
||||
// first digit
|
||||
ch := byte('0')
|
||||
if len(d.mant) > 0 {
|
||||
ch = d.mant[0]
|
||||
}
|
||||
buf = append(buf, ch)
|
||||
|
||||
// .moredigits
|
||||
if prec > 0 {
|
||||
buf = append(buf, '.')
|
||||
i := 1
|
||||
m := min(len(d.mant), prec+1)
|
||||
if i < m {
|
||||
buf = append(buf, d.mant[i:m]...)
|
||||
i = m
|
||||
}
|
||||
for ; i <= prec; i++ {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
}
|
||||
|
||||
// e±
|
||||
buf = append(buf, fmt)
|
||||
var exp int64
|
||||
if len(d.mant) > 0 {
|
||||
exp = int64(d.exp) - 1 // -1 because first digit was printed before '.'
|
||||
}
|
||||
if exp < 0 {
|
||||
ch = '-'
|
||||
exp = -exp
|
||||
} else {
|
||||
ch = '+'
|
||||
}
|
||||
buf = append(buf, ch)
|
||||
|
||||
// dd...d
|
||||
if exp < 10 {
|
||||
buf = append(buf, '0') // at least 2 exponent digits
|
||||
}
|
||||
return strconv.AppendInt(buf, exp, 10)
|
||||
}
|
||||
|
||||
// %f: ddddddd.ddddd
|
||||
func fmtF(buf []byte, prec int, d decimal) []byte {
|
||||
// integer, padded with zeros as needed
|
||||
if d.exp > 0 {
|
||||
m := min(len(d.mant), d.exp)
|
||||
buf = append(buf, d.mant[:m]...)
|
||||
for ; m < d.exp; m++ {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
} else {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
|
||||
// fraction
|
||||
if prec > 0 {
|
||||
buf = append(buf, '.')
|
||||
for i := 0; i < prec; i++ {
|
||||
buf = append(buf, d.at(d.exp+i))
|
||||
}
|
||||
}
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
// fmtB appends the string of x in the format mantissa "p" exponent
|
||||
// with a decimal mantissa and a binary exponent, or 0" if x is zero,
|
||||
// and returns the extended buffer.
|
||||
// The mantissa is normalized such that is uses x.Prec() bits in binary
|
||||
// representation.
|
||||
// The sign of x is ignored, and x must not be an Inf.
|
||||
func (x *Float) fmtB(buf []byte) []byte {
|
||||
if x.form == zero {
|
||||
return append(buf, '0')
|
||||
}
|
||||
|
||||
if debugFloat && x.form != finite {
|
||||
panic("non-finite float")
|
||||
}
|
||||
// x != 0
|
||||
|
||||
// adjust mantissa to use exactly x.prec bits
|
||||
m := x.mant
|
||||
switch w := uint32(len(x.mant)) * _W; {
|
||||
case w < x.prec:
|
||||
m = nat(nil).shl(m, uint(x.prec-w))
|
||||
case w > x.prec:
|
||||
m = nat(nil).shr(m, uint(w-x.prec))
|
||||
}
|
||||
|
||||
buf = append(buf, m.utoa(10)...)
|
||||
buf = append(buf, 'p')
|
||||
e := int64(x.exp) - int64(x.prec)
|
||||
if e >= 0 {
|
||||
buf = append(buf, '+')
|
||||
}
|
||||
return strconv.AppendInt(buf, e, 10)
|
||||
}
|
||||
|
||||
// fmtP appends the string of x in the format "0x." mantissa "p" exponent
|
||||
// with a hexadecimal mantissa and a binary exponent, or "0" if x is zero,
|
||||
// and returns the extended buffer.
|
||||
// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
|
||||
// The sign of x is ignored, and x must not be an Inf.
|
||||
func (x *Float) fmtP(buf []byte) []byte {
|
||||
if x.form == zero {
|
||||
return append(buf, '0')
|
||||
}
|
||||
|
||||
if debugFloat && x.form != finite {
|
||||
panic("non-finite float")
|
||||
}
|
||||
// x != 0
|
||||
|
||||
// remove trailing 0 words early
|
||||
// (no need to convert to hex 0's and trim later)
|
||||
m := x.mant
|
||||
i := 0
|
||||
for i < len(m) && m[i] == 0 {
|
||||
i++
|
||||
}
|
||||
m = m[i:]
|
||||
|
||||
buf = append(buf, "0x."...)
|
||||
buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
|
||||
buf = append(buf, 'p')
|
||||
if x.exp >= 0 {
|
||||
buf = append(buf, '+')
|
||||
}
|
||||
return strconv.AppendInt(buf, int64(x.exp), 10)
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter. It accepts all the regular
|
||||
// formats for floating-point numbers ('b', 'e', 'E', 'f', 'F',
|
||||
// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the
|
||||
// interpretation of 'p'. The 'v' format is handled like 'g'.
|
||||
// Format also supports specification of the minimum precision
|
||||
// in digits, the output field width, as well as the format flags
|
||||
// '+' and ' ' for sign control, '0' for space or zero padding,
|
||||
// and '-' for left or right justification. See the fmt package
|
||||
// for details.
|
||||
func (x *Float) Format(s fmt.State, format rune) {
|
||||
prec, hasPrec := s.Precision()
|
||||
if !hasPrec {
|
||||
prec = 6 // default precision for 'e', 'f'
|
||||
}
|
||||
|
||||
switch format {
|
||||
case 'e', 'E', 'f', 'b', 'p':
|
||||
// nothing to do
|
||||
case 'F':
|
||||
// (*Float).Text doesn't support 'F'; handle like 'f'
|
||||
format = 'f'
|
||||
case 'v':
|
||||
// handle like 'g'
|
||||
format = 'g'
|
||||
fallthrough
|
||||
case 'g', 'G':
|
||||
if !hasPrec {
|
||||
prec = -1 // default precision for 'g', 'G'
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
|
||||
return
|
||||
}
|
||||
var buf []byte
|
||||
buf = x.Append(buf, byte(format), prec)
|
||||
if len(buf) == 0 {
|
||||
buf = []byte("?") // should never happen, but don't crash
|
||||
}
|
||||
// len(buf) > 0
|
||||
|
||||
var sign string
|
||||
switch {
|
||||
case buf[0] == '-':
|
||||
sign = "-"
|
||||
buf = buf[1:]
|
||||
case buf[0] == '+':
|
||||
// +Inf
|
||||
sign = "+"
|
||||
if s.Flag(' ') {
|
||||
sign = " "
|
||||
}
|
||||
buf = buf[1:]
|
||||
case s.Flag('+'):
|
||||
sign = "+"
|
||||
case s.Flag(' '):
|
||||
sign = " "
|
||||
}
|
||||
|
||||
var padding int
|
||||
if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
|
||||
padding = width - len(sign) - len(buf)
|
||||
}
|
||||
|
||||
switch {
|
||||
case s.Flag('0') && !x.IsInf():
|
||||
// 0-padding on left
|
||||
writeMultiple(s, sign, 1)
|
||||
writeMultiple(s, "0", padding)
|
||||
s.Write(buf)
|
||||
case s.Flag('-'):
|
||||
// padding on right
|
||||
writeMultiple(s, sign, 1)
|
||||
s.Write(buf)
|
||||
writeMultiple(s, " ", padding)
|
||||
default:
|
||||
// padding on left
|
||||
writeMultiple(s, " ", padding)
|
||||
writeMultiple(s, sign, 1)
|
||||
s.Write(buf)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements a GCD benchmark.
|
||||
// Usage: go test math/big -test.bench GCD
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// randInt returns a pseudo-random Int in the range [1<<(size-1), (1<<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) }
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// A little test program and benchmark for rational arithmetics.
|
||||
// Computes a Hilbert matrix, its inverse, multiplies them
|
||||
// and verifies that the product is the identity matrix.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type matrix struct {
|
||||
n, m int
|
||||
a []*Rat
|
||||
}
|
||||
|
||||
func (a *matrix) at(i, j int) *Rat {
|
||||
if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
|
||||
panic("index out of range")
|
||||
}
|
||||
return a.a[i*a.m+j]
|
||||
}
|
||||
|
||||
func (a *matrix) set(i, j int, x *Rat) {
|
||||
if !(0 <= i && i < a.n && 0 <= j && j < a.m) {
|
||||
panic("index out of range")
|
||||
}
|
||||
a.a[i*a.m+j] = x
|
||||
}
|
||||
|
||||
func newMatrix(n, m int) *matrix {
|
||||
if !(0 <= n && 0 <= m) {
|
||||
panic("illegal matrix")
|
||||
}
|
||||
a := new(matrix)
|
||||
a.n = n
|
||||
a.m = m
|
||||
a.a = make([]*Rat, n*m)
|
||||
return a
|
||||
}
|
||||
|
||||
func newUnit(n int) *matrix {
|
||||
a := newMatrix(n, n)
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
x := NewRat(0, 1)
|
||||
if i == j {
|
||||
x.SetInt64(1)
|
||||
}
|
||||
a.set(i, j, x)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func newHilbert(n int) *matrix {
|
||||
a := newMatrix(n, n)
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
a.set(i, j, NewRat(1, int64(i+j+1)))
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func newInverseHilbert(n int) *matrix {
|
||||
a := newMatrix(n, n)
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
x1 := new(Rat).SetInt64(int64(i + j + 1))
|
||||
x2 := new(Rat).SetInt(new(Int).Binomial(int64(n+i), int64(n-j-1)))
|
||||
x3 := new(Rat).SetInt(new(Int).Binomial(int64(n+j), int64(n-i-1)))
|
||||
x4 := new(Rat).SetInt(new(Int).Binomial(int64(i+j), int64(i)))
|
||||
|
||||
x1.Mul(x1, x2)
|
||||
x1.Mul(x1, x3)
|
||||
x1.Mul(x1, x4)
|
||||
x1.Mul(x1, x4)
|
||||
|
||||
if (i+j)&1 != 0 {
|
||||
x1.Neg(x1)
|
||||
}
|
||||
|
||||
a.set(i, j, x1)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *matrix) mul(b *matrix) *matrix {
|
||||
if a.m != b.n {
|
||||
panic("illegal matrix multiply")
|
||||
}
|
||||
c := newMatrix(a.n, b.m)
|
||||
for i := 0; i < c.n; i++ {
|
||||
for j := 0; j < c.m; j++ {
|
||||
x := NewRat(0, 1)
|
||||
for k := 0; k < a.m; k++ {
|
||||
x.Add(x, new(Rat).Mul(a.at(i, k), b.at(k, j)))
|
||||
}
|
||||
c.set(i, j, x)
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (a *matrix) eql(b *matrix) bool {
|
||||
if a.n != b.n || a.m != b.m {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < a.n; i++ {
|
||||
for j := 0; j < a.m; j++ {
|
||||
if a.at(i, j).Cmp(b.at(i, j)) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *matrix) String() string {
|
||||
s := ""
|
||||
for i := 0; i < a.n; i++ {
|
||||
for j := 0; j < a.m; j++ {
|
||||
s += fmt.Sprintf("\t%s", a.at(i, j))
|
||||
}
|
||||
s += "\n"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func doHilbert(t *testing.T, n int) {
|
||||
a := newHilbert(n)
|
||||
b := newInverseHilbert(n)
|
||||
I := newUnit(n)
|
||||
ab := a.mul(b)
|
||||
if !ab.eql(I) {
|
||||
if t == nil {
|
||||
panic("Hilbert failed")
|
||||
}
|
||||
t.Errorf("a = %s\n", a)
|
||||
t.Errorf("b = %s\n", b)
|
||||
t.Errorf("a*b = %s\n", ab)
|
||||
t.Errorf("I = %s\n", I)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHilbert(t *testing.T) {
|
||||
doHilbert(t, 10)
|
||||
}
|
||||
|
||||
func BenchmarkHilbert(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
doHilbert(nil, 10)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,934 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements signed multi-precision integers.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// An Int represents a signed multi-precision integer.
|
||||
// The zero value for an Int represents the value 0.
|
||||
type Int struct {
|
||||
neg bool // sign
|
||||
abs nat // absolute value of the integer
|
||||
}
|
||||
|
||||
var intOne = &Int{false, natOne}
|
||||
|
||||
// Sign returns:
|
||||
//
|
||||
// -1 if x < 0
|
||||
// 0 if x == 0
|
||||
// +1 if x > 0
|
||||
//
|
||||
func (x *Int) Sign() int {
|
||||
if len(x.abs) == 0 {
|
||||
return 0
|
||||
}
|
||||
if x.neg {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// SetInt64 sets z to x and returns z.
|
||||
func (z *Int) SetInt64(x int64) *Int {
|
||||
neg := false
|
||||
if x < 0 {
|
||||
neg = true
|
||||
x = -x
|
||||
}
|
||||
z.abs = z.abs.setUint64(uint64(x))
|
||||
z.neg = neg
|
||||
return z
|
||||
}
|
||||
|
||||
// SetUint64 sets z to x and returns z.
|
||||
func (z *Int) SetUint64(x uint64) *Int {
|
||||
z.abs = z.abs.setUint64(x)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// NewInt allocates and returns a new Int set to x.
|
||||
func NewInt(x int64) *Int {
|
||||
return new(Int).SetInt64(x)
|
||||
}
|
||||
|
||||
// Set sets z to x and returns z.
|
||||
func (z *Int) Set(x *Int) *Int {
|
||||
if z != x {
|
||||
z.abs = z.abs.set(x.abs)
|
||||
z.neg = x.neg
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
// Bits provides raw (unchecked but fast) access to x by returning its
|
||||
// absolute value as a little-endian Word slice. The result and x share
|
||||
// the same underlying array.
|
||||
// Bits is intended to support implementation of missing low-level Int
|
||||
// functionality outside this package; it should be avoided otherwise.
|
||||
func (x *Int) Bits() []Word {
|
||||
return x.abs
|
||||
}
|
||||
|
||||
// SetBits provides raw (unchecked but fast) access to z by setting its
|
||||
// value to abs, interpreted as a little-endian Word slice, and returning
|
||||
// z. The result and abs share the same underlying array.
|
||||
// SetBits is intended to support implementation of missing low-level Int
|
||||
// functionality outside this package; it should be avoided otherwise.
|
||||
func (z *Int) SetBits(abs []Word) *Int {
|
||||
z.abs = nat(abs).norm()
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// Abs sets z to |x| (the absolute value of x) and returns z.
|
||||
func (z *Int) Abs(x *Int) *Int {
|
||||
z.Set(x)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// Neg sets z to -x and returns z.
|
||||
func (z *Int) Neg(x *Int) *Int {
|
||||
z.Set(x)
|
||||
z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// Add sets z to the sum x+y and returns z.
|
||||
func (z *Int) Add(x, y *Int) *Int {
|
||||
neg := x.neg
|
||||
if x.neg == y.neg {
|
||||
// x + y == x + y
|
||||
// (-x) + (-y) == -(x + y)
|
||||
z.abs = z.abs.add(x.abs, y.abs)
|
||||
} else {
|
||||
// x + (-y) == x - y == -(y - x)
|
||||
// (-x) + y == y - x == -(x - y)
|
||||
if x.abs.cmp(y.abs) >= 0 {
|
||||
z.abs = z.abs.sub(x.abs, y.abs)
|
||||
} else {
|
||||
neg = !neg
|
||||
z.abs = z.abs.sub(y.abs, x.abs)
|
||||
}
|
||||
}
|
||||
z.neg = len(z.abs) > 0 && neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// Sub sets z to the difference x-y and returns z.
|
||||
func (z *Int) Sub(x, y *Int) *Int {
|
||||
neg := x.neg
|
||||
if x.neg != y.neg {
|
||||
// x - (-y) == x + y
|
||||
// (-x) - y == -(x + y)
|
||||
z.abs = z.abs.add(x.abs, y.abs)
|
||||
} else {
|
||||
// x - y == x - y == -(y - x)
|
||||
// (-x) - (-y) == y - x == -(x - y)
|
||||
if x.abs.cmp(y.abs) >= 0 {
|
||||
z.abs = z.abs.sub(x.abs, y.abs)
|
||||
} else {
|
||||
neg = !neg
|
||||
z.abs = z.abs.sub(y.abs, x.abs)
|
||||
}
|
||||
}
|
||||
z.neg = len(z.abs) > 0 && neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// Mul sets z to the product x*y and returns z.
|
||||
func (z *Int) Mul(x, y *Int) *Int {
|
||||
// x * y == x * y
|
||||
// x * (-y) == -(x * y)
|
||||
// (-x) * y == -(x * y)
|
||||
// (-x) * (-y) == x * y
|
||||
z.abs = z.abs.mul(x.abs, y.abs)
|
||||
z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// MulRange sets z to the product of all integers
|
||||
// in the range [a, b] inclusively and returns z.
|
||||
// If a > b (empty range), the result is 1.
|
||||
func (z *Int) MulRange(a, b int64) *Int {
|
||||
switch {
|
||||
case a > b:
|
||||
return z.SetInt64(1) // empty range
|
||||
case a <= 0 && b >= 0:
|
||||
return z.SetInt64(0) // range includes 0
|
||||
}
|
||||
// a <= b && (b < 0 || a > 0)
|
||||
|
||||
neg := false
|
||||
if a < 0 {
|
||||
neg = (b-a)&1 == 0
|
||||
a, b = -b, -a
|
||||
}
|
||||
|
||||
z.abs = z.abs.mulRange(uint64(a), uint64(b))
|
||||
z.neg = neg
|
||||
return z
|
||||
}
|
||||
|
||||
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
|
||||
func (z *Int) Binomial(n, k int64) *Int {
|
||||
// reduce the number of multiplications by reducing k
|
||||
if n/2 < k && k <= n {
|
||||
k = n - k // Binomial(n, k) == Binomial(n, n-k)
|
||||
}
|
||||
var a, b Int
|
||||
a.MulRange(n-k+1, n)
|
||||
b.MulRange(1, k)
|
||||
return z.Quo(&a, &b)
|
||||
}
|
||||
|
||||
// Quo sets z to the quotient x/y for y != 0 and returns z.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
// Quo implements truncated division (like Go); see QuoRem for more details.
|
||||
func (z *Int) Quo(x, y *Int) *Int {
|
||||
z.abs, _ = z.abs.div(nil, x.abs, y.abs)
|
||||
z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// Rem sets z to the remainder x%y for y != 0 and returns z.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
// Rem implements truncated modulus (like Go); see QuoRem for more details.
|
||||
func (z *Int) Rem(x, y *Int) *Int {
|
||||
_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
|
||||
z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
|
||||
return z
|
||||
}
|
||||
|
||||
// QuoRem sets z to the quotient x/y and r to the remainder x%y
|
||||
// and returns the pair (z, r) for y != 0.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
//
|
||||
// QuoRem implements T-division and modulus (like Go):
|
||||
//
|
||||
// q = x/y with the result truncated to zero
|
||||
// r = x - y*q
|
||||
//
|
||||
// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
|
||||
// See DivMod for Euclidean division and modulus (unlike Go).
|
||||
//
|
||||
func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
|
||||
z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs)
|
||||
z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign
|
||||
return z, r
|
||||
}
|
||||
|
||||
// Div sets z to the quotient x/y for y != 0 and returns z.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
// Div implements Euclidean division (unlike Go); see DivMod for more details.
|
||||
func (z *Int) Div(x, y *Int) *Int {
|
||||
y_neg := y.neg // z may be an alias for y
|
||||
var r Int
|
||||
z.QuoRem(x, y, &r)
|
||||
if r.neg {
|
||||
if y_neg {
|
||||
z.Add(z, intOne)
|
||||
} else {
|
||||
z.Sub(z, intOne)
|
||||
}
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
// Mod sets z to the modulus x%y for y != 0 and returns z.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
|
||||
func (z *Int) Mod(x, y *Int) *Int {
|
||||
y0 := y // save y
|
||||
if z == y || alias(z.abs, y.abs) {
|
||||
y0 = new(Int).Set(y)
|
||||
}
|
||||
var q Int
|
||||
q.QuoRem(x, y, z)
|
||||
if z.neg {
|
||||
if y0.neg {
|
||||
z.Sub(z, y0)
|
||||
} else {
|
||||
z.Add(z, y0)
|
||||
}
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
// DivMod sets z to the quotient x div y and m to the modulus x mod y
|
||||
// and returns the pair (z, m) for y != 0.
|
||||
// If y == 0, a division-by-zero run-time panic occurs.
|
||||
//
|
||||
// DivMod implements Euclidean division and modulus (unlike Go):
|
||||
//
|
||||
// q = x div y such that
|
||||
// m = x - y*q with 0 <= m < |y|
|
||||
//
|
||||
// (See Raymond T. Boute, ``The Euclidean definition of the functions
|
||||
// div and mod''. ACM Transactions on Programming Languages and
|
||||
// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
|
||||
// ACM press.)
|
||||
// See QuoRem for T-division and modulus (like Go).
|
||||
//
|
||||
func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
|
||||
y0 := y // save y
|
||||
if z == y || alias(z.abs, y.abs) {
|
||||
y0 = new(Int).Set(y)
|
||||
}
|
||||
z.QuoRem(x, y, m)
|
||||
if m.neg {
|
||||
if y0.neg {
|
||||
z.Add(z, intOne)
|
||||
m.Sub(m, y0)
|
||||
} else {
|
||||
z.Sub(z, intOne)
|
||||
m.Add(m, y0)
|
||||
}
|
||||
}
|
||||
return z, m
|
||||
}
|
||||
|
||||
// Cmp compares x and y and returns:
|
||||
//
|
||||
// -1 if x < y
|
||||
// 0 if x == y
|
||||
// +1 if x > y
|
||||
//
|
||||
func (x *Int) Cmp(y *Int) (r int) {
|
||||
// x cmp y == x cmp y
|
||||
// x cmp (-y) == x
|
||||
// (-x) cmp y == y
|
||||
// (-x) cmp (-y) == -(x cmp y)
|
||||
switch {
|
||||
case x.neg == y.neg:
|
||||
r = x.abs.cmp(y.abs)
|
||||
if x.neg {
|
||||
r = -r
|
||||
}
|
||||
case x.neg:
|
||||
r = -1
|
||||
default:
|
||||
r = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// low32 returns the least significant 32 bits of z.
|
||||
func low32(z nat) uint32 {
|
||||
if len(z) == 0 {
|
||||
return 0
|
||||
}
|
||||
return uint32(z[0])
|
||||
}
|
||||
|
||||
// low64 returns the least significant 64 bits of z.
|
||||
func low64(z nat) uint64 {
|
||||
if len(z) == 0 {
|
||||
return 0
|
||||
}
|
||||
v := uint64(z[0])
|
||||
if _W == 32 && len(z) > 1 {
|
||||
v |= uint64(z[1]) << 32
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int64 returns the int64 representation of x.
|
||||
// If x cannot be represented in an int64, the result is undefined.
|
||||
func (x *Int) Int64() int64 {
|
||||
v := int64(low64(x.abs))
|
||||
if x.neg {
|
||||
v = -v
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Uint64 returns the uint64 representation of x.
|
||||
// If x cannot be represented in a uint64, the result is undefined.
|
||||
func (x *Int) Uint64() uint64 {
|
||||
return low64(x.abs)
|
||||
}
|
||||
|
||||
// SetString sets z to the value of s, interpreted in the given base,
|
||||
// and returns z and a boolean indicating success. If SetString fails,
|
||||
// the value of z is undefined but the returned value is nil.
|
||||
//
|
||||
// The base argument must be 0 or a value between 2 and MaxBase. If the base
|
||||
// is 0, the string prefix determines the actual conversion base. A prefix of
|
||||
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
|
||||
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
|
||||
//
|
||||
func (z *Int) SetString(s string, base int) (*Int, bool) {
|
||||
r := strings.NewReader(s)
|
||||
_, _, err := z.scan(r, base)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
_, err = r.ReadByte()
|
||||
if err != io.EOF {
|
||||
return nil, false
|
||||
}
|
||||
return z, true // err == io.EOF => scan consumed all of s
|
||||
}
|
||||
|
||||
// SetBytes interprets buf as the bytes of a big-endian unsigned
|
||||
// integer, sets z to that value, and returns z.
|
||||
func (z *Int) SetBytes(buf []byte) *Int {
|
||||
z.abs = z.abs.setBytes(buf)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// Bytes returns the absolute value of x as a big-endian byte slice.
|
||||
func (x *Int) Bytes() []byte {
|
||||
buf := make([]byte, len(x.abs)*_S)
|
||||
return buf[x.abs.bytes(buf):]
|
||||
}
|
||||
|
||||
// BitLen returns the length of the absolute value of x in bits.
|
||||
// The bit length of 0 is 0.
|
||||
func (x *Int) BitLen() int {
|
||||
return x.abs.bitLen()
|
||||
}
|
||||
|
||||
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
|
||||
// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y.
|
||||
// See Knuth, volume 2, section 4.6.3.
|
||||
func (z *Int) Exp(x, y, m *Int) *Int {
|
||||
var yWords nat
|
||||
if !y.neg {
|
||||
yWords = y.abs
|
||||
}
|
||||
// y >= 0
|
||||
|
||||
var mWords nat
|
||||
if m != nil {
|
||||
mWords = m.abs // m.abs may be nil for m == 0
|
||||
}
|
||||
|
||||
z.abs = z.abs.expNN(x.abs, yWords, mWords)
|
||||
z.neg = len(z.abs) > 0 && x.neg && len(yWords) > 0 && yWords[0]&1 == 1 // 0 has no sign
|
||||
if z.neg && len(mWords) > 0 {
|
||||
// make modulus result positive
|
||||
z.abs = z.abs.sub(mWords, z.abs) // z == x**y mod |m| && 0 <= z < |m|
|
||||
z.neg = false
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// GCD sets z to the greatest common divisor of a and b, which both must
|
||||
// be > 0, and returns z.
|
||||
// If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
|
||||
// If either a or b is <= 0, GCD sets z = x = y = 0.
|
||||
func (z *Int) GCD(x, y, a, b *Int) *Int {
|
||||
if a.Sign() <= 0 || b.Sign() <= 0 {
|
||||
z.SetInt64(0)
|
||||
if x != nil {
|
||||
x.SetInt64(0)
|
||||
}
|
||||
if y != nil {
|
||||
y.SetInt64(0)
|
||||
}
|
||||
return z
|
||||
}
|
||||
if x == nil && y == nil {
|
||||
return z.binaryGCD(a, b)
|
||||
}
|
||||
|
||||
A := new(Int).Set(a)
|
||||
B := new(Int).Set(b)
|
||||
|
||||
X := new(Int)
|
||||
Y := new(Int).SetInt64(1)
|
||||
|
||||
lastX := new(Int).SetInt64(1)
|
||||
lastY := new(Int)
|
||||
|
||||
q := new(Int)
|
||||
temp := new(Int)
|
||||
|
||||
r := new(Int)
|
||||
for len(B.abs) > 0 {
|
||||
q, r = q.QuoRem(A, B, r)
|
||||
|
||||
A, B, r = B, r, A
|
||||
|
||||
temp.Set(X)
|
||||
X.Mul(X, q)
|
||||
X.neg = !X.neg
|
||||
X.Add(X, lastX)
|
||||
lastX.Set(temp)
|
||||
|
||||
temp.Set(Y)
|
||||
Y.Mul(Y, q)
|
||||
Y.neg = !Y.neg
|
||||
Y.Add(Y, lastY)
|
||||
lastY.Set(temp)
|
||||
}
|
||||
|
||||
if x != nil {
|
||||
*x = *lastX
|
||||
}
|
||||
|
||||
if y != nil {
|
||||
*y = *lastY
|
||||
}
|
||||
|
||||
*z = *A
|
||||
return z
|
||||
}
|
||||
|
||||
// binaryGCD sets z to the greatest common divisor of a and b, which both must
|
||||
// be > 0, and returns z.
|
||||
// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B.
|
||||
func (z *Int) binaryGCD(a, b *Int) *Int {
|
||||
u := z
|
||||
v := new(Int)
|
||||
|
||||
// use one Euclidean iteration to ensure that u and v are approx. the same size
|
||||
switch {
|
||||
case len(a.abs) > len(b.abs):
|
||||
// must set v before u since u may be alias for a or b (was issue #11284)
|
||||
v.Rem(a, b)
|
||||
u.Set(b)
|
||||
case len(a.abs) < len(b.abs):
|
||||
v.Rem(b, a)
|
||||
u.Set(a)
|
||||
default:
|
||||
v.Set(b)
|
||||
u.Set(a)
|
||||
}
|
||||
// a, b must not be used anymore (may be aliases with u)
|
||||
|
||||
// v might be 0 now
|
||||
if len(v.abs) == 0 {
|
||||
return u
|
||||
}
|
||||
// u > 0 && v > 0
|
||||
|
||||
// determine largest k such that u = u' << k, v = v' << k
|
||||
k := u.abs.trailingZeroBits()
|
||||
if vk := v.abs.trailingZeroBits(); vk < k {
|
||||
k = vk
|
||||
}
|
||||
u.Rsh(u, k)
|
||||
v.Rsh(v, k)
|
||||
|
||||
// determine t (we know that u > 0)
|
||||
t := new(Int)
|
||||
if u.abs[0]&1 != 0 {
|
||||
// u is odd
|
||||
t.Neg(v)
|
||||
} else {
|
||||
t.Set(u)
|
||||
}
|
||||
|
||||
for len(t.abs) > 0 {
|
||||
// reduce t
|
||||
t.Rsh(t, t.abs.trailingZeroBits())
|
||||
if t.neg {
|
||||
v, t = t, v
|
||||
v.neg = len(v.abs) > 0 && !v.neg // 0 has no sign
|
||||
} else {
|
||||
u, t = t, u
|
||||
}
|
||||
t.Sub(u, v)
|
||||
}
|
||||
|
||||
return z.Lsh(u, k)
|
||||
}
|
||||
|
||||
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
|
||||
// If x is prime, it returns true.
|
||||
// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
|
||||
//
|
||||
// It is not suitable for judging primes that an adversary may have crafted
|
||||
// to fool this test.
|
||||
func (x *Int) ProbablyPrime(n int) bool {
|
||||
if n <= 0 {
|
||||
panic("non-positive n for ProbablyPrime")
|
||||
}
|
||||
return !x.neg && x.abs.probablyPrime(n)
|
||||
}
|
||||
|
||||
// Rand sets z to a pseudo-random number in [0, n) and returns z.
|
||||
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
|
||||
z.neg = false
|
||||
if n.neg == true || len(n.abs) == 0 {
|
||||
z.abs = nil
|
||||
return z
|
||||
}
|
||||
z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen())
|
||||
return z
|
||||
}
|
||||
|
||||
// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ
|
||||
// and returns z. If g and n are not relatively prime, the result is undefined.
|
||||
func (z *Int) ModInverse(g, n *Int) *Int {
|
||||
var d Int
|
||||
d.GCD(z, nil, g, n)
|
||||
// x and y are such that g*x + n*y = d. Since g and n are
|
||||
// relatively prime, d = 1. Taking that modulo n results in
|
||||
// g*x = 1, therefore x is the inverse element.
|
||||
if z.neg {
|
||||
z.Add(z, n)
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
// Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0.
|
||||
// The y argument must be an odd integer.
|
||||
func Jacobi(x, y *Int) int {
|
||||
if len(y.abs) == 0 || y.abs[0]&1 == 0 {
|
||||
panic(fmt.Sprintf("big: invalid 2nd argument to Int.Jacobi: need odd integer but got %s", y))
|
||||
}
|
||||
|
||||
// We use the formulation described in chapter 2, section 2.4,
|
||||
// "The Yacas Book of Algorithms":
|
||||
// http://yacas.sourceforge.net/Algo.book.pdf
|
||||
|
||||
var a, b, c Int
|
||||
a.Set(x)
|
||||
b.Set(y)
|
||||
j := 1
|
||||
|
||||
if b.neg {
|
||||
if a.neg {
|
||||
j = -1
|
||||
}
|
||||
b.neg = false
|
||||
}
|
||||
|
||||
for {
|
||||
if b.Cmp(intOne) == 0 {
|
||||
return j
|
||||
}
|
||||
if len(a.abs) == 0 {
|
||||
return 0
|
||||
}
|
||||
a.Mod(&a, &b)
|
||||
if len(a.abs) == 0 {
|
||||
return 0
|
||||
}
|
||||
// a > 0
|
||||
|
||||
// handle factors of 2 in 'a'
|
||||
s := a.abs.trailingZeroBits()
|
||||
if s&1 != 0 {
|
||||
bmod8 := b.abs[0] & 7
|
||||
if bmod8 == 3 || bmod8 == 5 {
|
||||
j = -j
|
||||
}
|
||||
}
|
||||
c.Rsh(&a, s) // a = 2^s*c
|
||||
|
||||
// swap numerator and denominator
|
||||
if b.abs[0]&3 == 3 && c.abs[0]&3 == 3 {
|
||||
j = -j
|
||||
}
|
||||
a.Set(&b)
|
||||
b.Set(&c)
|
||||
}
|
||||
}
|
||||
|
||||
// modSqrt3Mod4 uses the identity
|
||||
// (a^((p+1)/4))^2 mod p
|
||||
// == u^(p+1) mod p
|
||||
// == u^2 mod p
|
||||
// to calculate the square root of any quadratic residue mod p quickly for 3
|
||||
// mod 4 primes.
|
||||
func (z *Int) modSqrt3Mod4Prime(x, p *Int) *Int {
|
||||
z.Set(p) // z = p
|
||||
z.Add(z, intOne) // z = p + 1
|
||||
z.Rsh(z, 2) // z = (p + 1) / 4
|
||||
z.Exp(x, z, p) // z = x^z mod p
|
||||
return z
|
||||
}
|
||||
|
||||
// modSqrtTonelliShanks uses the Tonelli-Shanks algorithm to find the square
|
||||
// root of a quadratic residue modulo any prime.
|
||||
func (z *Int) modSqrtTonelliShanks(x, p *Int) *Int {
|
||||
// Break p-1 into s*2^e such that s is odd.
|
||||
var s Int
|
||||
s.Sub(p, intOne)
|
||||
e := s.abs.trailingZeroBits()
|
||||
s.Rsh(&s, e)
|
||||
|
||||
// find some non-square n
|
||||
var n Int
|
||||
n.SetInt64(2)
|
||||
for Jacobi(&n, p) != -1 {
|
||||
n.Add(&n, intOne)
|
||||
}
|
||||
|
||||
// Core of the Tonelli-Shanks algorithm. Follows the description in
|
||||
// section 6 of "Square roots from 1; 24, 51, 10 to Dan Shanks" by Ezra
|
||||
// Brown:
|
||||
// https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf
|
||||
var y, b, g, t Int
|
||||
y.Add(&s, intOne)
|
||||
y.Rsh(&y, 1)
|
||||
y.Exp(x, &y, p) // y = x^((s+1)/2)
|
||||
b.Exp(x, &s, p) // b = x^s
|
||||
g.Exp(&n, &s, p) // g = n^s
|
||||
r := e
|
||||
for {
|
||||
// find the least m such that ord_p(b) = 2^m
|
||||
var m uint
|
||||
t.Set(&b)
|
||||
for t.Cmp(intOne) != 0 {
|
||||
t.Mul(&t, &t).Mod(&t, p)
|
||||
m++
|
||||
}
|
||||
|
||||
if m == 0 {
|
||||
return z.Set(&y)
|
||||
}
|
||||
|
||||
t.SetInt64(0).SetBit(&t, int(r-m-1), 1).Exp(&g, &t, p)
|
||||
// t = g^(2^(r-m-1)) mod p
|
||||
g.Mul(&t, &t).Mod(&g, p) // g = g^(2^(r-m)) mod p
|
||||
y.Mul(&y, &t).Mod(&y, p)
|
||||
b.Mul(&b, &g).Mod(&b, p)
|
||||
r = m
|
||||
}
|
||||
}
|
||||
|
||||
// ModSqrt sets z to a square root of x mod p if such a square root exists, and
|
||||
// returns z. The modulus p must be an odd prime. If x is not a square mod p,
|
||||
// ModSqrt leaves z unchanged and returns nil. This function panics if p is
|
||||
// not an odd integer.
|
||||
func (z *Int) ModSqrt(x, p *Int) *Int {
|
||||
switch Jacobi(x, p) {
|
||||
case -1:
|
||||
return nil // x is not a square mod p
|
||||
case 0:
|
||||
return z.SetInt64(0) // sqrt(0) mod p = 0
|
||||
case 1:
|
||||
break
|
||||
}
|
||||
if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
|
||||
x = new(Int).Mod(x, p)
|
||||
}
|
||||
|
||||
// Check whether p is 3 mod 4, and if so, use the faster algorithm.
|
||||
if len(p.abs) > 0 && p.abs[0]%4 == 3 {
|
||||
return z.modSqrt3Mod4Prime(x, p)
|
||||
}
|
||||
// Otherwise, use Tonelli-Shanks.
|
||||
return z.modSqrtTonelliShanks(x, p)
|
||||
}
|
||||
|
||||
// Lsh sets z = x << n and returns z.
|
||||
func (z *Int) Lsh(x *Int, n uint) *Int {
|
||||
z.abs = z.abs.shl(x.abs, n)
|
||||
z.neg = x.neg
|
||||
return z
|
||||
}
|
||||
|
||||
// Rsh sets z = x >> n and returns z.
|
||||
func (z *Int) Rsh(x *Int, n uint) *Int {
|
||||
if x.neg {
|
||||
// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
|
||||
t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0
|
||||
t = t.shr(t, n)
|
||||
z.abs = t.add(t, natOne)
|
||||
z.neg = true // z cannot be zero if x is negative
|
||||
return z
|
||||
}
|
||||
|
||||
z.abs = z.abs.shr(x.abs, n)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// Bit returns the value of the i'th bit of x. That is, it
|
||||
// returns (x>>i)&1. The bit index i must be >= 0.
|
||||
func (x *Int) Bit(i int) uint {
|
||||
if i == 0 {
|
||||
// optimization for common case: odd/even test of x
|
||||
if len(x.abs) > 0 {
|
||||
return uint(x.abs[0] & 1) // bit 0 is same for -x
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if i < 0 {
|
||||
panic("negative bit index")
|
||||
}
|
||||
if x.neg {
|
||||
t := nat(nil).sub(x.abs, natOne)
|
||||
return t.bit(uint(i)) ^ 1
|
||||
}
|
||||
|
||||
return x.abs.bit(uint(i))
|
||||
}
|
||||
|
||||
// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
|
||||
// That is, if b is 1 SetBit sets z = x | (1 << i);
|
||||
// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
|
||||
// SetBit will panic.
|
||||
func (z *Int) SetBit(x *Int, i int, b uint) *Int {
|
||||
if i < 0 {
|
||||
panic("negative bit index")
|
||||
}
|
||||
if x.neg {
|
||||
t := z.abs.sub(x.abs, natOne)
|
||||
t = t.setBit(t, uint(i), b^1)
|
||||
z.abs = t.add(t, natOne)
|
||||
z.neg = len(z.abs) > 0
|
||||
return z
|
||||
}
|
||||
z.abs = z.abs.setBit(x.abs, uint(i), b)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// And sets z = x & y and returns z.
|
||||
func (z *Int) And(x, y *Int) *Int {
|
||||
if x.neg == y.neg {
|
||||
if x.neg {
|
||||
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
|
||||
x1 := nat(nil).sub(x.abs, natOne)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
|
||||
z.neg = true // z cannot be zero if x and y are negative
|
||||
return z
|
||||
}
|
||||
|
||||
// x & y == x & y
|
||||
z.abs = z.abs.and(x.abs, y.abs)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// x.neg != y.neg
|
||||
if x.neg {
|
||||
x, y = y, x // & is symmetric
|
||||
}
|
||||
|
||||
// x & (-y) == x & ^(y-1) == x &^ (y-1)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.andNot(x.abs, y1)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// AndNot sets z = x &^ y and returns z.
|
||||
func (z *Int) AndNot(x, y *Int) *Int {
|
||||
if x.neg == y.neg {
|
||||
if x.neg {
|
||||
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
|
||||
x1 := nat(nil).sub(x.abs, natOne)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.andNot(y1, x1)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// x &^ y == x &^ y
|
||||
z.abs = z.abs.andNot(x.abs, y.abs)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
if x.neg {
|
||||
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
|
||||
x1 := nat(nil).sub(x.abs, natOne)
|
||||
z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
|
||||
z.neg = true // z cannot be zero if x is negative and y is positive
|
||||
return z
|
||||
}
|
||||
|
||||
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.and(x.abs, y1)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// Or sets z = x | y and returns z.
|
||||
func (z *Int) Or(x, y *Int) *Int {
|
||||
if x.neg == y.neg {
|
||||
if x.neg {
|
||||
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
|
||||
x1 := nat(nil).sub(x.abs, natOne)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
|
||||
z.neg = true // z cannot be zero if x and y are negative
|
||||
return z
|
||||
}
|
||||
|
||||
// x | y == x | y
|
||||
z.abs = z.abs.or(x.abs, y.abs)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// x.neg != y.neg
|
||||
if x.neg {
|
||||
x, y = y, x // | is symmetric
|
||||
}
|
||||
|
||||
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
|
||||
z.neg = true // z cannot be zero if one of x or y is negative
|
||||
return z
|
||||
}
|
||||
|
||||
// Xor sets z = x ^ y and returns z.
|
||||
func (z *Int) Xor(x, y *Int) *Int {
|
||||
if x.neg == y.neg {
|
||||
if x.neg {
|
||||
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
|
||||
x1 := nat(nil).sub(x.abs, natOne)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.xor(x1, y1)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// x ^ y == x ^ y
|
||||
z.abs = z.abs.xor(x.abs, y.abs)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// x.neg != y.neg
|
||||
if x.neg {
|
||||
x, y = y, x // ^ is symmetric
|
||||
}
|
||||
|
||||
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
|
||||
y1 := nat(nil).sub(y.abs, natOne)
|
||||
z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
|
||||
z.neg = true // z cannot be zero if only one of x or y is negative
|
||||
return z
|
||||
}
|
||||
|
||||
// Not sets z = ^x and returns z.
|
||||
func (z *Int) Not(x *Int) *Int {
|
||||
if x.neg {
|
||||
// ^(-x) == ^(^(x-1)) == x-1
|
||||
z.abs = z.abs.sub(x.abs, natOne)
|
||||
z.neg = false
|
||||
return z
|
||||
}
|
||||
|
||||
// ^x == -x-1 == -(x+1)
|
||||
z.abs = z.abs.add(x.abs, natOne)
|
||||
z.neg = true // z cannot be zero if x is positive
|
||||
return z
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,248 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements int-to-string conversion functions.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// TODO(gri) Should rename itoa to utoa (there's no sign). That
|
||||
// would permit the introduction of itoa which is like utoa but
|
||||
// reserves a byte for a possible sign that's passed in. That
|
||||
// would permit Int.Text to be implemented w/o the need for
|
||||
// string copy if the number is negative.
|
||||
|
||||
// Text returns the string representation of x in the given base.
|
||||
// Base must be between 2 and 36, inclusive. The result uses the
|
||||
// lower-case letters 'a' to 'z' for digit values >= 10. No base
|
||||
// prefix (such as "0x") is added to the string.
|
||||
func (x *Int) Text(base int) string {
|
||||
if x == nil {
|
||||
return "<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
|
||||
}
|
||||
|
|
@ -1,391 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var stringTests = []struct {
|
||||
in string
|
||||
out string
|
||||
base int
|
||||
val int64
|
||||
ok bool
|
||||
}{
|
||||
{in: ""},
|
||||
{in: "a"},
|
||||
{in: "z"},
|
||||
{in: "+"},
|
||||
{in: "-"},
|
||||
{in: "0b"},
|
||||
{in: "0x"},
|
||||
{in: "2", base: 2},
|
||||
{in: "0b2", base: 0},
|
||||
{in: "08"},
|
||||
{in: "8", base: 8},
|
||||
{in: "0xg", base: 0},
|
||||
{in: "g", base: 16},
|
||||
{"0", "0", 0, 0, true},
|
||||
{"0", "0", 10, 0, true},
|
||||
{"0", "0", 16, 0, true},
|
||||
{"+0", "0", 0, 0, true},
|
||||
{"-0", "0", 0, 0, true},
|
||||
{"10", "10", 0, 10, true},
|
||||
{"10", "10", 10, 10, true},
|
||||
{"10", "10", 16, 16, true},
|
||||
{"-10", "-10", 16, -16, true},
|
||||
{"+10", "10", 16, 16, true},
|
||||
{"0x10", "16", 0, 16, true},
|
||||
{in: "0x10", base: 16},
|
||||
{"-0x10", "-16", 0, -16, true},
|
||||
{"+0x10", "16", 0, 16, true},
|
||||
{"00", "0", 0, 0, true},
|
||||
{"0", "0", 8, 0, true},
|
||||
{"07", "7", 0, 7, true},
|
||||
{"7", "7", 8, 7, true},
|
||||
{"023", "19", 0, 19, true},
|
||||
{"23", "23", 8, 19, true},
|
||||
{"cafebabe", "cafebabe", 16, 0xcafebabe, true},
|
||||
{"0b0", "0", 0, 0, true},
|
||||
{"-111", "-111", 2, -7, true},
|
||||
{"-0b111", "-7", 0, -7, true},
|
||||
{"0b1001010111", "599", 0, 0x257, true},
|
||||
{"1001010111", "1001010111", 2, 0x257, true},
|
||||
}
|
||||
|
||||
func TestIntText(t *testing.T) {
|
||||
z := new(Int)
|
||||
for _, test := range stringTests {
|
||||
if !test.ok {
|
||||
continue
|
||||
}
|
||||
|
||||
_, ok := z.SetString(test.in, test.base)
|
||||
if !ok {
|
||||
t.Errorf("%v: failed to parse", test)
|
||||
continue
|
||||
}
|
||||
|
||||
base := test.base
|
||||
if base == 0 {
|
||||
base = 10
|
||||
}
|
||||
|
||||
if got := z.Text(base); got != test.out {
|
||||
t.Errorf("%v: got %s; want %s", test, got, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendText(t *testing.T) {
|
||||
z := new(Int)
|
||||
var buf []byte
|
||||
for _, test := range stringTests {
|
||||
if !test.ok {
|
||||
continue
|
||||
}
|
||||
|
||||
_, ok := z.SetString(test.in, test.base)
|
||||
if !ok {
|
||||
t.Errorf("%v: failed to parse", test)
|
||||
continue
|
||||
}
|
||||
|
||||
base := test.base
|
||||
if base == 0 {
|
||||
base = 10
|
||||
}
|
||||
|
||||
i := len(buf)
|
||||
buf = z.Append(buf, base)
|
||||
if got := string(buf[i:]); got != test.out {
|
||||
t.Errorf("%v: got %s; want %s", test, got, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func format(base int) string {
|
||||
switch base {
|
||||
case 2:
|
||||
return "%b"
|
||||
case 8:
|
||||
return "%o"
|
||||
case 16:
|
||||
return "%x"
|
||||
}
|
||||
return "%d"
|
||||
}
|
||||
|
||||
func TestGetString(t *testing.T) {
|
||||
z := new(Int)
|
||||
for i, test := range stringTests {
|
||||
if !test.ok {
|
||||
continue
|
||||
}
|
||||
z.SetInt64(test.val)
|
||||
|
||||
if test.base == 10 {
|
||||
if got := z.String(); got != test.out {
|
||||
t.Errorf("#%da got %s; want %s", i, got, test.out)
|
||||
}
|
||||
}
|
||||
|
||||
if got := fmt.Sprintf(format(test.base), z); got != test.out {
|
||||
t.Errorf("#%db got %s; want %s", i, got, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetString(t *testing.T) {
|
||||
tmp := new(Int)
|
||||
for i, test := range stringTests {
|
||||
// initialize to a non-zero value so that issues with parsing
|
||||
// 0 are detected
|
||||
tmp.SetInt64(1234567890)
|
||||
n1, ok1 := new(Int).SetString(test.in, test.base)
|
||||
n2, ok2 := tmp.SetString(test.in, test.base)
|
||||
expected := NewInt(test.val)
|
||||
if ok1 != test.ok || ok2 != test.ok {
|
||||
t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
|
||||
continue
|
||||
}
|
||||
if !ok1 {
|
||||
if n1 != nil {
|
||||
t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !ok2 {
|
||||
if n2 != nil {
|
||||
t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if ok1 && !isNormalized(n1) {
|
||||
t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
|
||||
}
|
||||
if ok2 && !isNormalized(n2) {
|
||||
t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
|
||||
}
|
||||
|
||||
if n1.Cmp(expected) != 0 {
|
||||
t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
|
||||
}
|
||||
if n2.Cmp(expected) != 0 {
|
||||
t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var formatTests = []struct {
|
||||
input string
|
||||
format string
|
||||
output string
|
||||
}{
|
||||
{"<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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements encoding/decoding of Ints.
|
||||
|
||||
package big
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||
const intGobVersion byte = 1
|
||||
|
||||
// GobEncode implements the gob.GobEncoder interface.
|
||||
func (x *Int) GobEncode() ([]byte, error) {
|
||||
if x == nil {
|
||||
return nil, nil
|
||||
}
|
||||
buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
|
||||
i := x.abs.bytes(buf) - 1 // i >= 0
|
||||
b := intGobVersion << 1 // make space for sign bit
|
||||
if x.neg {
|
||||
b |= 1
|
||||
}
|
||||
buf[i] = b
|
||||
return buf[i:], nil
|
||||
}
|
||||
|
||||
// GobDecode implements the gob.GobDecoder interface.
|
||||
func (z *Int) GobDecode(buf []byte) error {
|
||||
if len(buf) == 0 {
|
||||
// Other side sent a nil or default value.
|
||||
*z = Int{}
|
||||
return nil
|
||||
}
|
||||
b := buf[0]
|
||||
if b>>1 != intGobVersion {
|
||||
return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
|
||||
}
|
||||
z.neg = b&1 != 0
|
||||
z.abs = z.abs.setBytes(buf[1:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface.
|
||||
func (x *Int) MarshalText() (text []byte, err error) {
|
||||
if x == nil {
|
||||
return []byte("<nil>"), 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)
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var encodingTests = []string{
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"10",
|
||||
"1000",
|
||||
"1234567890",
|
||||
"298472983472983471903246121093472394872319615612417471234712061",
|
||||
}
|
||||
|
||||
func TestIntGobEncoding(t *testing.T) {
|
||||
var medium bytes.Buffer
|
||||
enc := gob.NewEncoder(&medium)
|
||||
dec := gob.NewDecoder(&medium)
|
||||
for _, test := range encodingTests {
|
||||
for _, sign := range []string{"", "+", "-"} {
|
||||
x := sign + test
|
||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||
var tx Int
|
||||
tx.SetString(x, 10)
|
||||
if err := enc.Encode(&tx); err != nil {
|
||||
t.Errorf("encoding of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Int
|
||||
if err := dec.Decode(&rx); err != nil {
|
||||
t.Errorf("decoding of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
|
||||
// TODO: top-level nils.
|
||||
func TestGobEncodingNilIntInSlice(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
enc := gob.NewEncoder(buf)
|
||||
dec := gob.NewDecoder(buf)
|
||||
|
||||
var in = make([]*Int, 1)
|
||||
err := enc.Encode(&in)
|
||||
if err != nil {
|
||||
t.Errorf("gob encode failed: %q", err)
|
||||
}
|
||||
var out []*Int
|
||||
err = dec.Decode(&out)
|
||||
if err != nil {
|
||||
t.Fatalf("gob decode failed: %q", err)
|
||||
}
|
||||
if len(out) != 1 {
|
||||
t.Fatalf("wrong len; want 1 got %d", len(out))
|
||||
}
|
||||
var zero Int
|
||||
if out[0].Cmp(&zero) != 0 {
|
||||
t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntJSONEncoding(t *testing.T) {
|
||||
for _, test := range encodingTests {
|
||||
for _, sign := range []string{"", "+", "-"} {
|
||||
x := sign + test
|
||||
var tx Int
|
||||
tx.SetString(x, 10)
|
||||
b, err := json.Marshal(&tx)
|
||||
if err != nil {
|
||||
t.Errorf("marshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Int
|
||||
if err := json.Unmarshal(b, &rx); err != nil {
|
||||
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntXMLEncoding(t *testing.T) {
|
||||
for _, test := range encodingTests {
|
||||
for _, sign := range []string{"", "+", "-"} {
|
||||
x := sign + test
|
||||
var tx Int
|
||||
tx.SetString(x, 0)
|
||||
b, err := xml.Marshal(&tx)
|
||||
if err != nil {
|
||||
t.Errorf("marshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Int
|
||||
if err := xml.Unmarshal(b, &rx); err != nil {
|
||||
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,651 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var cmpTests = []struct {
|
||||
x, y nat
|
||||
r int
|
||||
}{
|
||||
{nil, nil, 0},
|
||||
{nil, nat(nil), 0},
|
||||
{nat(nil), nil, 0},
|
||||
{nat(nil), nat(nil), 0},
|
||||
{nat{0}, nat{0}, 0},
|
||||
{nat{0}, nat{1}, -1},
|
||||
{nat{1}, nat{0}, 1},
|
||||
{nat{1}, nat{1}, 0},
|
||||
{nat{0, _M}, nat{1}, 1},
|
||||
{nat{1}, nat{0, _M}, -1},
|
||||
{nat{1, _M}, nat{0, _M}, 1},
|
||||
{nat{0, _M}, nat{1, _M}, -1},
|
||||
{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
|
||||
{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
|
||||
}
|
||||
|
||||
func TestCmp(t *testing.T) {
|
||||
for i, a := range cmpTests {
|
||||
r := a.x.cmp(a.y)
|
||||
if r != a.r {
|
||||
t.Errorf("#%d got r = %v; want %v", i, r, a.r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type funNN func(z, x, y nat) nat
|
||||
type argNN struct {
|
||||
z, x, y nat
|
||||
}
|
||||
|
||||
var sumNN = []argNN{
|
||||
{},
|
||||
{nat{1}, nil, nat{1}},
|
||||
{nat{1111111110}, nat{123456789}, nat{987654321}},
|
||||
{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
|
||||
{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
|
||||
{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
|
||||
}
|
||||
|
||||
var prodNN = []argNN{
|
||||
{},
|
||||
{nil, nil, nil},
|
||||
{nil, nat{991}, nil},
|
||||
{nat{991}, nat{991}, nat{1}},
|
||||
{nat{991 * 991}, nat{991}, nat{991}},
|
||||
{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
|
||||
{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
|
||||
{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
|
||||
// 3^100 * 3^28 = 3^128
|
||||
{
|
||||
natFromString("11790184577738583171520872861412518665678211592275841109096961"),
|
||||
natFromString("515377520732011331036461129765621272702107522001"),
|
||||
natFromString("22876792454961"),
|
||||
},
|
||||
// z = 111....1 (70000 digits)
|
||||
// x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
|
||||
// y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
|
||||
{
|
||||
natFromString(strings.Repeat("1", 70000)),
|
||||
natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
|
||||
natFromString(strings.Repeat("1", 700)),
|
||||
},
|
||||
// z = 111....1 (20000 digits)
|
||||
// x = 10^10000 + 1
|
||||
// y = 111....1 (10000 digits)
|
||||
{
|
||||
natFromString(strings.Repeat("1", 20000)),
|
||||
natFromString("1" + strings.Repeat("0", 9999) + "1"),
|
||||
natFromString(strings.Repeat("1", 10000)),
|
||||
},
|
||||
}
|
||||
|
||||
func natFromString(s string) nat {
|
||||
x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
for _, a := range sumNN {
|
||||
z := nat(nil).set(a.z)
|
||||
if z.cmp(a.z) != 0 {
|
||||
t.Errorf("got z = %v; want %v", z, a.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
|
||||
z := f(nil, a.x, a.y)
|
||||
if z.cmp(a.z) != 0 {
|
||||
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunNN(t *testing.T) {
|
||||
for _, a := range sumNN {
|
||||
arg := a
|
||||
testFunNN(t, "add", nat.add, arg)
|
||||
|
||||
arg = argNN{a.z, a.y, a.x}
|
||||
testFunNN(t, "add symmetric", nat.add, arg)
|
||||
|
||||
arg = argNN{a.x, a.z, a.y}
|
||||
testFunNN(t, "sub", nat.sub, arg)
|
||||
|
||||
arg = argNN{a.y, a.z, a.x}
|
||||
testFunNN(t, "sub symmetric", nat.sub, arg)
|
||||
}
|
||||
|
||||
for _, a := range prodNN {
|
||||
arg := a
|
||||
testFunNN(t, "mul", nat.mul, arg)
|
||||
|
||||
arg = argNN{a.z, a.y, a.x}
|
||||
testFunNN(t, "mul symmetric", nat.mul, arg)
|
||||
}
|
||||
}
|
||||
|
||||
var mulRangesN = []struct {
|
||||
a, b uint64
|
||||
prod string
|
||||
}{
|
||||
{0, 0, "0"},
|
||||
{1, 1, "1"},
|
||||
{1, 2, "2"},
|
||||
{1, 3, "6"},
|
||||
{10, 10, "10"},
|
||||
{0, 100, "0"},
|
||||
{0, 1e9, "0"},
|
||||
{1, 0, "1"}, // empty range
|
||||
{100, 1, "1"}, // empty range
|
||||
{1, 10, "3628800"}, // 10!
|
||||
{1, 20, "2432902008176640000"}, // 20!
|
||||
{1, 100,
|
||||
"933262154439441526816992388562667004907159682643816214685929" +
|
||||
"638952175999932299156089414639761565182862536979208272237582" +
|
||||
"51185210916864000000000000000000000000", // 100!
|
||||
},
|
||||
}
|
||||
|
||||
func TestMulRangeN(t *testing.T) {
|
||||
for i, r := range mulRangesN {
|
||||
prod := string(nat(nil).mulRange(r.a, r.b).utoa(10))
|
||||
if prod != r.prod {
|
||||
t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allocBytes returns the number of bytes allocated by invoking f.
|
||||
func allocBytes(f func()) uint64 {
|
||||
var stats runtime.MemStats
|
||||
runtime.ReadMemStats(&stats)
|
||||
t := stats.TotalAlloc
|
||||
f()
|
||||
runtime.ReadMemStats(&stats)
|
||||
return stats.TotalAlloc - t
|
||||
}
|
||||
|
||||
// TestMulUnbalanced tests that multiplying numbers of different lengths
|
||||
// does not cause deep recursion and in turn allocate too much memory.
|
||||
// Test case for issue 3807.
|
||||
func TestMulUnbalanced(t *testing.T) {
|
||||
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
|
||||
x := rndNat(50000)
|
||||
y := rndNat(40)
|
||||
allocSize := allocBytes(func() {
|
||||
nat(nil).mul(x, y)
|
||||
})
|
||||
inputSize := uint64(len(x)+len(y)) * _S
|
||||
if ratio := allocSize / uint64(inputSize); ratio > 10 {
|
||||
t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
|
||||
}
|
||||
}
|
||||
|
||||
func rndNat(n int) nat {
|
||||
return nat(rndV(n)).norm()
|
||||
}
|
||||
|
||||
func BenchmarkMul(b *testing.B) {
|
||||
mulx := rndNat(1e4)
|
||||
muly := rndNat(1e4)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var z nat
|
||||
z.mul(mulx, muly)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNLZ(t *testing.T) {
|
||||
var x Word = _B >> 1
|
||||
for i := 0; i <= _W; i++ {
|
||||
if int(nlz(x)) != i {
|
||||
t.Errorf("failed at %x: got %d want %d", x, nlz(x), i)
|
||||
}
|
||||
x >>= 1
|
||||
}
|
||||
}
|
||||
|
||||
type shiftTest struct {
|
||||
in nat
|
||||
shift uint
|
||||
out nat
|
||||
}
|
||||
|
||||
var leftShiftTests = []shiftTest{
|
||||
{nil, 0, nil},
|
||||
{nil, 1, nil},
|
||||
{natOne, 0, natOne},
|
||||
{natOne, 1, natTwo},
|
||||
{nat{1 << (_W - 1)}, 1, nat{0}},
|
||||
{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
|
||||
}
|
||||
|
||||
func TestShiftLeft(t *testing.T) {
|
||||
for i, test := range leftShiftTests {
|
||||
var z nat
|
||||
z = z.shl(test.in, test.shift)
|
||||
for j, d := range test.out {
|
||||
if j >= len(z) || z[j] != d {
|
||||
t.Errorf("#%d: got: %v want: %v", i, z, test.out)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rightShiftTests = []shiftTest{
|
||||
{nil, 0, nil},
|
||||
{nil, 1, nil},
|
||||
{natOne, 0, natOne},
|
||||
{natOne, 1, nil},
|
||||
{natTwo, 1, natOne},
|
||||
{nat{0, 1}, 1, nat{1 << (_W - 1)}},
|
||||
{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
|
||||
}
|
||||
|
||||
func TestShiftRight(t *testing.T) {
|
||||
for i, test := range rightShiftTests {
|
||||
var z nat
|
||||
z = z.shr(test.in, test.shift)
|
||||
for j, d := range test.out {
|
||||
if j >= len(z) || z[j] != d {
|
||||
t.Errorf("#%d: got: %v want: %v", i, z, test.out)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type modWTest struct {
|
||||
in string
|
||||
dividend string
|
||||
out string
|
||||
}
|
||||
|
||||
var modWTests32 = []modWTest{
|
||||
{"23492635982634928349238759823742", "252341", "220170"},
|
||||
}
|
||||
|
||||
var modWTests64 = []modWTest{
|
||||
{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
|
||||
}
|
||||
|
||||
func runModWTests(t *testing.T, tests []modWTest) {
|
||||
for i, test := range tests {
|
||||
in, _ := new(Int).SetString(test.in, 10)
|
||||
d, _ := new(Int).SetString(test.dividend, 10)
|
||||
out, _ := new(Int).SetString(test.out, 10)
|
||||
|
||||
r := in.abs.modW(d.abs[0])
|
||||
if r != out.abs[0] {
|
||||
t.Errorf("#%d failed: got %d want %s", i, r, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestModW(t *testing.T) {
|
||||
if _W >= 32 {
|
||||
runModWTests(t, modWTests32)
|
||||
}
|
||||
if _W >= 64 {
|
||||
runModWTests(t, modWTests64)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrailingZeroBits(t *testing.T) {
|
||||
// test 0 case explicitly
|
||||
if n := trailingZeroBits(0); n != 0 {
|
||||
t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
|
||||
}
|
||||
|
||||
x := Word(1)
|
||||
for i := uint(0); i < _W; i++ {
|
||||
n := trailingZeroBits(x)
|
||||
if n != i {
|
||||
t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
|
||||
}
|
||||
x <<= 1
|
||||
}
|
||||
|
||||
// test 0 case explicitly
|
||||
if n := nat(nil).trailingZeroBits(); n != 0 {
|
||||
t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
|
||||
}
|
||||
|
||||
y := nat(nil).set(natOne)
|
||||
for i := uint(0); i <= 3*_W; i++ {
|
||||
n := y.trailingZeroBits()
|
||||
if n != i {
|
||||
t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
|
||||
}
|
||||
y = y.shl(y, 1)
|
||||
}
|
||||
}
|
||||
|
||||
var montgomeryTests = []struct {
|
||||
x, y, m string
|
||||
k0 uint64
|
||||
out32, out64 string
|
||||
}{
|
||||
{
|
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
|
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
|
||||
"0xfffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
1,
|
||||
"0x1000000000000000000000000000000000000000000",
|
||||
"0x10000000000000000000000000000000000",
|
||||
},
|
||||
{
|
||||
"0x000000000ffffff5",
|
||||
"0x000000000ffffff0",
|
||||
"0x0000000010000001",
|
||||
0xff0000000fffffff,
|
||||
"0x000000000bfffff4",
|
||||
"0x0000000003400001",
|
||||
},
|
||||
{
|
||||
"0x0000000080000000",
|
||||
"0x00000000ffffffff",
|
||||
"0x1000000000000001",
|
||||
0xfffffffffffffff,
|
||||
"0x0800000008000001",
|
||||
"0x0800000008000001",
|
||||
},
|
||||
{
|
||||
"0x0000000080000000",
|
||||
"0x0000000080000000",
|
||||
"0xffffffff00000001",
|
||||
0xfffffffeffffffff,
|
||||
"0xbfffffff40000001",
|
||||
"0xbfffffff40000001",
|
||||
},
|
||||
{
|
||||
"0x0000000080000000",
|
||||
"0x0000000080000000",
|
||||
"0x00ffffff00000001",
|
||||
0xfffffeffffffff,
|
||||
"0xbfffff40000001",
|
||||
"0xbfffff40000001",
|
||||
},
|
||||
{
|
||||
"0x0000000080000000",
|
||||
"0x0000000080000000",
|
||||
"0x0000ffff00000001",
|
||||
0xfffeffffffff,
|
||||
"0xbfff40000001",
|
||||
"0xbfff40000001",
|
||||
},
|
||||
{
|
||||
"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
|
||||
"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
|
||||
"0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
|
||||
0xdecc8f1249812adf,
|
||||
"0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5",
|
||||
"0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0",
|
||||
},
|
||||
{
|
||||
"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
|
||||
"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
|
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
|
||||
0xdecc8f1249812adf,
|
||||
"0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715",
|
||||
"0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6",
|
||||
},
|
||||
}
|
||||
|
||||
func TestMontgomery(t *testing.T) {
|
||||
one := NewInt(1)
|
||||
_B := new(Int).Lsh(one, _W)
|
||||
for i, test := range montgomeryTests {
|
||||
x := natFromString(test.x)
|
||||
y := natFromString(test.y)
|
||||
m := natFromString(test.m)
|
||||
for len(x) < len(m) {
|
||||
x = append(x, 0)
|
||||
}
|
||||
for len(y) < len(m) {
|
||||
y = append(y, 0)
|
||||
}
|
||||
|
||||
if x.cmp(m) > 0 {
|
||||
_, r := nat(nil).div(nil, x, m)
|
||||
t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16))
|
||||
}
|
||||
if y.cmp(m) > 0 {
|
||||
_, r := nat(nil).div(nil, x, m)
|
||||
t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16))
|
||||
}
|
||||
|
||||
var out nat
|
||||
if _W == 32 {
|
||||
out = natFromString(test.out32)
|
||||
} else {
|
||||
out = natFromString(test.out64)
|
||||
}
|
||||
|
||||
// t.Logf("#%d: len=%d\n", i, len(m))
|
||||
|
||||
// check output in table
|
||||
xi := &Int{abs: x}
|
||||
yi := &Int{abs: y}
|
||||
mi := &Int{abs: m}
|
||||
p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi)
|
||||
if out.cmp(p.abs.norm()) != 0 {
|
||||
t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16))
|
||||
}
|
||||
|
||||
// check k0 in table
|
||||
k := new(Int).Mod(&Int{abs: m}, _B)
|
||||
k = new(Int).Sub(_B, k)
|
||||
k = new(Int).Mod(k, _B)
|
||||
k0 := Word(new(Int).ModInverse(k, _B).Uint64())
|
||||
if k0 != Word(test.k0) {
|
||||
t.Errorf("#%d: k0 in table=%#x, computed=%#x\n", i, test.k0, k0)
|
||||
}
|
||||
|
||||
// check montgomery with correct k0 produces correct output
|
||||
z := nat(nil).montgomery(x, y, m, k0, len(m))
|
||||
z = z.norm()
|
||||
if z.cmp(out) != 0 {
|
||||
t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var expNNTests = []struct {
|
||||
x, y, m string
|
||||
out string
|
||||
}{
|
||||
{"0", "0", "0", "1"},
|
||||
{"0", "0", "1", "0"},
|
||||
{"1", "1", "1", "0"},
|
||||
{"2", "1", "1", "0"},
|
||||
{"2", "2", "1", "0"},
|
||||
{"10", "100000000000", "1", "0"},
|
||||
{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
|
||||
{"0x8000000000000000", "2", "6719", "4944"},
|
||||
{"0x8000000000000000", "3", "6719", "5447"},
|
||||
{"0x8000000000000000", "1000", "6719", "1603"},
|
||||
{"0x8000000000000000", "1000000", "6719", "3199"},
|
||||
{
|
||||
"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
|
||||
"298472983472983471903246121093472394872319615612417471234712061",
|
||||
"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
|
||||
"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
|
||||
},
|
||||
{
|
||||
"11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
|
||||
"426343618817810911523",
|
||||
"444747819283133684179",
|
||||
"42",
|
||||
},
|
||||
}
|
||||
|
||||
func TestExpNN(t *testing.T) {
|
||||
for i, test := range expNNTests {
|
||||
x := natFromString(test.x)
|
||||
y := natFromString(test.y)
|
||||
out := natFromString(test.out)
|
||||
|
||||
var m nat
|
||||
if len(test.m) > 0 {
|
||||
m = natFromString(test.m)
|
||||
}
|
||||
|
||||
z := nat(nil).expNN(x, y, m)
|
||||
if z.cmp(out) != 0 {
|
||||
t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExp3Power(b *testing.B) {
|
||||
const x = 3
|
||||
for _, y := range []Word{
|
||||
0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000,
|
||||
} {
|
||||
b.Run(fmt.Sprintf("%#x", y), func(b *testing.B) {
|
||||
var z nat
|
||||
for i := 0; i < b.N; i++ {
|
||||
z.expWW(x, y)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func fibo(n int) nat {
|
||||
switch n {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
return nat{1}
|
||||
}
|
||||
f0 := fibo(0)
|
||||
f1 := fibo(1)
|
||||
var f2 nat
|
||||
for i := 1; i < n; i++ {
|
||||
f2 = f2.add(f0, f1)
|
||||
f0, f1, f2 = f1, f2, f0
|
||||
}
|
||||
return f1
|
||||
}
|
||||
|
||||
var fiboNums = []string{
|
||||
"0",
|
||||
"55",
|
||||
"6765",
|
||||
"832040",
|
||||
"102334155",
|
||||
"12586269025",
|
||||
"1548008755920",
|
||||
"190392490709135",
|
||||
"23416728348467685",
|
||||
"2880067194370816120",
|
||||
"354224848179261915075",
|
||||
}
|
||||
|
||||
func TestFibo(t *testing.T) {
|
||||
for i, want := range fiboNums {
|
||||
n := i * 10
|
||||
got := string(fibo(n).utoa(10))
|
||||
if got != want {
|
||||
t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFibo(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
fibo(1e0)
|
||||
fibo(1e1)
|
||||
fibo(1e2)
|
||||
fibo(1e3)
|
||||
fibo(1e4)
|
||||
fibo(1e5)
|
||||
}
|
||||
}
|
||||
|
||||
var bitTests = []struct {
|
||||
x string
|
||||
i uint
|
||||
want uint
|
||||
}{
|
||||
{"0", 0, 0},
|
||||
{"0", 1, 0},
|
||||
{"0", 1000, 0},
|
||||
|
||||
{"0x1", 0, 1},
|
||||
{"0x10", 0, 0},
|
||||
{"0x10", 3, 0},
|
||||
{"0x10", 4, 1},
|
||||
{"0x10", 5, 0},
|
||||
|
||||
{"0x8000000000000000", 62, 0},
|
||||
{"0x8000000000000000", 63, 1},
|
||||
{"0x8000000000000000", 64, 0},
|
||||
|
||||
{"0x3" + strings.Repeat("0", 32), 127, 0},
|
||||
{"0x3" + strings.Repeat("0", 32), 128, 1},
|
||||
{"0x3" + strings.Repeat("0", 32), 129, 1},
|
||||
{"0x3" + strings.Repeat("0", 32), 130, 0},
|
||||
}
|
||||
|
||||
func TestBit(t *testing.T) {
|
||||
for i, test := range bitTests {
|
||||
x := natFromString(test.x)
|
||||
if got := x.bit(test.i); got != test.want {
|
||||
t.Errorf("#%d: %s.bit(%d) = %v; want %v", i, test.x, test.i, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stickyTests = []struct {
|
||||
x string
|
||||
i uint
|
||||
want uint
|
||||
}{
|
||||
{"0", 0, 0},
|
||||
{"0", 1, 0},
|
||||
{"0", 1000, 0},
|
||||
|
||||
{"0x1", 0, 0},
|
||||
{"0x1", 1, 1},
|
||||
|
||||
{"0x1350", 0, 0},
|
||||
{"0x1350", 4, 0},
|
||||
{"0x1350", 5, 1},
|
||||
|
||||
{"0x8000000000000000", 63, 0},
|
||||
{"0x8000000000000000", 64, 1},
|
||||
|
||||
{"0x1" + strings.Repeat("0", 100), 400, 0},
|
||||
{"0x1" + strings.Repeat("0", 100), 401, 1},
|
||||
}
|
||||
|
||||
func TestSticky(t *testing.T) {
|
||||
for i, test := range stickyTests {
|
||||
x := natFromString(test.x)
|
||||
if got := x.sticky(test.i); got != test.want {
|
||||
t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i, got, test.want)
|
||||
}
|
||||
if test.want == 1 {
|
||||
// all subsequent i's should also return 1
|
||||
for d := uint(1); d <= 3; d++ {
|
||||
if got := x.sticky(test.i + d); got != 1 {
|
||||
t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i+d, got, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,492 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements nat-to-string conversion functions.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
// Note: MaxBase = len(digits), but it must remain a rune constant
|
||||
// for API compatibility.
|
||||
|
||||
// MaxBase is the largest number base accepted for string conversions.
|
||||
const MaxBase = 'z' - 'a' + 10 + 1
|
||||
|
||||
// maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
|
||||
// For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
|
||||
// In other words, at most n digits in base b fit into a Word.
|
||||
// TODO(gri) replace this with a table, generated at build time.
|
||||
func maxPow(b Word) (p Word, n int) {
|
||||
p, n = b, 1 // assuming b <= _M
|
||||
for max := _M / b; p <= max; {
|
||||
// p == b**n && p <= max
|
||||
p *= b
|
||||
n++
|
||||
}
|
||||
// p == b**n && p <= _M
|
||||
return
|
||||
}
|
||||
|
||||
// pow returns x**n for n > 0, and 1 otherwise.
|
||||
func pow(x Word, n int) (p Word) {
|
||||
// n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
|
||||
// thus x**n == product of x**(2**i) for all i where bi == 1
|
||||
// (Russian Peasant Method for exponentiation)
|
||||
p = 1
|
||||
for n > 0 {
|
||||
if n&1 != 0 {
|
||||
p *= x
|
||||
}
|
||||
x *= x
|
||||
n >>= 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// scan scans the number corresponding to the longest possible prefix
|
||||
// from r representing an unsigned number in a given conversion base.
|
||||
// It returns the corresponding natural number res, the actual base b,
|
||||
// a digit count, and a read or syntax error err, if any.
|
||||
//
|
||||
// number = [ prefix ] mantissa .
|
||||
// prefix = "0" [ "x" | "X" | "b" | "B" ] .
|
||||
// mantissa = digits | digits "." [ digits ] | "." digits .
|
||||
// digits = digit { digit } .
|
||||
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
|
||||
//
|
||||
// Unless fracOk is set, the base argument must be 0 or a value between
|
||||
// 2 and MaxBase. If fracOk is set, the base argument must be one of
|
||||
// 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
|
||||
// time panic.
|
||||
//
|
||||
// For base 0, the number prefix determines the actual base: A prefix of
|
||||
// ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
|
||||
// selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
|
||||
// the selected base is 10 and no prefix is accepted.
|
||||
//
|
||||
// If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
|
||||
// stands for a zero digit), and a period followed by a fractional part
|
||||
// is permitted. The result value is computed as if there were no period
|
||||
// present; and the count value is used to determine the fractional part.
|
||||
//
|
||||
// A result digit count > 0 corresponds to the number of (non-prefix) digits
|
||||
// parsed. A digit count <= 0 indicates the presence of a period (if fracOk
|
||||
// is set, only), and -count is the number of fractional digits found.
|
||||
// In this case, the actual value of the scanned number is res * b**count.
|
||||
//
|
||||
func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count int, err error) {
|
||||
// reject illegal bases
|
||||
baseOk := base == 0 ||
|
||||
!fracOk && 2 <= base && base <= MaxBase ||
|
||||
fracOk && (base == 2 || base == 10 || base == 16)
|
||||
if !baseOk {
|
||||
panic(fmt.Sprintf("illegal number base %d", base))
|
||||
}
|
||||
|
||||
// one char look-ahead
|
||||
ch, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// determine actual base
|
||||
b = base
|
||||
if base == 0 {
|
||||
// actual base is 10 unless there's a base prefix
|
||||
b = 10
|
||||
if ch == '0' {
|
||||
count = 1
|
||||
switch ch, err = r.ReadByte(); err {
|
||||
case nil:
|
||||
// possibly one of 0x, 0X, 0b, 0B
|
||||
if !fracOk {
|
||||
b = 8
|
||||
}
|
||||
switch ch {
|
||||
case 'x', 'X':
|
||||
b = 16
|
||||
case 'b', 'B':
|
||||
b = 2
|
||||
}
|
||||
switch b {
|
||||
case 16, 2:
|
||||
count = 0 // prefix is not counted
|
||||
if ch, err = r.ReadByte(); err != nil {
|
||||
// io.EOF is also an error in this case
|
||||
return
|
||||
}
|
||||
case 8:
|
||||
count = 0 // prefix is not counted
|
||||
}
|
||||
case io.EOF:
|
||||
// input is "0"
|
||||
res = z[:0]
|
||||
err = nil
|
||||
return
|
||||
default:
|
||||
// read error
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert string
|
||||
// Algorithm: Collect digits in groups of at most n digits in di
|
||||
// and then use mulAddWW for every such group to add them to the
|
||||
// result.
|
||||
z = z[:0]
|
||||
b1 := Word(b)
|
||||
bn, n := maxPow(b1) // at most n digits in base b1 fit into Word
|
||||
di := Word(0) // 0 <= di < b1**i < bn
|
||||
i := 0 // 0 <= i < n
|
||||
dp := -1 // position of decimal point
|
||||
for {
|
||||
if fracOk && ch == '.' {
|
||||
fracOk = false
|
||||
dp = count
|
||||
// advance
|
||||
if ch, err = r.ReadByte(); err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// convert rune into digit value d1
|
||||
var d1 Word
|
||||
switch {
|
||||
case '0' <= ch && ch <= '9':
|
||||
d1 = Word(ch - '0')
|
||||
case 'a' <= ch && ch <= 'z':
|
||||
d1 = Word(ch - 'a' + 10)
|
||||
case 'A' <= ch && ch <= 'Z':
|
||||
d1 = Word(ch - 'A' + 10)
|
||||
default:
|
||||
d1 = MaxBase + 1
|
||||
}
|
||||
if d1 >= b1 {
|
||||
r.UnreadByte() // ch does not belong to number anymore
|
||||
break
|
||||
}
|
||||
count++
|
||||
|
||||
// collect d1 in di
|
||||
di = di*b1 + d1
|
||||
i++
|
||||
|
||||
// if di is "full", add it to the result
|
||||
if i == n {
|
||||
z = z.mulAddWW(z, bn, di)
|
||||
di = 0
|
||||
i = 0
|
||||
}
|
||||
|
||||
// advance
|
||||
if ch, err = r.ReadByte(); err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
// no digits found
|
||||
switch {
|
||||
case base == 0 && b == 8:
|
||||
// there was only the octal prefix 0 (possibly followed by digits > 7);
|
||||
// count as one digit and return base 10, not 8
|
||||
count = 1
|
||||
b = 10
|
||||
case base != 0 || b != 8:
|
||||
// there was neither a mantissa digit nor the octal prefix 0
|
||||
err = errors.New("syntax error scanning number")
|
||||
}
|
||||
return
|
||||
}
|
||||
// count > 0
|
||||
|
||||
// add remaining digits to result
|
||||
if i > 0 {
|
||||
z = z.mulAddWW(z, pow(b1, i), di)
|
||||
}
|
||||
res = z.norm()
|
||||
|
||||
// adjust for fraction, if any
|
||||
if dp >= 0 {
|
||||
// 0 <= dp <= count > 0
|
||||
count = dp - count
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// utoa converts x to an ASCII representation in the given base;
|
||||
// base must be between 2 and MaxBase, inclusive.
|
||||
func (x nat) utoa(base int) []byte {
|
||||
return x.itoa(false, base)
|
||||
}
|
||||
|
||||
// itoa is like utoa but it prepends a '-' if neg && x != 0.
|
||||
func (x nat) itoa(neg bool, base int) []byte {
|
||||
if base < 2 || base > MaxBase {
|
||||
panic("invalid base")
|
||||
}
|
||||
|
||||
// x == 0
|
||||
if len(x) == 0 {
|
||||
return []byte("0")
|
||||
}
|
||||
// len(x) > 0
|
||||
|
||||
// allocate buffer for conversion
|
||||
i := int(float64(x.bitLen())/math.Log2(float64(base))) + 1 // off by 1 at most
|
||||
if neg {
|
||||
i++
|
||||
}
|
||||
s := make([]byte, i)
|
||||
|
||||
// convert power of two and non power of two bases separately
|
||||
if b := Word(base); b == b&-b {
|
||||
// shift is base b digit size in bits
|
||||
shift := trailingZeroBits(b) // shift > 0 because b >= 2
|
||||
mask := Word(1<<shift - 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
|
||||
}
|
||||
|
|
@ -1,379 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func itoa(x nat, base int) []byte {
|
||||
// special cases
|
||||
switch {
|
||||
case base < 2:
|
||||
panic("illegal base")
|
||||
case len(x) == 0:
|
||||
return []byte("0")
|
||||
}
|
||||
|
||||
// allocate buffer for conversion
|
||||
i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
|
||||
s := make([]byte, i)
|
||||
|
||||
// don't destroy x
|
||||
q := nat(nil).set(x)
|
||||
|
||||
// convert
|
||||
for len(q) > 0 {
|
||||
i--
|
||||
var r Word
|
||||
q, r = q.divW(q, Word(base))
|
||||
s[i] = digits[r]
|
||||
}
|
||||
|
||||
return s[i:]
|
||||
}
|
||||
|
||||
var strTests = []struct {
|
||||
x nat // nat value to be converted
|
||||
b int // conversion base
|
||||
s string // expected result
|
||||
}{
|
||||
{nil, 2, "0"},
|
||||
{nat{1}, 2, "1"},
|
||||
{nat{0xc5}, 2, "11000101"},
|
||||
{nat{03271}, 8, "3271"},
|
||||
{nat{10}, 10, "10"},
|
||||
{nat{1234567890}, 10, "1234567890"},
|
||||
{nat{0xdeadbeef}, 16, "deadbeef"},
|
||||
{nat{0x229be7}, 17, "1a2b3c"},
|
||||
{nat{0x309663e6}, 32, "o9cov6"},
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
// test invalid base explicitly
|
||||
var panicStr string
|
||||
func() {
|
||||
defer func() {
|
||||
panicStr = recover().(string)
|
||||
}()
|
||||
natOne.utoa(1)
|
||||
}()
|
||||
if panicStr != "invalid base" {
|
||||
t.Errorf("expected panic for invalid base")
|
||||
}
|
||||
|
||||
for _, a := range strTests {
|
||||
s := string(a.x.utoa(a.b))
|
||||
if s != a.s {
|
||||
t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
|
||||
}
|
||||
|
||||
x, b, _, err := nat(nil).scan(strings.NewReader(a.s), a.b, false)
|
||||
if x.cmp(a.x) != 0 {
|
||||
t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
|
||||
}
|
||||
if b != a.b {
|
||||
t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.b)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("scan%+v\n\tgot error = %s", a, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var natScanTests = []struct {
|
||||
s string // string to be scanned
|
||||
base int // input base
|
||||
frac bool // fraction ok
|
||||
x nat // expected nat
|
||||
b int // expected base
|
||||
count int // expected digit count
|
||||
ok bool // expected success
|
||||
next rune // next character (or 0, if at EOF)
|
||||
}{
|
||||
// error: no mantissa
|
||||
{},
|
||||
{s: "?"},
|
||||
{base: 10},
|
||||
{base: 36},
|
||||
{s: "?", base: 10},
|
||||
{s: "0x"},
|
||||
{s: "345", base: 2},
|
||||
|
||||
// error: incorrect use of decimal point
|
||||
{s: ".0"},
|
||||
{s: ".0", base: 10},
|
||||
{s: ".", base: 0},
|
||||
{s: "0x.0"},
|
||||
|
||||
// no errors
|
||||
{"0", 0, false, nil, 10, 1, true, 0},
|
||||
{"0", 10, false, nil, 10, 1, true, 0},
|
||||
{"0", 36, false, nil, 36, 1, true, 0},
|
||||
{"1", 0, false, nat{1}, 10, 1, true, 0},
|
||||
{"1", 10, false, nat{1}, 10, 1, true, 0},
|
||||
{"0 ", 0, false, nil, 10, 1, true, ' '},
|
||||
{"08", 0, false, nil, 10, 1, true, '8'},
|
||||
{"08", 10, false, nat{8}, 10, 2, true, 0},
|
||||
{"018", 0, false, nat{1}, 8, 1, true, '8'},
|
||||
{"0b1", 0, false, nat{1}, 2, 1, true, 0},
|
||||
{"0b11000101", 0, false, nat{0xc5}, 2, 8, true, 0},
|
||||
{"03271", 0, false, nat{03271}, 8, 4, true, 0},
|
||||
{"10ab", 0, false, nat{10}, 10, 2, true, 'a'},
|
||||
{"1234567890", 0, false, nat{1234567890}, 10, 10, true, 0},
|
||||
{"xyz", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, 0},
|
||||
{"xyz?", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, '?'},
|
||||
{"0x", 16, false, nil, 16, 1, true, 'x'},
|
||||
{"0xdeadbeef", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
|
||||
{"0XDEADBEEF", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
|
||||
|
||||
// no errors, decimal point
|
||||
{"0.", 0, false, nil, 10, 1, true, '.'},
|
||||
{"0.", 10, true, nil, 10, 0, true, 0},
|
||||
{"0.1.2", 10, true, nat{1}, 10, -1, true, '.'},
|
||||
{".000", 10, true, nil, 10, -3, true, 0},
|
||||
{"12.3", 10, true, nat{123}, 10, -1, true, 0},
|
||||
{"012.345", 10, true, nat{12345}, 10, -3, true, 0},
|
||||
}
|
||||
|
||||
func TestScanBase(t *testing.T) {
|
||||
for _, a := range natScanTests {
|
||||
r := strings.NewReader(a.s)
|
||||
x, b, count, err := nat(nil).scan(r, a.base, a.frac)
|
||||
if err == nil && !a.ok {
|
||||
t.Errorf("scan%+v\n\texpected error", a)
|
||||
}
|
||||
if err != nil {
|
||||
if a.ok {
|
||||
t.Errorf("scan%+v\n\tgot error = %s", a, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if x.cmp(a.x) != 0 {
|
||||
t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
|
||||
}
|
||||
if b != a.b {
|
||||
t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
|
||||
}
|
||||
if count != a.count {
|
||||
t.Errorf("scan%+v\n\tgot count = %d; want %d", a, count, a.count)
|
||||
}
|
||||
next, _, err := r.ReadRune()
|
||||
if err == io.EOF {
|
||||
next = 0
|
||||
err = nil
|
||||
}
|
||||
if err == nil && next != a.next {
|
||||
t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pi = "3" +
|
||||
"14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
|
||||
"32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
|
||||
"28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
|
||||
"96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
|
||||
"31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
|
||||
"60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
|
||||
"22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
|
||||
"29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
|
||||
"81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
|
||||
"21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
|
||||
"55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
|
||||
"63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
|
||||
"75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
|
||||
"45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
|
||||
"34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
|
||||
"16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
|
||||
"04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
|
||||
"26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
|
||||
"99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
|
||||
"53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
|
||||
"68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
|
||||
"13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
|
||||
"88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
|
||||
"79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
|
||||
"68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
|
||||
"21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
|
||||
"06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
|
||||
"14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
|
||||
"21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
|
||||
"05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
|
||||
"23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
|
||||
"90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
|
||||
"31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
|
||||
"20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
|
||||
"97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
|
||||
"44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
|
||||
"44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
|
||||
"85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
|
||||
"58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
|
||||
"27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
|
||||
"09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
|
||||
"79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
|
||||
"06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
|
||||
"91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
|
||||
"94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
|
||||
"78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
|
||||
"24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
|
||||
"59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
|
||||
"34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
|
||||
"88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
|
||||
"94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
|
||||
|
||||
// Test case for BenchmarkScanPi.
|
||||
func TestScanPi(t *testing.T) {
|
||||
var x nat
|
||||
z, _, _, err := x.scan(strings.NewReader(pi), 10, false)
|
||||
if err != nil {
|
||||
t.Errorf("scanning pi: %s", err)
|
||||
}
|
||||
if s := string(z.utoa(10)); s != pi {
|
||||
t.Errorf("scanning pi: got %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanPiParallel(t *testing.T) {
|
||||
const n = 2
|
||||
c := make(chan int)
|
||||
for i := 0; i < n; i++ {
|
||||
go func() {
|
||||
TestScanPi(t)
|
||||
c <- 0
|
||||
}()
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
<-c
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkScanPi(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var x nat
|
||||
x.scan(strings.NewReader(pi), 10, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStringPiParallel(b *testing.B) {
|
||||
var x nat
|
||||
x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
|
||||
if string(x.utoa(10)) != pi {
|
||||
panic("benchmark incorrect: conversion failed")
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
x.utoa(10)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkScan(b *testing.B) {
|
||||
const x = 10
|
||||
for _, base := range []int{2, 8, 10, 16} {
|
||||
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
|
||||
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var z nat
|
||||
z = z.expWW(x, y)
|
||||
|
||||
s := z.utoa(base)
|
||||
if t := itoa(z, base); !bytes.Equal(s, t) {
|
||||
b.Fatalf("scanning: got %s; want %s", s, t)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
z.scan(bytes.NewReader(s), base, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
const x = 10
|
||||
for _, base := range []int{2, 8, 10, 16} {
|
||||
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
|
||||
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var z nat
|
||||
z = z.expWW(x, y)
|
||||
z.utoa(base) // warm divisor cache
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = z.utoa(base)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLeafSize(b *testing.B) {
|
||||
for n := 0; n <= 16; n++ {
|
||||
b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) })
|
||||
}
|
||||
// Try some large lengths
|
||||
for _, n := range []int{32, 64} {
|
||||
b.Run(fmt.Sprint(n), func(b *testing.B) { LeafSizeHelper(b, 10, n) })
|
||||
}
|
||||
}
|
||||
|
||||
func LeafSizeHelper(b *testing.B, base, size int) {
|
||||
b.StopTimer()
|
||||
originalLeafSize := leafSize
|
||||
resetTable(cacheBase10.table[:])
|
||||
leafSize = size
|
||||
b.StartTimer()
|
||||
|
||||
for d := 1; d <= 10000; d *= 10 {
|
||||
b.StopTimer()
|
||||
var z nat
|
||||
z = z.expWW(Word(base), Word(d)) // build target number
|
||||
_ = z.utoa(base) // warm divisor cache
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = z.utoa(base)
|
||||
}
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
resetTable(cacheBase10.table[:])
|
||||
leafSize = originalLeafSize
|
||||
b.StartTimer()
|
||||
}
|
||||
|
||||
func resetTable(table []divisor) {
|
||||
if table != nil && table[0].bbb != nil {
|
||||
for i := 0; i < len(table); i++ {
|
||||
table[i].bbb = nil
|
||||
table[i].nbits = 0
|
||||
table[i].ndigits = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringPowers(t *testing.T) {
|
||||
var p Word
|
||||
for b := 2; b <= 16; b++ {
|
||||
for p = 0; p <= 512; p++ {
|
||||
x := nat(nil).expWW(Word(b), p)
|
||||
xs := x.utoa(b)
|
||||
xs2 := itoa(x, b)
|
||||
if !bytes.Equal(xs, xs2) {
|
||||
t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
|
||||
}
|
||||
}
|
||||
if b >= 3 && testing.Short() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,510 +0,0 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements multi-precision rational numbers.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// A Rat represents a quotient a/b of arbitrary precision.
|
||||
// The zero value for a Rat represents the value 0.
|
||||
type Rat struct {
|
||||
// To make zero values for Rat work w/o initialization,
|
||||
// a zero value of b (len(b) == 0) acts like b == 1.
|
||||
// a.neg determines the sign of the Rat, b.neg is ignored.
|
||||
a, b Int
|
||||
}
|
||||
|
||||
// NewRat creates a new Rat with numerator a and denominator b.
|
||||
func NewRat(a, b int64) *Rat {
|
||||
return new(Rat).SetFrac64(a, b)
|
||||
}
|
||||
|
||||
// SetFloat64 sets z to exactly f and returns z.
|
||||
// If f is not finite, SetFloat returns nil.
|
||||
func (z *Rat) SetFloat64(f float64) *Rat {
|
||||
const expMask = 1<<11 - 1
|
||||
bits := math.Float64bits(f)
|
||||
mantissa := bits & (1<<52 - 1)
|
||||
exp := int((bits >> 52) & expMask)
|
||||
switch exp {
|
||||
case expMask: // non-finite
|
||||
return nil
|
||||
case 0: // denormal
|
||||
exp -= 1022
|
||||
default: // normal
|
||||
mantissa |= 1 << 52
|
||||
exp -= 1023
|
||||
}
|
||||
|
||||
shift := 52 - exp
|
||||
|
||||
// Optimization (?): partially pre-normalise.
|
||||
for mantissa&1 == 0 && shift > 0 {
|
||||
mantissa >>= 1
|
||||
shift--
|
||||
}
|
||||
|
||||
z.a.SetUint64(mantissa)
|
||||
z.a.neg = f < 0
|
||||
z.b.Set(intOne)
|
||||
if shift > 0 {
|
||||
z.b.Lsh(&z.b, uint(shift))
|
||||
} else {
|
||||
z.a.Lsh(&z.a, uint(-shift))
|
||||
}
|
||||
return z.norm()
|
||||
}
|
||||
|
||||
// quotToFloat32 returns the non-negative float32 value
|
||||
// nearest to the quotient a/b, using round-to-even in
|
||||
// halfway cases. It does not mutate its arguments.
|
||||
// Preconditions: b is non-zero; a and b have no common factors.
|
||||
func quotToFloat32(a, b nat) (f float32, exact bool) {
|
||||
const (
|
||||
// float size in bits
|
||||
Fsize = 32
|
||||
|
||||
// mantissa
|
||||
Msize = 23
|
||||
Msize1 = Msize + 1 // incl. implicit 1
|
||||
Msize2 = Msize1 + 1
|
||||
|
||||
// exponent
|
||||
Esize = Fsize - Msize1
|
||||
Ebias = 1<<(Esize-1) - 1
|
||||
Emin = 1 - Ebias
|
||||
Emax = Ebias
|
||||
)
|
||||
|
||||
// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
|
||||
alen := a.bitLen()
|
||||
if alen == 0 {
|
||||
return 0, true
|
||||
}
|
||||
blen := b.bitLen()
|
||||
if blen == 0 {
|
||||
panic("division by zero")
|
||||
}
|
||||
|
||||
// 1. Left-shift A or B such that quotient A/B is in [1<<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()
|
||||
}
|
||||
|
|
@ -1,622 +0,0 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestZeroRat(t *testing.T) {
|
||||
var x, y, z Rat
|
||||
y.SetFrac64(0, 42)
|
||||
|
||||
if x.Cmp(&y) != 0 {
|
||||
t.Errorf("x and y should be both equal and zero")
|
||||
}
|
||||
|
||||
if s := x.String(); s != "0/1" {
|
||||
t.Errorf("got x = %s, want 0/1", s)
|
||||
}
|
||||
|
||||
if s := x.RatString(); s != "0" {
|
||||
t.Errorf("got x = %s, want 0", s)
|
||||
}
|
||||
|
||||
z.Add(&x, &y)
|
||||
if s := z.RatString(); s != "0" {
|
||||
t.Errorf("got x+y = %s, want 0", s)
|
||||
}
|
||||
|
||||
z.Sub(&x, &y)
|
||||
if s := z.RatString(); s != "0" {
|
||||
t.Errorf("got x-y = %s, want 0", s)
|
||||
}
|
||||
|
||||
z.Mul(&x, &y)
|
||||
if s := z.RatString(); s != "0" {
|
||||
t.Errorf("got x*y = %s, want 0", s)
|
||||
}
|
||||
|
||||
// check for division by zero
|
||||
defer func() {
|
||||
if s := recover(); s == nil || s.(string) != "division by zero" {
|
||||
panic(s)
|
||||
}
|
||||
}()
|
||||
z.Quo(&x, &y)
|
||||
}
|
||||
|
||||
func TestRatSign(t *testing.T) {
|
||||
zero := NewRat(0, 1)
|
||||
for _, a := range setStringTests {
|
||||
x, ok := new(Rat).SetString(a.in)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
s := x.Sign()
|
||||
e := x.Cmp(zero)
|
||||
if s != e {
|
||||
t.Errorf("got %d; want %d for z = %v", s, e, &x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var ratCmpTests = []struct {
|
||||
rat1, rat2 string
|
||||
out int
|
||||
}{
|
||||
{"0", "0/1", 0},
|
||||
{"1/1", "1", 0},
|
||||
{"-1", "-2/2", 0},
|
||||
{"1", "0", 1},
|
||||
{"0/1", "1/1", -1},
|
||||
{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
|
||||
{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
|
||||
{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
|
||||
{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
|
||||
}
|
||||
|
||||
func TestRatCmp(t *testing.T) {
|
||||
for i, test := range ratCmpTests {
|
||||
x, _ := new(Rat).SetString(test.rat1)
|
||||
y, _ := new(Rat).SetString(test.rat2)
|
||||
|
||||
out := x.Cmp(y)
|
||||
if out != test.out {
|
||||
t.Errorf("#%d got out = %v; want %v", i, out, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInt(t *testing.T) {
|
||||
one := NewInt(1)
|
||||
for _, a := range setStringTests {
|
||||
x, ok := new(Rat).SetString(a.in)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
i := x.IsInt()
|
||||
e := x.Denom().Cmp(one) == 0
|
||||
if i != e {
|
||||
t.Errorf("got IsInt(%v) == %v; want %v", x, i, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatAbs(t *testing.T) {
|
||||
zero := new(Rat)
|
||||
for _, a := range setStringTests {
|
||||
x, ok := new(Rat).SetString(a.in)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
e := new(Rat).Set(x)
|
||||
if e.Cmp(zero) < 0 {
|
||||
e.Sub(zero, e)
|
||||
}
|
||||
z := new(Rat).Abs(x)
|
||||
if z.Cmp(e) != 0 {
|
||||
t.Errorf("got Abs(%v) = %v; want %v", x, z, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatNeg(t *testing.T) {
|
||||
zero := new(Rat)
|
||||
for _, a := range setStringTests {
|
||||
x, ok := new(Rat).SetString(a.in)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
e := new(Rat).Sub(zero, x)
|
||||
z := new(Rat).Neg(x)
|
||||
if z.Cmp(e) != 0 {
|
||||
t.Errorf("got Neg(%v) = %v; want %v", x, z, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatInv(t *testing.T) {
|
||||
zero := new(Rat)
|
||||
for _, a := range setStringTests {
|
||||
x, ok := new(Rat).SetString(a.in)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if x.Cmp(zero) == 0 {
|
||||
continue // avoid division by zero
|
||||
}
|
||||
e := new(Rat).SetFrac(x.Denom(), x.Num())
|
||||
z := new(Rat).Inv(x)
|
||||
if z.Cmp(e) != 0 {
|
||||
t.Errorf("got Inv(%v) = %v; want %v", x, z, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ratBinFun func(z, x, y *Rat) *Rat
|
||||
type ratBinArg struct {
|
||||
x, y, z string
|
||||
}
|
||||
|
||||
func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
|
||||
x, _ := new(Rat).SetString(a.x)
|
||||
y, _ := new(Rat).SetString(a.y)
|
||||
z, _ := new(Rat).SetString(a.z)
|
||||
out := f(new(Rat), x, y)
|
||||
|
||||
if out.Cmp(z) != 0 {
|
||||
t.Errorf("%s #%d got %s want %s", name, i, out, z)
|
||||
}
|
||||
}
|
||||
|
||||
var ratBinTests = []struct {
|
||||
x, y string
|
||||
sum, prod string
|
||||
}{
|
||||
{"0", "0", "0", "0"},
|
||||
{"0", "1", "1", "0"},
|
||||
{"-1", "0", "-1", "0"},
|
||||
{"-1", "1", "0", "-1"},
|
||||
{"1", "1", "2", "1"},
|
||||
{"1/2", "1/2", "1", "1/4"},
|
||||
{"1/4", "1/3", "7/12", "1/12"},
|
||||
{"2/5", "-14/3", "-64/15", "-28/15"},
|
||||
{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
|
||||
{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
|
||||
{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
|
||||
{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
|
||||
{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
|
||||
{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
|
||||
{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
|
||||
{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
|
||||
{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
|
||||
{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
|
||||
}
|
||||
|
||||
func TestRatBin(t *testing.T) {
|
||||
for i, test := range ratBinTests {
|
||||
arg := ratBinArg{test.x, test.y, test.sum}
|
||||
testRatBin(t, i, "Add", (*Rat).Add, arg)
|
||||
|
||||
arg = ratBinArg{test.y, test.x, test.sum}
|
||||
testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
|
||||
|
||||
arg = ratBinArg{test.sum, test.x, test.y}
|
||||
testRatBin(t, i, "Sub", (*Rat).Sub, arg)
|
||||
|
||||
arg = ratBinArg{test.sum, test.y, test.x}
|
||||
testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
|
||||
|
||||
arg = ratBinArg{test.x, test.y, test.prod}
|
||||
testRatBin(t, i, "Mul", (*Rat).Mul, arg)
|
||||
|
||||
arg = ratBinArg{test.y, test.x, test.prod}
|
||||
testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
|
||||
|
||||
if test.x != "0" {
|
||||
arg = ratBinArg{test.prod, test.x, test.y}
|
||||
testRatBin(t, i, "Quo", (*Rat).Quo, arg)
|
||||
}
|
||||
|
||||
if test.y != "0" {
|
||||
arg = ratBinArg{test.prod, test.y, test.x}
|
||||
testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue820(t *testing.T) {
|
||||
x := NewRat(3, 1)
|
||||
y := NewRat(2, 1)
|
||||
z := y.Quo(x, y)
|
||||
q := NewRat(3, 2)
|
||||
if z.Cmp(q) != 0 {
|
||||
t.Errorf("got %s want %s", z, q)
|
||||
}
|
||||
|
||||
y = NewRat(3, 1)
|
||||
x = NewRat(2, 1)
|
||||
z = y.Quo(x, y)
|
||||
q = NewRat(2, 3)
|
||||
if z.Cmp(q) != 0 {
|
||||
t.Errorf("got %s want %s", z, q)
|
||||
}
|
||||
|
||||
x = NewRat(3, 1)
|
||||
z = x.Quo(x, x)
|
||||
q = NewRat(3, 3)
|
||||
if z.Cmp(q) != 0 {
|
||||
t.Errorf("got %s want %s", z, q)
|
||||
}
|
||||
}
|
||||
|
||||
var setFrac64Tests = []struct {
|
||||
a, b int64
|
||||
out string
|
||||
}{
|
||||
{0, 1, "0"},
|
||||
{0, -1, "0"},
|
||||
{1, 1, "1"},
|
||||
{-1, 1, "-1"},
|
||||
{1, -1, "-1"},
|
||||
{-1, -1, "1"},
|
||||
{-9223372036854775808, -9223372036854775808, "1"},
|
||||
}
|
||||
|
||||
func TestRatSetFrac64Rat(t *testing.T) {
|
||||
for i, test := range setFrac64Tests {
|
||||
x := new(Rat).SetFrac64(test.a, test.b)
|
||||
if x.RatString() != test.out {
|
||||
t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue2379(t *testing.T) {
|
||||
// 1) no aliasing
|
||||
q := NewRat(3, 2)
|
||||
x := new(Rat)
|
||||
x.SetFrac(NewInt(3), NewInt(2))
|
||||
if x.Cmp(q) != 0 {
|
||||
t.Errorf("1) got %s want %s", x, q)
|
||||
}
|
||||
|
||||
// 2) aliasing of numerator
|
||||
x = NewRat(2, 3)
|
||||
x.SetFrac(NewInt(3), x.Num())
|
||||
if x.Cmp(q) != 0 {
|
||||
t.Errorf("2) got %s want %s", x, q)
|
||||
}
|
||||
|
||||
// 3) aliasing of denominator
|
||||
x = NewRat(2, 3)
|
||||
x.SetFrac(x.Denom(), NewInt(2))
|
||||
if x.Cmp(q) != 0 {
|
||||
t.Errorf("3) got %s want %s", x, q)
|
||||
}
|
||||
|
||||
// 4) aliasing of numerator and denominator
|
||||
x = NewRat(2, 3)
|
||||
x.SetFrac(x.Denom(), x.Num())
|
||||
if x.Cmp(q) != 0 {
|
||||
t.Errorf("4) got %s want %s", x, q)
|
||||
}
|
||||
|
||||
// 5) numerator and denominator are the same
|
||||
q = NewRat(1, 1)
|
||||
x = new(Rat)
|
||||
n := NewInt(7)
|
||||
x.SetFrac(n, n)
|
||||
if x.Cmp(q) != 0 {
|
||||
t.Errorf("5) got %s want %s", x, q)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue3521(t *testing.T) {
|
||||
a := new(Int)
|
||||
b := new(Int)
|
||||
a.SetString("64375784358435883458348587", 0)
|
||||
b.SetString("4789759874531", 0)
|
||||
|
||||
// 0) a raw zero value has 1 as denominator
|
||||
zero := new(Rat)
|
||||
one := NewInt(1)
|
||||
if zero.Denom().Cmp(one) != 0 {
|
||||
t.Errorf("0) got %s want %s", zero.Denom(), one)
|
||||
}
|
||||
|
||||
// 1a) a zero value remains zero independent of denominator
|
||||
x := new(Rat)
|
||||
x.Denom().Set(new(Int).Neg(b))
|
||||
if x.Cmp(zero) != 0 {
|
||||
t.Errorf("1a) got %s want %s", x, zero)
|
||||
}
|
||||
|
||||
// 1b) a zero value may have a denominator != 0 and != 1
|
||||
x.Num().Set(a)
|
||||
qab := new(Rat).SetFrac(a, b)
|
||||
if x.Cmp(qab) != 0 {
|
||||
t.Errorf("1b) got %s want %s", x, qab)
|
||||
}
|
||||
|
||||
// 2a) an integral value becomes a fraction depending on denominator
|
||||
x.SetFrac64(10, 2)
|
||||
x.Denom().SetInt64(3)
|
||||
q53 := NewRat(5, 3)
|
||||
if x.Cmp(q53) != 0 {
|
||||
t.Errorf("2a) got %s want %s", x, q53)
|
||||
}
|
||||
|
||||
// 2b) an integral value becomes a fraction depending on denominator
|
||||
x = NewRat(10, 2)
|
||||
x.Denom().SetInt64(3)
|
||||
if x.Cmp(q53) != 0 {
|
||||
t.Errorf("2b) got %s want %s", x, q53)
|
||||
}
|
||||
|
||||
// 3) changing the numerator/denominator of a Rat changes the Rat
|
||||
x.SetFrac(a, b)
|
||||
a = x.Num()
|
||||
b = x.Denom()
|
||||
a.SetInt64(5)
|
||||
b.SetInt64(3)
|
||||
if x.Cmp(q53) != 0 {
|
||||
t.Errorf("3) got %s want %s", x, q53)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat32Distribution(t *testing.T) {
|
||||
// Generate a distribution of (sign, mantissa, exp) values
|
||||
// broader than the float32 range, and check Rat.Float32()
|
||||
// always picks the closest float32 approximation.
|
||||
var add = []int64{
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
9,
|
||||
11,
|
||||
}
|
||||
var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64)
|
||||
if testing.Short() {
|
||||
winc, einc = 5, 15 // quick test (~60ms on x86-64)
|
||||
}
|
||||
|
||||
for _, sign := range "+-" {
|
||||
for _, a := range add {
|
||||
for wid := uint64(0); wid < 30; wid += winc {
|
||||
b := 1<<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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements rat-to-string conversion functions.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ratTok(ch rune) bool {
|
||||
return strings.ContainsRune("+-/0123456789.eE", ch)
|
||||
}
|
||||
|
||||
// Scan is a support routine for fmt.Scanner. It accepts the formats
|
||||
// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
|
||||
func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
|
||||
tok, err := s.Token(true, ratTok)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.ContainsRune("efgEFGv", ch) {
|
||||
return errors.New("Rat.Scan: invalid verb")
|
||||
}
|
||||
if _, ok := z.SetString(string(tok)); !ok {
|
||||
return errors.New("Rat.Scan: invalid syntax")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetString sets z to the value of s and returns z and a boolean indicating
|
||||
// success. s can be given as a fraction "a/b" or as a floating-point number
|
||||
// optionally followed by an exponent. If the operation failed, the value of
|
||||
// z is undefined but the returned value is nil.
|
||||
func (z *Rat) SetString(s string) (*Rat, bool) {
|
||||
if len(s) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
// len(s) > 0
|
||||
|
||||
// parse fraction a/b, if any
|
||||
if sep := strings.Index(s, "/"); sep >= 0 {
|
||||
if _, ok := z.a.SetString(s[:sep], 0); !ok {
|
||||
return nil, false
|
||||
}
|
||||
s = s[sep+1:]
|
||||
var err error
|
||||
if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
|
||||
return nil, false
|
||||
}
|
||||
if len(z.b.abs) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return z.norm(), true
|
||||
}
|
||||
|
||||
// parse floating-point number
|
||||
r := strings.NewReader(s)
|
||||
|
||||
// sign
|
||||
neg, err := scanSign(r)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// mantissa
|
||||
var ecorr int
|
||||
z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// exponent
|
||||
var exp int64
|
||||
exp, _, err = scanExponent(r, false)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// there should be no unread characters left
|
||||
if _, err = r.ReadByte(); err != io.EOF {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// special-case 0 (see also issue #16176)
|
||||
if len(z.a.abs) == 0 {
|
||||
return z, true
|
||||
}
|
||||
// len(z.a.abs) > 0
|
||||
|
||||
// correct exponent
|
||||
if ecorr < 0 {
|
||||
exp += int64(ecorr)
|
||||
}
|
||||
|
||||
// compute exponent power
|
||||
expabs := exp
|
||||
if expabs < 0 {
|
||||
expabs = -expabs
|
||||
}
|
||||
powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
|
||||
|
||||
// complete fraction
|
||||
if exp < 0 {
|
||||
z.b.abs = powTen
|
||||
z.norm()
|
||||
} else {
|
||||
z.a.abs = z.a.abs.mul(z.a.abs, powTen)
|
||||
z.b.abs = z.b.abs[:0]
|
||||
}
|
||||
|
||||
z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
|
||||
|
||||
return z, true
|
||||
}
|
||||
|
||||
// scanExponent scans the longest possible prefix of r representing a decimal
|
||||
// ('e', 'E') or binary ('p') exponent, if any. It returns the exponent, the
|
||||
// exponent base (10 or 2), or a read or syntax error, if any.
|
||||
//
|
||||
// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
|
||||
// sign = "+" | "-" .
|
||||
// digits = digit { digit } .
|
||||
// digit = "0" ... "9" .
|
||||
//
|
||||
// A binary exponent is only permitted if binExpOk is set.
|
||||
func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err error) {
|
||||
base = 10
|
||||
|
||||
var ch byte
|
||||
if ch, err = r.ReadByte(); err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil // no exponent; same as e0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch ch {
|
||||
case 'e', 'E':
|
||||
// ok
|
||||
case 'p':
|
||||
if binExpOk {
|
||||
base = 2
|
||||
break // ok
|
||||
}
|
||||
fallthrough // binary exponent not permitted
|
||||
default:
|
||||
r.UnreadByte()
|
||||
return // no exponent; same as e0
|
||||
}
|
||||
|
||||
var neg bool
|
||||
if neg, err = scanSign(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var digits []byte
|
||||
if neg {
|
||||
digits = append(digits, '-')
|
||||
}
|
||||
|
||||
// no need to use nat.scan for exponent digits
|
||||
// since we only care about int64 values - the
|
||||
// from-scratch scan is easy enough and faster
|
||||
for i := 0; ; i++ {
|
||||
if ch, err = r.ReadByte(); err != nil {
|
||||
if err != io.EOF || i == 0 {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
break // i > 0
|
||||
}
|
||||
if ch < '0' || '9' < ch {
|
||||
if i == 0 {
|
||||
r.UnreadByte()
|
||||
err = fmt.Errorf("invalid exponent (missing digits)")
|
||||
return
|
||||
}
|
||||
break // i > 0
|
||||
}
|
||||
digits = append(digits, ch)
|
||||
}
|
||||
// i > 0 => we have at least one digit
|
||||
|
||||
exp, err = strconv.ParseInt(string(digits), 10, 64)
|
||||
return
|
||||
}
|
||||
|
||||
// String returns a string representation of x in the form "a/b" (even if b == 1).
|
||||
func (x *Rat) String() string {
|
||||
var buf []byte
|
||||
buf = x.a.Append(buf, 10)
|
||||
buf = append(buf, '/')
|
||||
if len(x.b.abs) != 0 {
|
||||
buf = x.b.Append(buf, 10)
|
||||
} else {
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// RatString returns a string representation of x in the form "a/b" if b != 1,
|
||||
// and in the form "a" if b == 1.
|
||||
func (x *Rat) RatString() string {
|
||||
if x.IsInt() {
|
||||
return x.a.String()
|
||||
}
|
||||
return x.String()
|
||||
}
|
||||
|
||||
// FloatString returns a string representation of x in decimal form with prec
|
||||
// digits of precision after the decimal point. The last digit is rounded to
|
||||
// nearest, with halves rounded away from zero.
|
||||
func (x *Rat) FloatString(prec int) string {
|
||||
var buf []byte
|
||||
|
||||
if x.IsInt() {
|
||||
buf = x.a.Append(buf, 10)
|
||||
if prec > 0 {
|
||||
buf = append(buf, '.')
|
||||
for i := prec; i > 0; i-- {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
// x.b.abs != 0
|
||||
|
||||
q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
|
||||
|
||||
p := natOne
|
||||
if prec > 0 {
|
||||
p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
|
||||
}
|
||||
|
||||
r = r.mul(r, p)
|
||||
r, r2 := r.div(nat(nil), r, x.b.abs)
|
||||
|
||||
// see if we need to round up
|
||||
r2 = r2.add(r2, r2)
|
||||
if x.b.abs.cmp(r2) <= 0 {
|
||||
r = r.add(r, natOne)
|
||||
if r.cmp(p) >= 0 {
|
||||
q = nat(nil).add(q, natOne)
|
||||
r = nat(nil).sub(r, p)
|
||||
}
|
||||
}
|
||||
|
||||
if x.a.neg {
|
||||
buf = append(buf, '-')
|
||||
}
|
||||
buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
|
||||
|
||||
if prec > 0 {
|
||||
buf = append(buf, '.')
|
||||
rs := r.utoa(10)
|
||||
for i := prec - len(rs); i > 0; i-- {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
buf = append(buf, rs...)
|
||||
}
|
||||
|
||||
return string(buf)
|
||||
}
|
||||
|
|
@ -1,454 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type StringTest struct {
|
||||
in, out string
|
||||
ok bool
|
||||
}
|
||||
|
||||
var setStringTests = []StringTest{
|
||||
{"0", "0", true},
|
||||
{"-0", "0", true},
|
||||
{"1", "1", true},
|
||||
{"-1", "-1", true},
|
||||
{"1.", "1", true},
|
||||
{"1e0", "1", true},
|
||||
{"1.e1", "10", true},
|
||||
{in: "1e"},
|
||||
{in: "1.e"},
|
||||
{in: "1e+14e-5"},
|
||||
{in: "1e4.5"},
|
||||
{in: "r"},
|
||||
{in: "a/b"},
|
||||
{in: "a.b"},
|
||||
{"-0.1", "-1/10", true},
|
||||
{"-.1", "-1/10", true},
|
||||
{"2/4", "1/2", true},
|
||||
{".25", "1/4", true},
|
||||
{"-1/5", "-1/5", true},
|
||||
{"8129567.7690E14", "812956776900000000000", true},
|
||||
{"78189e+4", "781890000", true},
|
||||
{"553019.8935e+8", "55301989350000", true},
|
||||
{"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
|
||||
{"9877861857500000E-7", "3951144743/4", true},
|
||||
{"2169378.417e-3", "2169378417/1000000", true},
|
||||
{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
|
||||
{"53/70893980658822810696", "53/70893980658822810696", true},
|
||||
{"106/141787961317645621392", "53/70893980658822810696", true},
|
||||
{"204211327800791583.81095", "4084226556015831676219/20000", true},
|
||||
{"0e9999999999", "0", true}, // issue #16176
|
||||
{in: "1/0"},
|
||||
}
|
||||
|
||||
// These are not supported by fmt.Fscanf.
|
||||
var setStringTests2 = []StringTest{
|
||||
{"0x10", "16", true},
|
||||
{"-010/1", "-8", true}, // TODO(gri) should we even permit octal here?
|
||||
{"-010.", "-10", true},
|
||||
{"0x10/0x20", "1/2", true},
|
||||
{"0b1000/3", "8/3", true},
|
||||
// TODO(gri) add more tests
|
||||
}
|
||||
|
||||
func TestRatSetString(t *testing.T) {
|
||||
var tests []StringTest
|
||||
tests = append(tests, setStringTests...)
|
||||
tests = append(tests, setStringTests2...)
|
||||
|
||||
for i, test := range tests {
|
||||
x, ok := new(Rat).SetString(test.in)
|
||||
|
||||
if ok {
|
||||
if !test.ok {
|
||||
t.Errorf("#%d SetString(%q) expected failure", i, test.in)
|
||||
} else if x.RatString() != test.out {
|
||||
t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
|
||||
}
|
||||
} else if x != nil {
|
||||
t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatScan(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
for i, test := range setStringTests {
|
||||
x := new(Rat)
|
||||
buf.Reset()
|
||||
buf.WriteString(test.in)
|
||||
|
||||
_, err := fmt.Fscanf(&buf, "%v", x)
|
||||
if err == nil != test.ok {
|
||||
if test.ok {
|
||||
t.Errorf("#%d (%s) error: %s", i, test.in, err)
|
||||
} else {
|
||||
t.Errorf("#%d (%s) expected error", i, test.in)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err == nil && x.RatString() != test.out {
|
||||
t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var floatStringTests = []struct {
|
||||
in string
|
||||
prec int
|
||||
out string
|
||||
}{
|
||||
{"0", 0, "0"},
|
||||
{"0", 4, "0.0000"},
|
||||
{"1", 0, "1"},
|
||||
{"1", 2, "1.00"},
|
||||
{"-1", 0, "-1"},
|
||||
{"0.05", 1, "0.1"},
|
||||
{"-0.05", 1, "-0.1"},
|
||||
{".25", 2, "0.25"},
|
||||
{".25", 1, "0.3"},
|
||||
{".25", 3, "0.250"},
|
||||
{"-1/3", 3, "-0.333"},
|
||||
{"-2/3", 4, "-0.6667"},
|
||||
{"0.96", 1, "1.0"},
|
||||
{"0.999", 2, "1.00"},
|
||||
{"0.9", 0, "1"},
|
||||
{".25", -1, "0"},
|
||||
{".55", -1, "1"},
|
||||
}
|
||||
|
||||
func TestFloatString(t *testing.T) {
|
||||
for i, test := range floatStringTests {
|
||||
x, _ := new(Rat).SetString(test.in)
|
||||
|
||||
if x.FloatString(test.prec) != test.out {
|
||||
t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test inputs to Rat.SetString. The prefix "long:" causes the test
|
||||
// to be skipped in --test.short mode. (The threshold is about 500us.)
|
||||
var float64inputs = []string{
|
||||
// Constants plundered from strconv/testfp.txt.
|
||||
|
||||
// Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
|
||||
"5e+125",
|
||||
"69e+267",
|
||||
"999e-026",
|
||||
"7861e-034",
|
||||
"75569e-254",
|
||||
"928609e-261",
|
||||
"9210917e+080",
|
||||
"84863171e+114",
|
||||
"653777767e+273",
|
||||
"5232604057e-298",
|
||||
"27235667517e-109",
|
||||
"653532977297e-123",
|
||||
"3142213164987e-294",
|
||||
"46202199371337e-072",
|
||||
"231010996856685e-073",
|
||||
"9324754620109615e+212",
|
||||
"78459735791271921e+049",
|
||||
"272104041512242479e+200",
|
||||
"6802601037806061975e+198",
|
||||
"20505426358836677347e-221",
|
||||
"836168422905420598437e-234",
|
||||
"4891559871276714924261e+222",
|
||||
|
||||
// Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
|
||||
"9e-265",
|
||||
"85e-037",
|
||||
"623e+100",
|
||||
"3571e+263",
|
||||
"81661e+153",
|
||||
"920657e-023",
|
||||
"4603285e-024",
|
||||
"87575437e-309",
|
||||
"245540327e+122",
|
||||
"6138508175e+120",
|
||||
"83356057653e+193",
|
||||
"619534293513e+124",
|
||||
"2335141086879e+218",
|
||||
"36167929443327e-159",
|
||||
"609610927149051e-255",
|
||||
"3743626360493413e-165",
|
||||
"94080055902682397e-242",
|
||||
"899810892172646163e+283",
|
||||
"7120190517612959703e+120",
|
||||
"25188282901709339043e-252",
|
||||
"308984926168550152811e-052",
|
||||
"6372891218502368041059e+064",
|
||||
|
||||
// Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
|
||||
"5e-20",
|
||||
"67e+14",
|
||||
"985e+15",
|
||||
"7693e-42",
|
||||
"55895e-16",
|
||||
"996622e-44",
|
||||
"7038531e-32",
|
||||
"60419369e-46",
|
||||
"702990899e-20",
|
||||
"6930161142e-48",
|
||||
"25933168707e+13",
|
||||
"596428896559e+20",
|
||||
|
||||
// Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
|
||||
"3e-23",
|
||||
"57e+18",
|
||||
"789e-35",
|
||||
"2539e-18",
|
||||
"76173e+28",
|
||||
"887745e-11",
|
||||
"5382571e-37",
|
||||
"82381273e-35",
|
||||
"750486563e-38",
|
||||
"3752432815e-39",
|
||||
"75224575729e-45",
|
||||
"459926601011e+15",
|
||||
|
||||
// Constants plundered from strconv/atof_test.go.
|
||||
|
||||
"0",
|
||||
"1",
|
||||
"+1",
|
||||
"1e23",
|
||||
"1E23",
|
||||
"100000000000000000000000",
|
||||
"1e-100",
|
||||
"123456700",
|
||||
"99999999999999974834176",
|
||||
"100000000000000000000001",
|
||||
"100000000000000008388608",
|
||||
"100000000000000016777215",
|
||||
"100000000000000016777216",
|
||||
"-1",
|
||||
"-0.1",
|
||||
"-0", // NB: exception made for this input
|
||||
"1e-20",
|
||||
"625e-3",
|
||||
|
||||
// largest float64
|
||||
"1.7976931348623157e308",
|
||||
"-1.7976931348623157e308",
|
||||
// next float64 - too large
|
||||
"1.7976931348623159e308",
|
||||
"-1.7976931348623159e308",
|
||||
// the border is ...158079
|
||||
// borderline - okay
|
||||
"1.7976931348623158e308",
|
||||
"-1.7976931348623158e308",
|
||||
// borderline - too large
|
||||
"1.797693134862315808e308",
|
||||
"-1.797693134862315808e308",
|
||||
|
||||
// a little too large
|
||||
"1e308",
|
||||
"2e308",
|
||||
"1e309",
|
||||
|
||||
// way too large
|
||||
"1e310",
|
||||
"-1e310",
|
||||
"1e400",
|
||||
"-1e400",
|
||||
"long:1e400000",
|
||||
"long:-1e400000",
|
||||
|
||||
// denormalized
|
||||
"1e-305",
|
||||
"1e-306",
|
||||
"1e-307",
|
||||
"1e-308",
|
||||
"1e-309",
|
||||
"1e-310",
|
||||
"1e-322",
|
||||
// smallest denormal
|
||||
"5e-324",
|
||||
"4e-324",
|
||||
"3e-324",
|
||||
// too small
|
||||
"2e-324",
|
||||
// way too small
|
||||
"1e-350",
|
||||
"long:1e-400000",
|
||||
// way too small, negative
|
||||
"-1e-350",
|
||||
"long:-1e-400000",
|
||||
|
||||
// try to overflow exponent
|
||||
// [Disabled: too slow and memory-hungry with rationals.]
|
||||
// "1e-4294967296",
|
||||
// "1e+4294967296",
|
||||
// "1e-18446744073709551616",
|
||||
// "1e+18446744073709551616",
|
||||
|
||||
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
||||
"2.2250738585072012e-308",
|
||||
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
|
||||
"2.2250738585072011e-308",
|
||||
|
||||
// A very large number (initially wrongly parsed by the fast algorithm).
|
||||
"4.630813248087435e+307",
|
||||
|
||||
// A different kind of very large number.
|
||||
"22.222222222222222",
|
||||
"long:2." + strings.Repeat("2", 4000) + "e+1",
|
||||
|
||||
// Exactly halfway between 1 and math.Nextafter(1, 2).
|
||||
// Round to even (down).
|
||||
"1.00000000000000011102230246251565404236316680908203125",
|
||||
// Slightly lower; still round down.
|
||||
"1.00000000000000011102230246251565404236316680908203124",
|
||||
// Slightly higher; round up.
|
||||
"1.00000000000000011102230246251565404236316680908203126",
|
||||
// Slightly higher, but you have to read all the way to the end.
|
||||
"long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
|
||||
|
||||
// Smallest denormal, 2^(-1022-52)
|
||||
"4.940656458412465441765687928682213723651e-324",
|
||||
// Half of smallest denormal, 2^(-1022-53)
|
||||
"2.470328229206232720882843964341106861825e-324",
|
||||
// A little more than the exact half of smallest denormal
|
||||
// 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
|
||||
"2.470328302827751011111470718709768633275e-324",
|
||||
// The exact halfway between smallest normal and largest denormal:
|
||||
// 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
|
||||
"2.225073858507201136057409796709131975935e-308",
|
||||
|
||||
"1152921504606846975", // 1<<60 - 1
|
||||
"-1152921504606846975", // -(1<<60 - 1)
|
||||
"1152921504606846977", // 1<<60 + 1
|
||||
"-1152921504606846977", // -(1<<60 + 1)
|
||||
|
||||
"1/3",
|
||||
}
|
||||
|
||||
// isFinite reports whether f represents a finite rational value.
|
||||
// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
|
||||
func isFinite(f float64) bool {
|
||||
return math.Abs(f) <= math.MaxFloat64
|
||||
}
|
||||
|
||||
func TestFloat32SpecialCases(t *testing.T) {
|
||||
for _, input := range float64inputs {
|
||||
if strings.HasPrefix(input, "long:") {
|
||||
if testing.Short() {
|
||||
continue
|
||||
}
|
||||
input = input[len("long:"):]
|
||||
}
|
||||
|
||||
r, ok := new(Rat).SetString(input)
|
||||
if !ok {
|
||||
t.Errorf("Rat.SetString(%q) failed", input)
|
||||
continue
|
||||
}
|
||||
f, exact := r.Float32()
|
||||
|
||||
// 1. Check string -> Rat -> float32 conversions are
|
||||
// consistent with strconv.ParseFloat.
|
||||
// Skip this check if the input uses "a/b" rational syntax.
|
||||
if !strings.Contains(input, "/") {
|
||||
e64, _ := strconv.ParseFloat(input, 32)
|
||||
e := float32(e64)
|
||||
|
||||
// Careful: negative Rats too small for
|
||||
// float64 become -0, but Rat obviously cannot
|
||||
// preserve the sign from SetString("-0").
|
||||
switch {
|
||||
case math.Float32bits(e) == math.Float32bits(f):
|
||||
// Ok: bitwise equal.
|
||||
case f == 0 && r.Num().BitLen() == 0:
|
||||
// Ok: Rat(0) is equivalent to both +/- float64(0).
|
||||
default:
|
||||
t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
|
||||
}
|
||||
}
|
||||
|
||||
if !isFinite(float64(f)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 2. Check f is best approximation to r.
|
||||
if !checkIsBestApprox32(t, f, r) {
|
||||
// Append context information.
|
||||
t.Errorf("(input was %q)", input)
|
||||
}
|
||||
|
||||
// 3. Check f->R->f roundtrip is non-lossy.
|
||||
checkNonLossyRoundtrip32(t, f)
|
||||
|
||||
// 4. Check exactness using slow algorithm.
|
||||
if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
|
||||
t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat64SpecialCases(t *testing.T) {
|
||||
for _, input := range float64inputs {
|
||||
if strings.HasPrefix(input, "long:") {
|
||||
if testing.Short() {
|
||||
continue
|
||||
}
|
||||
input = input[len("long:"):]
|
||||
}
|
||||
|
||||
r, ok := new(Rat).SetString(input)
|
||||
if !ok {
|
||||
t.Errorf("Rat.SetString(%q) failed", input)
|
||||
continue
|
||||
}
|
||||
f, exact := r.Float64()
|
||||
|
||||
// 1. Check string -> Rat -> float64 conversions are
|
||||
// consistent with strconv.ParseFloat.
|
||||
// Skip this check if the input uses "a/b" rational syntax.
|
||||
if !strings.Contains(input, "/") {
|
||||
e, _ := strconv.ParseFloat(input, 64)
|
||||
|
||||
// Careful: negative Rats too small for
|
||||
// float64 become -0, but Rat obviously cannot
|
||||
// preserve the sign from SetString("-0").
|
||||
switch {
|
||||
case math.Float64bits(e) == math.Float64bits(f):
|
||||
// Ok: bitwise equal.
|
||||
case f == 0 && r.Num().BitLen() == 0:
|
||||
// Ok: Rat(0) is equivalent to both +/- float64(0).
|
||||
default:
|
||||
t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
|
||||
}
|
||||
}
|
||||
|
||||
if !isFinite(f) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 2. Check f is best approximation to r.
|
||||
if !checkIsBestApprox64(t, f, r) {
|
||||
// Append context information.
|
||||
t.Errorf("(input was %q)", input)
|
||||
}
|
||||
|
||||
// 3. Check f->R->f roundtrip is non-lossy.
|
||||
checkNonLossyRoundtrip64(t, f)
|
||||
|
||||
// 4. Check exactness using slow algorithm.
|
||||
if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
|
||||
t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements encoding/decoding of Rats.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Gob codec version. Permits backward-compatible changes to the encoding.
|
||||
const ratGobVersion byte = 1
|
||||
|
||||
// GobEncode implements the gob.GobEncoder interface.
|
||||
func (x *Rat) GobEncode() ([]byte, error) {
|
||||
if x == nil {
|
||||
return nil, nil
|
||||
}
|
||||
buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
|
||||
i := x.b.abs.bytes(buf)
|
||||
j := x.a.abs.bytes(buf[:i])
|
||||
n := i - j
|
||||
if int(uint32(n)) != n {
|
||||
// this should never happen
|
||||
return nil, errors.New("Rat.GobEncode: numerator too large")
|
||||
}
|
||||
binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
|
||||
j -= 1 + 4
|
||||
b := ratGobVersion << 1 // make space for sign bit
|
||||
if x.a.neg {
|
||||
b |= 1
|
||||
}
|
||||
buf[j] = b
|
||||
return buf[j:], nil
|
||||
}
|
||||
|
||||
// GobDecode implements the gob.GobDecoder interface.
|
||||
func (z *Rat) GobDecode(buf []byte) error {
|
||||
if len(buf) == 0 {
|
||||
// Other side sent a nil or default value.
|
||||
*z = Rat{}
|
||||
return nil
|
||||
}
|
||||
b := buf[0]
|
||||
if b>>1 != ratGobVersion {
|
||||
return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
|
||||
}
|
||||
const j = 1 + 4
|
||||
i := j + binary.BigEndian.Uint32(buf[j-4:j])
|
||||
z.a.neg = b&1 != 0
|
||||
z.a.abs = z.a.abs.setBytes(buf[j:i])
|
||||
z.b.abs = z.b.abs.setBytes(buf[i:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface.
|
||||
func (x *Rat) MarshalText() (text []byte, err error) {
|
||||
// TODO(gri): get rid of the []byte/string conversion
|
||||
return []byte(x.RatString()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
func (z *Rat) UnmarshalText(text []byte) error {
|
||||
// TODO(gri): get rid of the []byte/string conversion
|
||||
if _, ok := z.SetString(string(text)); !ok {
|
||||
return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package big
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRatGobEncoding(t *testing.T) {
|
||||
var medium bytes.Buffer
|
||||
enc := gob.NewEncoder(&medium)
|
||||
dec := gob.NewDecoder(&medium)
|
||||
for _, test := range encodingTests {
|
||||
medium.Reset() // empty buffer for each test case (in case of failures)
|
||||
var tx Rat
|
||||
tx.SetString(test + ".14159265")
|
||||
if err := enc.Encode(&tx); err != nil {
|
||||
t.Errorf("encoding of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Rat
|
||||
if err := dec.Decode(&rx); err != nil {
|
||||
t.Errorf("decoding of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
|
||||
// TODO: top-level nils.
|
||||
func TestGobEncodingNilRatInSlice(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
enc := gob.NewEncoder(buf)
|
||||
dec := gob.NewDecoder(buf)
|
||||
|
||||
var in = make([]*Rat, 1)
|
||||
err := enc.Encode(&in)
|
||||
if err != nil {
|
||||
t.Errorf("gob encode failed: %q", err)
|
||||
}
|
||||
var out []*Rat
|
||||
err = dec.Decode(&out)
|
||||
if err != nil {
|
||||
t.Fatalf("gob decode failed: %q", err)
|
||||
}
|
||||
if len(out) != 1 {
|
||||
t.Fatalf("wrong len; want 1 got %d", len(out))
|
||||
}
|
||||
var zero Rat
|
||||
if out[0].Cmp(&zero) != 0 {
|
||||
t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out)
|
||||
}
|
||||
}
|
||||
|
||||
var ratNums = []string{
|
||||
"-141592653589793238462643383279502884197169399375105820974944592307816406286",
|
||||
"-1415926535897932384626433832795028841971",
|
||||
"-141592653589793",
|
||||
"-1",
|
||||
"0",
|
||||
"1",
|
||||
"141592653589793",
|
||||
"1415926535897932384626433832795028841971",
|
||||
"141592653589793238462643383279502884197169399375105820974944592307816406286",
|
||||
}
|
||||
|
||||
var ratDenoms = []string{
|
||||
"1",
|
||||
"718281828459045",
|
||||
"7182818284590452353602874713526624977572",
|
||||
"718281828459045235360287471352662497757247093699959574966967627724076630353",
|
||||
}
|
||||
|
||||
func TestRatJSONEncoding(t *testing.T) {
|
||||
for _, num := range ratNums {
|
||||
for _, denom := range ratDenoms {
|
||||
var tx Rat
|
||||
tx.SetString(num + "/" + denom)
|
||||
b, err := json.Marshal(&tx)
|
||||
if err != nil {
|
||||
t.Errorf("marshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Rat
|
||||
if err := json.Unmarshal(b, &rx); err != nil {
|
||||
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatXMLEncoding(t *testing.T) {
|
||||
for _, num := range ratNums {
|
||||
for _, denom := range ratDenoms {
|
||||
var tx Rat
|
||||
tx.SetString(num + "/" + denom)
|
||||
b, err := xml.Marshal(&tx)
|
||||
if err != nil {
|
||||
t.Errorf("marshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
var rx Rat
|
||||
if err := xml.Unmarshal(b, &rx); err != nil {
|
||||
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
|
||||
continue
|
||||
}
|
||||
if rx.Cmp(&tx) != 0 {
|
||||
t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
// generated by stringer -type=RoundingMode; DO NOT EDIT
|
||||
|
||||
package big
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _RoundingMode_name = "ToNearestEvenToNearestAwayToZeroAwayFromZeroToNegativeInfToPositiveInf"
|
||||
|
||||
var _RoundingMode_index = [...]uint8{0, 13, 26, 32, 44, 57, 70}
|
||||
|
||||
func (i RoundingMode) String() string {
|
||||
if i+1 >= RoundingMode(len(_RoundingMode_index)) {
|
||||
return fmt.Sprintf("RoundingMode(%d)", i)
|
||||
}
|
||||
return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2015 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# Run this script to obtain an up-to-date vendored version of math/big.
|
||||
|
||||
BIGDIR=../../../../math/big
|
||||
|
||||
# Start from scratch.
|
||||
rm *.go
|
||||
|
||||
# We don't want any assembly files.
|
||||
cp $BIGDIR/*.go .
|
||||
|
||||
# Use pure Go arith ops w/o build tag.
|
||||
sed 's|^// \+build math_big_pure_go$||' arith_decl_pure.go > arith_decl.go
|
||||
rm arith_decl_pure.go
|
||||
|
||||
# Import vendored math/big in external tests (e.g., floatexample_test.go).
|
||||
for f in *_test.go; do
|
||||
sed 's|"math/big"|"cmd/compile/internal/big"|' $f > foo.go
|
||||
mv foo.go $f
|
||||
done
|
||||
|
||||
# gofmt to clean up after sed
|
||||
gofmt -w .
|
||||
|
||||
# Test that it works
|
||||
go test -short
|
||||
|
|
@ -132,7 +132,7 @@ package gc
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"cmd/compile/internal/big"
|
||||
"math/big"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ package gc
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"cmd/compile/internal/big"
|
||||
"math/big"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
package gc
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// implements float arithmetic
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
package gc
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// implements integer arithmetic
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
package gc
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/big"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
|
|||
118
src/cmd/dist/buildtool.go
vendored
118
src/cmd/dist/buildtool.go
vendored
|
|
@ -18,49 +18,60 @@ import (
|
|||
|
||||
// bootstrapDirs is a list of directories holding code that must be
|
||||
// compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
|
||||
// All directories in this list are relative to and must be below $GOROOT/src/cmd.
|
||||
// The list is assumed to have two kinds of entries: names without slashes,
|
||||
// which are commands, and entries beginning with internal/, which are
|
||||
// packages supporting the commands.
|
||||
// All directories in this list are relative to and must be below $GOROOT/src.
|
||||
//
|
||||
// The list has have two kinds of entries: names beginning with cmd/ with
|
||||
// no other slashes, which are commands, and other paths, which are packages
|
||||
// supporting the commands. Packages in the standard library can be listed
|
||||
// if a newer copy needs to be substituted for the Go 1.4 copy when used
|
||||
// by the command packages.
|
||||
// These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big.
|
||||
var bootstrapDirs = []string{
|
||||
"asm",
|
||||
"asm/internal/arch",
|
||||
"asm/internal/asm",
|
||||
"asm/internal/flags",
|
||||
"asm/internal/lex",
|
||||
"compile",
|
||||
"compile/internal/amd64",
|
||||
"compile/internal/arm",
|
||||
"compile/internal/arm64",
|
||||
"compile/internal/big",
|
||||
"compile/internal/gc",
|
||||
"compile/internal/mips64",
|
||||
"compile/internal/ppc64",
|
||||
"compile/internal/s390x",
|
||||
"compile/internal/ssa",
|
||||
"compile/internal/syntax",
|
||||
"compile/internal/x86",
|
||||
"internal/bio",
|
||||
"internal/gcprog",
|
||||
"internal/dwarf",
|
||||
"internal/obj",
|
||||
"internal/obj/arm",
|
||||
"internal/obj/arm64",
|
||||
"internal/obj/mips",
|
||||
"internal/obj/ppc64",
|
||||
"internal/obj/s390x",
|
||||
"internal/obj/x86",
|
||||
"internal/sys",
|
||||
"link",
|
||||
"link/internal/amd64",
|
||||
"link/internal/arm",
|
||||
"link/internal/arm64",
|
||||
"link/internal/pe",
|
||||
"link/internal/ld",
|
||||
"link/internal/mips64",
|
||||
"link/internal/ppc64",
|
||||
"link/internal/s390x",
|
||||
"link/internal/x86",
|
||||
"cmd/asm",
|
||||
"cmd/asm/internal/arch",
|
||||
"cmd/asm/internal/asm",
|
||||
"cmd/asm/internal/flags",
|
||||
"cmd/asm/internal/lex",
|
||||
"cmd/compile",
|
||||
"cmd/compile/internal/amd64",
|
||||
"cmd/compile/internal/arm",
|
||||
"cmd/compile/internal/arm64",
|
||||
"cmd/compile/internal/gc",
|
||||
"cmd/compile/internal/mips64",
|
||||
"cmd/compile/internal/ppc64",
|
||||
"cmd/compile/internal/s390x",
|
||||
"cmd/compile/internal/ssa",
|
||||
"cmd/compile/internal/syntax",
|
||||
"cmd/compile/internal/x86",
|
||||
"cmd/internal/bio",
|
||||
"cmd/internal/gcprog",
|
||||
"cmd/internal/dwarf",
|
||||
"cmd/internal/obj",
|
||||
"cmd/internal/obj/arm",
|
||||
"cmd/internal/obj/arm64",
|
||||
"cmd/internal/obj/mips",
|
||||
"cmd/internal/obj/ppc64",
|
||||
"cmd/internal/obj/s390x",
|
||||
"cmd/internal/obj/x86",
|
||||
"cmd/internal/sys",
|
||||
"cmd/link",
|
||||
"cmd/link/internal/amd64",
|
||||
"cmd/link/internal/arm",
|
||||
"cmd/link/internal/arm64",
|
||||
"cmd/link/internal/ld",
|
||||
"cmd/link/internal/mips64",
|
||||
"cmd/link/internal/pe",
|
||||
"cmd/link/internal/ppc64",
|
||||
"cmd/link/internal/s390x",
|
||||
"cmd/link/internal/x86",
|
||||
"math/big",
|
||||
}
|
||||
|
||||
// File suffixes that use build tags introduced since Go 1.4.
|
||||
// These must not be copied into the bootstrap build directory.
|
||||
var ignoreSuffixes = []string{
|
||||
"_arm64.s",
|
||||
"_arm64.go",
|
||||
}
|
||||
|
||||
func bootstrapBuildTools() {
|
||||
|
|
@ -84,10 +95,16 @@ func bootstrapBuildTools() {
|
|||
|
||||
// Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
|
||||
for _, dir := range bootstrapDirs {
|
||||
src := pathf("%s/src/cmd/%s", goroot, dir)
|
||||
src := pathf("%s/src/%s", goroot, dir)
|
||||
dst := pathf("%s/%s", base, dir)
|
||||
xmkdirall(dst)
|
||||
Dir:
|
||||
for _, name := range xreaddirfiles(src) {
|
||||
for _, suf := range ignoreSuffixes {
|
||||
if strings.HasSuffix(name, suf) {
|
||||
continue Dir
|
||||
}
|
||||
}
|
||||
srcFile := pathf("%s/%s", src, name)
|
||||
text := readfile(srcFile)
|
||||
text = bootstrapFixImports(text, srcFile)
|
||||
|
|
@ -122,10 +139,14 @@ func bootstrapBuildTools() {
|
|||
// Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to
|
||||
// workaround bugs in Go 1.4's compiler. See discussion thread:
|
||||
// https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ
|
||||
run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/...")
|
||||
run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-v", "bootstrap/cmd/...")
|
||||
|
||||
// Copy binaries into tool binary directory.
|
||||
for _, name := range bootstrapDirs {
|
||||
if !strings.HasPrefix(name, "cmd/") {
|
||||
continue
|
||||
}
|
||||
name = name[len("cmd/"):]
|
||||
if !strings.Contains(name, "/") {
|
||||
copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
|
||||
}
|
||||
|
|
@ -148,7 +169,14 @@ func bootstrapFixImports(text, srcFile string) string {
|
|||
}
|
||||
if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
|
||||
inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
|
||||
lines[i] = strings.Replace(line, `"cmd/`, `"bootstrap/`, -1)
|
||||
line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
|
||||
for _, dir := range bootstrapDirs {
|
||||
if strings.HasPrefix(dir, "cmd/") {
|
||||
continue
|
||||
}
|
||||
line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
|
||||
}
|
||||
lines[i] = line
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue