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
diff --git a/src/pkg/big/arith_test.go b/src/pkg/big/arith_test.go
index b0f6bf6..49908e3 100644
--- a/src/pkg/big/arith_test.go
+++ b/src/pkg/big/arith_test.go
@@ -52,7 +52,7 @@
 }
 
 
-func addr(x []Word) *Word {
+func addr(x nat) *Word {
 	if len(x) == 0 {
 		return nil
 	}
@@ -62,26 +62,26 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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 ca94c5a..6b570a0 100644
--- a/src/pkg/big/int.go
+++ b/src/pkg/big/int.go
@@ -9,8 +9,8 @@
 // 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 @@
 		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 @@
 // 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 @@
 		// 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 @@
 		// 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 @@
 	// 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 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 @@
 	// (-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 @@
 	if z.neg {
 		s = "-"
 	}
-	return s + stringN(z.abs, 10)
+	return s + z.abs.string(10)
 }
 
 
@@ -212,7 +212,7 @@
 		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 @@
 // 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 @@
 		z.abs[j] = w
 	}
 
-	z.abs = normN(z.abs)
+	z.abs = z.abs.norm()
 
 	return z
 }
@@ -306,12 +306,12 @@
 		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 @@
 // 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) 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 914a631..bb42f81 100644
--- a/src/pkg/big/int_test.go
+++ b/src/pkg/big/int_test.go
@@ -327,8 +327,8 @@
 	// 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 8843d43..2c8f837 100644
--- a/src/pkg/big/nat.go
+++ b/src/pkg/big/nat.go
@@ -34,10 +34,9 @@
 // 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 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 @@
 	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 @@
 	}
 
 	// 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 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 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 subNN(z, x, y []Word) []Word {
+func (z nat) sub(x, y nat) nat {
 	m := len(x)
 	n := len(y)
 
@@ -143,14 +142,14 @@
 		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 @@
 	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 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 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 @@
 // 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 @@
 		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 @@
 }
 
 
-// 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 @@
 // 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 @@
 	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 @@
 // 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 @@
 	}
 
 	// 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 @@
 }
 
 
-// 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 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 @@
 	// 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 @@
 
 		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 @@
 
 	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 @@
 		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 @@
 }
 
 
-// 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 @@
 	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 @@
 	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 @@
 		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 9c89504..ec24d61 100644
--- a/src/pkg/big/nat_test.go
+++ b/src/pkg/big/nat_test.go
@@ -7,32 +7,32 @@
 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 @@
 }
 
 
-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 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) {
 	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 @@
 
 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 @@
 
 
 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 @@
 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 @@
 }
 
 
-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 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 @@
 }
 
 
-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 @@
 }
 
 
-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)
 		}
 	}