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}