]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: better test coverage, misc. cleanups
authorRobert Griesemer <gri@golang.org>
Fri, 16 Jan 2015 23:11:26 +0000 (15:11 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 20 Jan 2015 19:23:47 +0000 (19:23 +0000)
Change-Id: I4ce5cee63093d917095bf90f4e11123f7ec0f93c
Reviewed-on: https://go-review.googlesource.com/2964
Reviewed-by: Alan Donovan <adonovan@google.com>
src/math/big/int.go
src/math/big/int_test.go
src/math/big/nat.go
src/math/big/nat_test.go

index 38297707436e845a9b72a888dd2bc054e35b18be..62a07d69a05a91249d6f3da93ff5fa6ea754258a 100644 (file)
@@ -736,7 +736,7 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
 
 // ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
 // If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime. n must be >0.
+// If it returns false, x is not prime. n must be > 0.
 func (x *Int) ProbablyPrime(n int) bool {
        if n <= 0 {
                panic("non-positive n for ProbablyPrime")
index 520fcb31d5802ad89601d2370d59f1c8d6d2095f..a698e2de2dffc9eca60a87c1b16f4c159c33525f 100644 (file)
@@ -621,6 +621,44 @@ func TestDivisionSigns(t *testing.T) {
        }
 }
 
+var bitTests = []nat{
+       nil,
+       {0},
+       {1},
+       {0, 1, 2, 3, 4},
+       {4, 3, 2, 1, 0},
+       {4, 3, 2, 1, 0, 0, 0, 0},
+}
+
+func norm(x nat) nat {
+       i := len(x)
+       for i > 0 && x[i-1] == 0 {
+               i--
+       }
+       return x[:i]
+}
+
+func TestBits(t *testing.T) {
+       for _, test := range bitTests {
+               var z Int
+               z.neg = true
+               got := z.SetBits(test)
+               want := norm(test)
+               if got.abs.cmp(want) != 0 {
+                       t.Errorf("SetBits(%v) = %v; want %v", test, got.abs, want)
+               }
+
+               if got.neg {
+                       t.Errorf("SetBits(%v): got negative result")
+               }
+
+               bits := nat(z.Bits())
+               if bits.cmp(want) != 0 {
+                       t.Errorf("%v.Bits() = %v; want %v", z.abs, bits, want)
+               }
+       }
+}
+
 func checkSetBytes(b []byte) bool {
        hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
        hex2 := hex.EncodeToString(b)
@@ -962,6 +1000,8 @@ var primes = []string{
 }
 
 var composites = []string{
+       "0",
+       "1",
        "21284175091214687912771199898307297748211672914763848041968395774954376176754",
        "6084766654921918907427900243509372380954290099172559290432744450051395395951",
        "84594350493221918389213352992032324280367711247940675652888030554255915464401",
index 6e65ea1cb44adb9d312740eb483dc1f4ff0ddb36..bf00b8858a8050d1b88cafad294b38c4419f90e1 100644 (file)
@@ -610,7 +610,7 @@ func (x nat) bitLen() int {
 const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
 
 func hexValue(ch rune) Word {
-       d := int(MaxBase + 1) // illegal base
+       d := int(MaxBase + 1) // invalid base
        switch {
        case '0' <= ch && ch <= '9':
                d = int(ch - '0')
@@ -634,9 +634,9 @@ func hexValue(ch rune) Word {
 // ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
 //
 func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) {
-       // reject illegal bases
+       // reject invalid bases
        if base < 0 || base == 1 || MaxBase < base {
-               return z, 0, errors.New("illegal number base")
+               return z, 0, errors.New("invalid number base")
        }
 
        // one char look-ahead
@@ -728,7 +728,13 @@ const (
 // decimalString returns a decimal representation of x.
 // It calls x.string with the charset "0123456789".
 func (x nat) decimalString() string {
-       return x.string(lowercaseDigits[0:10])
+       return x.string(lowercaseDigits[:10])
+}
+
+// hexString returns a hexadecimal representation of x.
+// It calls x.string with the charset "0123456789abcdef".
+func (x nat) hexString() string {
+       return x.string(lowercaseDigits[:16])
 }
 
 // string converts x to a string using digits from a charset; a digit with
@@ -739,8 +745,8 @@ func (x nat) string(charset string) string {
 
        // special cases
        switch {
-       case b < 2 || MaxBase > 256:
-               panic("illegal base")
+       case b < 2 || b > 256:
+               panic("invalid character set length")
        case len(x) == 0:
                return string(charset[0])
        }
index 5d93df735deebd84c22ea9a61123a2ad431fa0f9..acd265bd392049599b4713d58c629ad23878b93c 100644 (file)
@@ -243,16 +243,28 @@ var strTests = []struct {
        {nil, "01", "0"},
        {nat{1}, "01", "1"},
        {nat{0xc5}, "01", "11000101"},
-       {nat{03271}, lowercaseDigits[0:8], "3271"},
-       {nat{10}, lowercaseDigits[0:10], "10"},
-       {nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
-       {nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
-       {nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
-       {nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
-       {nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
+       {nat{03271}, lowercaseDigits[:8], "3271"},
+       {nat{10}, lowercaseDigits[:10], "10"},
+       {nat{1234567890}, uppercaseDigits[:10], "1234567890"},
+       {nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
+       {nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
+       {nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
+       {nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
 }
 
 func TestString(t *testing.T) {
+       // test invalid character set explicitly
+       var panicStr string
+       func() {
+               defer func() {
+                       panicStr = recover().(string)
+               }()
+               natOne.string("0")
+       }()
+       if panicStr != "invalid character set length" {
+               t.Errorf("expected panic for invalid character set")
+       }
+
        for _, a := range strTests {
                s := a.x.string(a.c)
                if s != a.s {
@@ -474,8 +486,8 @@ func ScanHelper(b *testing.B, base int, x, y Word) {
        z = z.expWW(x, y)
 
        var s string
-       s = z.string(lowercaseDigits[0:base])
-       if t := toString(z, lowercaseDigits[0:base]); t != s {
+       s = z.string(lowercaseDigits[:base])
+       if t := toString(z, lowercaseDigits[:base]); t != s {
                b.Fatalf("scanning: got %s; want %s", s, t)
        }
        b.StartTimer()
@@ -513,11 +525,11 @@ func StringHelper(b *testing.B, base int, x, y Word) {
        b.StopTimer()
        var z nat
        z = z.expWW(x, y)
-       z.string(lowercaseDigits[0:base]) // warm divisor cache
+       z.string(lowercaseDigits[:base]) // warm divisor cache
        b.StartTimer()
 
        for i := 0; i < b.N; i++ {
-               _ = z.string(lowercaseDigits[0:base])
+               _ = z.string(lowercaseDigits[:base])
        }
 }
 
@@ -551,12 +563,12 @@ func LeafSizeHelper(b *testing.B, base Word, size int) {
        for d := 1; d <= 10000; d *= 10 {
                b.StopTimer()
                var z nat
-               z = z.expWW(base, Word(d))            // build target number
-               _ = z.string(lowercaseDigits[0:base]) // warm divisor cache
+               z = z.expWW(base, Word(d))           // build target number
+               _ = z.string(lowercaseDigits[:base]) // warm divisor cache
                b.StartTimer()
 
                for i := 0; i < b.N; i++ {
-                       _ = z.string(lowercaseDigits[0:base])
+                       _ = z.string(lowercaseDigits[:base])
                }
        }
 
@@ -581,8 +593,8 @@ func TestStringPowers(t *testing.T) {
        for b = 2; b <= 16; b++ {
                for p = 0; p <= 512; p++ {
                        x := nat(nil).expWW(b, p)
-                       xs := x.string(lowercaseDigits[0:b])
-                       xs2 := toString(x, lowercaseDigits[0:b])
+                       xs := x.string(lowercaseDigits[:b])
+                       xs2 := toString(x, lowercaseDigits[:b])
                        if xs != xs2 {
                                t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
                        }
@@ -691,20 +703,30 @@ func TestModW(t *testing.T) {
 }
 
 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++ {
+       for i := uint(0); i < _W; i++ {
                n := trailingZeroBits(x)
-               if n != i%_W {
+               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.string(lowercaseDigits[0:16]), n, i)
+                       t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
                }
                y = y.shl(y, 1)
        }