Commit 28a0971c authored by Evan Shaw's avatar Evan Shaw Committed by Robert Griesemer

big: Several fixes to bitwise functions

Fixed:
* SetString calls in bitwise tests
* Aliasing problem with self bitwise test
* One test case that was just flat out wrong
* Slice panics in nat.or and nat.xor
* Aliasing problems in Int.And, Int.AndNot, Int.Or, Int.Xor

Fixes #1007.

R=gri
CC=golang-dev
https://golang.org/cl/1895049
parent e2c7e53d
...@@ -590,7 +590,7 @@ func (z *Int) And(x, y *Int) *Int { ...@@ -590,7 +590,7 @@ func (z *Int) And(x, y *Int) *Int {
if x.neg { if x.neg {
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) // (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
x1 := nat{}.sub(x.abs, natOne) x1 := nat{}.sub(x.abs, natOne)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.or(x1, y1), natOne) z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
z.neg = true // z cannot be zero if x and y are negative z.neg = true // z cannot be zero if x and y are negative
return z return z
...@@ -608,7 +608,7 @@ func (z *Int) And(x, y *Int) *Int { ...@@ -608,7 +608,7 @@ func (z *Int) And(x, y *Int) *Int {
} }
// x & (-y) == x & ^(y-1) == x &^ (y-1) // x & (-y) == x & ^(y-1) == x &^ (y-1)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.andNot(x.abs, y1) z.abs = z.abs.andNot(x.abs, y1)
z.neg = false z.neg = false
return z return z
...@@ -621,7 +621,7 @@ func (z *Int) AndNot(x, y *Int) *Int { ...@@ -621,7 +621,7 @@ func (z *Int) AndNot(x, y *Int) *Int {
if x.neg { if x.neg {
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1) // (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
x1 := nat{}.sub(x.abs, natOne) x1 := nat{}.sub(x.abs, natOne)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.andNot(y1, x1) z.abs = z.abs.andNot(y1, x1)
z.neg = false z.neg = false
return z return z
...@@ -635,14 +635,14 @@ func (z *Int) AndNot(x, y *Int) *Int { ...@@ -635,14 +635,14 @@ func (z *Int) AndNot(x, y *Int) *Int {
if x.neg { if x.neg {
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1) // (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
x1 := z.abs.sub(x.abs, natOne) x1 := nat{}.sub(x.abs, natOne)
z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne) z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
z.neg = true // z cannot be zero if x is negative and y is positive z.neg = true // z cannot be zero if x is negative and y is positive
return z return z
} }
// x &^ (-y) == x &^ ^(y-1) == x & (y-1) // x &^ (-y) == x &^ ^(y-1) == x & (y-1)
y1 := z.abs.add(y.abs, natOne) y1 := nat{}.add(y.abs, natOne)
z.abs = z.abs.and(x.abs, y1) z.abs = z.abs.and(x.abs, y1)
z.neg = false z.neg = false
return z return z
...@@ -655,7 +655,7 @@ func (z *Int) Or(x, y *Int) *Int { ...@@ -655,7 +655,7 @@ func (z *Int) Or(x, y *Int) *Int {
if x.neg { if x.neg {
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1) // (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
x1 := nat{}.sub(x.abs, natOne) x1 := nat{}.sub(x.abs, natOne)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.and(x1, y1), natOne) z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
z.neg = true // z cannot be zero if x and y are negative z.neg = true // z cannot be zero if x and y are negative
return z return z
...@@ -673,7 +673,7 @@ func (z *Int) Or(x, y *Int) *Int { ...@@ -673,7 +673,7 @@ func (z *Int) Or(x, y *Int) *Int {
} }
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1) // x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne) z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
z.neg = true // z cannot be zero if one of x or y is negative z.neg = true // z cannot be zero if one of x or y is negative
return z return z
...@@ -686,7 +686,7 @@ func (z *Int) Xor(x, y *Int) *Int { ...@@ -686,7 +686,7 @@ func (z *Int) Xor(x, y *Int) *Int {
if x.neg { if x.neg {
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1) // (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
x1 := nat{}.sub(x.abs, natOne) x1 := nat{}.sub(x.abs, natOne)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.xor(x1, y1) z.abs = z.abs.xor(x1, y1)
z.neg = false z.neg = false
return z return z
...@@ -704,7 +704,7 @@ func (z *Int) Xor(x, y *Int) *Int { ...@@ -704,7 +704,7 @@ func (z *Int) Xor(x, y *Int) *Int {
} }
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1) // x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
y1 := z.abs.sub(y.abs, natOne) y1 := nat{}.sub(y.abs, natOne)
z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne) z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
z.neg = true // z cannot be zero if only one of x or y is negative z.neg = true // z cannot be zero if only one of x or y is negative
return z return z
......
...@@ -938,7 +938,7 @@ var bitwiseTests = []bitwiseTest{ ...@@ -938,7 +938,7 @@ var bitwiseTests = []bitwiseTest{
bitwiseTest{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"}, bitwiseTest{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"},
bitwiseTest{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"}, bitwiseTest{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"},
bitwiseTest{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"}, bitwiseTest{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"},
bitwiseTest{"-0xAF", "-0x50", "0x00", "-0xFF", "-0x01", "-0x01"}, bitwiseTest{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"},
bitwiseTest{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"}, bitwiseTest{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"},
bitwiseTest{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"}, bitwiseTest{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"},
bitwiseTest{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"}, bitwiseTest{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
...@@ -978,24 +978,24 @@ type bitFun func(z, x, y *Int) *Int ...@@ -978,24 +978,24 @@ type bitFun func(z, x, y *Int) *Int
func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
expected := new(Int) expected := new(Int)
expected.SetString(exp, 16) expected.SetString(exp, 0)
out := f(new(Int), x, y) out := f(new(Int), x, y)
if out.Cmp(expected) != 0 { if out.Cmp(expected) != 0 {
println("Test failed")
t.Errorf("%s: got %s want %s", msg, out, expected) t.Errorf("%s: got %s want %s", msg, out, expected)
} }
} }
func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
self := new(Int)
self.Set(x)
expected := new(Int) expected := new(Int)
expected.SetString(exp, 16) expected.SetString(exp, 0)
x = f(x, x, y) self = f(self, self, y)
if x.Cmp(expected) != 0 { if self.Cmp(expected) != 0 {
println("Test failed") t.Errorf("%s: got %s want %s", msg, self, expected)
t.Errorf("%s: got %s want %s", msg, x, expected)
} }
} }
...@@ -1004,8 +1004,8 @@ func TestBitwise(t *testing.T) { ...@@ -1004,8 +1004,8 @@ func TestBitwise(t *testing.T) {
x := new(Int) x := new(Int)
y := new(Int) y := new(Int)
for _, test := range bitwiseTests { for _, test := range bitwiseTests {
x.SetString(test.x, 16) x.SetString(test.x, 0)
y.SetString(test.y, 16) y.SetString(test.y, 0)
testBitFun(t, "and", (*Int).And, x, y, test.and) testBitFun(t, "and", (*Int).And, x, y, test.and)
testBitFunSelf(t, "and", (*Int).And, x, y, test.and) testBitFunSelf(t, "and", (*Int).And, x, y, test.and)
......
...@@ -816,13 +816,13 @@ func (z nat) or(x, y nat) nat { ...@@ -816,13 +816,13 @@ func (z nat) or(x, y nat) nat {
n, m = m, n n, m = m, n
s = y s = y
} }
// n >= m // m >= n
z = z.make(n) z = z.make(m)
for i := 0; i < m; i++ { for i := 0; i < n; i++ {
z[i] = x[i] | y[i] z[i] = x[i] | y[i]
} }
copy(z[m:n], s[m:n]) copy(z[n:m], s[n:m])
return z.norm() return z.norm()
} }
...@@ -832,17 +832,17 @@ func (z nat) xor(x, y nat) nat { ...@@ -832,17 +832,17 @@ func (z nat) xor(x, y nat) nat {
m := len(x) m := len(x)
n := len(y) n := len(y)
s := x s := x
if n < m { if m < n {
n, m = m, n n, m = m, n
s = y s = y
} }
// n >= m // m >= n
z = z.make(n) z = z.make(m)
for i := 0; i < m; i++ { for i := 0; i < n; i++ {
z[i] = x[i] ^ y[i] z[i] = x[i] ^ y[i]
} }
copy(z[m:n], s[m:n]) copy(z[n:m], s[n:m])
return z.norm() return z.norm()
} }
......
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