uint256: Add general comparison support.
This adds the ability to compare a uint256 to another uint256 or a uint64 along with associated tests to ensure proper functionality. The comparison logic is the usual logic where -1 is returned when the uint256 is less than the value being compared to, 0 when it is equal, and 1 when it is greater. This is part of a series of commits to fully implement the uint256 package.
This commit is contained in:
parent
e8ba80ed6a
commit
2d86902ba7
@ -19,16 +19,15 @@ var (
|
||||
// callers may rely on "wrap around" semantics.
|
||||
//
|
||||
// It currently implements support for comparison operations (equals, less,
|
||||
// greater), interpreting and producing big and little endian bytes, and other
|
||||
// convenience methods such as whether or not the value can be represented as a
|
||||
// uint64 without loss of precision.
|
||||
// greater, cmp), interpreting and producing big and little endian bytes, and
|
||||
// other convenience methods such as whether or not the value can be represented
|
||||
// as a uint64 without loss of precision.
|
||||
//
|
||||
// Future commits will implement the primary arithmetic operations (addition,
|
||||
// subtraction, multiplication, squaring, division, negation), bitwise
|
||||
// operations (lsh, rsh, not, or, and, xor), comparison operations (cmp), and
|
||||
// other convenience methods such as determining the minimum number of bits
|
||||
// required to represent the current value and text formatting with base
|
||||
// conversion.
|
||||
// operations (lsh, rsh, not, or, and, xor), and other convenience methods such
|
||||
// as determining the minimum number of bits required to represent the current
|
||||
// value and text formatting with base conversion.
|
||||
type Uint256 struct {
|
||||
// The uint256 is represented as 4 unsigned 64-bit integers in base 2^64.
|
||||
//
|
||||
@ -422,3 +421,45 @@ func (n *Uint256) GtEq(n2 *Uint256) bool {
|
||||
func (n *Uint256) GtEqUint64(n2 uint64) bool {
|
||||
return !n.LtUint64(n2)
|
||||
}
|
||||
|
||||
// Cmp compares the two uint256s and returns -1, 0, or 1 depending on whether
|
||||
// the uint256 is less than, equal to, or greater than the given one.
|
||||
//
|
||||
// That is, it returns:
|
||||
//
|
||||
// -1 when n < n2
|
||||
// 0 when n == n2
|
||||
// +1 when n > n2
|
||||
func (n *Uint256) Cmp(n2 *Uint256) int {
|
||||
var borrow uint64
|
||||
r0, borrow := bits.Sub64(n.n[0], n2.n[0], borrow)
|
||||
r1, borrow := bits.Sub64(n.n[1], n2.n[1], borrow)
|
||||
r2, borrow := bits.Sub64(n.n[2], n2.n[2], borrow)
|
||||
r3, borrow := bits.Sub64(n.n[3], n2.n[3], borrow)
|
||||
if borrow != 0 {
|
||||
return -1
|
||||
}
|
||||
if r0|r1|r2|r3 == 0 {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// CmpUint64 compares the uint256 with the given uint64 and returns -1, 0, or 1
|
||||
// depending on whether the uint256 is less than, equal to, or greater than the
|
||||
// uint64.
|
||||
//
|
||||
// That is, it returns:
|
||||
//
|
||||
// -1 when n < n2
|
||||
// 0 when n == n2
|
||||
// +1 when n > n2
|
||||
func (n *Uint256) CmpUint64(n2 uint64) int {
|
||||
if n.LtUint64(n2) {
|
||||
return -1
|
||||
}
|
||||
if n.GtUint64(n2) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -848,9 +848,17 @@ func TestUint256Comparison(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
// Ensure comparing the numbers produces the expected cmp result.
|
||||
n1 := hexToUint256(test.n1)
|
||||
n2 := hexToUint256(test.n2)
|
||||
gotCmp := n1.Cmp(n2)
|
||||
if gotCmp != test.wantCmp {
|
||||
t.Errorf("%q: incorrect cmp result -- got: %v, want: %v", test.name,
|
||||
gotCmp, test.wantCmp)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
isEq := n1.Eq(n2)
|
||||
wantEq := test.wantCmp == 0
|
||||
if isEq != wantEq {
|
||||
@ -924,8 +932,15 @@ func TestUint256ComparisonRandom(t *testing.T) {
|
||||
t.Fatalf("failed equality check -- n2: %x", n2)
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
// Ensure the uint256 comparison result matches the one using big ints.
|
||||
bigCmpResult := bigN1.Cmp(bigN2)
|
||||
cmpResult := n1.Cmp(n2)
|
||||
if cmpResult != bigCmpResult {
|
||||
t.Errorf("incorrect cmp result n1: %x, n2: %x -- got %v, want %v",
|
||||
n1, n2, cmpResult, bigCmpResult)
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
isEq := n1.Eq(n2)
|
||||
wantEq := bigCmpResult == 0
|
||||
if isEq != wantEq {
|
||||
@ -1060,8 +1075,16 @@ func TestUint256ComparisonUint64(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
// Ensure comparing the numbers produces the expected cmp result.
|
||||
n1 := hexToUint256(test.n1)
|
||||
gotCmp := n1.CmpUint64(test.n2)
|
||||
if gotCmp != test.wantCmp {
|
||||
t.Errorf("%q: incorrect cmp result -- got: %v, want: %v", test.name,
|
||||
gotCmp, test.wantCmp)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
isEq := n1.EqUint64(test.n2)
|
||||
wantEq := test.wantCmp == 0
|
||||
if isEq != wantEq {
|
||||
@ -1137,8 +1160,15 @@ func TestUint256ComparisonUint64Random(t *testing.T) {
|
||||
t.Fatalf("failed equality check -- n: %x", truncatedN1)
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
// Ensure the uint256 comparison result matches the one using big ints.
|
||||
bigCmpResult := bigN1.Cmp(bigN2)
|
||||
cmpResult := n1.CmpUint64(n2)
|
||||
if cmpResult != bigCmpResult {
|
||||
t.Errorf("incorrect cmp result n1: %x, n2: %x -- got %v, want %v",
|
||||
n1, n2, cmpResult, bigCmpResult)
|
||||
}
|
||||
|
||||
// Ensure comparing the numbers produces the expected == result.
|
||||
isEq := n1.EqUint64(n2)
|
||||
wantEq := bigCmpResult == 0
|
||||
if isEq != wantEq {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user