mirror of
https://github.com/golang/go
synced 2024-11-26 06:17:57 -07:00
implemented outstanding bit ops on negative integerts
R=rsc DELTA=195 (146 added, 1 deleted, 48 changed) OCL=31895 CL=31931
This commit is contained in:
parent
90ffb7b8f5
commit
2b1ec70d0f
@ -110,10 +110,10 @@ func dump(x []digit) {
|
|||||||
type Natural []digit;
|
type Natural []digit;
|
||||||
|
|
||||||
var (
|
var (
|
||||||
natZero Natural = Natural{};
|
natZero = Natural{};
|
||||||
natOne Natural = Natural{1};
|
natOne = Natural{1};
|
||||||
natTwo Natural = Natural{2};
|
natTwo = Natural{2};
|
||||||
natTen Natural = Natural{10};
|
natTen = Natural{10};
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -588,7 +588,7 @@ func (x Natural) Shr(s uint) Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// And returns the ``bitwise and'' x & y for the binary representation of x and y.
|
// And returns the ``bitwise and'' x & y for the 2's-complement representation of x and y.
|
||||||
//
|
//
|
||||||
func (x Natural) And(y Natural) Natural {
|
func (x Natural) And(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
@ -614,7 +614,7 @@ func copy(z, x []digit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AndNot returns the ``bitwise clear'' x &^ y for the binary representation of x and y.
|
// AndNot returns the ``bitwise clear'' x &^ y for the 2's-complement representation of x and y.
|
||||||
//
|
//
|
||||||
func (x Natural) AndNot(y Natural) Natural {
|
func (x Natural) AndNot(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
@ -633,7 +633,7 @@ func (x Natural) AndNot(y Natural) Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Or returns the ``bitwise or'' x | y for the binary representation of x and y.
|
// Or returns the ``bitwise or'' x | y for the 2's-complement representation of x and y.
|
||||||
//
|
//
|
||||||
func (x Natural) Or(y Natural) Natural {
|
func (x Natural) Or(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
@ -652,7 +652,7 @@ func (x Natural) Or(y Natural) Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Xor returns the ``bitwise exclusive or'' x ^ y for the binary representation of x and y.
|
// Xor returns the ``bitwise exclusive or'' x ^ y for the 2's-complement representation of x and y.
|
||||||
//
|
//
|
||||||
func (x Natural) Xor(y Natural) Natural {
|
func (x Natural) Xor(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
@ -1230,68 +1230,135 @@ func (x *Integer) Shl(s uint) *Integer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The bitwise operations on integers are defined on the 2's-complement
|
||||||
|
// representation of integers. From
|
||||||
|
//
|
||||||
|
// -x == ^x + 1 (1) 2's complement representation
|
||||||
|
//
|
||||||
|
// follows:
|
||||||
|
//
|
||||||
|
// -(x) == ^(x) + 1
|
||||||
|
// -(-x) == ^(-x) + 1
|
||||||
|
// x-1 == ^(-x)
|
||||||
|
// ^(x-1) == -x (2)
|
||||||
|
//
|
||||||
|
// Using (1) and (2), operations on negative integers of the form -x are
|
||||||
|
// converted to operations on negated positive integers of the form ~(x-1).
|
||||||
|
|
||||||
|
|
||||||
// Shr implements ``shift right'' x >> s. It returns x / 2^s.
|
// Shr implements ``shift right'' x >> s. It returns x / 2^s.
|
||||||
// Implementation restriction: Shl is not yet implemented for negative x.
|
|
||||||
//
|
//
|
||||||
func (x *Integer) Shr(s uint) *Integer {
|
func (x *Integer) Shr(s uint) *Integer {
|
||||||
if !x.sign {
|
if x.sign {
|
||||||
return MakeInt(false, x.mant.Shr(s));
|
// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
|
||||||
|
return MakeInt(true, x.mant.Sub(natOne).Shr(s).Add(natOne));
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNIMPLEMENTED Integer.Shr of negative value");
|
return MakeInt(false, x.mant.Shr(s));
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// And returns the ``bitwise and'' x & y for the binary representation of x and y.
|
// Not returns the ``bitwise not'' ^x for the 2's-complement representation of x.
|
||||||
// Implementation restriction: And is not implemented for negative integers.
|
func (x *Integer) Not() *Integer {
|
||||||
|
if x.sign {
|
||||||
|
// ^(-x) == ^(^(x-1)) == x-1
|
||||||
|
return MakeInt(false, x.mant.Sub(natOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^x == -x-1 == -(x+1)
|
||||||
|
return MakeInt(true, x.mant.Add(natOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// And returns the ``bitwise and'' x & y for the 2's-complement representation of x and y.
|
||||||
//
|
//
|
||||||
func (x *Integer) And(y *Integer) *Integer {
|
func (x *Integer) And(y *Integer) *Integer {
|
||||||
if !x.sign && !y.sign {
|
if x.sign == y.sign {
|
||||||
|
if x.sign {
|
||||||
|
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
|
||||||
|
return MakeInt(true, x.mant.Sub(natOne).Or(y.mant.Sub(natOne)).Add(natOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
// x & y == x & y
|
||||||
return MakeInt(false, x.mant.And(y.mant));
|
return MakeInt(false, x.mant.And(y.mant));
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNIMPLEMENTED Integer.And of negative values");
|
// x.sign != y.sign
|
||||||
return nil;
|
if x.sign {
|
||||||
|
x, y = y, x; // & is symmetric
|
||||||
|
}
|
||||||
|
|
||||||
|
// x & (-y) == x & ^(y-1) == x &^ (y-1)
|
||||||
|
return MakeInt(false, x.mant.AndNot(y.mant.Sub(natOne)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AndNot returns the ``bitwise clear'' x &^ y for the binary representation of x and y.
|
// AndNot returns the ``bitwise clear'' x &^ y for the 2's-complement representation of x and y.
|
||||||
// Implementation restriction: AndNot is not implemented for negative integers.
|
|
||||||
//
|
//
|
||||||
func (x *Integer) AndNot(y *Integer) *Integer {
|
func (x *Integer) AndNot(y *Integer) *Integer {
|
||||||
if !x.sign && !y.sign {
|
if x.sign == y.sign {
|
||||||
|
if x.sign {
|
||||||
|
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
|
||||||
|
return MakeInt(false, y.mant.Sub(natOne).AndNot(x.mant.Sub(natOne)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// x &^ y == x &^ y
|
||||||
return MakeInt(false, x.mant.AndNot(y.mant));
|
return MakeInt(false, x.mant.AndNot(y.mant));
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNIMPLEMENTED Integer.AndNot of negative values");
|
if x.sign {
|
||||||
return nil;
|
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
|
||||||
|
return MakeInt(true, x.mant.Sub(natOne).Or(y.mant).Add(natOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
|
||||||
|
return MakeInt(false, x.mant.And(y.mant.Sub(natOne)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Or returns the ``bitwise or'' x | y for the binary representation of x and y.
|
// Or returns the ``bitwise or'' x | y for the 2's-complement representation of x and y.
|
||||||
// Implementation restriction: Or is not implemented for negative integers.
|
|
||||||
//
|
//
|
||||||
func (x *Integer) Or(y *Integer) *Integer {
|
func (x *Integer) Or(y *Integer) *Integer {
|
||||||
if !x.sign && !y.sign {
|
if x.sign == y.sign {
|
||||||
|
if x.sign {
|
||||||
|
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
|
||||||
|
return MakeInt(true, x.mant.Sub(natOne).And(y.mant.Sub(natOne)).Add(natOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
// x | y == x | y
|
||||||
return MakeInt(false, x.mant.Or(y.mant));
|
return MakeInt(false, x.mant.Or(y.mant));
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNIMPLEMENTED Integer.Or of negative values");
|
// x.sign != y.sign
|
||||||
return nil;
|
if x.sign {
|
||||||
|
x, y = y, x; // | or symmetric
|
||||||
|
}
|
||||||
|
|
||||||
|
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
|
||||||
|
return MakeInt(true, y.mant.Sub(natOne).AndNot(x.mant).Add(natOne));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Xor returns the ``bitwise xor'' x | y for the binary representation of x and y.
|
// Xor returns the ``bitwise xor'' x | y for the 2's-complement representation of x and y.
|
||||||
// Implementation restriction: Xor is not implemented for negative integers.
|
|
||||||
//
|
//
|
||||||
func (x *Integer) Xor(y *Integer) *Integer {
|
func (x *Integer) Xor(y *Integer) *Integer {
|
||||||
if !x.sign && !y.sign {
|
if x.sign == y.sign {
|
||||||
|
if x.sign {
|
||||||
|
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
|
||||||
|
return MakeInt(false, x.mant.Sub(natOne).Xor(y.mant.Sub(natOne)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// x ^ y == x ^ y
|
||||||
return MakeInt(false, x.mant.Xor(y.mant));
|
return MakeInt(false, x.mant.Xor(y.mant));
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNIMPLEMENTED Integer.Xor of negative values");
|
// x.sign != y.sign
|
||||||
return nil;
|
if x.sign {
|
||||||
|
x, y = y, x; // ^ is symmetric
|
||||||
|
}
|
||||||
|
|
||||||
|
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
|
||||||
|
return MakeInt(true, x.mant.Xor(y.mant.Sub(natOne)).Add(natOne));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,8 +467,9 @@ func TestIntShift(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "IntShift4R";
|
test_msg = "IntShift4R";
|
||||||
//int_eq(0, Int(-43).Shr(1), Int(-43 >> 1));
|
int_eq(0, Int(-43).Shr(1), Int(-43 >> 1));
|
||||||
//int_eq(1, ip.Neg().Shr(10), ip.Neg().Div(Int(1).Shl(10)));
|
int_eq(0, Int(-1024).Shr(100), Int(-1));
|
||||||
|
int_eq(1, ip.Neg().Shr(10), ip.Neg().Div(Int(1).Shl(10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -507,6 +508,83 @@ func TestNatBitOps(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestIntBitOps1(t *testing.T) {
|
||||||
|
tester = t;
|
||||||
|
test_msg = "IntBitOps1";
|
||||||
|
type T struct { x, y int64 };
|
||||||
|
a := []T {
|
||||||
|
T{ +7, +3 },
|
||||||
|
T{ +7, -3 },
|
||||||
|
T{ -7, +3 },
|
||||||
|
T{ -7, -3 },
|
||||||
|
};
|
||||||
|
for i := uint(0); i < uint(len(a)); i++ {
|
||||||
|
e := &a[i];
|
||||||
|
int_eq(4*i+0, Int(e.x).And(Int(e.y)), Int(e.x & e.y));
|
||||||
|
int_eq(4*i+1, Int(e.x).AndNot(Int(e.y)), Int(e.x &^ e.y));
|
||||||
|
int_eq(4*i+2, Int(e.x).Or(Int(e.y)), Int(e.x | e.y));
|
||||||
|
int_eq(4*i+3, Int(e.x).Xor(Int(e.y)), Int(e.x ^ e.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestIntBitOps2(t *testing.T) {
|
||||||
|
tester = t;
|
||||||
|
|
||||||
|
test_msg = "IntNot";
|
||||||
|
int_eq(0, Int(-2).Not(), Int( 1));
|
||||||
|
int_eq(0, Int(-1).Not(), Int( 0));
|
||||||
|
int_eq(0, Int( 0).Not(), Int(-1));
|
||||||
|
int_eq(0, Int( 1).Not(), Int(-2));
|
||||||
|
int_eq(0, Int( 2).Not(), Int(-3));
|
||||||
|
|
||||||
|
test_msg = "IntAnd";
|
||||||
|
for x := int64(-15); x < 5; x++ {
|
||||||
|
bx := Int(x);
|
||||||
|
for y := int64(-5); y < 15; y++ {
|
||||||
|
by := Int(y);
|
||||||
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
|
int_eq(i, bx.Shl(i).And(by.Shl(i)), Int(x & y).Shl(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_msg = "IntAndNot";
|
||||||
|
for x := int64(-15); x < 5; x++ {
|
||||||
|
bx := Int(x);
|
||||||
|
for y := int64(-5); y < 15; y++ {
|
||||||
|
by := Int(y);
|
||||||
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
|
int_eq(2*i+0, bx.Shl(i).AndNot(by.Shl(i)), Int(x &^ y).Shl(i));
|
||||||
|
int_eq(2*i+1, bx.Shl(i).And(by.Shl(i).Not()), Int(x &^ y).Shl(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_msg = "IntOr";
|
||||||
|
for x := int64(-15); x < 5; x++ {
|
||||||
|
bx := Int(x);
|
||||||
|
for y := int64(-5); y < 15; y++ {
|
||||||
|
by := Int(y);
|
||||||
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
|
int_eq(i, bx.Shl(i).Or(by.Shl(i)), Int(x | y).Shl(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_msg = "IntXor";
|
||||||
|
for x := int64(-15); x < 5; x++ {
|
||||||
|
bx := Int(x);
|
||||||
|
for y := int64(-5); y < 15; y++ {
|
||||||
|
by := Int(y);
|
||||||
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
|
int_eq(i, bx.Shl(i).Xor(by.Shl(i)), Int(x ^ y).Shl(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestNatCmp(t *testing.T) {
|
func TestNatCmp(t *testing.T) {
|
||||||
tester = t;
|
tester = t;
|
||||||
test_msg = "NatCmp";
|
test_msg = "NatCmp";
|
||||||
|
Loading…
Reference in New Issue
Block a user