arithmetic_test.gno
13.09 Kb ยท 674 lines
1package int256
2
3import (
4 "testing"
5
6 "gno.land/p/demo/uint256"
7)
8
9const (
10 // 2^255 - 1
11 MAX_INT256 = "57896044618658097711785492504343953926634992332820282019728792003956564819967"
12 // -(2^255 - 1)
13 MINUS_MAX_INT256 = "-57896044618658097711785492504343953926634992332820282019728792003956564819967"
14
15 // 2^255 - 1
16 MAX_UINT256 = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
17 MAX_UINT256_MINUS_1 = "115792089237316195423570985008687907853269984665640564039457584007913129639934"
18
19 MINUS_MAX_UINT256 = "-115792089237316195423570985008687907853269984665640564039457584007913129639935"
20 MINUS_MAX_UINT256_PLUS_1 = "-115792089237316195423570985008687907853269984665640564039457584007913129639934"
21
22 TWO_POW_128 = "340282366920938463463374607431768211456"
23 MINUS_TWO_POW_128 = "-340282366920938463463374607431768211456"
24 MINUS_TWO_POW_128_MINUS_1 = "-340282366920938463463374607431768211457"
25 TWO_POW_128_MINUS_1 = "340282366920938463463374607431768211455"
26
27 TWO_POW_129_MINUS_1 = "680564733841876926926749214863536422911"
28
29 TWO_POW_254 = "28948022309329048855892746252171976963317496166410141009864396001978282409984"
30 MINUS_TWO_POW_254 = "-28948022309329048855892746252171976963317496166410141009864396001978282409984"
31 HALF_MAX_INT256 = "28948022309329048855892746252171976963317496166410141009864396001978282409983"
32 MINUS_HALF_MAX_INT256 = "-28948022309329048855892746252171976963317496166410141009864396001978282409983"
33
34 TWO_POW_255 = "57896044618658097711785492504343953926634992332820282019728792003956564819968"
35 MIN_INT256 = "-57896044618658097711785492504343953926634992332820282019728792003956564819968"
36 MIN_INT256_MINUS_1 = "-57896044618658097711785492504343953926634992332820282019728792003956564819969"
37)
38
39func TestAdd(t *testing.T) {
40 tests := []struct {
41 x, y, want string
42 }{
43 {"0", "1", "1"},
44 {"1", "0", "1"},
45 {"1", "1", "2"},
46 {"1", "2", "3"},
47 // NEGATIVE
48 {"-1", "1", "0"},
49 {"1", "-1", "0"},
50 {"3", "-3", "0"},
51 {"-1", "-1", "-2"},
52 {"-1", "-2", "-3"},
53 {"-1", "3", "2"},
54 {"3", "-1", "2"},
55 // OVERFLOW
56 {MAX_UINT256, "1", "0"},
57 {MAX_INT256, "1", MIN_INT256},
58 {MIN_INT256, "-1", MAX_INT256},
59 {MAX_INT256, MAX_INT256, "-2"},
60 }
61
62 for _, tc := range tests {
63 x, err := FromDecimal(tc.x)
64 if err != nil {
65 t.Error(err)
66 continue
67 }
68
69 y, err := FromDecimal(tc.y)
70 if err != nil {
71 t.Error(err)
72 continue
73 }
74
75 want, err := FromDecimal(tc.want)
76 if err != nil {
77 t.Error(err)
78 continue
79 }
80
81 got := New()
82 got.Add(x, y)
83
84 if got.Neq(want) {
85 t.Errorf("Add(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
86 }
87 }
88}
89
90func TestAddUint256(t *testing.T) {
91 tests := []struct {
92 x, y, want string
93 }{
94 {"0", "1", "1"},
95 {"1", "0", "1"},
96 {"1", "1", "2"},
97 {"1", "2", "3"},
98 {"-1", "1", "0"},
99 {"-1", "3", "2"},
100 {MINUS_MAX_UINT256_PLUS_1, MAX_UINT256, "1"},
101 {MINUS_MAX_UINT256, MAX_UINT256_MINUS_1, "-1"},
102 // OVERFLOW
103 {MINUS_MAX_UINT256, MAX_UINT256, "0"},
104 }
105
106 for _, tc := range tests {
107 x, err := FromDecimal(tc.x)
108 if err != nil {
109 t.Error(err)
110 continue
111 }
112
113 y, err := uint256.FromDecimal(tc.y)
114 if err != nil {
115 t.Error(err)
116 continue
117 }
118
119 want, err := FromDecimal(tc.want)
120 if err != nil {
121 t.Error(err)
122 continue
123 }
124
125 got := New()
126 got.AddUint256(x, y)
127
128 if got.Neq(want) {
129 t.Errorf("AddUint256(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
130 }
131 }
132}
133
134func TestAddDelta(t *testing.T) {
135 tests := []struct {
136 z, x, y, want string
137 }{
138 {"0", "0", "0", "0"},
139 {"0", "0", "1", "1"},
140 {"0", "1", "0", "1"},
141 {"0", "1", "1", "2"},
142 {"1", "2", "3", "5"},
143 {"5", "10", "-3", "7"},
144 // underflow
145 {"1", "2", "-3", MAX_UINT256},
146 }
147
148 for _, tc := range tests {
149 z, err := uint256.FromDecimal(tc.z)
150 if err != nil {
151 t.Error(err)
152 continue
153 }
154
155 x, err := uint256.FromDecimal(tc.x)
156 if err != nil {
157 t.Error(err)
158 continue
159 }
160
161 y, err := FromDecimal(tc.y)
162 if err != nil {
163 t.Error(err)
164 continue
165 }
166
167 want, err := uint256.FromDecimal(tc.want)
168 if err != nil {
169 t.Error(err)
170 continue
171 }
172
173 AddDelta(z, x, y)
174
175 if z.Neq(want) {
176 t.Errorf("AddDelta(%s, %s, %s) = %v, want %v", tc.z, tc.x, tc.y, z.String(), want.String())
177 }
178 }
179}
180
181func TestAddDeltaOverflow(t *testing.T) {
182 tests := []struct {
183 z, x, y string
184 want bool
185 }{
186 {"0", "0", "0", false},
187 // underflow
188 {"1", "2", "-3", true},
189 }
190
191 for _, tc := range tests {
192 z, err := uint256.FromDecimal(tc.z)
193 if err != nil {
194 t.Error(err)
195 continue
196 }
197
198 x, err := uint256.FromDecimal(tc.x)
199 if err != nil {
200 t.Error(err)
201 continue
202 }
203
204 y, err := FromDecimal(tc.y)
205 if err != nil {
206 t.Error(err)
207 continue
208 }
209
210 result := AddDeltaOverflow(z, x, y)
211 if result != tc.want {
212 t.Errorf("AddDeltaOverflow(%s, %s, %s) = %v, want %v", tc.z, tc.x, tc.y, result, tc.want)
213 }
214 }
215}
216
217func TestSub(t *testing.T) {
218 tests := []struct {
219 x, y, want string
220 }{
221 {"1", "0", "1"},
222 {"1", "1", "0"},
223 {"-1", "1", "-2"},
224 {"1", "-1", "2"},
225 {"-1", "-1", "0"},
226 {MINUS_MAX_UINT256, MINUS_MAX_UINT256, "0"},
227 {MINUS_MAX_UINT256, "0", MINUS_MAX_UINT256},
228 {MAX_INT256, MIN_INT256, "-1"},
229 {MIN_INT256, MIN_INT256, "0"},
230 {MAX_INT256, MAX_INT256, "0"},
231 }
232
233 for _, tc := range tests {
234 x, err := FromDecimal(tc.x)
235 if err != nil {
236 t.Error(err)
237 continue
238 }
239
240 y, err := FromDecimal(tc.y)
241 if err != nil {
242 t.Error(err)
243 continue
244 }
245
246 want, err := FromDecimal(tc.want)
247 if err != nil {
248 t.Error(err)
249 continue
250 }
251
252 got := New()
253 got.Sub(x, y)
254
255 if got.Neq(want) {
256 t.Errorf("Sub(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
257 }
258 }
259}
260
261func TestSubUint256(t *testing.T) {
262 tests := []struct {
263 x, y, want string
264 }{
265 {"0", "1", "-1"},
266 {"1", "0", "1"},
267 {"1", "1", "0"},
268 {"1", "2", "-1"},
269 {"-1", "1", "-2"},
270 {"-1", "3", "-4"},
271 // underflow
272 {MINUS_MAX_UINT256, "1", "0"},
273 {MINUS_MAX_UINT256, "2", "-1"},
274 {MINUS_MAX_UINT256, "3", "-2"},
275 }
276
277 for _, tc := range tests {
278 x, err := FromDecimal(tc.x)
279 if err != nil {
280 t.Error(err)
281 continue
282 }
283
284 y, err := uint256.FromDecimal(tc.y)
285 if err != nil {
286 t.Error(err)
287 continue
288 }
289
290 want, err := FromDecimal(tc.want)
291 if err != nil {
292 t.Error(err)
293 continue
294 }
295
296 got := New()
297 got.SubUint256(x, y)
298
299 if got.Neq(want) {
300 t.Errorf("SubUint256(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
301 }
302 }
303}
304
305func TestMul(t *testing.T) {
306 tests := []struct {
307 x, y, want string
308 }{
309 {"5", "3", "15"},
310 {"-5", "3", "-15"},
311 {"5", "-3", "-15"},
312 {"0", "3", "0"},
313 {"3", "0", "0"},
314 {"-5", "-3", "15"},
315 {MAX_UINT256, "1", MAX_UINT256},
316 {MAX_INT256, "2", "-2"},
317 {TWO_POW_254, "2", MIN_INT256},
318 {MINUS_TWO_POW_254, "2", MIN_INT256},
319 {MAX_INT256, "1", MAX_INT256},
320 }
321
322 for _, tc := range tests {
323 x, err := FromDecimal(tc.x)
324 if err != nil {
325 t.Error(err)
326 continue
327 }
328
329 y, err := FromDecimal(tc.y)
330 if err != nil {
331 t.Error(err)
332 continue
333 }
334
335 want, err := FromDecimal(tc.want)
336 if err != nil {
337 t.Error(err)
338 continue
339 }
340
341 got := New()
342 got.Mul(x, y)
343
344 if got.Neq(want) {
345 t.Errorf("Mul(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
346 }
347 }
348}
349
350func TestDiv(t *testing.T) {
351 tests := []struct {
352 x, y, expected string
353 }{
354 {"1", "1", "1"},
355 {"0", "1", "0"},
356 {"-1", "1", "-1"},
357 {"1", "-1", "-1"},
358 {"-1", "-1", "1"},
359 {"-6", "3", "-2"},
360 {"10", "-2", "-5"},
361 {"-10", "3", "-3"},
362 {"7", "3", "2"},
363 {"-7", "3", "-2"},
364 // the maximum value of a positive number in int256 is less than the maximum value of a uint256
365 {MAX_INT256, "2", HALF_MAX_INT256},
366 {MINUS_MAX_INT256, "2", MINUS_HALF_MAX_INT256},
367 {MAX_INT256, "-1", MINUS_MAX_INT256},
368 }
369
370 for _, tt := range tests {
371 t.Run(tt.x+"/"+tt.y, func(t *testing.T) {
372 x := MustFromDecimal(tt.x)
373 y := MustFromDecimal(tt.y)
374 result := Zero().Div(x, y)
375 if result.String() != tt.expected {
376 t.Errorf("Div(%s, %s) = %s, want %s", tt.x, tt.y, result.String(), tt.expected)
377 }
378 })
379 }
380
381 t.Run("Division by zero", func(t *testing.T) {
382 defer func() {
383 if r := recover(); r == nil {
384 t.Errorf("Div(1, 0) did not panic")
385 }
386 }()
387 x := MustFromDecimal("1")
388 y := MustFromDecimal("0")
389 Zero().Div(x, y)
390 })
391}
392
393func TestQuo(t *testing.T) {
394 tests := []struct {
395 x, y, want string
396 }{
397 {"0", "1", "0"},
398 {"0", "-1", "0"},
399 {"10", "1", "10"},
400 {"10", "-1", "-10"},
401 {"-10", "1", "-10"},
402 {"-10", "-1", "10"},
403 {"10", "-3", "-3"},
404 {"-10", "3", "-3"},
405 {"10", "3", "3"},
406 }
407
408 for _, tc := range tests {
409 x, err := FromDecimal(tc.x)
410 if err != nil {
411 t.Error(err)
412 continue
413 }
414
415 y, err := FromDecimal(tc.y)
416 if err != nil {
417 t.Error(err)
418 continue
419 }
420
421 want, err := FromDecimal(tc.want)
422 if err != nil {
423 t.Error(err)
424 continue
425 }
426
427 got := New()
428 got.Quo(x, y)
429
430 if got.Neq(want) {
431 t.Errorf("Quo(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
432 }
433 }
434}
435
436func TestRem(t *testing.T) {
437 tests := []struct {
438 x, y, want string
439 }{
440 {"0", "1", "0"},
441 {"0", "-1", "0"},
442 {"10", "1", "0"},
443 {"10", "-1", "0"},
444 {"-10", "1", "0"},
445 {"-10", "-1", "0"},
446 {"10", "3", "1"},
447 {"10", "-3", "1"},
448 {"-10", "3", "-1"},
449 {"-10", "-3", "-1"},
450 }
451
452 for _, tc := range tests {
453 x, err := FromDecimal(tc.x)
454 if err != nil {
455 t.Error(err)
456 continue
457 }
458
459 y, err := FromDecimal(tc.y)
460 if err != nil {
461 t.Error(err)
462 continue
463 }
464
465 want, err := FromDecimal(tc.want)
466 if err != nil {
467 t.Error(err)
468 continue
469 }
470
471 got := New()
472 got.Rem(x, y)
473
474 if got.Neq(want) {
475 t.Errorf("Rem(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
476 }
477 }
478}
479
480func TestMod(t *testing.T) {
481 tests := []struct {
482 x, y, want string
483 }{
484 {"0", "1", "0"},
485 {"0", "-1", "0"},
486 {"10", "1", "0"},
487 {"10", "-1", "0"},
488 {"-10", "1", "0"},
489 {"-10", "-1", "0"},
490 {"10", "3", "1"},
491 {"10", "-3", "1"},
492 {"-10", "3", "2"},
493 {"-10", "-3", "2"},
494 }
495
496 for _, tc := range tests {
497 x, err := FromDecimal(tc.x)
498 if err != nil {
499 t.Error(err)
500 continue
501 }
502
503 y, err := FromDecimal(tc.y)
504 if err != nil {
505 t.Error(err)
506 continue
507 }
508
509 want, err := FromDecimal(tc.want)
510 if err != nil {
511 t.Error(err)
512 continue
513 }
514
515 got := New()
516 got.Mod(x, y)
517
518 if got.Neq(want) {
519 t.Errorf("Mod(%s, %s) = %v, want %v", tc.x, tc.y, got.String(), want.String())
520 }
521 }
522}
523
524func TestModeOverflow(t *testing.T) {
525 tests := []struct {
526 x, y, want string
527 }{
528 {MIN_INT256, "2", "0"}, // MIN_INT256 % 2 = 0
529 {MAX_INT256, "2", "1"}, // MAX_INT256 % 2 = 1
530 {MIN_INT256, "-1", "0"}, // MIN_INT256 % -1 = 0
531 {MAX_INT256, "-1", "0"}, // MAX_INT256 % -1 = 0
532 }
533
534 for _, tt := range tests {
535 x := MustFromDecimal(tt.x)
536 y := MustFromDecimal(tt.y)
537 want := MustFromDecimal(tt.want)
538 got := New().Mod(x, y)
539 if got.Neq(want) {
540 t.Errorf("Mod(%s, %s) = %v, want %v", tt.x, tt.y, got.String(), want.String())
541 }
542 }
543}
544
545func TestModPanic(t *testing.T) {
546 tests := []struct {
547 x, y string
548 }{
549 {"10", "0"},
550 {"10", "-0"},
551 {"-10", "0"},
552 {"-10", "-0"},
553 }
554
555 for _, tc := range tests {
556 defer func() {
557 if r := recover(); r == nil {
558 t.Errorf("Mod(%s, %s) did not panic", tc.x, tc.y)
559 }
560 }()
561 x, err := FromDecimal(tc.x)
562 if err != nil {
563 t.Error(err)
564 continue
565 }
566
567 y, err := FromDecimal(tc.y)
568 if err != nil {
569 t.Error(err)
570 continue
571 }
572
573 result := New().Mod(x, y)
574 t.Errorf("Mod(%s, %s) = %v, want %v", tc.x, tc.y, result.String(), "0")
575 }
576}
577
578func TestDivE(t *testing.T) {
579 testCases := []struct {
580 x, y int64
581 want int64
582 }{
583 {8, 3, 2},
584 {8, -3, -2},
585 {-8, 3, -3},
586 {-8, -3, 3},
587 {1, 2, 0},
588 {1, -2, 0},
589 {-1, 2, -1},
590 {-1, -2, 1},
591 {0, 1, 0},
592 {0, -1, 0},
593 }
594
595 for _, tc := range testCases {
596 x := NewInt(tc.x)
597 y := NewInt(tc.y)
598 want := NewInt(tc.want)
599 got := new(Int).DivE(x, y)
600 if got.Cmp(want) != 0 {
601 t.Errorf("DivE(%v, %v) = %v, want %v", tc.x, tc.y, got, want)
602 }
603 }
604}
605
606func TestDivEByZero(t *testing.T) {
607 defer func() {
608 if r := recover(); r == nil {
609 t.Errorf("DivE did not panic on division by zero")
610 }
611 }()
612
613 x := NewInt(1)
614 y := NewInt(0)
615 new(Int).DivE(x, y)
616}
617
618func TestModEByZero(t *testing.T) {
619 defer func() {
620 if r := recover(); r == nil {
621 t.Errorf("ModE did not panic on division by zero")
622 }
623 }()
624
625 x := NewInt(1)
626 y := NewInt(0)
627 new(Int).ModE(x, y)
628}
629
630func TestLargeNumbers(t *testing.T) {
631 x, _ := new(Int).SetString("123456789012345678901234567890")
632 y, _ := new(Int).SetString("987654321098765432109876543210")
633
634 // Expected results (calculated separately)
635 expectedQ, _ := new(Int).SetString("0")
636 expectedR, _ := new(Int).SetString("123456789012345678901234567890")
637
638 gotQ := new(Int).DivE(x, y)
639 gotR := new(Int).ModE(x, y)
640
641 if gotQ.Cmp(expectedQ) != 0 {
642 t.Errorf("DivE with large numbers: got %v, want %v", gotQ, expectedQ)
643 }
644
645 if gotR.Cmp(expectedR) != 0 {
646 t.Errorf("ModE with large numbers: got %v, want %v", gotR, expectedR)
647 }
648}
649
650func TestAbs(t *testing.T) {
651 tests := []struct {
652 x, want string
653 }{
654 {"0", "0"},
655 {"1", "1"},
656 {"-1", "1"},
657 {"-2", "2"},
658 {"-100000000000", "100000000000"},
659 }
660
661 for _, tc := range tests {
662 x, err := FromDecimal(tc.x)
663 if err != nil {
664 t.Error(err)
665 continue
666 }
667
668 got := x.Abs()
669
670 if got.String() != tc.want {
671 t.Errorf("Abs(%s) = %v, want %v", tc.x, got.String(), tc.want)
672 }
673 }
674}