diff options
author | Evan Shaw <chickencha@gmail.com> | 2010-04-22 16:57:29 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2010-04-22 16:57:29 -0700 |
commit | 841a32dd5ec836e171d04604710d88a6b8e59467 (patch) | |
tree | 534ecca6cbc6f946870c6831d3ad771ab5acba43 | |
parent | 5cd8c830374627af75bd30b2ff1106b6d4e48773 (diff) | |
download | go-841a32dd5ec836e171d04604710d88a6b8e59467.tar.gz go-841a32dd5ec836e171d04604710d88a6b8e59467.zip |
big: Create type nat
Changed most of the functions in nat.go to methods on nat.
R=gri
CC=golang-dev
https://golang.org/cl/976041
-rw-r--r-- | src/pkg/big/arith_test.go | 112 | ||||
-rw-r--r-- | src/pkg/big/int.go | 58 | ||||
-rw-r--r-- | src/pkg/big/int_test.go | 4 | ||||
-rw-r--r-- | src/pkg/big/nat.go | 266 | ||||
-rw-r--r-- | src/pkg/big/nat_test.go | 182 |
5 files changed, 312 insertions, 310 deletions
diff --git a/src/pkg/big/arith_test.go b/src/pkg/big/arith_test.go index b0f6bf6f1f..49908e342d 100644 --- a/src/pkg/big/arith_test.go +++ b/src/pkg/big/arith_test.go @@ -52,7 +52,7 @@ func TestFunWW(t *testing.T) { } -func addr(x []Word) *Word { +func addr(x nat) *Word { if len(x) == 0 { return nil } @@ -62,26 +62,26 @@ func addr(x []Word) *Word { type funVV func(z, x, y *Word, n int) (c Word) type argVV struct { - z, x, y []Word + z, x, y nat c Word } var sumVV = []argVV{ argVV{}, - argVV{[]Word{0}, []Word{0}, []Word{0}, 0}, - argVV{[]Word{1}, []Word{1}, []Word{0}, 0}, - argVV{[]Word{0}, []Word{_M}, []Word{1}, 1}, - argVV{[]Word{80235}, []Word{12345}, []Word{67890}, 0}, - argVV{[]Word{_M - 1}, []Word{_M}, []Word{_M}, 1}, - argVV{[]Word{0, 0, 0, 0}, []Word{_M, _M, _M, _M}, []Word{1, 0, 0, 0}, 1}, - argVV{[]Word{0, 0, 0, _M}, []Word{_M, _M, _M, _M - 1}, []Word{1, 0, 0, 0}, 0}, - argVV{[]Word{0, 0, 0, 0}, []Word{_M, 0, _M, 0}, []Word{1, _M, 0, _M}, 1}, + argVV{nat{0}, nat{0}, nat{0}, 0}, + argVV{nat{1}, nat{1}, nat{0}, 0}, + argVV{nat{0}, nat{_M}, nat{1}, 1}, + argVV{nat{80235}, nat{12345}, nat{67890}, 0}, + argVV{nat{_M - 1}, nat{_M}, nat{_M}, 1}, + argVV{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1}, + argVV{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0}, + argVV{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) { n := len(a.z) - z := make([]Word, n) + z := make(nat, n) c := f(addr(z), addr(a.x), addr(a.y), n) for i, zi := range z { if zi != a.z[i] { @@ -118,39 +118,39 @@ func TestFunVV(t *testing.T) { type funVW func(z, x *Word, y Word, n int) (c Word) type argVW struct { - z, x []Word + z, x nat y Word c Word } var sumVW = []argVW{ argVW{}, - argVW{[]Word{0}, []Word{0}, 0, 0}, - argVW{[]Word{1}, []Word{0}, 1, 0}, - argVW{[]Word{1}, []Word{1}, 0, 0}, - argVW{[]Word{0}, []Word{_M}, 1, 1}, - argVW{[]Word{0, 0, 0, 0}, []Word{_M, _M, _M, _M}, 1, 1}, + argVW{nat{0}, nat{0}, 0, 0}, + argVW{nat{1}, nat{0}, 1, 0}, + argVW{nat{1}, nat{1}, 0, 0}, + argVW{nat{0}, nat{_M}, 1, 1}, + argVW{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1}, } var prodVW = []argVW{ argVW{}, - argVW{[]Word{0}, []Word{0}, 0, 0}, - argVW{[]Word{0}, []Word{_M}, 0, 0}, - argVW{[]Word{0}, []Word{0}, _M, 0}, - argVW{[]Word{1}, []Word{1}, 1, 0}, - argVW{[]Word{22793}, []Word{991}, 23, 0}, - argVW{[]Word{0, 0, 0, 22793}, []Word{0, 0, 0, 991}, 23, 0}, - argVW{[]Word{0, 0, 0, 0}, []Word{7893475, 7395495, 798547395, 68943}, 0, 0}, - argVW{[]Word{0, 0, 0, 0}, []Word{0, 0, 0, 0}, 894375984, 0}, - argVW{[]Word{_M << 1 & _M}, []Word{_M}, 1 << 1, _M >> (_W - 1)}, - argVW{[]Word{_M << 7 & _M}, []Word{_M}, 1 << 7, _M >> (_W - 7)}, - argVW{[]Word{_M << 7 & _M, _M, _M, _M}, []Word{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)}, + argVW{nat{0}, nat{0}, 0, 0}, + argVW{nat{0}, nat{_M}, 0, 0}, + argVW{nat{0}, nat{0}, _M, 0}, + argVW{nat{1}, nat{1}, 1, 0}, + argVW{nat{22793}, nat{991}, 23, 0}, + argVW{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0}, + argVW{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0}, + argVW{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0}, + argVW{nat{_M << 1 & _M}, nat{_M}, 1 << 1, _M >> (_W - 1)}, + argVW{nat{_M << 7 & _M}, nat{_M}, 1 << 7, _M >> (_W - 7)}, + argVW{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)}, } func testFunVW(t *testing.T, msg string, f funVW, a argVW) { n := len(a.z) - z := make([]Word, n) + z := make(nat, n) c := f(addr(z), addr(a.x), a.y, n) for i, zi := range z { if zi != a.z[i] { @@ -179,41 +179,41 @@ func TestFunVW(t *testing.T) { type funVWW func(z, x *Word, y, r Word, n int) (c Word) type argVWW struct { - z, x []Word + z, x nat y, r Word c Word } var prodVWW = []argVWW{ argVWW{}, - argVWW{[]Word{0}, []Word{0}, 0, 0, 0}, - argVWW{[]Word{991}, []Word{0}, 0, 991, 0}, - argVWW{[]Word{0}, []Word{_M}, 0, 0, 0}, - argVWW{[]Word{991}, []Word{_M}, 0, 991, 0}, - argVWW{[]Word{0}, []Word{0}, _M, 0, 0}, - argVWW{[]Word{991}, []Word{0}, _M, 991, 0}, - argVWW{[]Word{1}, []Word{1}, 1, 0, 0}, - argVWW{[]Word{992}, []Word{1}, 1, 991, 0}, - argVWW{[]Word{22793}, []Word{991}, 23, 0, 0}, - argVWW{[]Word{22800}, []Word{991}, 23, 7, 0}, - argVWW{[]Word{0, 0, 0, 22793}, []Word{0, 0, 0, 991}, 23, 0, 0}, - argVWW{[]Word{7, 0, 0, 22793}, []Word{0, 0, 0, 991}, 23, 7, 0}, - argVWW{[]Word{0, 0, 0, 0}, []Word{7893475, 7395495, 798547395, 68943}, 0, 0, 0}, - argVWW{[]Word{991, 0, 0, 0}, []Word{7893475, 7395495, 798547395, 68943}, 0, 991, 0}, - argVWW{[]Word{0, 0, 0, 0}, []Word{0, 0, 0, 0}, 894375984, 0, 0}, - argVWW{[]Word{991, 0, 0, 0}, []Word{0, 0, 0, 0}, 894375984, 991, 0}, - argVWW{[]Word{_M << 1 & _M}, []Word{_M}, 1 << 1, 0, _M >> (_W - 1)}, - argVWW{[]Word{_M<<1&_M + 1}, []Word{_M}, 1 << 1, 1, _M >> (_W - 1)}, - argVWW{[]Word{_M << 7 & _M}, []Word{_M}, 1 << 7, 0, _M >> (_W - 7)}, - argVWW{[]Word{_M<<7&_M + 1<<6}, []Word{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, - argVWW{[]Word{_M << 7 & _M, _M, _M, _M}, []Word{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)}, - argVWW{[]Word{_M<<7&_M + 1<<6, _M, _M, _M}, []Word{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, + argVWW{nat{0}, nat{0}, 0, 0, 0}, + argVWW{nat{991}, nat{0}, 0, 991, 0}, + argVWW{nat{0}, nat{_M}, 0, 0, 0}, + argVWW{nat{991}, nat{_M}, 0, 991, 0}, + argVWW{nat{0}, nat{0}, _M, 0, 0}, + argVWW{nat{991}, nat{0}, _M, 991, 0}, + argVWW{nat{1}, nat{1}, 1, 0, 0}, + argVWW{nat{992}, nat{1}, 1, 991, 0}, + argVWW{nat{22793}, nat{991}, 23, 0, 0}, + argVWW{nat{22800}, nat{991}, 23, 7, 0}, + argVWW{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0}, + argVWW{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0}, + argVWW{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0}, + argVWW{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0}, + argVWW{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0}, + argVWW{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0}, + argVWW{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)}, + argVWW{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)}, + argVWW{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)}, + argVWW{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, + argVWW{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)}, + argVWW{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) { n := len(a.z) - z := make([]Word, n) + z := make(nat, n) c := f(addr(z), addr(a.x), a.y, a.r, n) for i, zi := range z { if zi != a.z[i] { @@ -232,16 +232,16 @@ func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) { type funWVW func(z *Word, xn Word, x *Word, y Word, n int) (r Word) type argWVW struct { - z []Word + z nat xn Word - x []Word + x nat y Word r Word } func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) { n := len(a.z) - z := make([]Word, n) + z := make(nat, n) r := f(addr(z), a.xn, addr(a.x), a.y, n) for i, zi := range z { if zi != a.z[i] { diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go index ca94c5a427..6b570a07d6 100644 --- a/src/pkg/big/int.go +++ b/src/pkg/big/int.go @@ -9,8 +9,8 @@ package big // 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 []Word // absolute value of the integer + neg bool // sign + abs nat // absolute value of the integer } @@ -21,7 +21,7 @@ func (z *Int) New(x int64) *Int { z.neg = true x = -x } - z.abs = newN(z.abs, uint64(x)) + z.abs = z.abs.new(uint64(x)) return z } @@ -33,7 +33,7 @@ func NewInt(x int64) *Int { return new(Int).New(x) } // Set sets z to x. func (z *Int) Set(x *Int) *Int { z.neg = x.neg - z.abs = setN(z.abs, x.abs) + z.abs = z.abs.set(x.abs) return z } @@ -44,16 +44,16 @@ func (z *Int) Add(x, y *Int) *Int { // x + y == x + y // (-x) + (-y) == -(x + y) z.neg = x.neg - z.abs = addNN(z.abs, x.abs, y.abs) + z.abs = z.abs.add(x.abs, y.abs) } else { // x + (-y) == x - y == -(y - x) // (-x) + y == y - x == -(x - y) - if cmpNN(x.abs, y.abs) >= 0 { + if x.abs.cmp(y.abs) >= 0 { z.neg = x.neg - z.abs = subNN(z.abs, x.abs, y.abs) + z.abs = z.abs.sub(x.abs, y.abs) } else { z.neg = !x.neg - z.abs = subNN(z.abs, y.abs, x.abs) + z.abs = z.abs.sub(y.abs, x.abs) } } if len(z.abs) == 0 { @@ -69,16 +69,16 @@ func (z *Int) Sub(x, y *Int) *Int { // x - (-y) == x + y // (-x) - y == -(x + y) z.neg = x.neg - z.abs = addNN(z.abs, x.abs, y.abs) + z.abs = z.abs.add(x.abs, y.abs) } else { // x - y == x - y == -(y - x) // (-x) - (-y) == y - x == -(x - y) - if cmpNN(x.abs, y.abs) >= 0 { + if x.abs.cmp(y.abs) >= 0 { z.neg = x.neg - z.abs = subNN(z.abs, x.abs, y.abs) + z.abs = z.abs.sub(x.abs, y.abs) } else { z.neg = !x.neg - z.abs = subNN(z.abs, y.abs, x.abs) + z.abs = z.abs.sub(y.abs, x.abs) } } if len(z.abs) == 0 { @@ -94,7 +94,7 @@ func (z *Int) Mul(x, y *Int) *Int { // x * (-y) == -(x * y) // (-x) * y == -(x * y) // (-x) * (-y) == x * y - z.abs = mulNN(z.abs, x.abs, y.abs) + 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 } @@ -126,14 +126,14 @@ func (z *Int) DivMod(x, y, r *Int) (*Int, *Int) { func div(q, r, x, y *Int) { q.neg = x.neg != y.neg r.neg = x.neg - q.abs, r.abs = divNN(q.abs, r.abs, x.abs, y.abs) + q.abs, r.abs = q.abs.div(r.abs, x.abs, y.abs) return } // Neg computes z = -x. func (z *Int) Neg(x *Int) *Int { - z.abs = setN(z.abs, x.abs) + z.abs = z.abs.set(x.abs) z.neg = len(z.abs) > 0 && !x.neg // 0 has no sign return z } @@ -152,7 +152,7 @@ func (x *Int) Cmp(y *Int) (r int) { // (-x) cmp (-y) == -(x cmp y) switch { case x.neg == y.neg: - r = cmpNN(x.abs, y.abs) + r = x.abs.cmp(y.abs) if x.neg { r = -r } @@ -170,7 +170,7 @@ func (z *Int) String() string { if z.neg { s = "-" } - return s + stringN(z.abs, 10) + return s + z.abs.string(10) } @@ -212,7 +212,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) { z.neg = false } - z.abs, _, scanned = scanN(z.abs, s, base) + z.abs, _, scanned = z.abs.scan(s, base) if scanned != len(s) { goto Error } @@ -230,7 +230,7 @@ Error: // sets z to that value. func (z *Int) SetBytes(b []byte) *Int { s := int(_S) - z.abs = makeN(z.abs, (len(b)+s-1)/s, false) + z.abs = z.abs.make((len(b)+s-1)/s, false) z.neg = false j := 0 @@ -258,7 +258,7 @@ func (z *Int) SetBytes(b []byte) *Int { z.abs[j] = w } - z.abs = normN(z.abs) + z.abs = z.abs.norm() return z } @@ -306,12 +306,12 @@ func (z *Int) Exp(x, y, m *Int) *Int { return z } - var mWords []Word + var mWords nat if m != nil { mWords = m.abs } - z.abs = expNNN(z.abs, x.abs, y.abs, mWords) + z.abs = z.abs.expNN(x.abs, y.abs, mWords) z.neg = x.neg && y.abs[0]&1 == 1 return z } @@ -379,20 +379,20 @@ func GcdInt(d, x, y, a, b *Int) { // ProbablyPrime performs n Miller-Rabin tests to check whether z is prime. // If it returns true, z is prime with probability 1 - 1/4^n. // If it returns false, z is not prime. -func ProbablyPrime(z *Int, n int) bool { return !z.neg && probablyPrime(z.abs, n) } +func ProbablyPrime(z *Int, n int) bool { return !z.neg && z.abs.probablyPrime(n) } // Lsh sets z = x << n and returns z. func (z *Int) Lsh(x *Int, n uint) *Int { addedWords := int(n) / _W // Don't assign z.abs yet, in case z == x - znew := makeN(z.abs, len(x.abs)+addedWords+1, false) + znew := z.abs.make(len(x.abs)+addedWords+1, false) z.neg = x.neg - shiftLeft(znew[addedWords:], x.abs, n%_W) + znew[addedWords:].shiftLeft(x.abs, n%_W) for i := range znew[0:addedWords] { znew[i] = 0 } - z.abs = normN(znew) + z.abs = znew.norm() return z } @@ -401,9 +401,9 @@ func (z *Int) Lsh(x *Int, n uint) *Int { func (z *Int) Rsh(x *Int, n uint) *Int { removedWords := int(n) / _W // Don't assign z.abs yet, in case z == x - znew := makeN(z.abs, len(x.abs)-removedWords, false) + znew := z.abs.make(len(x.abs)-removedWords, false) z.neg = x.neg - shiftRight(znew, x.abs[removedWords:], n%_W) - z.abs = normN(znew) + znew.shiftRight(x.abs[removedWords:], n%_W) + z.abs = znew.norm() return z } diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go index 914a631e51..bb42f81856 100644 --- a/src/pkg/big/int_test.go +++ b/src/pkg/big/int_test.go @@ -327,8 +327,8 @@ func TestDivStepD6(t *testing.T) { // See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises // a code path which only triggers 1 in 10^{-19} cases. - u := &Int{false, []Word{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}} - v := &Int{false, []Word{5, 2 + 1<<(_W-1), 1 << (_W - 1)}} + u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}} + v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}} r := new(Int) q, r := new(Int).DivMod(u, v, r) diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go index 8843d43549..2c8f837de6 100644 --- a/src/pkg/big/nat.go +++ b/src/pkg/big/nat.go @@ -34,10 +34,9 @@ import "rand" // always normalized before returning the final result. The normalized // representation of 0 is the empty or nil slice (length = 0). -// TODO(gri) - convert these routines into methods for type 'nat' -// - decide if type 'nat' should be exported +type nat []Word -func normN(z []Word) []Word { +func (z nat) norm() nat { i := len(z) for i > 0 && z[i-1] == 0 { i-- @@ -47,7 +46,7 @@ func normN(z []Word) []Word { } -func makeN(z []Word, m int, clear bool) []Word { +func (z nat) make(m int, clear bool) nat { if cap(z) > m { z = z[0:m] // reuse z - has at least one extra word for a carry, if any if clear { @@ -62,18 +61,18 @@ func makeN(z []Word, m int, clear bool) []Word { if m > c { c = m } - return make([]Word, m, c+1) // +1: extra word for a carry, if any + return make(nat, m, c+1) // +1: extra word for a carry, if any } -func newN(z []Word, x uint64) []Word { +func (z nat) new(x uint64) nat { if x == 0 { - return makeN(z, 0, false) + return z.make(0, false) } // single-digit values if x == uint64(Word(x)) { - z = makeN(z, 1, false) + z = z.make(1, false) z[0] = Word(x) return z } @@ -85,7 +84,7 @@ func newN(z []Word, x uint64) []Word { } // split x into n words - z = makeN(z, n, false) + z = z.make(n, false) for i := 0; i < n; i++ { z[i] = Word(x & _M) x >>= _W @@ -95,8 +94,8 @@ func newN(z []Word, x uint64) []Word { } -func setN(z, x []Word) []Word { - z = makeN(z, len(x), false) +func (z nat) set(x nat) nat { + z = z.make(len(x), false) for i, d := range x { z[i] = d } @@ -104,23 +103,23 @@ func setN(z, x []Word) []Word { } -func addNN(z, x, y []Word) []Word { +func (z nat) add(x, y nat) nat { m := len(x) n := len(y) switch { case m < n: - return addNN(z, y, x) + return z.add(y, x) case m == 0: // n == 0 because m >= n; result is 0 - return makeN(z, 0, false) + return z.make(0, false) case n == 0: // result is x - return setN(z, x) + return z.set(x) } // m > 0 - z = makeN(z, m, false) + z = z.make(m, false) c := addVV(&z[0], &x[0], &y[0], n) if m > n { c = addVW(&z[n], &x[n], c, m-n) @@ -134,7 +133,7 @@ func addNN(z, x, y []Word) []Word { } -func subNN(z, x, y []Word) []Word { +func (z nat) sub(x, y nat) nat { m := len(x) n := len(y) @@ -143,14 +142,14 @@ func subNN(z, x, y []Word) []Word { panic("underflow") case m == 0: // n == 0 because m >= n; result is 0 - return makeN(z, 0, false) + return z.make(0, false) case n == 0: // result is x - return setN(z, x) + return z.set(x) } // m > 0 - z = makeN(z, m, false) + z = z.make(m, false) c := subVV(&z[0], &x[0], &y[0], n) if m > n { c = subVW(&z[n], &x[n], c, m-n) @@ -158,13 +157,13 @@ func subNN(z, x, y []Word) []Word { if c != 0 { panic("underflow") } - z = normN(z) + z = z.norm() return z } -func cmpNN(x, y []Word) (r int) { +func (x nat) cmp(y nat) (r int) { m := len(x) n := len(y) if m != n || m == 0 { @@ -192,14 +191,14 @@ func cmpNN(x, y []Word) (r int) { } -func mulAddNWW(z, x []Word, y, r Word) []Word { +func (z nat) mulAddWW(x nat, y, r Word) nat { m := len(x) if m == 0 || y == 0 { - return newN(z, uint64(r)) // result is r + return z.new(uint64(r)) // result is r } // m > 0 - z = makeN(z, m, false) + z = z.make(m, false) c := mulAddVWW(&z[0], &x[0], y, r, m) if c > 0 { z = z[0 : m+1] @@ -210,81 +209,81 @@ func mulAddNWW(z, x []Word, y, r Word) []Word { } -func mulNN(z, x, y []Word) []Word { +func (z nat) mul(x, y nat) nat { m := len(x) n := len(y) switch { case m < n: - return mulNN(z, y, x) + return z.mul(y, x) case m == 0 || n == 0: - return makeN(z, 0, false) + return z.make(0, false) case n == 1: - return mulAddNWW(z, x, y[0], 0) + return z.mulAddWW(x, y[0], 0) } // m >= n && m > 1 && n > 1 if z == nil || &z[0] == &x[0] || &z[0] == &y[0] { - z = makeN(nil, m+n, true) // z is an alias for x or y - cannot reuse + z = nat(nil).make(m+n, true) // z is an alias for x or y - cannot reuse } else { - z = makeN(z, m+n, true) + z = z.make(m+n, true) } for i := 0; i < n; i++ { if f := y[i]; f != 0 { z[m+i] = addMulVVW(&z[i], &x[0], f, m) } } - z = normN(z) + z = z.norm() return z } // q = (x-r)/y, with 0 <= r < y -func divNW(z, x []Word, y Word) (q []Word, r Word) { +func (z nat) divW(x nat, y Word) (q nat, r Word) { m := len(x) switch { case y == 0: panic("division by zero") case y == 1: - q = setN(z, x) // result is x + q = z.set(x) // result is x return case m == 0: - q = setN(z, nil) // result is 0 + q = z.set(nil) // result is 0 return } // m > 0 - z = makeN(z, m, false) + z = z.make(m, false) r = divWVW(&z[0], 0, &x[0], y, m) - q = normN(z) + q = z.norm() return } -func divNN(z, z2, u, v []Word) (q, r []Word) { +func (z nat) div(z2, u, v nat) (q, r nat) { if len(v) == 0 { - panic("Divide by zero undefined") + panic("division by zero") } - if cmpNN(u, v) < 0 { - q = makeN(z, 0, false) - r = setN(z2, u) + if u.cmp(v) < 0 { + q = z.make(0, false) + r = z2.set(u) return } if len(v) == 1 { var rprime Word - q, rprime = divNW(z, u, v[0]) + q, rprime = z.divW(u, v[0]) if rprime > 0 { - r = makeN(z2, 1, false) + r = z2.make(1, false) r[0] = rprime } else { - r = makeN(z2, 0, false) + r = z2.make(0, false) } return } - q, r = divLargeNN(z, z2, u, v) + q, r = z.divLarge(z2, u, v) return } @@ -294,23 +293,23 @@ func divNN(z, z2, u, v []Word) (q, r []Word) { // Preconditions: // len(v) >= 2 // len(uIn) >= len(v) -func divLargeNN(z, z2, uIn, v []Word) (q, r []Word) { +func (z nat) divLarge(z2, uIn, v nat) (q, r nat) { n := len(v) m := len(uIn) - len(v) - var u []Word + var u nat if z2 == nil || &z2[0] == &uIn[0] { - u = makeN(nil, len(uIn)+1, true) // uIn is an alias for z2 + u = u.make(len(uIn)+1, true) // uIn is an alias for z2 } else { - u = makeN(z2, len(uIn)+1, true) + u = z2.make(len(uIn)+1, true) } - qhatv := make([]Word, len(v)+1) - q = makeN(z, m+1, false) + qhatv := make(nat, len(v)+1) + q = z.make(m+1, false) // D1. shift := uint(leadingZeroBits(v[n-1])) - shiftLeft(v, v, shift) - shiftLeft(u, uIn, shift) + v.shiftLeft(v, shift) + u.shiftLeft(uIn, shift) u[len(uIn)] = uIn[len(uIn)-1] >> (_W - uint(shift)) // D2. @@ -351,10 +350,10 @@ func divLargeNN(z, z2, uIn, v []Word) (q, r []Word) { q[j] = qhat } - q = normN(q) - shiftRight(u, u, shift) - shiftRight(v, v, shift) - r = normN(u) + q = q.norm() + u.shiftRight(u, shift) + v.shiftRight(v, shift) + r = u.norm() return q, r } @@ -372,10 +371,10 @@ func log2(x Word) int { } -// log2N computes the integer binary logarithm of x. +// 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 log2N(x []Word) int { +func (x nat) log2() int { m := len(x) if m > 0 { return (m-1)*_W + log2(x[m-1]) @@ -410,7 +409,7 @@ func hexValue(ch byte) int { // conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the // ``0'' prefix selects base 8. Otherwise the selected base is 10. // -func scanN(z []Word, s string, base int) ([]Word, int, int) { +func (z nat) scan(s string, base int) (nat, int, int) { // determine base if necessary i, n := 0, len(s) if base == 0 { @@ -436,7 +435,7 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) { for ; i < n; i++ { d := hexValue(s[i]) if 0 <= d && d < base { - z = mulAddNWW(z, z, Word(base), Word(d)) + z = z.mulAddWW(z, Word(base), Word(d)) } else { break } @@ -449,7 +448,7 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) { // string converts x to a string for a given base, with 2 <= base <= 16. // TODO(gri) in the style of the other routines, perhaps this should take // a []byte buffer and return it -func stringN(x []Word, base int) string { +func (x nat) string(base int) string { if base < 2 || 16 < base { panic("illegal base") } @@ -459,17 +458,17 @@ func stringN(x []Word, base int) string { } // allocate buffer for conversion - i := (log2N(x)+1)/log2(Word(base)) + 1 // +1: round up + i := (x.log2()+1)/log2(Word(base)) + 1 // +1: round up s := make([]byte, i) // don't destroy x - q := setN(nil, x) + q := nat(nil).set(x) // convert for len(q) > 0 { i-- var r Word - q, r = divNW(q, q, Word(base)) + q, r = q.divW(q, Word(base)) s[i] = "0123456789abcdef"[r] } @@ -536,40 +535,42 @@ func trailingZeroBits(x Word) int { } -// To avoid losing the top n bits, dst should be sized so that -// len(dst) == len(src) + 1. -func shiftLeft(dst, src []Word, n uint) { - if len(src) == 0 { - return +// To avoid losing the top n bits, z should be sized so that +// len(z) == len(x) + 1. +func (z nat) shiftLeft(x nat, n uint) nat { + if len(x) == 0 { + return x } ñ := _W - n - x := src[len(src)-1] - if len(dst) > len(src) { - dst[len(src)] = x >> ñ + m := x[len(x)-1] + if len(z) > len(x) { + z[len(x)] = m >> ñ } - for i := len(src) - 1; i >= 1; i-- { - y := src[i-1] - dst[i] = x<<n | y>>ñ - x = y + for i := len(x) - 1; i >= 1; i-- { + y := x[i-1] + z[i] = m<<n | y>>ñ + m = y } - dst[0] = x << n + z[0] = m << n + return z } -func shiftRight(dst, src []Word, n uint) { - if len(src) == 0 { - return +func (z nat) shiftRight(x nat, n uint) nat { + if len(x) == 0 { + return x } ñ := _W - n - x := src[0] - for i := 0; i < len(src)-1; i++ { - y := src[i+1] - dst[i] = x>>n | y<<ñ - x = y + m := x[0] + for i := 0; i < len(x)-1; i++ { + y := x[i+1] + z[i] = m>>n | y<<ñ + m = y } - dst[len(src)-1] = x >> n + z[len(x)-1] = m >> n + return z } @@ -577,16 +578,17 @@ func shiftRight(dst, src []Word, n uint) { func greaterThan(x1, x2, y1, y2 Word) bool { return x1 > y1 || x1 == y1 && x2 > y2 } -// modNW returns x % d. -func modNW(x []Word, d Word) (r Word) { +// modW returns x % d. +func (x nat) modW(d Word) (r Word) { // TODO(agl): we don't actually need to store the q value. - q := makeN(nil, len(x), false) + var q nat + q = q.make(len(x), false) return divWVW(&q[0], 0, &x[0], d, len(x)) } // powersOfTwoDecompose finds q and k such that q * 1<<k = n and q is odd. -func powersOfTwoDecompose(n []Word) (q []Word, k Word) { +func (n nat) powersOfTwoDecompose() (q nat, k Word) { if len(n) == 0 { return n, 0 } @@ -599,24 +601,24 @@ func powersOfTwoDecompose(n []Word) (q []Word, k Word) { // zeroWords < len(n). x := trailingZeroBits(n[zeroWords]) - q = makeN(nil, len(n)-zeroWords, false) - shiftRight(q, n[zeroWords:], uint(x)) - q = normN(q) + q = q.make(len(n)-zeroWords, false) + q.shiftRight(n[zeroWords:], uint(x)) + q = q.norm() k = Word(_W*zeroWords + x) return } -// randomN creates a random integer in [0..limit), using the space in z if +// random creates a random integer in [0..limit), using the space in z if // possible. n is the bit length of limit. -func randomN(z []Word, rand *rand.Rand, limit []Word, n int) []Word { +func (z nat) random(rand *rand.Rand, limit nat, n int) nat { bitLengthOfMSW := uint(n % _W) if bitLengthOfMSW == 0 { bitLengthOfMSW = _W } mask := Word((1 << bitLengthOfMSW) - 1) - z = makeN(z, len(limit), false) + z = z.make(len(limit), false) for { for i := range z { @@ -630,35 +632,35 @@ func randomN(z []Word, rand *rand.Rand, limit []Word, n int) []Word { z[len(limit)-1] &= mask - if cmpNN(z, limit) < 0 { + if z.cmp(limit) < 0 { break } } - return normN(z) + return z.norm() } -// If m != nil, expNNN calculates x**y mod m. Otherwise it calculates x**y. It +// If m != nil, expNN calculates x**y mod m. Otherwise it calculates x**y. It // reuses the storage of z if possible. -func expNNN(z, x, y, m []Word) []Word { +func (z nat) expNN(x, y, m nat) nat { if len(y) == 0 { - z = makeN(z, 1, false) + z = z.make(1, false) z[0] = 1 return z } if m != nil { // We likely end up being as long as the modulus. - z = makeN(z, len(m), false) + z = z.make(len(m), false) } - z = setN(z, x) + z = z.set(x) v := y[len(y)-1] // It's invalid for the most significant word to be zero, therefore we // will find a one bit. shift := leadingZeros(v) + 1 v <<= shift - var q []Word + var q nat const mask = 1 << (_W - 1) @@ -668,14 +670,14 @@ func expNNN(z, x, y, m []Word) []Word { w := _W - int(shift) for j := 0; j < w; j++ { - z = mulNN(z, z, z) + z = z.mul(z, z) if v&mask != 0 { - z = mulNN(z, z, x) + z = z.mul(z, x) } if m != nil { - q, z = divNN(q, z, z, m) + q, z = q.div(z, z, m) } v <<= 1 @@ -685,14 +687,14 @@ func expNNN(z, x, y, m []Word) []Word { v = y[i] for j := 0; j < _W; j++ { - z = mulNN(z, z, z) + z = z.mul(z, z) if v&mask != 0 { - z = mulNN(z, z, x) + z = z.mul(z, x) } if m != nil { - q, z = divNN(q, z, z, m) + q, z = q.div(z, z, m) } v <<= 1 @@ -703,8 +705,8 @@ func expNNN(z, x, y, m []Word) []Word { } -// lenN returns the bit length of z. -func lenN(z []Word) int { +// len returns the bit length of z. +func (z nat) len() int { if len(z) == 0 { return 0 } @@ -718,13 +720,13 @@ const ( primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53} ) -var bigOne = []Word{1} -var bigTwo = []Word{2} +var bigOne = nat{1} +var bigTwo = nat{2} // probablyPrime performs reps Miller-Rabin tests to check whether n is prime. // If it returns true, n is prime with probability 1 - 1/4^reps. // If it returns false, n is not prime. -func probablyPrime(n []Word, reps int) bool { +func (n nat) probablyPrime(reps int) bool { if len(n) == 0 { return false } @@ -751,9 +753,9 @@ func probablyPrime(n []Word, reps int) bool { var r Word switch _W { case 32: - r = modNW(n, primesProduct32) + r = n.modW(primesProduct32) case 64: - r = modNW(n, primesProduct64&_M) + r = n.modW(primesProduct64 & _M) default: panic("Unknown word size") } @@ -768,31 +770,31 @@ func probablyPrime(n []Word, reps int) bool { return false } - nm1 := subNN(nil, n, bigOne) + nm1 := nat(nil).sub(n, bigOne) // 1<<k * q = nm1; - q, k := powersOfTwoDecompose(nm1) + q, k := nm1.powersOfTwoDecompose() - nm3 := subNN(nil, nm1, bigTwo) + nm3 := nat(nil).sub(nm1, bigTwo) rand := rand.New(rand.NewSource(int64(n[0]))) - var x, y, quotient []Word - nm3Len := lenN(nm3) + var x, y, quotient nat + nm3Len := nm3.len() NextRandom: for i := 0; i < reps; i++ { - x = randomN(x, rand, nm3, nm3Len) - x = addNN(x, x, bigTwo) - y = expNNN(y, x, q, n) - if cmpNN(y, bigOne) == 0 || cmpNN(y, nm1) == 0 { + x = x.random(rand, nm3, nm3Len) + x = x.add(x, bigTwo) + y = y.expNN(x, q, n) + if y.cmp(bigOne) == 0 || y.cmp(nm1) == 0 { continue } for j := Word(1); j < k; j++ { - y = mulNN(y, y, y) - quotient, y = divNN(quotient, y, y, n) - if cmpNN(y, nm1) == 0 { + y = y.mul(y, y) + quotient, y = quotient.div(y, y, n) + if y.cmp(nm1) == 0 { continue NextRandom } - if cmpNN(y, bigOne) == 0 { + if y.cmp(bigOne) == 0 { return false } } diff --git a/src/pkg/big/nat_test.go b/src/pkg/big/nat_test.go index 9c89504d78..ec24d61409 100644 --- a/src/pkg/big/nat_test.go +++ b/src/pkg/big/nat_test.go @@ -7,32 +7,32 @@ package big import "testing" type cmpTest struct { - x, y []Word + x, y nat r int } var cmpTests = []cmpTest{ cmpTest{nil, nil, 0}, - cmpTest{nil, []Word{}, 0}, - cmpTest{[]Word{}, nil, 0}, - cmpTest{[]Word{}, []Word{}, 0}, - cmpTest{[]Word{0}, []Word{0}, 0}, - cmpTest{[]Word{0}, []Word{1}, -1}, - cmpTest{[]Word{1}, []Word{0}, 1}, - cmpTest{[]Word{1}, []Word{1}, 0}, - cmpTest{[]Word{0, _M}, []Word{1}, 1}, - cmpTest{[]Word{1}, []Word{0, _M}, -1}, - cmpTest{[]Word{1, _M}, []Word{0, _M}, 1}, - cmpTest{[]Word{0, _M}, []Word{1, _M}, -1}, - cmpTest{[]Word{16, 571956, 8794, 68}, []Word{837, 9146, 1, 754489}, -1}, - cmpTest{[]Word{34986, 41, 105, 1957}, []Word{56, 7458, 104, 1957}, 1}, + cmpTest{nil, nat{}, 0}, + cmpTest{nat{}, nil, 0}, + cmpTest{nat{}, nat{}, 0}, + cmpTest{nat{0}, nat{0}, 0}, + cmpTest{nat{0}, nat{1}, -1}, + cmpTest{nat{1}, nat{0}, 1}, + cmpTest{nat{1}, nat{1}, 0}, + cmpTest{nat{0, _M}, nat{1}, 1}, + cmpTest{nat{1}, nat{0, _M}, -1}, + cmpTest{nat{1, _M}, nat{0, _M}, 1}, + cmpTest{nat{0, _M}, nat{1, _M}, -1}, + cmpTest{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1}, + cmpTest{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1}, } -func TestCmpNN(t *testing.T) { +func TestCmp(t *testing.T) { for i, a := range cmpTests { - r := cmpNN(a.x, a.y) + r := a.x.cmp(a.y) if r != a.r { t.Errorf("#%d got r = %v; want %v", i, r, a.r) } @@ -40,38 +40,38 @@ func TestCmpNN(t *testing.T) { } -type funNN func(z, x, y []Word) []Word +type funNN func(z, x, y nat) nat type argNN struct { - z, x, y []Word + z, x, y nat } var sumNN = []argNN{ argNN{}, - argNN{[]Word{1}, nil, []Word{1}}, - argNN{[]Word{1111111110}, []Word{123456789}, []Word{987654321}}, - argNN{[]Word{0, 0, 0, 1}, nil, []Word{0, 0, 0, 1}}, - argNN{[]Word{0, 0, 0, 1111111110}, []Word{0, 0, 0, 123456789}, []Word{0, 0, 0, 987654321}}, - argNN{[]Word{0, 0, 0, 1}, []Word{0, 0, _M}, []Word{0, 0, 1}}, + argNN{nat{1}, nil, nat{1}}, + argNN{nat{1111111110}, nat{123456789}, nat{987654321}}, + argNN{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}}, + argNN{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}}, + argNN{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}}, } var prodNN = []argNN{ argNN{}, argNN{nil, nil, nil}, - argNN{nil, []Word{991}, nil}, - argNN{[]Word{991}, []Word{991}, []Word{1}}, - argNN{[]Word{991 * 991}, []Word{991}, []Word{991}}, - argNN{[]Word{0, 0, 991 * 991}, []Word{0, 991}, []Word{0, 991}}, - argNN{[]Word{1 * 991, 2 * 991, 3 * 991, 4 * 991}, []Word{1, 2, 3, 4}, []Word{991}}, - argNN{[]Word{4, 11, 20, 30, 20, 11, 4}, []Word{1, 2, 3, 4}, []Word{4, 3, 2, 1}}, + argNN{nil, nat{991}, nil}, + argNN{nat{991}, nat{991}, nat{1}}, + argNN{nat{991 * 991}, nat{991}, nat{991}}, + argNN{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}}, + argNN{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}}, + argNN{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}}, } -func TestSetN(t *testing.T) { +func TestSet(t *testing.T) { for _, a := range sumNN { - z := setN(nil, a.z) - if cmpNN(z, a.z) != 0 { + z := nat(nil).set(a.z) + if z.cmp(a.z) != 0 { t.Errorf("got z = %v; want %v", z, a.z) } } @@ -80,7 +80,7 @@ func TestSetN(t *testing.T) { func testFunNN(t *testing.T, msg string, f funNN, a argNN) { z := f(nil, a.x, a.y) - if cmpNN(z, a.z) != 0 { + if z.cmp(a.z) != 0 { t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z) } } @@ -89,30 +89,30 @@ func testFunNN(t *testing.T, msg string, f funNN, a argNN) { func TestFunNN(t *testing.T) { for _, a := range sumNN { arg := a - testFunNN(t, "addNN", addNN, arg) + testFunNN(t, "add", nat.add, arg) arg = argNN{a.z, a.y, a.x} - testFunNN(t, "addNN symmetric", addNN, arg) + testFunNN(t, "add symmetric", nat.add, arg) arg = argNN{a.x, a.z, a.y} - testFunNN(t, "subNN", subNN, arg) + testFunNN(t, "sub", nat.sub, arg) arg = argNN{a.y, a.z, a.x} - testFunNN(t, "subNN symmetric", subNN, arg) + testFunNN(t, "sub symmetric", nat.sub, arg) } for _, a := range prodNN { arg := a - testFunNN(t, "mulNN", mulNN, arg) + testFunNN(t, "mul", nat.mul, arg) arg = argNN{a.z, a.y, a.x} - testFunNN(t, "mulNN symmetric", mulNN, arg) + testFunNN(t, "mul symmetric", nat.mul, arg) } } type strN struct { - x []Word + x nat b int s string } @@ -120,21 +120,21 @@ type strN struct { var tabN = []strN{ strN{nil, 10, "0"}, - strN{[]Word{1}, 10, "1"}, - strN{[]Word{10}, 10, "10"}, - strN{[]Word{1234567890}, 10, "1234567890"}, + strN{nat{1}, 10, "1"}, + strN{nat{10}, 10, "10"}, + strN{nat{1234567890}, 10, "1234567890"}, } -func TestStringN(t *testing.T) { +func TestString(t *testing.T) { for _, a := range tabN { - s := stringN(a.x, a.b) + s := a.x.string(a.b) if s != a.s { t.Errorf("stringN%+v\n\tgot s = %s; want %s", a, s, a.s) } - x, b, n := scanN(nil, a.s, a.b) - if cmpNN(x, a.x) != 0 { + x, b, n := nat(nil).scan(a.s, a.b) + if x.cmp(a.x) != 0 { t.Errorf("scanN%+v\n\tgot z = %v; want %v", a, x, a.x) } if b != a.b { @@ -159,27 +159,27 @@ func TestLeadingZeroBits(t *testing.T) { type shiftTest struct { - in []Word + in nat shift uint - out []Word + out nat } var leftShiftTests = []shiftTest{ shiftTest{nil, 0, nil}, shiftTest{nil, 1, nil}, - shiftTest{[]Word{0}, 0, []Word{0}}, - shiftTest{[]Word{1}, 0, []Word{1}}, - shiftTest{[]Word{1}, 1, []Word{2}}, - shiftTest{[]Word{1 << (_W - 1)}, 1, []Word{0}}, - shiftTest{[]Word{1 << (_W - 1), 0}, 1, []Word{0, 1}}, + shiftTest{nat{0}, 0, nat{0}}, + shiftTest{nat{1}, 0, nat{1}}, + shiftTest{nat{1}, 1, nat{2}}, + shiftTest{nat{1 << (_W - 1)}, 1, nat{0}}, + shiftTest{nat{1 << (_W - 1), 0}, 1, nat{0, 1}}, } func TestShiftLeft(t *testing.T) { for i, test := range leftShiftTests { - dst := make([]Word, len(test.out)) - shiftLeft(dst, test.in, test.shift) + dst := make(nat, len(test.out)) + dst.shiftLeft(test.in, test.shift) for j, v := range dst { if test.out[j] != v { t.Errorf("#%d: got: %v want: %v", i, dst, test.out) @@ -193,19 +193,19 @@ func TestShiftLeft(t *testing.T) { var rightShiftTests = []shiftTest{ shiftTest{nil, 0, nil}, shiftTest{nil, 1, nil}, - shiftTest{[]Word{0}, 0, []Word{0}}, - shiftTest{[]Word{1}, 0, []Word{1}}, - shiftTest{[]Word{1}, 1, []Word{0}}, - shiftTest{[]Word{2}, 1, []Word{1}}, - shiftTest{[]Word{0, 1}, 1, []Word{1 << (_W - 1), 0}}, - shiftTest{[]Word{2, 1, 1}, 1, []Word{1<<(_W-1) + 1, 1 << (_W - 1), 0}}, + shiftTest{nat{0}, 0, nat{0}}, + shiftTest{nat{1}, 0, nat{1}}, + shiftTest{nat{1}, 1, nat{0}}, + shiftTest{nat{2}, 1, nat{1}}, + shiftTest{nat{0, 1}, 1, nat{1 << (_W - 1), 0}}, + shiftTest{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1), 0}}, } func TestShiftRight(t *testing.T) { for i, test := range rightShiftTests { - dst := make([]Word, len(test.out)) - shiftRight(dst, test.in, test.shift) + dst := make(nat, len(test.out)) + dst.shiftRight(test.in, test.shift) for j, v := range dst { if test.out[j] != v { t.Errorf("#%d: got: %v want: %v", i, dst, test.out) @@ -216,30 +216,30 @@ func TestShiftRight(t *testing.T) { } -type modNWTest struct { +type modWTest struct { in string dividend string out string } -var modNWTests32 = []modNWTest{ - modNWTest{"23492635982634928349238759823742", "252341", "220170"}, +var modWTests32 = []modWTest{ + modWTest{"23492635982634928349238759823742", "252341", "220170"}, } -var modNWTests64 = []modNWTest{ - modNWTest{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"}, +var modWTests64 = []modWTest{ + modWTest{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"}, } -func runModNWTests(t *testing.T, tests []modNWTest) { +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 := modNW(in.abs, d.abs[0]) + r := in.abs.modW(d.abs[0]) if r != out.abs[0] { t.Errorf("#%d failed: got %s want %s\n", i, r, out) } @@ -247,12 +247,12 @@ func runModNWTests(t *testing.T, tests []modNWTest) { } -func TestModNW(t *testing.T) { +func TestModW(t *testing.T) { if _W >= 32 { - runModNWTests(t, modNWTests32) + runModWTests(t, modWTests32) } if _W >= 64 { - runModNWTests(t, modNWTests32) + runModWTests(t, modWTests64) } } @@ -269,19 +269,19 @@ func TestTrailingZeroBits(t *testing.T) { } -type expNNNTest struct { +type expNNTest struct { x, y, m string out string } -var expNNNTests = []expNNNTest{ - expNNNTest{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, - expNNNTest{"0x8000000000000000", "2", "6719", "4944"}, - expNNNTest{"0x8000000000000000", "3", "6719", "5447"}, - expNNNTest{"0x8000000000000000", "1000", "6719", "1603"}, - expNNNTest{"0x8000000000000000", "1000000", "6719", "3199"}, - expNNNTest{ +var expNNTests = []expNNTest{ + expNNTest{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, + expNNTest{"0x8000000000000000", "2", "6719", "4944"}, + expNNTest{"0x8000000000000000", "3", "6719", "5447"}, + expNNTest{"0x8000000000000000", "1000", "6719", "1603"}, + expNNTest{"0x8000000000000000", "1000000", "6719", "3199"}, + expNNTest{ "2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347", "298472983472983471903246121093472394872319615612417471234712061", "29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464", @@ -290,20 +290,20 @@ var expNNNTests = []expNNNTest{ } -func TestExpNNN(t *testing.T) { - for i, test := range expNNNTests { - x, _, _ := scanN(nil, test.x, 0) - y, _, _ := scanN(nil, test.y, 0) - out, _, _ := scanN(nil, test.out, 0) +func TestExpNN(t *testing.T) { + for i, test := range expNNTests { + x, _, _ := nat(nil).scan(test.x, 0) + y, _, _ := nat(nil).scan(test.y, 0) + out, _, _ := nat(nil).scan(test.out, 0) - var m []Word + var m nat if len(test.m) > 0 { - m, _, _ = scanN(nil, test.m, 0) + m, _, _ = nat(nil).scan(test.m, 0) } - z := expNNN(nil, x, y, m) - if cmpNN(z, out) != 0 { + z := nat(nil).expNN(x, y, m) + if z.cmp(out) != 0 { t.Errorf("#%d got %v want %v", i, z, out) } } |