cmp.gno

2.73 Kb ยท 125 lines
  1// cmp (or, comparisons) includes methods for comparing Uint instances.
  2// These comparison functions cover a range of operations including equality checks, less than/greater than
  3// evaluations, and specialized comparisons such as signed greater than. These are fundamental for logical
  4// decision making based on Uint values.
  5package uint256
  6
  7import (
  8	"math/bits"
  9)
 10
 11// Cmp compares z and x and returns:
 12//
 13//	-1 if z <  x
 14//	 0 if z == x
 15//	+1 if z >  x
 16func (z *Uint) Cmp(x *Uint) (r int) {
 17	// z < x <=> z - x < 0 i.e. when subtraction overflows.
 18	d0, carry := bits.Sub64(z.arr[0], x.arr[0], 0)
 19	d1, carry := bits.Sub64(z.arr[1], x.arr[1], carry)
 20	d2, carry := bits.Sub64(z.arr[2], x.arr[2], carry)
 21	d3, carry := bits.Sub64(z.arr[3], x.arr[3], carry)
 22	if carry == 1 {
 23		return -1
 24	}
 25	if d0|d1|d2|d3 == 0 {
 26		return 0
 27	}
 28	return 1
 29}
 30
 31// IsZero returns true if z == 0
 32func (z *Uint) IsZero() bool {
 33	return (z.arr[0] | z.arr[1] | z.arr[2] | z.arr[3]) == 0
 34}
 35
 36// Sign returns:
 37//
 38//	-1 if z <  0
 39//	 0 if z == 0
 40//	+1 if z >  0
 41//
 42// Where z is interpreted as a two's complement signed number
 43func (z *Uint) Sign() int {
 44	if z.IsZero() {
 45		return 0
 46	}
 47	if z.arr[3] < 0x8000000000000000 {
 48		return 1
 49	}
 50	return -1
 51}
 52
 53// LtUint64 returns true if z is smaller than n
 54func (z *Uint) LtUint64(n uint64) bool {
 55	return z.arr[0] < n && (z.arr[1]|z.arr[2]|z.arr[3]) == 0
 56}
 57
 58// GtUint64 returns true if z is larger than n
 59func (z *Uint) GtUint64(n uint64) bool {
 60	return z.arr[0] > n || (z.arr[1]|z.arr[2]|z.arr[3]) != 0
 61}
 62
 63// Lt returns true if z < x
 64func (z *Uint) Lt(x *Uint) bool {
 65	// z < x <=> z - x < 0 i.e. when subtraction overflows.
 66	_, carry := bits.Sub64(z.arr[0], x.arr[0], 0)
 67	_, carry = bits.Sub64(z.arr[1], x.arr[1], carry)
 68	_, carry = bits.Sub64(z.arr[2], x.arr[2], carry)
 69	_, carry = bits.Sub64(z.arr[3], x.arr[3], carry)
 70
 71	return carry != 0
 72}
 73
 74// Gt returns true if z > x
 75func (z *Uint) Gt(x *Uint) bool {
 76	return x.Lt(z)
 77}
 78
 79// Lte returns true if z <= x
 80func (z *Uint) Lte(x *Uint) bool {
 81	cond1 := z.Lt(x)
 82	cond2 := z.Eq(x)
 83
 84	if cond1 || cond2 {
 85		return true
 86	}
 87	return false
 88}
 89
 90// Gte returns true if z >= x
 91func (z *Uint) Gte(x *Uint) bool {
 92	cond1 := z.Gt(x)
 93	cond2 := z.Eq(x)
 94
 95	if cond1 || cond2 {
 96		return true
 97	}
 98	return false
 99}
100
101// Eq returns true if z == x
102func (z *Uint) Eq(x *Uint) bool {
103	return (z.arr[0] == x.arr[0]) && (z.arr[1] == x.arr[1]) && (z.arr[2] == x.arr[2]) && (z.arr[3] == x.arr[3])
104}
105
106// Neq returns true if z != x
107func (z *Uint) Neq(x *Uint) bool {
108	return !z.Eq(x)
109}
110
111// Sgt interprets z and x as signed integers, and returns
112// true if z > x
113func (z *Uint) Sgt(x *Uint) bool {
114	zSign := z.Sign()
115	xSign := x.Sign()
116
117	switch {
118	case zSign >= 0 && xSign < 0:
119		return true
120	case zSign < 0 && xSign >= 0:
121		return false
122	default:
123		return z.Gt(x)
124	}
125}