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}