Commit 841a32dd authored by Evan Shaw's avatar Evan Shaw Committed by Robert Griesemer

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
parent 5cd8c830
......@@ -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] {
......
......@@ -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
}
......@@ -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)
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment