11package int
22
3- import "testing"
3+ import (
4+ "math"
5+ "math/big"
6+ "testing"
7+ )
48
59func TestRecodeSigned5_161 (t * testing.T ) {
610 scalar1 := Signed161 {
@@ -18,3 +22,140 @@ func TestRecodeSigned5_161(t *testing.T) {
1822 }
1923 }
2024}
25+
26+ func FuzzTestAdd (f * testing.F ) {
27+ f .Add (uint64 (0 ), uint64 (0 ), uint64 (0 ), uint64 (0 ))
28+ f .Add (uint64 (math .MaxUint64 ), uint64 (1 ), uint64 (1 ), uint64 (0 ))
29+ f .Add (uint64 (math .MaxUint64 ), uint64 (0 ), uint64 (1 ), uint64 (0 ))
30+ f .Add (uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ))
31+
32+ f .Fuzz (func (t * testing.T , a , b , c , d uint64 ) {
33+ i128a := UInt128 {Hi : a , Lo : b }
34+ i128b := UInt128 {Hi : c , Lo : d }
35+ result := AddUInt128 (i128a , i128b )
36+
37+ expected := new (big.Int ).Add (new (big.Int ).SetBits ([]big.Word {big .Word (b ), big .Word (a )}), new (big.Int ).SetBits ([]big.Word {big .Word (d ), big .Word (c )}))
38+ expectedReduced := new (big.Int ).And (expected , new (big.Int ).Sub (new (big.Int ).Lsh (big .NewInt (1 ), 128 ), big .NewInt (1 )))
39+
40+ if ! equalsBigInt (result , expectedReduced ) {
41+ t .Errorf ("Add(%d, %d): got %v, want %v" ,
42+ a , b , result .ToBigInt (), expected )
43+ }
44+
45+ i128ab := AddUint64 (a , b )
46+ expected = new (big.Int ).Add (new (big.Int ).SetUint64 (a ), new (big.Int ).SetUint64 (b ))
47+ if ! equalsBigInt (i128ab , expected ) {
48+ t .Errorf ("AddUint64(%d, %d): got %v, want %v" ,
49+ a , b , i128ab .ToBigInt (), expected )
50+ }
51+ })
52+ }
53+
54+ func FuzzTestAddUInt64 (f * testing.F ) {
55+ f .Add (uint64 (0 ), uint64 (0 ), uint64 (0 ))
56+ f .Add (uint64 (math .MaxUint64 ), uint64 (1 ), uint64 (1 ))
57+ f .Add (uint64 (math .MaxUint64 ), uint64 (0 ), uint64 (0 ))
58+ f .Add (uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ))
59+
60+ f .Fuzz (func (t * testing.T , hi , lo uint64 , b uint64 ) {
61+ i128 := UInt128 {Hi : hi , Lo : lo }
62+ result := AddUint128AndUint64 (i128 , b )
63+
64+ big128 := i128 .ToBigInt ()
65+ expected := new (big.Int ).Add (big128 , new (big.Int ).SetUint64 (b ))
66+
67+ if fitsInInt128 (expected ) {
68+ if ! equalsBigInt (result , expected ) {
69+ t .Errorf ("AddInt64({%d, %d}, %d): got %v, want %v" ,
70+ hi , lo , b , result .ToBigInt (), expected )
71+ }
72+ } else {
73+ expectedReduced := new (big.Int ).And (expected , new (big.Int ).Sub (new (big.Int ).Lsh (big .NewInt (1 ), 128 ), big .NewInt (1 )))
74+ if ! equalsBigInt (result , expectedReduced ) {
75+ t .Errorf ("AddInt64({%d, %d}, %d): got %v, want %v (reduced)" ,
76+ hi , lo , b , result .ToBigInt (), expectedReduced )
77+ }
78+ }
79+ })
80+ }
81+
82+ func FuzzTestMulUInt64 (f * testing.F ) {
83+ f .Add (uint64 (0 ), uint64 (0 ))
84+ f .Add (uint64 (math .MaxUint64 ), uint64 (1 ))
85+ f .Add (uint64 (math .MaxUint64 ), uint64 (0 ))
86+ f .Add (uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ))
87+
88+ f .Fuzz (func (t * testing.T , a , b uint64 ) {
89+ result := MulUInt64 (a , b )
90+ expected := new (big.Int ).Mul (new (big.Int ).SetUint64 (a ), new (big.Int ).SetUint64 (b ))
91+
92+ if fitsInInt128 (expected ) {
93+ if ! equalsBigInt (result , expected ) {
94+ t .Errorf ("MulInt64(%d, %d): got %v, want %v" ,
95+ a , b , result .ToBigInt (), expected )
96+ }
97+ }
98+ })
99+ }
100+
101+ func FuzzTestMulUint128AndUint64 (f * testing.F ) {
102+ f .Add (uint64 (0 ), uint64 (0 ), uint64 (0 ))
103+ f .Add (uint64 (math .MaxUint64 ), uint64 (1 ), uint64 (1 ))
104+ f .Add (uint64 (math .MaxUint64 ), uint64 (0 ), uint64 (0 ))
105+ f .Add (uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ))
106+
107+ f .Fuzz (func (t * testing.T , hi , lo uint64 , b uint64 ) {
108+ i128 := UInt128 {Hi : hi , Lo : lo }
109+ result := MulUint128AndUint64 (i128 , b )
110+
111+ big128 := i128 .ToBigInt ()
112+ expected := new (big.Int ).Mul (big128 , new (big.Int ).SetUint64 (b ))
113+
114+ if fitsInInt128 (expected ) {
115+ if ! equalsBigInt (result , expected ) {
116+ t .Errorf ("MulUint128AndUint64({%d, %d}, %d): got %v, want %v" ,
117+ hi , lo , b , result .ToBigInt (), expected )
118+ }
119+ } else {
120+ expectedReduced := new (big.Int ).And (expected , new (big.Int ).Sub (new (big.Int ).Lsh (big .NewInt (1 ), 128 ), big .NewInt (1 )))
121+ if ! equalsBigInt (result , expectedReduced ) {
122+ t .Errorf ("MulUint128AndUint64({%d, %d}, %d): got %v, want %v (reduced)" ,
123+ hi , lo , b , result .ToBigInt (), expectedReduced )
124+ }
125+ }
126+ })
127+ }
128+
129+ func FuzzTestSubUint128AndUint64 (f * testing.F ) {
130+ f .Add (uint64 (0 ), uint64 (0 ), uint64 (0 ))
131+ f .Add (uint64 (1 ), uint64 (1 ), uint64 (0 ))
132+ f .Add (uint64 (0 ), uint64 (1 ), uint64 (0 ))
133+ f .Add (uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ), uint64 (math .MaxUint64 ))
134+
135+ f .Fuzz (func (t * testing.T , hi , lo uint64 , b uint64 ) {
136+ i128 := UInt128 {Hi : hi , Lo : lo }
137+ result := SubUint128AndUint64 (i128 , b )
138+
139+ expected := new (big.Int ).Sub (new (big.Int ).SetBits ([]big.Word {big .Word (lo ), big .Word (hi )}), new (big.Int ).SetUint64 (b ))
140+ if expected .Sign () < 0 {
141+ expected .Add (expected , new (big.Int ).Lsh (big .NewInt (1 ), 128 ))
142+ }
143+
144+ if ! equalsBigInt (result , expected ) {
145+ t .Errorf ("SubUint64({%d, %d}, %d): got %v, want %v" ,
146+ hi , lo , b , result .ToBigInt (), expected )
147+ }
148+ })
149+ }
150+
151+ func equalsBigInt (a UInt128 , b * big.Int ) bool {
152+ return a .ToBigInt ().Cmp (b ) == 0
153+ }
154+
155+ func fitsInInt128 (b * big.Int ) bool {
156+ max := new (big.Int ).Lsh (big .NewInt (1 ), 127 )
157+ max .Sub (max , big .NewInt (1 )) // (2^127) - 1
158+ min := new (big.Int ).Lsh (big .NewInt (- 1 ), 127 ) // -(2^127)
159+
160+ return b .Cmp (min ) >= 0 && b .Cmp (max ) <= 0
161+ }
0 commit comments