]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: correctly test for positive inputs in Int.GCD
authorRobert Griesemer <gri@golang.org>
Wed, 13 Jun 2012 20:54:36 +0000 (13:54 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 13 Jun 2012 20:54:36 +0000 (13:54 -0700)
Also: better GCD tests.

R=rsc
CC=golang-dev
https://golang.org/cl/6295076

src/pkg/math/big/int.go
src/pkg/math/big/int_test.go

index 74e5c2313b1117553a7fd2ccfe4165d4143174b7..4bd7958ae5045c8cf063fcffb5b92250af6d813f 100644 (file)
@@ -581,12 +581,12 @@ func (z *Int) Exp(x, y, m *Int) *Int {
        return z
 }
 
-// GCD sets z to the greatest common divisor of a and b, which must be
-// positive numbers, and returns z.
+// GCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
 // If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
-// If either a or b is not positive, GCD sets z = x = y = 0.
+// If either a or b is <= 0, GCD sets z = x = y = 0.
 func (z *Int) GCD(x, y, a, b *Int) *Int {
-       if a.neg || b.neg {
+       if a.Sign() <= 0 || b.Sign() <= 0 {
                z.SetInt64(0)
                if x != nil {
                        x.SetInt64(0)
index 4ec2ac56f39535450dea37a8421446d031735a1a..27834cec6af1c8cd6a4afe431e3174cf0d0ce55b 100644 (file)
@@ -818,14 +818,12 @@ func TestExp(t *testing.T) {
 }
 
 func checkGcd(aBytes, bBytes []byte) bool {
-       a := new(Int).SetBytes(aBytes)
-       b := new(Int).SetBytes(bBytes)
-
        x := new(Int)
        y := new(Int)
-       d := new(Int)
+       a := new(Int).SetBytes(aBytes)
+       b := new(Int).SetBytes(bBytes)
 
-       d.GCD(x, y, a, b)
+       d := new(Int).GCD(x, y, a, b)
        x.Mul(x, a)
        y.Mul(y, b)
        x.Add(x, y)
@@ -834,39 +832,70 @@ func checkGcd(aBytes, bBytes []byte) bool {
 }
 
 var gcdTests = []struct {
-       a, b    int64
-       d, x, y int64
+       d, x, y, a, b string
 }{
-       {120, 23, 1, -9, 47},
-}
-
-func TestGcd(t *testing.T) {
-       for i, test := range gcdTests {
-               a := NewInt(test.a)
-               b := NewInt(test.b)
-
-               x := new(Int)
-               y := new(Int)
-               d := new(Int)
-
-               expectedX := NewInt(test.x)
-               expectedY := NewInt(test.y)
-               expectedD := NewInt(test.d)
-
-               d.GCD(x, y, a, b)
+       // a <= 0 || b <= 0
+       {"0", "0", "0", "0", "0"},
+       {"0", "0", "0", "0", "7"},
+       {"0", "0", "0", "11", "0"},
+       {"0", "0", "0", "-77", "35"},
+       {"0", "0", "0", "64515", "-24310"},
+       {"0", "0", "0", "-64515", "-24310"},
+
+       {"1", "-9", "47", "120", "23"},
+       {"7", "1", "-2", "77", "35"},
+       {"935", "-3", "8", "64515", "24310"},
+       {"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"},
+       {"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"},
+
+       // test early exit (after one Euclidean iteration) in binaryGCD
+       {"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"},
+}
+
+func testGcd(t *testing.T, d, x, y, a, b *Int) {
+       var X *Int
+       if x != nil {
+               X = new(Int)
+       }
+       var Y *Int
+       if y != nil {
+               Y = new(Int)
+       }
 
-               if expectedX.Cmp(x) != 0 ||
-                       expectedY.Cmp(y) != 0 ||
-                       expectedD.Cmp(d) != 0 {
-                       t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
-               }
+       D := new(Int).GCD(X, Y, a, b)
+       if D.Cmp(d) != 0 {
+               t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d)
+       }
+       if x != nil && X.Cmp(x) != 0 {
+               t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x)
+       }
+       if y != nil && Y.Cmp(y) != 0 {
+               t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y)
+       }
 
-               d.binaryGCD(a, b)
+       // binaryGCD requires a > 0 && b > 0
+       if a.Sign() <= 0 || b.Sign() <= 0 {
+               return
+       }
 
-               if expectedD.Cmp(d) != 0 {
-                       t.Errorf("#%d got (%s) want (%s)", i, d, expectedD)
-               }
+       D.binaryGCD(a, b)
+       if D.Cmp(d) != 0 {
+               t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
+       }
+}
 
+func TestGcd(t *testing.T) {
+       for _, test := range gcdTests {
+               d, _ := new(Int).SetString(test.d, 0)
+               x, _ := new(Int).SetString(test.x, 0)
+               y, _ := new(Int).SetString(test.y, 0)
+               a, _ := new(Int).SetString(test.a, 0)
+               b, _ := new(Int).SetString(test.b, 0)
+
+               testGcd(t, d, nil, nil, a, b)
+               testGcd(t, d, x, nil, a, b)
+               testGcd(t, d, nil, y, a, b)
+               testGcd(t, d, x, y, a, b)
        }
 
        quick.Check(checkGcd, nil)