1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectEqualSlices = std.testing.expectEqualSlices;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7const mem = std.mem;
8
9test "assignment operators" {
10    var i: u32 = 0;
11    i += 5;
12    try expect(i == 5);
13    i -= 2;
14    try expect(i == 3);
15    i *= 20;
16    try expect(i == 60);
17    i /= 3;
18    try expect(i == 20);
19    i %= 11;
20    try expect(i == 9);
21    i <<= 1;
22    try expect(i == 18);
23    i >>= 2;
24    try expect(i == 4);
25    i = 6;
26    i &= 5;
27    try expect(i == 4);
28    i ^= 6;
29    try expect(i == 2);
30    i = 6;
31    i |= 3;
32    try expect(i == 7);
33}
34
35test "three expr in a row" {
36    try testThreeExprInARow(false, true);
37    comptime try testThreeExprInARow(false, true);
38}
39fn testThreeExprInARow(f: bool, t: bool) !void {
40    try assertFalse(f or f or f);
41    try assertFalse(t and t and f);
42    try assertFalse(1 | 2 | 4 != 7);
43    try assertFalse(3 ^ 6 ^ 8 != 13);
44    try assertFalse(7 & 14 & 28 != 4);
45    try assertFalse(9 << 1 << 2 != 9 << 3);
46    try assertFalse(90 >> 1 >> 2 != 90 >> 3);
47    try assertFalse(100 - 1 + 1000 != 1099);
48    try assertFalse(5 * 4 / 2 % 3 != 1);
49    try assertFalse(@as(i32, @as(i32, 5)) != 5);
50    try assertFalse(!!false);
51    try assertFalse(@as(i32, 7) != --(@as(i32, 7)));
52}
53fn assertFalse(b: bool) !void {
54    try expect(!b);
55}
56
57test "@clz" {
58    try testClz();
59    comptime try testClz();
60}
61
62fn testClz() !void {
63    try expect(testOneClz(u8, 0b10001010) == 0);
64    try expect(testOneClz(u8, 0b00001010) == 4);
65    try expect(testOneClz(u8, 0b00011010) == 3);
66    try expect(testOneClz(u8, 0b00000000) == 8);
67    try expect(testOneClz(u128, 0xffffffffffffffff) == 64);
68    try expect(testOneClz(u128, 0x10000000000000000) == 63);
69}
70
71fn testOneClz(comptime T: type, x: T) u32 {
72    return @clz(T, x);
73}
74
75test "const number literal" {
76    const one = 1;
77    const eleven = ten + one;
78
79    try expect(eleven == 11);
80}
81const ten = 10;
82
83test "float equality" {
84    const x: f64 = 0.012;
85    const y: f64 = x + 1.0;
86
87    try testFloatEqualityImpl(x, y);
88    comptime try testFloatEqualityImpl(x, y);
89}
90
91fn testFloatEqualityImpl(x: f64, y: f64) !void {
92    const y2 = x + 1.0;
93    try expect(y == y2);
94}
95
96test "hex float literal parsing" {
97    comptime try expect(0x1.0 == 1.0);
98}
99
100test "quad hex float literal parsing in range" {
101    const a = 0x1.af23456789bbaaab347645365cdep+5;
102    const b = 0x1.dedafcff354b6ae9758763545432p-9;
103    const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
104    const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
105    _ = a;
106    _ = b;
107    _ = c;
108    _ = d;
109}
110
111test "underscore separator parsing" {
112    try expect(0_0_0_0 == 0);
113    try expect(1_234_567 == 1234567);
114    try expect(001_234_567 == 1234567);
115    try expect(0_0_1_2_3_4_5_6_7 == 1234567);
116
117    try expect(0b0_0_0_0 == 0);
118    try expect(0b1010_1010 == 0b10101010);
119    try expect(0b0000_1010_1010 == 0b10101010);
120    try expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
121
122    try expect(0o0_0_0_0 == 0);
123    try expect(0o1010_1010 == 0o10101010);
124    try expect(0o0000_1010_1010 == 0o10101010);
125    try expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
126
127    try expect(0x0_0_0_0 == 0);
128    try expect(0x1010_1010 == 0x10101010);
129    try expect(0x0000_1010_1010 == 0x10101010);
130    try expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
131
132    try expect(123_456.789_000e1_0 == 123456.789000e10);
133    try expect(0_1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
134
135    try expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
136    try expect(0x1_2_3_4_5_6_7_8.9_A_B_C_D_E_F_0p-0_0_0_1_0 == 0x12345678.9ABCDEF0p-10);
137}
138
139test "hex float literal within range" {
140    const a = 0x1.0p16383;
141    const b = 0x0.1p16387;
142    const c = 0x1.0p-16382;
143    _ = a;
144    _ = b;
145    _ = c;
146}
147
148test "comptime_int addition" {
149    comptime {
150        try expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
151        try expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
152    }
153}
154
155test "comptime_int multiplication" {
156    comptime {
157        try expect(
158            45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
159        );
160        try expect(
161            594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
162        );
163    }
164}
165
166test "comptime_int shifting" {
167    comptime {
168        try expect((@as(u128, 1) << 127) == 0x80000000000000000000000000000000);
169    }
170}
171
172test "comptime_int multi-limb shift and mask" {
173    comptime {
174        var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
175
176        try expect(@as(u32, a & 0xffffffff) == 0xaaaaaaab);
177        a >>= 32;
178        try expect(@as(u32, a & 0xffffffff) == 0xeeeeeeef);
179        a >>= 32;
180        try expect(@as(u32, a & 0xffffffff) == 0xa0000001);
181        a >>= 32;
182        try expect(@as(u32, a & 0xffffffff) == 0xefffffff);
183        a >>= 32;
184
185        try expect(a == 0);
186    }
187}
188
189test "comptime_int multi-limb partial shift right" {
190    comptime {
191        var a = 0x1ffffffffeeeeeeee;
192        a >>= 16;
193        try expect(a == 0x1ffffffffeeee);
194    }
195}
196
197test "xor" {
198    try test_xor();
199    comptime try test_xor();
200}
201
202fn test_xor() !void {
203    try testOneXor(0xFF, 0x00, 0xFF);
204    try testOneXor(0xF0, 0x0F, 0xFF);
205    try testOneXor(0xFF, 0xF0, 0x0F);
206    try testOneXor(0xFF, 0x0F, 0xF0);
207    try testOneXor(0xFF, 0xFF, 0x00);
208}
209
210fn testOneXor(a: u8, b: u8, c: u8) !void {
211    try expect(a ^ b == c);
212}
213
214test "comptime_int xor" {
215    comptime {
216        try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
217        try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
218        try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
219        try expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
220        try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
221        try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
222        try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
223        try expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
224    }
225}
226
227test "comptime_int param and return" {
228    const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
229    try expect(a == 137114567242441932203689521744947848950);
230
231    const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
232    try expect(b == 985095453608931032642182098849559179469148836107390954364380);
233}
234
235fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
236    return a + b;
237}
238
239test "binary not" {
240    try expect(comptime x: {
241        break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
242    });
243    try expect(comptime x: {
244        break :x ~@as(u64, 2147483647) == 18446744071562067968;
245    });
246    try testBinaryNot(0b1010101010101010);
247}
248
249fn testBinaryNot(x: u16) !void {
250    try expect(~x == 0b0101010101010101);
251}
252
253test "division" {
254    try testDivision();
255    comptime try testDivision();
256}
257fn testDivision() !void {
258    try expect(div(u32, 13, 3) == 4);
259    try expect(div(f16, 1.0, 2.0) == 0.5);
260    try expect(div(f32, 1.0, 2.0) == 0.5);
261
262    try expect(divExact(u32, 55, 11) == 5);
263    try expect(divExact(i32, -55, 11) == -5);
264    try expect(divExact(f16, 55.0, 11.0) == 5.0);
265    try expect(divExact(f16, -55.0, 11.0) == -5.0);
266    try expect(divExact(f32, 55.0, 11.0) == 5.0);
267    try expect(divExact(f32, -55.0, 11.0) == -5.0);
268
269    try expect(divFloor(i32, 5, 3) == 1);
270    try expect(divFloor(i32, -5, 3) == -2);
271    try expect(divFloor(f16, 5.0, 3.0) == 1.0);
272    try expect(divFloor(f16, -5.0, 3.0) == -2.0);
273    try expect(divFloor(f32, 5.0, 3.0) == 1.0);
274    try expect(divFloor(f32, -5.0, 3.0) == -2.0);
275    try expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
276    try expect(divFloor(i32, 0, -0x80000000) == 0);
277    try expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
278    try expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
279    try expect(divFloor(i32, 10, 12) == 0);
280    try expect(divFloor(i32, -14, 12) == -2);
281    try expect(divFloor(i32, -2, 12) == -1);
282
283    try expect(divTrunc(i32, 5, 3) == 1);
284    try expect(divTrunc(i32, -5, 3) == -1);
285    try expect(divTrunc(i32, 9, -10) == 0);
286    try expect(divTrunc(i32, -9, 10) == 0);
287    try expect(divTrunc(f16, 5.0, 3.0) == 1.0);
288    try expect(divTrunc(f16, -5.0, 3.0) == -1.0);
289    try expect(divTrunc(f16, 9.0, -10.0) == 0.0);
290    try expect(divTrunc(f16, -9.0, 10.0) == 0.0);
291    try expect(divTrunc(f32, 5.0, 3.0) == 1.0);
292    try expect(divTrunc(f32, -5.0, 3.0) == -1.0);
293    try expect(divTrunc(f32, 9.0, -10.0) == 0.0);
294    try expect(divTrunc(f32, -9.0, 10.0) == 0.0);
295    try expect(divTrunc(f64, 5.0, 3.0) == 1.0);
296    try expect(divTrunc(f64, -5.0, 3.0) == -1.0);
297    try expect(divTrunc(f64, 9.0, -10.0) == 0.0);
298    try expect(divTrunc(f64, -9.0, 10.0) == 0.0);
299    try expect(divTrunc(i32, 10, 12) == 0);
300    try expect(divTrunc(i32, -14, 12) == -1);
301    try expect(divTrunc(i32, -2, 12) == 0);
302
303    try expect(mod(i32, 10, 12) == 10);
304    try expect(mod(i32, -14, 12) == 10);
305    try expect(mod(i32, -2, 12) == 10);
306
307    comptime {
308        try expect(
309            1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
310        );
311        try expect(
312            @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
313        );
314        try expect(
315            1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
316        );
317        try expect(
318            @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
319        );
320        try expect(
321            @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
322        );
323        try expect(
324            @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
325        );
326        try expect(
327            4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
328        );
329    }
330}
331fn div(comptime T: type, a: T, b: T) T {
332    return a / b;
333}
334fn divExact(comptime T: type, a: T, b: T) T {
335    return @divExact(a, b);
336}
337fn divFloor(comptime T: type, a: T, b: T) T {
338    return @divFloor(a, b);
339}
340fn divTrunc(comptime T: type, a: T, b: T) T {
341    return @divTrunc(a, b);
342}
343fn mod(comptime T: type, a: T, b: T) T {
344    return @mod(a, b);
345}
346
347test "unsigned wrapping" {
348    try testUnsignedWrappingEval(maxInt(u32));
349    comptime try testUnsignedWrappingEval(maxInt(u32));
350}
351fn testUnsignedWrappingEval(x: u32) !void {
352    const zero = x +% 1;
353    try expect(zero == 0);
354    const orig = zero -% 1;
355    try expect(orig == maxInt(u32));
356}
357
358test "signed wrapping" {
359    try testSignedWrappingEval(maxInt(i32));
360    comptime try testSignedWrappingEval(maxInt(i32));
361}
362fn testSignedWrappingEval(x: i32) !void {
363    const min_val = x +% 1;
364    try expect(min_val == minInt(i32));
365    const max_val = min_val -% 1;
366    try expect(max_val == maxInt(i32));
367}
368
369test "signed negation wrapping" {
370    try testSignedNegationWrappingEval(minInt(i16));
371    comptime try testSignedNegationWrappingEval(minInt(i16));
372}
373fn testSignedNegationWrappingEval(x: i16) !void {
374    try expect(x == -32768);
375    const neg = -%x;
376    try expect(neg == -32768);
377}
378
379test "unsigned negation wrapping" {
380    try testUnsignedNegationWrappingEval(1);
381    comptime try testUnsignedNegationWrappingEval(1);
382}
383fn testUnsignedNegationWrappingEval(x: u16) !void {
384    try expect(x == 1);
385    const neg = -%x;
386    try expect(neg == maxInt(u16));
387}
388
389test "unsigned 64-bit division" {
390    try test_u64_div();
391    comptime try test_u64_div();
392}
393fn test_u64_div() !void {
394    const result = divWithResult(1152921504606846976, 34359738365);
395    try expect(result.quotient == 33554432);
396    try expect(result.remainder == 100663296);
397}
398fn divWithResult(a: u64, b: u64) DivResult {
399    return DivResult{
400        .quotient = a / b,
401        .remainder = a % b,
402    };
403}
404const DivResult = struct {
405    quotient: u64,
406    remainder: u64,
407};
408
409test "truncating shift right" {
410    try testShrTrunc(maxInt(u16));
411    comptime try testShrTrunc(maxInt(u16));
412}
413fn testShrTrunc(x: u16) !void {
414    const shifted = x >> 1;
415    try expect(shifted == 32767);
416}
417
418test "f128" {
419    try test_f128();
420    comptime try test_f128();
421}
422
423fn make_f128(x: f128) f128 {
424    return x;
425}
426
427fn test_f128() !void {
428    try expect(@sizeOf(f128) == 16);
429    try expect(make_f128(1.0) == 1.0);
430    try expect(make_f128(1.0) != 1.1);
431    try expect(make_f128(1.0) > 0.9);
432    try expect(make_f128(1.0) >= 0.9);
433    try expect(make_f128(1.0) >= 1.0);
434    try should_not_be_zero(1.0);
435}
436
437fn should_not_be_zero(x: f128) !void {
438    try expect(x != 0.0);
439}
440
441test "128-bit multiplication" {
442    var a: i128 = 3;
443    var b: i128 = 2;
444    var c = a * b;
445    try expect(c == 6);
446}
447