bitwise.gno
4.98 Kb ยท 264 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 = x | y and returns z.
7func (z *Uint) Or(x, y *Uint) *Uint {
8 z.arr[0] = x.arr[0] | y.arr[0]
9 z.arr[1] = x.arr[1] | y.arr[1]
10 z.arr[2] = x.arr[2] | y.arr[2]
11 z.arr[3] = x.arr[3] | y.arr[3]
12 return z
13}
14
15// And sets z = x & y and returns z.
16func (z *Uint) And(x, y *Uint) *Uint {
17 z.arr[0] = x.arr[0] & y.arr[0]
18 z.arr[1] = x.arr[1] & y.arr[1]
19 z.arr[2] = x.arr[2] & y.arr[2]
20 z.arr[3] = x.arr[3] & y.arr[3]
21 return z
22}
23
24// Not sets z = ^x and returns z.
25func (z *Uint) Not(x *Uint) *Uint {
26 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = ^x.arr[3], ^x.arr[2], ^x.arr[1], ^x.arr[0]
27 return z
28}
29
30// AndNot sets z = x &^ y and returns z.
31func (z *Uint) AndNot(x, y *Uint) *Uint {
32 z.arr[0] = x.arr[0] &^ y.arr[0]
33 z.arr[1] = x.arr[1] &^ y.arr[1]
34 z.arr[2] = x.arr[2] &^ y.arr[2]
35 z.arr[3] = x.arr[3] &^ y.arr[3]
36 return z
37}
38
39// Xor sets z = x ^ y and returns z.
40func (z *Uint) Xor(x, y *Uint) *Uint {
41 z.arr[0] = x.arr[0] ^ y.arr[0]
42 z.arr[1] = x.arr[1] ^ y.arr[1]
43 z.arr[2] = x.arr[2] ^ y.arr[2]
44 z.arr[3] = x.arr[3] ^ y.arr[3]
45 return z
46}
47
48// Lsh sets z = x << n and returns z.
49func (z *Uint) Lsh(x *Uint, n uint) *Uint {
50 // n % 64 == 0
51 if n&0x3f == 0 {
52 switch n {
53 case 0:
54 return z.Set(x)
55 case 64:
56 return z.lsh64(x)
57 case 128:
58 return z.lsh128(x)
59 case 192:
60 return z.lsh192(x)
61 default:
62 return z.Clear()
63 }
64 }
65 var a, b uint64
66 // Big swaps first
67 switch {
68 case n > 192:
69 if n > 256 {
70 return z.Clear()
71 }
72 z.lsh192(x)
73 n -= 192
74 goto sh192
75 case n > 128:
76 z.lsh128(x)
77 n -= 128
78 goto sh128
79 case n > 64:
80 z.lsh64(x)
81 n -= 64
82 goto sh64
83 default:
84 z.Set(x)
85 }
86
87 // remaining shifts
88 a = z.arr[0] >> (64 - n)
89 z.arr[0] = z.arr[0] << n
90
91sh64:
92 b = z.arr[1] >> (64 - n)
93 z.arr[1] = (z.arr[1] << n) | a
94
95sh128:
96 a = z.arr[2] >> (64 - n)
97 z.arr[2] = (z.arr[2] << n) | b
98
99sh192:
100 z.arr[3] = (z.arr[3] << n) | a
101
102 return z
103}
104
105// Rsh sets z = x >> n and returns z.
106func (z *Uint) Rsh(x *Uint, n uint) *Uint {
107 // n % 64 == 0
108 if n&0x3f == 0 {
109 switch n {
110 case 0:
111 return z.Set(x)
112 case 64:
113 return z.rsh64(x)
114 case 128:
115 return z.rsh128(x)
116 case 192:
117 return z.rsh192(x)
118 default:
119 return z.Clear()
120 }
121 }
122 var a, b uint64
123 // Big swaps first
124 switch {
125 case n > 192:
126 if n > 256 {
127 return z.Clear()
128 }
129 z.rsh192(x)
130 n -= 192
131 goto sh192
132 case n > 128:
133 z.rsh128(x)
134 n -= 128
135 goto sh128
136 case n > 64:
137 z.rsh64(x)
138 n -= 64
139 goto sh64
140 default:
141 z.Set(x)
142 }
143
144 // remaining shifts
145 a = z.arr[3] << (64 - n)
146 z.arr[3] = z.arr[3] >> n
147
148sh64:
149 b = z.arr[2] << (64 - n)
150 z.arr[2] = (z.arr[2] >> n) | a
151
152sh128:
153 a = z.arr[1] << (64 - n)
154 z.arr[1] = (z.arr[1] >> n) | b
155
156sh192:
157 z.arr[0] = (z.arr[0] >> n) | a
158
159 return z
160}
161
162// SRsh (Signed/Arithmetic right shift)
163// considers z to be a signed integer, during right-shift
164// and sets z = x >> n and returns z.
165func (z *Uint) SRsh(x *Uint, n uint) *Uint {
166 // If the MSB is 0, SRsh is same as Rsh.
167 if !x.isBitSet(255) {
168 return z.Rsh(x, n)
169 }
170 if n%64 == 0 {
171 switch n {
172 case 0:
173 return z.Set(x)
174 case 64:
175 return z.srsh64(x)
176 case 128:
177 return z.srsh128(x)
178 case 192:
179 return z.srsh192(x)
180 default:
181 return z.SetAllOne()
182 }
183 }
184 var a uint64 = MaxUint64 << (64 - n%64)
185 // Big swaps first
186 switch {
187 case n > 192:
188 if n > 256 {
189 return z.SetAllOne()
190 }
191 z.srsh192(x)
192 n -= 192
193 goto sh192
194 case n > 128:
195 z.srsh128(x)
196 n -= 128
197 goto sh128
198 case n > 64:
199 z.srsh64(x)
200 n -= 64
201 goto sh64
202 default:
203 z.Set(x)
204 }
205
206 // remaining shifts
207 z.arr[3], a = (z.arr[3]>>n)|a, z.arr[3]<<(64-n)
208
209sh64:
210 z.arr[2], a = (z.arr[2]>>n)|a, z.arr[2]<<(64-n)
211
212sh128:
213 z.arr[1], a = (z.arr[1]>>n)|a, z.arr[1]<<(64-n)
214
215sh192:
216 z.arr[0] = (z.arr[0] >> n) | a
217
218 return z
219}
220
221func (z *Uint) lsh64(x *Uint) *Uint {
222 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[2], x.arr[1], x.arr[0], 0
223 return z
224}
225
226func (z *Uint) lsh128(x *Uint) *Uint {
227 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[1], x.arr[0], 0, 0
228 return z
229}
230
231func (z *Uint) lsh192(x *Uint) *Uint {
232 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[0], 0, 0, 0
233 return z
234}
235
236func (z *Uint) rsh64(x *Uint) *Uint {
237 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, x.arr[3], x.arr[2], x.arr[1]
238 return z
239}
240
241func (z *Uint) rsh128(x *Uint) *Uint {
242 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, x.arr[3], x.arr[2]
243 return z
244}
245
246func (z *Uint) rsh192(x *Uint) *Uint {
247 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, x.arr[3]
248 return z
249}
250
251func (z *Uint) srsh64(x *Uint) *Uint {
252 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, x.arr[3], x.arr[2], x.arr[1]
253 return z
254}
255
256func (z *Uint) srsh128(x *Uint) *Uint {
257 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, x.arr[3], x.arr[2]
258 return z
259}
260
261func (z *Uint) srsh192(x *Uint) *Uint {
262 z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, MaxUint64, x.arr[3]
263 return z
264}