bitwise.gno
4.91 Kb · 276 lines
1// bitwise contains bitwise operations for Uint instances.
2// This file includes functions to perform bitwise AND, OR, XOR, and NOT operations, as well as bit shifting.
3// These operations are crucial for manipulating individual bits within a 256-bit unsigned integer.
4package uint256
5
6// Or sets z to the bitwise OR of x and y and returns z.
7func (z *Uint) Or(x, y *Uint) *Uint {
8 z[0] = x[0] | y[0]
9 z[1] = x[1] | y[1]
10 z[2] = x[2] | y[2]
11 z[3] = x[3] | y[3]
12 return z
13}
14
15// And sets z to the bitwise AND of x and y and returns z.
16func (z *Uint) And(x, y *Uint) *Uint {
17 z[0] = x[0] & y[0]
18 z[1] = x[1] & y[1]
19 z[2] = x[2] & y[2]
20 z[3] = x[3] & y[3]
21 return z
22}
23
24// Not sets z to the bitwise NOT of x and returns z.
25func (z *Uint) Not(x *Uint) *Uint {
26 z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0]
27 return z
28}
29
30// AndNot sets z to x AND NOT y and returns z.
31func (z *Uint) AndNot(x, y *Uint) *Uint {
32 z[0] = x[0] &^ y[0]
33 z[1] = x[1] &^ y[1]
34 z[2] = x[2] &^ y[2]
35 z[3] = x[3] &^ y[3]
36 return z
37}
38
39// Xor sets z to the bitwise XOR of x and y and returns z.
40func (z *Uint) Xor(x, y *Uint) *Uint {
41 z[0] = x[0] ^ y[0]
42 z[1] = x[1] ^ y[1]
43 z[2] = x[2] ^ y[2]
44 z[3] = x[3] ^ y[3]
45 return z
46}
47
48// Lsh sets z to x left-shifted by n bits and returns z.
49// The result is truncated to 256 bits. If n >= 256, z is set to 0.
50func (z *Uint) Lsh(x *Uint, n uint) *Uint {
51 if x.IsZero() {
52 return z.Clear()
53 }
54
55 if n == 0 {
56 return z.Set(x)
57 }
58
59 return z.lsh(x, n)
60}
61
62// lsh performs left shift without overflow checking
63func (z *Uint) lsh(x *Uint, n uint) *Uint {
64 // n % 64 == 0
65 if n&0x3f == 0 {
66 switch n {
67 case 0:
68 return z.Set(x)
69 case 64:
70 return z.lsh64(x)
71 case 128:
72 return z.lsh128(x)
73 case 192:
74 return z.lsh192(x)
75 default:
76 return z.Clear()
77 }
78 }
79 var a, b uint64
80 // Big swaps first
81 switch {
82 case n > 192:
83 z.lsh192(x)
84 n -= 192
85 goto sh192
86 case n > 128:
87 z.lsh128(x)
88 n -= 128
89 goto sh128
90 case n > 64:
91 z.lsh64(x)
92 n -= 64
93 goto sh64
94 default:
95 z.Set(x)
96 }
97
98 // remaining shifts
99 a = z[0] >> (64 - n)
100 z[0] = z[0] << n
101
102sh64:
103 b = z[1] >> (64 - n)
104 z[1] = (z[1] << n) | a
105
106sh128:
107 a = z[2] >> (64 - n)
108 z[2] = (z[2] << n) | b
109
110sh192:
111 z[3] = (z[3] << n) | a
112
113 return z
114}
115
116// Rsh sets z to x right-shifted by n bits and returns z.
117// If n >= 256, z is set to 0.
118func (z *Uint) Rsh(x *Uint, n uint) *Uint {
119 // n % 64 == 0
120 if n&0x3f == 0 {
121 switch n {
122 case 0:
123 return z.Set(x)
124 case 64:
125 return z.rsh64(x)
126 case 128:
127 return z.rsh128(x)
128 case 192:
129 return z.rsh192(x)
130 default:
131 return z.Clear()
132 }
133 }
134 var a, b uint64
135 // Big swaps first
136 switch {
137 case n > 192:
138 if n > 256 {
139 return z.Clear()
140 }
141 z.rsh192(x)
142 n -= 192
143 goto sh192
144 case n > 128:
145 z.rsh128(x)
146 n -= 128
147 goto sh128
148 case n > 64:
149 z.rsh64(x)
150 n -= 64
151 goto sh64
152 default:
153 z.Set(x)
154 }
155
156 // remaining shifts
157 a = z[3] << (64 - n)
158 z[3] = z[3] >> n
159
160sh64:
161 b = z[2] << (64 - n)
162 z[2] = (z[2] >> n) | a
163
164sh128:
165 a = z[1] << (64 - n)
166 z[1] = (z[1] >> n) | b
167
168sh192:
169 z[0] = (z[0] >> n) | a
170
171 return z
172}
173
174// SRsh sets z to x arithmetically right-shifted by n bits and returns z.
175// It treats x as a signed two's complement integer. For negative values,
176// high-order bits are filled with 1s instead of 0s. If n >= 256 and x is negative, z is set to all 1s.
177func (z *Uint) SRsh(x *Uint, n uint) *Uint {
178 // If the MSB is 0, SRsh is same as Rsh.
179 if !x.isBitSet(255) {
180 return z.Rsh(x, n)
181 }
182 if n%64 == 0 {
183 switch n {
184 case 0:
185 return z.Set(x)
186 case 64:
187 return z.srsh64(x)
188 case 128:
189 return z.srsh128(x)
190 case 192:
191 return z.srsh192(x)
192 default:
193 return z.SetAllOne()
194 }
195 }
196 var a uint64 = MAX_UINT64 << (64 - n%64)
197 // Big swaps first
198 switch {
199 case n > 192:
200 if n > 256 {
201 return z.SetAllOne()
202 }
203 z.srsh192(x)
204 n -= 192
205 goto sh192
206 case n > 128:
207 z.srsh128(x)
208 n -= 128
209 goto sh128
210 case n > 64:
211 z.srsh64(x)
212 n -= 64
213 goto sh64
214 default:
215 z.Set(x)
216 }
217
218 // remaining shifts
219 z[3], a = (z[3]>>n)|a, z[3]<<(64-n)
220
221sh64:
222 z[2], a = (z[2]>>n)|a, z[2]<<(64-n)
223
224sh128:
225 z[1], a = (z[1]>>n)|a, z[1]<<(64-n)
226
227sh192:
228 z[0] = (z[0] >> n) | a
229
230 return z
231}
232
233func (z *Uint) lsh64(x *Uint) *Uint {
234 z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0
235 return z
236}
237
238func (z *Uint) lsh128(x *Uint) *Uint {
239 z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0
240 return z
241}
242
243func (z *Uint) lsh192(x *Uint) *Uint {
244 z[3], z[2], z[1], z[0] = x[0], 0, 0, 0
245 return z
246}
247
248func (z *Uint) rsh64(x *Uint) *Uint {
249 z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1]
250 return z
251}
252
253func (z *Uint) rsh128(x *Uint) *Uint {
254 z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2]
255 return z
256}
257
258func (z *Uint) rsh192(x *Uint) *Uint {
259 z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]
260 return z
261}
262
263func (z *Uint) srsh64(x *Uint) *Uint {
264 z[3], z[2], z[1], z[0] = MAX_UINT64, x[3], x[2], x[1]
265 return z
266}
267
268func (z *Uint) srsh128(x *Uint) *Uint {
269 z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, x[3], x[2]
270 return z
271}
272
273func (z *Uint) srsh192(x *Uint) *Uint {
274 z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, MAX_UINT64, x[3]
275 return z
276}