-
Notifications
You must be signed in to change notification settings - Fork 1
/
operations.go
203 lines (163 loc) · 3.85 KB
/
operations.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Copyright 2018 Weborama. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uint128 // import "github.com/weborama/uint128"
import "math/bits"
// Cmp compares two Uint128 and returns one of the following values:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
// nolint: varnamelen
func Cmp(x, y Uint128) int {
if x.H < y.H {
return -1
} else if x.H > y.H {
return 1
}
if x.L < y.L {
return -1
} else if x.L > y.L {
return 1
}
return 0
}
// IsZero returns true if x is zero.
func IsZero(x Uint128) bool {
return x.H == 0 && x.L == 0
}
// ShiftLeft shifts x to the left by the provided number of bits.
// nolint: varnamelen
func ShiftLeft(x Uint128, bits uint) Uint128 {
switch {
case bits >= numBits:
x.H = 0
x.L = 0
case bits >= numHalfBits:
x.H = x.L << (bits - numHalfBits)
x.L = 0
default:
x.H <<= bits
x.H |= x.L >> (numHalfBits - bits)
x.L <<= bits
}
return x
}
// ShiftRight shifts x to the right by the provided number of bits.
// nolint: varnamelen
func ShiftRight(x Uint128, bits uint) Uint128 {
switch {
case bits >= numBits:
x.H = 0
x.L = 0
case bits >= numHalfBits:
x.L = x.H >> (bits - numHalfBits)
x.H = 0
default:
x.L >>= bits
x.L |= x.H << (numHalfBits - bits)
x.H >>= bits
}
return x
}
// And returns the logical AND of x and y.
func And(x, y Uint128) Uint128 {
x.H &= y.H
x.L &= y.L
return x
}
// AndNot returns the logical AND NOT of x and y.
func AndNot(x, y Uint128) Uint128 {
x.H &^= y.H
x.L &^= y.L
return x
}
// Not returns the logical NOT of x and o.
func Not(x Uint128) Uint128 {
x.H = ^x.H
x.L = ^x.L
return x
}
// Xor returns the logical XOR of x and y.
func Xor(x, y Uint128) Uint128 {
x.H ^= y.H
x.L ^= y.L
return x
}
// Or returns the logical OR of x and y.
func Or(x, y Uint128) Uint128 {
x.H |= y.H
x.L |= y.L
return x
}
// Add adds x and y.
func Add(x, y Uint128) Uint128 {
sum, _ := Add128(x, y, Zero())
return sum
}
// Add128 returns the sum with carry of x, y and carry: sum = x + y + carry.
// The carry input must be 0 or 1; otherwise the behavior is undefined.
// The carryOut output is guaranteed to be 0 or 1.
func Add128(x, y, carry Uint128) (sum, carryOut Uint128) {
sum.L, carryOut.L = bits.Add64(x.L, y.L, carry.L)
sum.H, carryOut.L = bits.Add64(x.H, y.H, carryOut.L)
return
}
// Incr increments x by one.
func Incr(x Uint128) Uint128 {
return Add(x, Uint128{H: 0, L: 1})
}
// Sub subtracts x and y.
// nolint: ifshort, varnamelen
func Sub(x, y Uint128) Uint128 {
pL := x.L
x.L -= y.L
x.H -= y.H
if x.L > pL {
x.H--
}
return x
}
// Decr decrements x by one.
// nolint: ifshort, varnamelen
func Decr(x Uint128) Uint128 {
pL := x.L
x.L--
if x.L > pL {
x.H--
}
return x
}
// Len returns the minimum number of bits required to represent x; the result is 0 for x == 0.
func Len(x Uint128) int {
if x.H == 0 {
return bits.Len64(x.L)
}
return numHalfBits + bits.Len64(x.H)
}
// LeadingZeros returns the number of leading zero bits in x; the result is 128 for x == 0.
func LeadingZeros(x Uint128) int {
return numBits - Len(x)
}
// OnesCount returns the number of one bits ("population count") in x.
func OnesCount(x Uint128) int {
return bits.OnesCount64(x.H) + bits.OnesCount64(x.L)
}
// TrailingZeros returns the number of trailing zero bits in x; the result is 128 for x == 0.
func TrailingZeros(x Uint128) int {
if x.L == 0 {
return bits.TrailingZeros64(x.H) + numHalfBits
}
return bits.TrailingZeros64(x.L)
}
// Reverse returns the value of x with its bits in reversed order.
func Reverse(x Uint128) (y Uint128) {
y.L, y.H = bits.Reverse64(x.H), bits.Reverse64(x.L)
return
}
// ReverseBytes returns the value of x with its bytes in reversed order.
func ReverseBytes(x Uint128) (y Uint128) {
y.L, y.H = bits.ReverseBytes64(x.H), bits.ReverseBytes64(x.L)
return
}