github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/uint256/cmp.gno (about) 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. 5 package uint256 6 7 import ( 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 16 func (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 32 func (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 43 func (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 54 func (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 59 func (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 64 func (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 75 func (z *Uint) Gt(x *Uint) bool { 76 return x.Lt(z) 77 } 78 79 // Lte returns true if z <= x 80 func (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 91 func (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 102 func (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 107 func (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 113 func (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 }