4
4
5
5
#include "int128.h"
6
6
7
- // void int128_printhex(char *name, int128 x)
8
- // {
9
- // printf("%s = %016" PRIx64 " %016" PRIx64 "\n", name, x.high, x.low);
10
- // }
11
- //
12
- // void uint128_printhex(char *name, uint128 x)
13
- // {
14
- // printf("%s = %016" PRIx64 " %016" PRIx64 "\n", name, x.high, x.low);
15
- // }
16
-
17
7
void int128_tests ()
18
8
{
19
9
// Left Shift
@@ -25,12 +15,28 @@ void int128_tests()
25
15
b = int128_shiftr (a , 1 );
26
16
assert (b .low == (UINT64_C (1 ) << 63 ));
27
17
18
+ // Left shift of more than 63 bits?
19
+ assert (int128_eq (int128_shiftl (INT128_C (1 ), 64 ),
20
+ (int128 ){ .high = 1 }));
21
+
28
22
// Right Shift
29
23
// For int128, this should be an arithmetic shift, meaning the sign bit
30
24
// is preserved.
31
25
a = INT128_C (-8 );
32
26
assert (int128_less (int128_shiftr (a , 1 ), INT128_C (0 )));
33
27
28
+ // Right shift of more than 63 bits?
29
+ assert (int128_eq (int128_shiftr ((int128 ){ .high = 1 }, 64 ),
30
+ INT128_C (1 )));
31
+ assert (int128_eq (int128_shiftr ((int128 ){ .high = 0xfffffffffffffffe ,
32
+ .low = UINT64_MAX },
33
+ 64 ),
34
+ INT128_C (-2 )));
35
+ assert (int128_eq (int128_shiftr ((int128 ){ .high = 0xbfffffffffffffff ,
36
+ .low = UINT64_MAX },
37
+ 126 ),
38
+ INT128_C (-2 )));
39
+
34
40
// Negation Sanity Check
35
41
assert (int128_eq (int128_neg (INT128_MAX ),
36
42
int128_add (INT128_MIN , INT128_C (1 ))));
@@ -77,6 +83,8 @@ void int128_tests()
77
83
int128_mul (INT128_MAX , INT128_C (-1 ))));
78
84
assert (int128_eq (int128_neg (INT128_MIN ),
79
85
int128_mul (INT128_MIN , INT128_C (-1 ))));
86
+ assert (int128_eq (int128_neg (INT128_MIN ),
87
+ int128_mul (INT128_C (-1 ), INT128_MIN )));
80
88
81
89
// Fun fact: INT128_MAX (170141183460469231731687303715884105727) is
82
90
// prime :)
@@ -86,15 +94,69 @@ void int128_tests()
86
94
b = int128_div (a , INT128_C (2 ));
87
95
assert (int128_eq (b , (int128 ){ .high = 100000000 }));
88
96
89
- // Modulo Sanity Check
97
+ // INT128_MIN divided by anything is 0, since INT128_MIN is less than
98
+ // every other number...
99
+ assert (int128_eq (int128_div (INT128_MIN , INT128_C (-123456789 )),
100
+ INT128_C (0 )));
101
+
102
+ // Except for when dividing INT128_MIN by INT128_MIN, which should be
103
+ // 1.
104
+ assert (int128_eq (int128_div (INT128_MIN , INT128_MIN ), INT128_C (1 )));
105
+
106
+ // Check to make sure the sign is preserved properly:
107
+ // - / - = +
108
+ // - / + = -
109
+ // + / - = -
110
+ // + / + = +
111
+
112
+ a = INT128_C (1 );
113
+ b = INT128_C (-1 );
114
+ assert (int128_eq (int128_div (b , b ), a ));
115
+ assert (int128_eq (int128_div (b , a ), b ));
116
+ assert (int128_eq (int128_div (a , b ), b ));
117
+ assert (int128_eq (int128_div (a , a ), a ));
118
+
119
+ // And of course anytime the denominator is greater than the numerator
120
+ // the result is also 0.
121
+ assert (int128_eq (int128_div (INT128_C (1 ), INT128_C (2 )), INT128_C (0 )));
122
+
123
+ // Remainder Sanity Check
90
124
// 85070591730234615865843651857942052863 % 1234567890 = 1122498603
91
125
a = int128_div (int128_sub (INT128_MAX , INT128_C (1 )), INT128_C (2 ));
92
126
b = INT128_C (1234567890 );
93
- assert (int128_eq (int128_mod (a , b ), INT128_C (1122498603 )));
127
+ assert (int128_eq (int128_rem (a , b ), INT128_C (1122498603 )));
128
+
129
+ a = int128_div (int128_sub (INT128_MAX , INT128_C (1 )), INT128_C (2 ));
130
+ b = INT128_C (-1234567890 );
131
+
132
+ // The remainder operation has the same sign as the left hand side.
133
+ assert (int128_eq (int128_rem (a , b ), INT128_C (1122498603 )));
134
+ a = int128_neg (a );
135
+ assert (int128_eq (int128_rem (a , b ), INT128_C (-1122498603 )));
136
+
137
+ // The remainder of anything divided by INT128_MIN is the left hand
138
+ // side...
139
+ assert (int128_eq (int128_rem (INT128_C (-1 ), INT128_MIN ), INT128_C (-1 )));
140
+
141
+ // Except for when the left hand side is INT128_MIN, in which case the
142
+ // remainder is 0.
143
+ assert (int128_eq (int128_rem (INT128_MIN , INT128_MIN ), INT128_C (0 )));
144
+
145
+ // This applies to all numbers.
146
+ assert (int128_eq (int128_rem (INT128_C (1 ), INT128_C (1 )), INT128_C (0 )));
147
+
148
+ // When both the numerator and denominator are positive, if the
149
+ // denominator is greater than the numerator the result is just the
150
+ // numerator.
151
+ assert (int128_eq (int128_rem (INT128_C (1 ), INT128_C (2 )), INT128_C (1 )));
94
152
}
95
153
96
154
void uint128_tests ()
97
155
{
156
+ // For most functions, the same logic is used for positive int128 and
157
+ // uint128, so we only need to test things which we can't use int128 to
158
+ // test, like large multiplication overflow.
159
+
98
160
// Multiplication Sanity Check
99
161
uint128 a = (uint128 ){ .high = 100000000 };
100
162
uint128 b = uint128_mul (a , UINT128_C (2 ));
@@ -122,6 +184,16 @@ void uint128_tests()
122
184
};
123
185
124
186
assert (uint128_eq (b , correct ));
187
+
188
+ // Right Shift Sanity Check
189
+ // For unsigned integers, the most significant bit should not be
190
+ // preserved.
191
+ a = (uint128 ){ .high = UINT64_C (1 ) << 63 };
192
+ assert (uint128_eq (uint128_shiftr (a , 1 ),
193
+ (uint128 ){ .high = UINT64_C (1 ) << 62 }));
194
+
195
+ // uint128_less when high bits are equal?
196
+ assert (uint128_less (UINT128_C (2 ), UINT128_C (5 )));
125
197
}
126
198
127
199
int main ()
0 commit comments