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