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}