bitwise_test.gno
14.21 Kb ยท 423 lines
1package uint256
2
3import "testing"
4
5type logicOpTest struct {
6 name string
7 x Uint
8 y Uint
9 want Uint
10}
11
12func TestOr(t *testing.T) {
13 tests := []logicOpTest{
14 {
15 name: "all zeros",
16 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
17 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
18 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
19 },
20 {
21 name: "all ones",
22 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
23 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
24 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
25 },
26 {
27 name: "mixed",
28 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
29 y: Uint{arr: [4]uint64{0, 0, ^uint64(0), ^uint64(0)}},
30 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
31 },
32 {
33 name: "one operand all ones",
34 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
35 y: Uint{arr: [4]uint64{0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000}},
36 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
37 },
38 }
39
40 for _, tt := range tests {
41 t.Run(tt.name, func(t *testing.T) {
42 res := new(Uint).Or(&tt.x, &tt.y)
43 if *res != tt.want {
44 t.Errorf(
45 "Or(%s, %s) = %s, want %s",
46 tt.x.String(), tt.y.String(), res.String(), (tt.want).String(),
47 )
48 }
49 })
50 }
51}
52
53func TestAnd(t *testing.T) {
54 tests := []logicOpTest{
55 {
56 name: "all zeros",
57 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
58 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
59 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
60 },
61 {
62 name: "all ones",
63 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
64 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
65 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
66 },
67 {
68 name: "mixed",
69 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
70 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
71 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
72 },
73 {
74 name: "mixed 2",
75 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
76 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
77 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
78 },
79 {
80 name: "mixed 3",
81 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
82 y: Uint{arr: [4]uint64{0, 0, ^uint64(0), ^uint64(0)}},
83 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
84 },
85 {
86 name: "one operand zero",
87 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
88 y: Uint{arr: [4]uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}},
89 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
90 },
91 {
92 name: "one operand all ones",
93 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
94 y: Uint{arr: [4]uint64{0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000}},
95 want: Uint{arr: [4]uint64{0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000}},
96 },
97 }
98
99 for _, tt := range tests {
100 t.Run(tt.name, func(t *testing.T) {
101 res := new(Uint).And(&tt.x, &tt.y)
102 if *res != tt.want {
103 t.Errorf(
104 "And(%s, %s) = %s, want %s",
105 tt.x.String(), tt.y.String(), res.String(), (tt.want).String(),
106 )
107 }
108 })
109 }
110}
111
112func TestNot(t *testing.T) {
113 tests := []struct {
114 name string
115 x Uint
116 want Uint
117 }{
118 {
119 name: "all zeros",
120 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
121 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
122 },
123 {
124 name: "all ones",
125 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
126 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
127 },
128 {
129 name: "mixed",
130 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
131 want: Uint{arr: [4]uint64{0, 0, ^uint64(0), ^uint64(0)}},
132 },
133 }
134
135 for _, tt := range tests {
136 t.Run(tt.name, func(t *testing.T) {
137 res := new(Uint).Not(&tt.x)
138 if *res != tt.want {
139 t.Errorf(
140 "Not(%s) = %s, want %s",
141 tt.x.String(), res.String(), (tt.want).String(),
142 )
143 }
144 })
145 }
146}
147
148func TestAndNot(t *testing.T) {
149 tests := []logicOpTest{
150 {
151 name: "all zeros",
152 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
153 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
154 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
155 },
156 {
157 name: "all ones",
158 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
159 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
160 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
161 },
162 {
163 name: "mixed",
164 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
165 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
166 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
167 },
168 {
169 name: "mixed 2",
170 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
171 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
172 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
173 },
174 {
175 name: "mixed 3",
176 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
177 y: Uint{arr: [4]uint64{0, 0, ^uint64(0), ^uint64(0)}},
178 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
179 },
180 {
181 name: "one operand zero",
182 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
183 y: Uint{arr: [4]uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}},
184 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
185 },
186 {
187 name: "one operand all ones",
188 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
189 y: Uint{arr: [4]uint64{0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000}},
190 want: Uint{arr: [4]uint64{0xAAAAAAAAAAAAAAAA, 0x5555555555555555, 0x0000000000000000, ^uint64(0)}},
191 },
192 }
193
194 for _, tt := range tests {
195 t.Run(tt.name, func(t *testing.T) {
196 res := new(Uint).AndNot(&tt.x, &tt.y)
197 if *res != tt.want {
198 t.Errorf(
199 "AndNot(%s, %s) = %s, want %s",
200 tt.x.String(), tt.y.String(), res.String(), (tt.want).String(),
201 )
202 }
203 })
204 }
205}
206
207func TestXor(t *testing.T) {
208 tests := []logicOpTest{
209 {
210 name: "all zeros",
211 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
212 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
213 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
214 },
215 {
216 name: "all ones",
217 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
218 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
219 want: Uint{arr: [4]uint64{0, 0, 0, 0}},
220 },
221 {
222 name: "mixed",
223 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
224 y: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
225 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
226 },
227 {
228 name: "mixed 2",
229 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
230 y: Uint{arr: [4]uint64{0, 0, 0, 0}},
231 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
232 },
233 {
234 name: "mixed 3",
235 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), 0, 0}},
236 y: Uint{arr: [4]uint64{0, 0, ^uint64(0), ^uint64(0)}},
237 want: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
238 },
239 {
240 name: "one operand zero",
241 x: Uint{arr: [4]uint64{0, 0, 0, 0}},
242 y: Uint{arr: [4]uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}},
243 want: Uint{arr: [4]uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}},
244 },
245 {
246 name: "one operand all ones",
247 x: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}},
248 y: Uint{arr: [4]uint64{0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000}},
249 want: Uint{arr: [4]uint64{0xAAAAAAAAAAAAAAAA, 0x5555555555555555, 0x0000000000000000, ^uint64(0)}},
250 },
251 }
252
253 for _, tt := range tests {
254 t.Run(tt.name, func(t *testing.T) {
255 res := new(Uint).Xor(&tt.x, &tt.y)
256 if *res != tt.want {
257 t.Errorf(
258 "Xor(%s, %s) = %s, want %s",
259 tt.x.String(), tt.y.String(), res.String(), (tt.want).String(),
260 )
261 }
262 })
263 }
264}
265
266func TestLsh(t *testing.T) {
267 tests := []struct {
268 x string
269 y uint
270 want string
271 }{
272 {"0", 0, "0"},
273 {"0", 1, "0"},
274 {"0", 64, "0"},
275 {"1", 0, "1"},
276 {"1", 1, "2"},
277 {"1", 64, "18446744073709551616"},
278 {"1", 128, "340282366920938463463374607431768211456"},
279 {"1", 192, "6277101735386680763835789423207666416102355444464034512896"},
280 {"1", 255, "57896044618658097711785492504343953926634992332820282019728792003956564819968"},
281 {"1", 256, "0"},
282 {"31337", 0, "31337"},
283 {"31337", 1, "62674"},
284 {"31337", 64, "578065619037836218990592"},
285 {"31337", 128, "10663428532201448629551770073089320442396672"},
286 {"31337", 192, "196705537081812415096322133155058642481399512563169449530621952"},
287 {"31337", 193, "393411074163624830192644266310117284962799025126338899061243904"},
288 {"31337", 255, "57896044618658097711785492504343953926634992332820282019728792003956564819968"},
289 {"31337", 256, "0"},
290 // 64 < n < 128
291 {"1", 65, "36893488147419103232"},
292 {"31337", 100, "39724366859352024754702188346867712"},
293
294 // 128 < n < 192
295 {"1", 129, "680564733841876926926749214863536422912"},
296 {"31337", 150, "44725660946326664792723507424638829088826130956288"},
297
298 // 192 < n < 256
299 {"1", 193, "12554203470773361527671578846415332832204710888928069025792"},
300 {"31337", 200, "50356617492943978264658466087695012475238275216171379079839219712"},
301
302 // n > 256
303 {"1", 257, "0"},
304 {"31337", 300, "0"},
305 }
306
307 for _, tt := range tests {
308 x := MustFromDecimal(tt.x)
309 want := MustFromDecimal(tt.want)
310
311 got := new(Uint).Lsh(x, tt.y)
312
313 if got.Neq(want) {
314 t.Errorf("Lsh(%s, %d) = %s, want %s", tt.x, tt.y, got.String(), want.String())
315 }
316 }
317}
318
319func TestRsh(t *testing.T) {
320 tests := []struct {
321 x string
322 y uint
323 want string
324 }{
325 {"0", 0, "0"},
326 {"0", 1, "0"},
327 {"0", 64, "0"},
328 {"1", 0, "1"},
329 {"1", 1, "0"},
330 {"1", 64, "0"},
331 {"1", 128, "0"},
332 {"1", 192, "0"},
333 {"1", 255, "0"},
334 {"57896044618658097711785492504343953926634992332820282019728792003956564819968", 255, "1"},
335 {"6277101735386680763835789423207666416102355444464034512896", 192, "1"},
336 {"340282366920938463463374607431768211456", 128, "1"},
337 {"18446744073709551616", 64, "1"},
338 {"393411074163624830192644266310117284962799025126338899061243904", 193, "31337"},
339 {"196705537081812415096322133155058642481399512563169449530621952", 192, "31337"},
340 {"10663428532201448629551770073089320442396672", 128, "31337"},
341 {"578065619037836218990592", 64, "31337"},
342 {twoPow256Sub1, 256, "0"},
343 // outliers
344 {"340282366920938463463374607431768211455", 129, "0"},
345 {"18446744073709551615", 65, "0"},
346 {twoPow256Sub1, 1, "57896044618658097711785492504343953926634992332820282019728792003956564819967"},
347
348 // n > 256
349 {"1", 257, "0"},
350 {"31337", 300, "0"},
351 }
352
353 for _, tt := range tests {
354 x := MustFromDecimal(tt.x)
355
356 want := MustFromDecimal(tt.want)
357 got := new(Uint).Rsh(x, tt.y)
358
359 if got.Neq(want) {
360 t.Errorf("Rsh(%s, %d) = %s, want %s", tt.x, tt.y, got.String(), want.String())
361 }
362 }
363}
364
365func TestSRsh(t *testing.T) {
366 tests := []struct {
367 x string
368 y uint
369 want string
370 }{
371 // Positive numbers (behaves like Rsh)
372 {"0x0", 0, "0x0"},
373 {"0x0", 1, "0x0"},
374 {"0x1", 0, "0x1"},
375 {"0x1", 1, "0x0"},
376 {"0x31337", 0, "0x31337"},
377 {"0x31337", 4, "0x3133"},
378 {"0x31337", 8, "0x313"},
379 {"0x31337", 16, "0x3"},
380 {"0x10000000000000000", 64, "0x1"}, // 2^64 >> 64
381
382 // // Numbers with MSB set (negative numbers in two's complement)
383 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
384 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
385 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 4, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
386 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
387 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
388 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
389 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
390
391 // Large positive number close to max value
392 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
393 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 2, "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
394 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0x7fffffffffffffffffffffffffffffffffffffffffffffff"},
395 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0x7fffffffffffffffffffffffffffffff"},
396 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0x7fffffffffffffff"},
397 {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0x0"},
398
399 // Specific cases
400 {"0x8000000000000000000000000000000000000000000000000000000000000000", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"},
401 {"0x8000000000000000000000000000000000000000000000000000000000000001", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"},
402
403 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 65, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
404 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 127, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
405 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 129, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
406 {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 193, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
407
408 // n > 256
409 {"0x1", 257, "0x0"},
410 {"0x31337", 300, "0x0"},
411 }
412
413 for _, tt := range tests {
414 x := MustFromHex(tt.x)
415 want := MustFromHex(tt.want)
416
417 got := new(Uint).SRsh(x, tt.y)
418
419 if !got.Eq(want) {
420 t.Errorf("SRsh(%s, %d) = %s, want %s", tt.x, tt.y, got.String(), want.String())
421 }
422 }
423}