master
1const builtin = @import("builtin");
2const std = @import("std");
3const assert = std.debug.assert;
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6const expectEqualSlices = std.testing.expectEqualSlices;
7const maxInt = std.math.maxInt;
8const minInt = std.math.minInt;
9const mem = std.mem;
10const math = std.math;
11
12test "assignment operators" {
13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
16
17 var i: u32 = 0;
18 i += 5;
19 try expect(i == 5);
20 i -= 2;
21 try expect(i == 3);
22 i *= 20;
23 try expect(i == 60);
24 i /= 3;
25 try expect(i == 20);
26 i %= 11;
27 try expect(i == 9);
28 i <<= 1;
29 try expect(i == 18);
30 i >>= 2;
31 try expect(i == 4);
32 i = 6;
33 i &= 5;
34 try expect(i == 4);
35 i ^= 6;
36 try expect(i == 2);
37 i = 6;
38 i |= 3;
39 try expect(i == 7);
40}
41
42test "three expr in a row" {
43 try testThreeExprInARow(false, true);
44 try comptime testThreeExprInARow(false, true);
45}
46fn testThreeExprInARow(f: bool, t: bool) !void {
47 try assertFalse(f or f or f);
48 try assertFalse(t and t and f);
49 try assertFalse(1 | 2 | 4 != 7);
50 try assertFalse(3 ^ 6 ^ 8 != 13);
51 try assertFalse(7 & 14 & 28 != 4);
52 try assertFalse(9 << 1 << 2 != 9 << 3);
53 try assertFalse(90 >> 1 >> 2 != 90 >> 3);
54 try assertFalse(100 - 1 + 1000 != 1099);
55 try assertFalse(5 * 4 / 2 % 3 != 1);
56 try assertFalse(@as(i32, @as(i32, 5)) != 5);
57 try assertFalse(!!false);
58 try assertFalse(@as(i32, 7) != --(@as(i32, 7)));
59}
60fn assertFalse(b: bool) !void {
61 try expect(!b);
62}
63
64test "@clz" {
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
68 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
69
70 try testClz();
71 try comptime testClz();
72}
73
74fn testClz() !void {
75 try expect(testOneClz(u8, 0b10001010) == 0);
76 try expect(testOneClz(u8, 0b00001010) == 4);
77 try expect(testOneClz(u8, 0b00011010) == 3);
78 try expect(testOneClz(u8, 0b00000000) == 8);
79 try expect(testOneClz(i8, -1) == 0);
80}
81
82test "@clz big ints" {
83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
87
88 try testClzBigInts();
89 try comptime testClzBigInts();
90}
91
92fn testClzBigInts() !void {
93 try expect(testOneClz(u128, 0xffffffffffffffff) == 64);
94 try expect(testOneClz(u128, 0x10000000000000000) == 63);
95}
96
97fn testOneClz(comptime T: type, x: T) u32 {
98 return @clz(x);
99}
100
101test "@clz vectors" {
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
107 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
108
109 try testClzVectors();
110 try comptime testClzVectors();
111}
112
113fn testClzVectors() !void {
114 if (comptime builtin.cpu.has(.loongarch, .lsx)) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/159529
115
116 const Vu4 = @Vector(64, u4);
117 const Vu8 = @Vector(64, u8);
118 const Vu128 = @Vector(64, u128);
119
120 @setEvalBranchQuota(10_000);
121 try testOneClzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(0)));
122 try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00001010)), @as(Vu4, @splat(4)));
123 try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00011010)), @as(Vu4, @splat(3)));
124 try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8)));
125 try testOneClzVector(u128, 64, @as(Vu128, @splat(0xffffffffffffffff)), @as(Vu8, @splat(64)));
126 try testOneClzVector(u128, 64, @as(Vu128, @splat(0x10000000000000000)), @as(Vu8, @splat(63)));
127}
128
129fn testOneClzVector(
130 comptime T: type,
131 comptime len: u32,
132 x: @Vector(len, T),
133 expected: @Vector(len, u32),
134) !void {
135 try expectVectorsEqual(@clz(x), expected);
136}
137
138fn expectVectorsEqual(a: anytype, b: anytype) !void {
139 const len_a = @typeInfo(@TypeOf(a)).vector.len;
140 const len_b = @typeInfo(@TypeOf(b)).vector.len;
141 try expect(len_a == len_b);
142 try expect(@reduce(.And, a == b));
143}
144
145test "@ctz" {
146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
150
151 try testCtz();
152 try comptime testCtz();
153}
154
155fn testCtz() !void {
156 try expect(testOneCtz(u8, 0b10100000) == 5);
157 try expect(testOneCtz(u8, 0b10001010) == 1);
158 try expect(testOneCtz(u8, 0b00000000) == 8);
159 try expect(testOneCtz(i8, -1) == 0);
160 try expect(testOneCtz(i8, -2) == 1);
161 try expect(testOneCtz(u16, 0b00000000) == 16);
162}
163
164fn testOneCtz(comptime T: type, x: T) u32 {
165 return @ctz(x);
166}
167
168test "@ctz 128-bit integers" {
169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
173
174 try testCtz128();
175 try comptime testCtz128();
176}
177
178fn testCtz128() !void {
179 try expect(testOneCtz(u128, @as(u128, 0x40000000000000000000000000000000)) == 126);
180 try expect(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1)) == @as(u128, 0x80000000000000000000000000000000));
181 try expect(testOneCtz(u128, @as(u128, 0x80000000000000000000000000000000)) == 127);
182 try expect(testOneCtz(u128, math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1))) == 127);
183}
184
185test "@ctz vectors" {
186 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
187 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
188 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
190 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
192
193 try testCtzVectors();
194 try comptime testCtzVectors();
195}
196
197fn testCtzVectors() !void {
198 if (comptime builtin.cpu.has(.loongarch, .lsx)) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/159529
199
200 const Vu4 = @Vector(64, u4);
201 const Vu8 = @Vector(64, u8);
202 @setEvalBranchQuota(10_000);
203 try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10100000)), @as(Vu4, @splat(5)));
204 try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(1)));
205 try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8)));
206 try testOneCtzVector(u16, 64, @as(@Vector(64, u16), @splat(0b00000000)), @as(@Vector(64, u5), @splat(16)));
207}
208
209fn testOneCtzVector(
210 comptime T: type,
211 comptime len: u32,
212 x: @Vector(len, T),
213 expected: @Vector(len, u32),
214) !void {
215 try expectVectorsEqual(@ctz(x), expected);
216}
217
218test "const number literal" {
219 const one = 1;
220 const eleven = ten + one;
221
222 try expect(eleven == 11);
223}
224const ten = 10;
225
226test "float equality" {
227 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
229
230 const x: f64 = 0.012;
231 const y: f64 = x + 1.0;
232
233 try testFloatEqualityImpl(x, y);
234 try comptime testFloatEqualityImpl(x, y);
235}
236
237fn testFloatEqualityImpl(x: f64, y: f64) !void {
238 const y2 = x + 1.0;
239 try expect(y == y2);
240}
241
242test "hex float literal parsing" {
243 comptime assert(0x1.0 == 1.0);
244}
245
246test "hex float literal within range" {
247 const a = 0x1.0p16383;
248 const b = 0x0.1p16387;
249 const c = 0x1.0p-16382;
250 _ = a;
251 _ = b;
252 _ = c;
253}
254
255test "quad hex float literal parsing in range" {
256 const a = 0x1.af23456789bbaaab347645365cdep+5;
257 const b = 0x1.dedafcff354b6ae9758763545432p-9;
258 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
259 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
260 _ = a;
261 _ = b;
262 _ = c;
263 _ = d;
264}
265
266test "underscore separator parsing" {
267 try expect(1_234_567 == 1234567);
268 try expect(1_234_567 == 1234567);
269 try expect(1_2_3_4_5_6_7 == 1234567);
270
271 try expect(0b0_0_0_0 == 0);
272 try expect(0b1010_1010 == 0b10101010);
273 try expect(0b0000_1010_1010 == 0b10101010);
274 try expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
275
276 try expect(0o0_0_0_0 == 0);
277 try expect(0o1010_1010 == 0o10101010);
278 try expect(0o0000_1010_1010 == 0o10101010);
279 try expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
280
281 try expect(0x0_0_0_0 == 0);
282 try expect(0x1010_1010 == 0x10101010);
283 try expect(0x0000_1010_1010 == 0x10101010);
284 try expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
285
286 try expect(123_456.789_000e1_0 == 123456.789000e10);
287 try expect(1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
288
289 try expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
290 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);
291}
292
293test "comptime_int addition" {
294 comptime {
295 try expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
296 try expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
297 }
298}
299
300test "comptime_int multiplication" {
301 comptime {
302 try expect(
303 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
304 );
305 try expect(
306 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
307 );
308 }
309}
310
311test "comptime_int shifting" {
312 comptime {
313 try expect((@as(u128, 1) << 127) == 0x80000000000000000000000000000000);
314 }
315}
316
317test "comptime_int multi-limb shift and mask" {
318 comptime {
319 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
320
321 try expect(@as(u32, a & 0xffffffff) == 0xaaaaaaab);
322 a >>= 32;
323 try expect(@as(u32, a & 0xffffffff) == 0xeeeeeeef);
324 a >>= 32;
325 try expect(@as(u32, a & 0xffffffff) == 0xa0000001);
326 a >>= 32;
327 try expect(@as(u32, a & 0xffffffff) == 0xefffffff);
328 a >>= 32;
329
330 try expect(a == 0);
331 }
332}
333
334test "comptime_int multi-limb partial shift right" {
335 comptime {
336 var a = 0x1ffffffffeeeeeeee;
337 a >>= 16;
338 try expect(a == 0x1ffffffffeeee);
339 }
340}
341
342test "xor" {
343 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
344
345 try test_xor();
346 try comptime test_xor();
347}
348
349fn test_xor() !void {
350 try testOneXor(0xFF, 0x00, 0xFF);
351 try testOneXor(0xF0, 0x0F, 0xFF);
352 try testOneXor(0xFF, 0xF0, 0x0F);
353 try testOneXor(0xFF, 0x0F, 0xF0);
354 try testOneXor(0xFF, 0xFF, 0x00);
355}
356
357fn testOneXor(a: u8, b: u8, c: u8) !void {
358 try expect(a ^ b == c);
359}
360
361test "comptime_int xor" {
362 comptime {
363 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
364 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
365 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
366 try expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
367 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
368 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
369 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
370 try expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
371 }
372}
373
374test "comptime_int param and return" {
375 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
376 try expect(a == 137114567242441932203689521744947848950);
377
378 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
379 try expect(b == 985095453608931032642182098849559179469148836107390954364380);
380}
381
382fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
383 return a + b;
384}
385
386fn not(comptime T: type, a: T) T {
387 return ~a;
388}
389
390test "binary not" {
391 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
392 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
393
394 try expect(not(u0, 0) == 0);
395 try expect(not(u1, 0) == 1);
396 try expect(not(u1, 1) == 0);
397 try expect(not(u5, 0b01001) == 0b10110);
398 try expect(not(u5, 0b10110) == 0b01001);
399 try expect(not(u16, 0b10101010_10101010) == 0b01010101_01010101);
400 try expect(not(u16, 0b01010101_01010101) == 0b10101010_10101010);
401 try expect(not(u32, 0xAAAA_3333) == 0x5555_CCCC);
402 try expect(not(u32, 0x5555_CCCC) == 0xAAAA_3333);
403 try expect(not(u35, 0x4_1111_FFFF) == 0x3_EEEE_0000);
404 try expect(not(u35, 0x3_EEEE_0000) == 0x4_1111_FFFF);
405 try expect(not(u48, 0x4567_89AB_CDEF) == 0xBA98_7654_3210);
406 try expect(not(u48, 0xBA98_7654_3210) == 0x4567_89AB_CDEF);
407 try expect(not(u64, 0x0123_4567_89AB_CDEF) == 0xFEDC_BA98_7654_3210);
408 try expect(not(u64, 0xFEDC_BA98_7654_3210) == 0x0123_4567_89AB_CDEF);
409
410 try expect(not(i0, 0) == 0);
411 try expect(not(i1, 0) == -1);
412 try expect(not(i1, -1) == 0);
413 try expect(not(i5, -2) == 1);
414 try expect(not(i5, 3) == -4);
415 try expect(not(i32, 0) == -1);
416 try expect(not(i32, -2147483648) == 2147483647);
417 try expect(not(i64, -1) == 0);
418 try expect(not(i64, 0) == -1);
419
420 try expect(comptime x: {
421 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
422 });
423 try expect(comptime x: {
424 break :x ~@as(u64, 2147483647) == 18446744071562067968;
425 });
426 try expect(comptime x: {
427 break :x ~@as(u0, 0) == 0;
428 });
429}
430
431test "binary not big int <= 128 bits" {
432 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
435 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
436
437 try expect(not(u65, 1) == 0x1_FFFFFFFF_FFFFFFFE);
438 try expect(not(u65, 0x1_FFFFFFFF_FFFFFFFE) == 1);
439
440 try expect(not(u96, 0x01234567_89ABCDEF_00000001) == 0xFEDCBA98_76543210_FFFFFFFE);
441 try expect(not(u96, 0xFEDCBA98_76543210_FFFFFFFE) == 0x01234567_89ABCDEF_00000001);
442
443 try expect(not(u128, 0xAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA) == 0x55555555_55555555_55555555_55555555);
444 try expect(not(u128, 0x55555555_55555555_55555555_55555555) == 0xAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA);
445
446 try expect(not(i65, -1) == 0);
447 try expect(not(i65, 0) == -1);
448 try expect(not(i65, -18446744073709551616) == 18446744073709551615);
449 try expect(not(i65, 18446744073709551615) == -18446744073709551616);
450
451 try expect(not(i128, -1) == 0);
452 try expect(not(i128, 0) == -1);
453 try expect(not(i128, -200) == 199);
454 try expect(not(i128, 199) == -200);
455
456 try expect(comptime x: {
457 break :x ~@as(u128, 0x55555555_55555555_55555555_55555555) == 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaaa;
458 });
459 try expect(comptime x: {
460 break :x ~@as(i128, 0x55555555_55555555_55555555_55555555) == @as(i128, @bitCast(@as(u128, 0xaaaaaaaa_aaaaaaaa_aaaaaaaa_aaaaaaaa)));
461 });
462}
463
464test "division" {
465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
468 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
469
470 try testIntDivision();
471 try comptime testIntDivision();
472
473 try testFloatDivision();
474 try comptime testFloatDivision();
475}
476
477fn testIntDivision() !void {
478 try expect(div(u32, 13, 3) == 4);
479 try expect(div(u64, 13, 3) == 4);
480 try expect(div(u8, 13, 3) == 4);
481
482 try expect(divExact(u32, 55, 11) == 5);
483 try expect(divExact(i32, -55, 11) == -5);
484 try expect(divExact(i64, -55, 11) == -5);
485 try expect(divExact(i16, -55, 11) == -5);
486
487 try expect(divFloor(i32, 5, 3) == 1);
488 try expect(divFloor(i32, -5, 3) == -2);
489 try expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
490 try expect(divFloor(i32, 0, -0x80000000) == 0);
491 try expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
492 try expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
493 try expect(divFloor(i32, 10, 12) == 0);
494 try expect(divFloor(i32, -14, 12) == -2);
495 try expect(divFloor(i32, -2, 12) == -1);
496
497 try expect(divFloor(i8, 5, 3) == 1);
498 try expect(divFloor(i16, -5, 3) == -2);
499 try expect(divFloor(i64, -0x80000000, -2) == 0x40000000);
500 try expect(divFloor(i64, -0x40000001, 0x40000000) == -2);
501
502 try expect(divTrunc(i32, 5, 3) == 1);
503 try expect(divTrunc(i32, -5, 3) == -1);
504 try expect(divTrunc(i32, 9, -10) == 0);
505 try expect(divTrunc(i32, -9, 10) == 0);
506 try expect(divTrunc(i32, 10, 12) == 0);
507 try expect(divTrunc(i32, -14, 12) == -1);
508 try expect(divTrunc(i32, -2, 12) == 0);
509
510 try expect(mod(i32, 10, 12) == 10);
511 try expect(mod(i32, -14, 12) == 10);
512 try expect(mod(i32, -2, 12) == 10);
513 try expect(mod(i32, 10, -12) == -2);
514 try expect(mod(i32, -14, -12) == -2);
515 try expect(mod(i32, -2, -12) == -2);
516
517 try expect(mod(i64, -118, 12) == 2);
518 try expect(mod(u32, 10, 12) == 10);
519 try expect(mod(i64, -14, 12) == 10);
520 try expect(mod(i16, -2, 12) == 10);
521 try expect(mod(i16, -118, 12) == 2);
522 try expect(mod(i8, -2, 12) == 10);
523
524 try expect(rem(i64, -118, 12) == -10);
525 try expect(rem(i32, 10, 12) == 10);
526 try expect(rem(i32, -14, 12) == -2);
527 try expect(rem(i32, -2, 12) == -2);
528 try expect(rem(i32, 118, -12) == 10);
529 try expect(rem(i32, -14, -12) == -2);
530 try expect(rem(i16, -118, 12) == -10);
531
532 try expect(divTrunc(i20, 20, -5) == -4);
533 try expect(divTrunc(i20, -20, -4) == 5);
534
535 comptime {
536 try expect(
537 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
538 );
539 try expect(
540 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
541 );
542 try expect(
543 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
544 );
545 try expect(
546 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
547 );
548 try expect(
549 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
550 );
551 try expect(
552 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
553 );
554 try expect(
555 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
556 );
557 }
558}
559
560fn testFloatDivision() !void {
561 try expect(div(f32, 1.0, 2.0) == 0.5);
562
563 try expect(divExact(f32, 55.0, 11.0) == 5.0);
564 try expect(divExact(f32, -55.0, 11.0) == -5.0);
565
566 try expect(divFloor(f32, 5.0, 3.0) == 1.0);
567 try expect(divFloor(f32, -5.0, 3.0) == -2.0);
568 try expect(divFloor(f32, 56.0, 9.0) == 6.0);
569 try expect(divFloor(f32, 1053.0, -41.0) == -26.0);
570 try expect(divFloor(f16, -43.0, 12.0) == -4.0);
571 try expect(divFloor(f64, -90.0, -9.0) == 10.0);
572
573 try expect(divTrunc(f32, 5.0, 3.0) == 1.0);
574 try expect(divTrunc(f32, -5.0, 3.0) == -1.0);
575 try expect(divTrunc(f32, 9.0, -10.0) == 0.0);
576 try expect(divTrunc(f32, -9.0, 10.0) == 0.0);
577 try expect(divTrunc(f64, 5.0, 3.0) == 1.0);
578 try expect(divTrunc(f64, -5.0, 3.0) == -1.0);
579 try expect(divTrunc(f64, 9.0, -10.0) == 0.0);
580 try expect(divTrunc(f64, -9.0, 10.0) == 0.0);
581}
582
583test "large integer division" {
584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
587 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
588 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
589 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
590
591 {
592 var numerator: u256 = 99999999999999999997315645440;
593 var divisor: u256 = 10000000000000000000000000000;
594 _ = .{ &numerator, &divisor };
595 try expect(numerator / divisor == 9);
596 }
597 {
598 var numerator: u256 = 99999999999999999999000000000000000000000;
599 var divisor: u256 = 10000000000000000000000000000000000000000;
600 _ = .{ &numerator, &divisor };
601 try expect(numerator / divisor == 9);
602 }
603}
604
605test "division half-precision floats" {
606 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
607 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
608 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
609
610 try testDivisionFP16();
611 try comptime testDivisionFP16();
612}
613
614fn testDivisionFP16() !void {
615 try expect(div(f16, 1.0, 2.0) == 0.5);
616
617 try expect(divExact(f16, 55.0, 11.0) == 5.0);
618 try expect(divExact(f16, -55.0, 11.0) == -5.0);
619
620 try expect(divFloor(f16, 5.0, 3.0) == 1.0);
621 try expect(divFloor(f16, -5.0, 3.0) == -2.0);
622 try expect(divTrunc(f16, 5.0, 3.0) == 1.0);
623 try expect(divTrunc(f16, -5.0, 3.0) == -1.0);
624 try expect(divTrunc(f16, 9.0, -10.0) == 0.0);
625 try expect(divTrunc(f16, -9.0, 10.0) == 0.0);
626}
627
628fn div(comptime T: type, a: T, b: T) T {
629 return a / b;
630}
631fn divExact(comptime T: type, a: T, b: T) T {
632 return @divExact(a, b);
633}
634fn divFloor(comptime T: type, a: T, b: T) T {
635 return @divFloor(a, b);
636}
637fn divTrunc(comptime T: type, a: T, b: T) T {
638 return @divTrunc(a, b);
639}
640fn mod(comptime T: type, a: T, b: T) T {
641 return @mod(a, b);
642}
643fn rem(comptime T: type, a: T, b: T) T {
644 return @rem(a, b);
645}
646
647test "unsigned wrapping" {
648 try testUnsignedWrappingEval(maxInt(u32));
649 try comptime testUnsignedWrappingEval(maxInt(u32));
650}
651fn testUnsignedWrappingEval(x: u32) !void {
652 const zero = x +% 1;
653 try expect(zero == 0);
654 const orig = zero -% 1;
655 try expect(orig == maxInt(u32));
656}
657
658test "signed wrapping" {
659 try testSignedWrappingEval(maxInt(i32));
660 try comptime testSignedWrappingEval(maxInt(i32));
661}
662fn testSignedWrappingEval(x: i32) !void {
663 const min_val = x +% 1;
664 try expect(min_val == minInt(i32));
665 const max_val = min_val -% 1;
666 try expect(max_val == maxInt(i32));
667}
668
669test "signed negation wrapping" {
670 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
671
672 try testSignedNegationWrappingEval(minInt(i16));
673 try comptime testSignedNegationWrappingEval(minInt(i16));
674}
675fn testSignedNegationWrappingEval(x: i16) !void {
676 try expect(x == -32768);
677 const neg = -%x;
678 try expect(neg == -32768);
679}
680
681test "unsigned negation wrapping" {
682 try testUnsignedNegationWrappingEval(1);
683 try comptime testUnsignedNegationWrappingEval(1);
684}
685fn testUnsignedNegationWrappingEval(x: u16) !void {
686 try expect(x == 1);
687 const neg = -%x;
688 try expect(neg == maxInt(u16));
689}
690
691test "negation wrapping" {
692 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
693 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
694
695 try expectEqual(@as(u1, 1), negateWrap(u1, 1));
696}
697
698fn negateWrap(comptime T: type, x: T) T {
699 // This is specifically testing a safety-checked add, so
700 // special case minInt(T) which would overflow otherwise.
701 return if (x == minInt(T)) minInt(T) else ~x + 1;
702}
703
704test "unsigned 64-bit division" {
705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
707
708 try test_u64_div();
709 try comptime test_u64_div();
710}
711fn test_u64_div() !void {
712 const result = divWithResult(1152921504606846976, 34359738365);
713 try expect(result.quotient == 33554432);
714 try expect(result.remainder == 100663296);
715}
716fn divWithResult(a: u64, b: u64) DivResult {
717 return DivResult{
718 .quotient = a / b,
719 .remainder = a % b,
720 };
721}
722const DivResult = struct {
723 quotient: u64,
724 remainder: u64,
725};
726
727test "bit shift a u1" {
728 var x: u1 = 1;
729 _ = &x;
730 const y = x << 0;
731 try expect(y == 1);
732}
733
734test "truncating shift right" {
735 try testShrTrunc(maxInt(u16));
736 try comptime testShrTrunc(maxInt(u16));
737}
738fn testShrTrunc(x: u16) !void {
739 const shifted = x >> 1;
740 try expect(shifted == 32767);
741}
742
743test "f128" {
744 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
745 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
746 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
747 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
748
749 try test_f128();
750 try comptime test_f128();
751}
752
753fn make_f128(x: f128) f128 {
754 return x;
755}
756
757fn test_f128() !void {
758 try expect(@sizeOf(f128) == 16);
759 try expect(make_f128(1.0) == 1.0);
760 try expect(make_f128(1.0) != 1.1);
761 try expect(make_f128(1.0) > 0.9);
762 try expect(make_f128(1.0) >= 0.9);
763 try expect(make_f128(1.0) >= 1.0);
764 try should_not_be_zero(1.0);
765}
766
767fn should_not_be_zero(x: f128) !void {
768 try expect(x != 0.0);
769}
770
771test "umax wrapped squaring" {
772 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
773 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
774 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
775
776 {
777 var x: u4 = maxInt(u4);
778 x *%= x;
779 try expect(x == 1);
780 }
781 {
782 var x: u8 = maxInt(u8);
783 x *%= x;
784 try expect(x == 1);
785 }
786 {
787 var x: u12 = maxInt(u12);
788 x *%= x;
789 try expect(x == 1);
790 }
791 {
792 var x: u16 = maxInt(u16);
793 x *%= x;
794 try expect(x == 1);
795 }
796 {
797 var x: u24 = maxInt(u24);
798 x *%= x;
799 try expect(x == 1);
800 }
801 {
802 var x: u32 = maxInt(u32);
803 x *%= x;
804 try expect(x == 1);
805 }
806 {
807 var x: u48 = maxInt(u48);
808 x *%= x;
809 try expect(x == 1);
810 }
811 {
812 var x: u64 = maxInt(u64);
813 x *%= x;
814 try expect(x == 1);
815 }
816 {
817 var x: u96 = maxInt(u96);
818 x *%= x;
819 try expect(x == 1);
820 }
821 {
822 var x: u128 = maxInt(u128);
823 x *%= x;
824 try expect(x == 1);
825 }
826}
827
828test "128-bit multiplication" {
829 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
830 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
831 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
832 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
833 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
834
835 {
836 var a: i128 = 3;
837 var b: i128 = 2;
838 var c = a * b;
839 try expect(c == 6);
840
841 a = -3;
842 b = 2;
843 c = a * b;
844 try expect(c == -6);
845 }
846
847 {
848 var a: u128 = 0xffffffffffffffff;
849 var b: u128 = 100;
850 _ = .{ &a, &b };
851 const c = a * b;
852 try expect(c == 0x63ffffffffffffff9c);
853 }
854}
855
856fn testAddWithOverflow(comptime T: type, a: T, b: T, add: T, bit: u1) !void {
857 const ov = @addWithOverflow(a, b);
858 try expect(ov[0] == add);
859 try expect(ov[1] == bit);
860}
861
862test "@addWithOverflow" {
863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
865 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
866
867 try testAddWithOverflow(u8, 250, 100, 94, 1);
868 try testAddWithOverflow(u8, 100, 150, 250, 0);
869
870 try testAddWithOverflow(u8, 200, 99, 43, 1);
871 try testAddWithOverflow(u8, 200, 55, 255, 0);
872
873 try testAddWithOverflow(usize, 6, 6, 12, 0);
874 try testAddWithOverflow(usize, maxInt(usize), 6, 5, 1);
875
876 try testAddWithOverflow(isize, -6, -6, -12, 0);
877 try testAddWithOverflow(isize, minInt(isize), -6, maxInt(isize) - 5, 1);
878}
879
880test "@addWithOverflow > 64 bits" {
881 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
882 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
883 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
884 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
885
886 try testAddWithOverflow(u65, 4, 105, 109, 0);
887 try testAddWithOverflow(u65, 1000, 100, 1100, 0);
888 try testAddWithOverflow(u65, 100, maxInt(u65) - 99, 0, 1);
889 try testAddWithOverflow(u65, maxInt(u65), maxInt(u65), maxInt(u65) - 1, 1);
890 try testAddWithOverflow(u65, maxInt(u65) - 1, maxInt(u65), maxInt(u65) - 2, 1);
891 try testAddWithOverflow(u65, maxInt(u65), maxInt(u65) - 1, maxInt(u65) - 2, 1);
892
893 try testAddWithOverflow(u128, 4, 105, 109, 0);
894 try testAddWithOverflow(u128, 1000, 100, 1100, 0);
895 try testAddWithOverflow(u128, 100, maxInt(u128) - 99, 0, 1);
896 try testAddWithOverflow(u128, maxInt(u128), maxInt(u128), maxInt(u128) - 1, 1);
897 try testAddWithOverflow(u128, maxInt(u128) - 1, maxInt(u128), maxInt(u128) - 2, 1);
898 try testAddWithOverflow(u128, maxInt(u128), maxInt(u128) - 1, maxInt(u128) - 2, 1);
899
900 try testAddWithOverflow(i65, 4, -105, -101, 0);
901 try testAddWithOverflow(i65, 1000, 100, 1100, 0);
902 try testAddWithOverflow(i65, minInt(i65), 1, minInt(i65) + 1, 0);
903 try testAddWithOverflow(i65, maxInt(i65), minInt(i65), -1, 0);
904 try testAddWithOverflow(i65, minInt(i65), maxInt(i65), -1, 0);
905 try testAddWithOverflow(i65, maxInt(i65), -2, maxInt(i65) - 2, 0);
906 try testAddWithOverflow(i65, maxInt(i65), maxInt(i65), -2, 1);
907 try testAddWithOverflow(i65, minInt(i65), minInt(i65), 0, 1);
908 try testAddWithOverflow(i65, maxInt(i65) - 1, maxInt(i65), -3, 1);
909 try testAddWithOverflow(i65, maxInt(i65), maxInt(i65) - 1, -3, 1);
910
911 try testAddWithOverflow(i128, 4, -105, -101, 0);
912 try testAddWithOverflow(i128, 1000, 100, 1100, 0);
913 try testAddWithOverflow(i128, minInt(i128), 1, minInt(i128) + 1, 0);
914 try testAddWithOverflow(i128, maxInt(i128), minInt(i128), -1, 0);
915 try testAddWithOverflow(i128, minInt(i128), maxInt(i128), -1, 0);
916 try testAddWithOverflow(i128, maxInt(i128), -2, maxInt(i128) - 2, 0);
917 try testAddWithOverflow(i128, maxInt(i128), maxInt(i128), -2, 1);
918 try testAddWithOverflow(i128, minInt(i128), minInt(i128), 0, 1);
919 try testAddWithOverflow(i128, maxInt(i128) - 1, maxInt(i128), -3, 1);
920 try testAddWithOverflow(i128, maxInt(i128), maxInt(i128) - 1, -3, 1);
921}
922
923test "small int addition" {
924 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
925 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
926 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
927
928 var x: u2 = 0;
929 try expect(x == 0);
930
931 x += 1;
932 try expect(x == 1);
933
934 x += 1;
935 try expect(x == 2);
936
937 x += 1;
938 try expect(x == 3);
939
940 const ov = @addWithOverflow(x, 1);
941 try expect(ov[0] == 0);
942 try expect(ov[1] == 1);
943}
944
945fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void {
946 const ov = @mulWithOverflow(a, b);
947 try expect(ov[0] == mul);
948 try expect(ov[1] == bit);
949}
950
951test "basic @mulWithOverflow" {
952 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
953 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
954 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
955
956 try testMulWithOverflow(u8, 86, 3, 2, 1);
957 try testMulWithOverflow(u8, 85, 3, 255, 0);
958
959 try testMulWithOverflow(u8, 123, 2, 246, 0);
960 try testMulWithOverflow(u8, 123, 4, 236, 1);
961}
962
963test "extensive @mulWithOverflow" {
964 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
965 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
966 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
967 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
968
969 try testMulWithOverflow(u5, 3, 10, 30, 0);
970 try testMulWithOverflow(u5, 3, 11, 1, 1);
971 try testMulWithOverflow(i5, 3, -5, -15, 0);
972 try testMulWithOverflow(i5, 3, -6, 14, 1);
973
974 try testMulWithOverflow(u8, 3, 85, 255, 0);
975 try testMulWithOverflow(u8, 3, 86, 2, 1);
976 try testMulWithOverflow(i8, 3, -42, -126, 0);
977 try testMulWithOverflow(i8, 3, -43, 127, 1);
978
979 try testMulWithOverflow(u14, 3, 0x1555, 0x3fff, 0);
980 try testMulWithOverflow(u14, 3, 0x1556, 2, 1);
981 try testMulWithOverflow(i14, 3, -0xaaa, -0x1ffe, 0);
982 try testMulWithOverflow(i14, 3, -0xaab, 0x1fff, 1);
983
984 try testMulWithOverflow(u16, 3, 0x5555, 0xffff, 0);
985 try testMulWithOverflow(u16, 3, 0x5556, 2, 1);
986 try testMulWithOverflow(i16, 3, -0x2aaa, -0x7ffe, 0);
987 try testMulWithOverflow(i16, 3, -0x2aab, 0x7fff, 1);
988
989 try testMulWithOverflow(u30, 3, 0x15555555, 0x3fffffff, 0);
990 try testMulWithOverflow(u30, 3, 0x15555556, 2, 1);
991 try testMulWithOverflow(i30, 3, -0xaaaaaaa, -0x1ffffffe, 0);
992 try testMulWithOverflow(i30, 3, -0xaaaaaab, 0x1fffffff, 1);
993
994 try testMulWithOverflow(u32, 3, 0x55555555, 0xffffffff, 0);
995 try testMulWithOverflow(u32, 3, 0x55555556, 2, 1);
996 try testMulWithOverflow(i32, 3, -0x2aaaaaaa, -0x7ffffffe, 0);
997 try testMulWithOverflow(i32, 3, -0x2aaaaaab, 0x7fffffff, 1);
998
999 try testMulWithOverflow(u31, 1 << 30, 1 << 30, 0, 1);
1000 try testMulWithOverflow(i31, minInt(i31), minInt(i31), 0, 1);
1001}
1002
1003test "@mulWithOverflow bitsize > 32" {
1004 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1008
1009 try testMulWithOverflow(u40, 3, 0x55_5555_5555, 0xff_ffff_ffff, 0);
1010 try testMulWithOverflow(u40, 3, 0x55_5555_5556, 2, 1);
1011 try testMulWithOverflow(u40, 0x10_0000_0000, 0x10_0000_0000, 0, 1);
1012
1013 try testMulWithOverflow(i40, 3, -0x2a_aaaa_aaaa, -0x7f_ffff_fffe, 0);
1014 try testMulWithOverflow(i40, 3, -0x2a_aaaa_aaab, 0x7f_ffff_ffff, 1);
1015 try testMulWithOverflow(i40, 6, -0x2a_aaaa_aaab, -2, 1);
1016 try testMulWithOverflow(i40, 0x08_0000_0000, -0x08_0000_0001, -0x8_0000_0000, 1);
1017
1018 try testMulWithOverflow(u62, 3, 0x1555555555555555, 0x3fffffffffffffff, 0);
1019 try testMulWithOverflow(u62, 3, 0x1555555555555556, 2, 1);
1020 try testMulWithOverflow(i62, 3, -0xaaaaaaaaaaaaaaa, -0x1ffffffffffffffe, 0);
1021 try testMulWithOverflow(i62, 3, -0xaaaaaaaaaaaaaab, 0x1fffffffffffffff, 1);
1022
1023 try testMulWithOverflow(u64, 3, 0x5555555555555555, 0xffffffffffffffff, 0);
1024 try testMulWithOverflow(u64, 3, 0x5555555555555556, 2, 1);
1025 try testMulWithOverflow(i64, 3, -0x2aaaaaaaaaaaaaaa, -0x7ffffffffffffffe, 0);
1026 try testMulWithOverflow(i64, 3, -0x2aaaaaaaaaaaaaab, 0x7fffffffffffffff, 1);
1027
1028 try testMulWithOverflow(u63, 1 << 62, 1 << 62, 0, 1);
1029 try testMulWithOverflow(i63, minInt(i63), minInt(i63), 0, 1);
1030}
1031
1032test "@mulWithOverflow bitsize 128 bits" {
1033 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1034 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1035 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1039
1040 try testMulWithOverflow(u128, 3, 0x5555555555555555_5555555555555555, 0xffffffffffffffff_ffffffffffffffff, 0);
1041 try testMulWithOverflow(u128, 3, 0x5555555555555555_5555555555555556, 2, 1);
1042
1043 try testMulWithOverflow(u128, 1 << 100, 1 << 27, 1 << 127, 0);
1044 try testMulWithOverflow(u128, maxInt(u128), maxInt(u128), 1, 1);
1045 try testMulWithOverflow(u128, 1 << 100, 1 << 28, 0, 1);
1046 try testMulWithOverflow(u128, 1 << 127, 1 << 127, 0, 1);
1047
1048 try testMulWithOverflow(i128, 3, -0x2aaaaaaaaaaaaaaa_aaaaaaaaaaaaaaaa, -0x7fffffffffffffff_fffffffffffffffe, 0);
1049 try testMulWithOverflow(i128, 3, -0x2aaaaaaaaaaaaaaa_aaaaaaaaaaaaaaab, 0x7fffffffffffffff_ffffffffffffffff, 1);
1050 try testMulWithOverflow(i128, -1, -1, 1, 0);
1051 try testMulWithOverflow(i128, minInt(i128), minInt(i128), 0, 1);
1052
1053 try testMulWithOverflow(i128, 1 << 126, 1 << 1, -1 << 127, 1);
1054 try testMulWithOverflow(i128, -1 << 105, 1 << 22, -1 << 127, 0);
1055 try testMulWithOverflow(i128, 1 << 84, -1 << 43, -1 << 127, 0);
1056 try testMulWithOverflow(i128, -1 << 63, -1 << 64, -1 << 127, 1);
1057}
1058
1059test "@mulWithOverflow bitsize 256 bits" {
1060 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1061 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1062 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1063 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1064 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1065
1066 {
1067 const const_lhs: u256 = 8035709466408580321693645878924206181189;
1068 const const_rhs: u256 = 343954217539185679456797259115612849079;
1069 const const_result = @mulWithOverflow(const_lhs, const_rhs);
1070 comptime assert(const_result[0] == 100698109432518020450541558444080472799095368135495022414802684874680804056403);
1071 comptime assert(const_result[1] == 1);
1072
1073 var var_lhs = const_lhs;
1074 var var_rhs = const_rhs;
1075 _ = .{ &var_lhs, &var_rhs };
1076 const var_result = @mulWithOverflow(var_lhs, var_rhs);
1077 try std.testing.expect(var_result[0] == const_result[0]);
1078 try std.testing.expect(var_result[1] == const_result[1]);
1079 }
1080 {
1081 const const_lhs: u256 = 100477140835310762407466294984162740292250605075409128262608;
1082 const const_rhs: u256 = 406310585934439581231;
1083 const const_result = @mulWithOverflow(const_lhs, const_rhs);
1084 comptime assert(const_result[0] == 66110554277021146912650321519727251744526528332039438002889524600764482652976);
1085 comptime assert(const_result[1] == 1);
1086
1087 var var_lhs = const_lhs;
1088 var var_rhs = const_rhs;
1089 _ = .{ &var_lhs, &var_rhs };
1090 const var_result = @mulWithOverflow(var_lhs, var_rhs);
1091 try std.testing.expect(var_result[0] == const_result[0]);
1092 try std.testing.expect(var_result[1] == const_result[1]);
1093 }
1094 try testMulWithOverflow(i256, 1 << 254, 1 << 1, -1 << 255, 1);
1095 try testMulWithOverflow(i256, -1 << 212, 1 << 43, -1 << 255, 0);
1096 try testMulWithOverflow(i256, 1 << 170, -1 << 85, -1 << 255, 0);
1097 try testMulWithOverflow(i256, -1 << 128, -1 << 127, -1 << 255, 1);
1098}
1099
1100fn testSubWithOverflow(comptime T: type, a: T, b: T, sub: T, bit: u1) !void {
1101 const ov = @subWithOverflow(a, b);
1102 try expect(ov[0] == sub);
1103 try expect(ov[1] == bit);
1104}
1105
1106test "@subWithOverflow" {
1107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1109
1110 try testSubWithOverflow(u8, 1, 2, 255, 1);
1111 try testSubWithOverflow(u8, 1, 1, 0, 0);
1112
1113 try testSubWithOverflow(u16, 10000, 10002, 65534, 1);
1114 try testSubWithOverflow(u16, 10000, 9999, 1, 0);
1115
1116 try testSubWithOverflow(usize, 6, 6, 0, 0);
1117 try testSubWithOverflow(usize, 6, 7, maxInt(usize), 1);
1118 try testSubWithOverflow(isize, -6, -6, 0, 0);
1119 try testSubWithOverflow(isize, minInt(isize), 6, maxInt(isize) - 5, 1);
1120}
1121
1122test "@subWithOverflow > 64 bits" {
1123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1125 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1126 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1127
1128 try testSubWithOverflow(u65, 4, 105, maxInt(u65) - 100, 1);
1129 try testSubWithOverflow(u65, 1000, 100, 900, 0);
1130 try testSubWithOverflow(u65, maxInt(u65), maxInt(u65), 0, 0);
1131 try testSubWithOverflow(u65, maxInt(u65) - 1, maxInt(u65), maxInt(u65), 1);
1132 try testSubWithOverflow(u65, maxInt(u65), maxInt(u65) - 1, 1, 0);
1133
1134 try testSubWithOverflow(u128, 4, 105, maxInt(u128) - 100, 1);
1135 try testSubWithOverflow(u128, 1000, 100, 900, 0);
1136 try testSubWithOverflow(u128, maxInt(u128), maxInt(u128), 0, 0);
1137 try testSubWithOverflow(u128, maxInt(u128) - 1, maxInt(u128), maxInt(u128), 1);
1138 try testSubWithOverflow(u128, maxInt(u128), maxInt(u128) - 1, 1, 0);
1139
1140 try testSubWithOverflow(i65, 4, 105, -101, 0);
1141 try testSubWithOverflow(i65, 1000, 100, 900, 0);
1142 try testSubWithOverflow(i65, maxInt(i65), maxInt(i65), 0, 0);
1143 try testSubWithOverflow(i65, minInt(i65), minInt(i65), 0, 0);
1144 try testSubWithOverflow(i65, maxInt(i65) - 1, maxInt(i65), -1, 0);
1145 try testSubWithOverflow(i65, maxInt(i65), maxInt(i65) - 1, 1, 0);
1146 try testSubWithOverflow(i65, minInt(i65), 1, maxInt(i65), 1);
1147 try testSubWithOverflow(i65, maxInt(i65), minInt(i65), -1, 1);
1148 try testSubWithOverflow(i65, minInt(i65), maxInt(i65), 1, 1);
1149 try testSubWithOverflow(i65, maxInt(i65), -2, minInt(i65) + 1, 1);
1150
1151 try testSubWithOverflow(i128, 4, 105, -101, 0);
1152 try testSubWithOverflow(i128, 1000, 100, 900, 0);
1153 try testSubWithOverflow(i128, maxInt(i128), maxInt(i128), 0, 0);
1154 try testSubWithOverflow(i128, minInt(i128), minInt(i128), 0, 0);
1155 try testSubWithOverflow(i128, maxInt(i128) - 1, maxInt(i128), -1, 0);
1156 try testSubWithOverflow(i128, maxInt(i128), maxInt(i128) - 1, 1, 0);
1157 try testSubWithOverflow(i128, minInt(i128), 1, maxInt(i128), 1);
1158 try testSubWithOverflow(i128, maxInt(i128), minInt(i128), -1, 1);
1159 try testSubWithOverflow(i128, minInt(i128), maxInt(i128), 1, 1);
1160 try testSubWithOverflow(i128, maxInt(i128), -2, minInt(i128) + 1, 1);
1161}
1162
1163fn testShlWithOverflow(comptime T: type, a: T, b: math.Log2Int(T), shl: T, bit: u1) !void {
1164 const ov = @shlWithOverflow(a, b);
1165 try expect(ov[0] == shl);
1166 try expect(ov[1] == bit);
1167}
1168
1169test "@shlWithOverflow" {
1170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1172 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1173 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1174
1175 try testShlWithOverflow(u4, 2, 1, 4, 0);
1176 try testShlWithOverflow(u4, 2, 3, 0, 1);
1177
1178 try testShlWithOverflow(i9, 127, 1, 254, 0);
1179 try testShlWithOverflow(i9, 127, 2, -4, 1);
1180
1181 try testShlWithOverflow(u16, 0b0010111111111111, 3, 0b0111111111111000, 1);
1182 try testShlWithOverflow(u16, 0b0010111111111111, 2, 0b1011111111111100, 0);
1183
1184 try testShlWithOverflow(u16, 0b0000_0000_0000_0011, 15, 0b1000_0000_0000_0000, 1);
1185 try testShlWithOverflow(u16, 0b0000_0000_0000_0011, 14, 0b1100_0000_0000_0000, 0);
1186}
1187
1188test "@shlWithOverflow > 64 bits" {
1189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1192 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1193
1194 try testShlWithOverflow(u65, 0x0_0100_0000_0000_0000, 7, 0x0_8000_0000_0000_0000, 0);
1195 try testShlWithOverflow(u65, 0x0_0100_0000_0000_0000, 8, 0x1_0000_0000_0000_0000, 0);
1196 try testShlWithOverflow(u65, 0x0_0100_0000_0000_0000, 9, 0, 1);
1197 try testShlWithOverflow(u65, 0x0_0100_0000_0000_0000, 10, 0, 1);
1198
1199 try testShlWithOverflow(u128, 0x0100_0000_0000_0000_0000000000000000, 6, 0x4000_0000_0000_0000_0000000000000000, 0);
1200 try testShlWithOverflow(u128, 0x0100_0000_0000_0000_0000000000000000, 7, 0x8000_0000_0000_0000_0000000000000000, 0);
1201 try testShlWithOverflow(u128, 0x0100_0000_0000_0000_0000000000000000, 8, 0, 1);
1202 try testShlWithOverflow(u128, 0x0100_0000_0000_0000_0000000000000000, 9, 0, 1);
1203
1204 try testShlWithOverflow(i65, 0x0_0100_0000_0000_0000, 7, 0x0_8000_0000_0000_0000, 0);
1205 try testShlWithOverflow(i65, 0x0_0100_0000_0000_0000, 8, minInt(i65), 1);
1206 try testShlWithOverflow(i65, 0x0_0100_0000_0000_0000, 9, 0, 1);
1207 try testShlWithOverflow(i65, 0x0_0100_0000_0000_0000, 10, 0, 1);
1208
1209 try testShlWithOverflow(i128, 0x0100_0000_0000_0000_0000000000000000, 6, 0x4000_0000_0000_0000_0000000000000000, 0);
1210 try testShlWithOverflow(i128, 0x0100_0000_0000_0000_0000000000000000, 7, minInt(i128), 1);
1211 try testShlWithOverflow(i128, 0x0100_0000_0000_0000_0000000000000000, 8, 0, 1);
1212 try testShlWithOverflow(i128, 0x0100_0000_0000_0000_0000000000000000, 9, 0, 1);
1213}
1214
1215test "overflow arithmetic with u0 values" {
1216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1217
1218 {
1219 var a: u0 = 0;
1220 _ = &a;
1221 const ov = @addWithOverflow(a, 0);
1222 try expect(ov[1] == 0);
1223 try expect(ov[1] == 0);
1224 }
1225 {
1226 var a: u0 = 0;
1227 _ = &a;
1228 const ov = @subWithOverflow(a, 0);
1229 try expect(ov[1] == 0);
1230 try expect(ov[1] == 0);
1231 }
1232 {
1233 var a: u0 = 0;
1234 _ = &a;
1235 const ov = @mulWithOverflow(a, 0);
1236 try expect(ov[1] == 0);
1237 try expect(ov[1] == 0);
1238 }
1239 {
1240 var a: u0 = 0;
1241 _ = &a;
1242 const ov = @shlWithOverflow(a, 0);
1243 try expect(ov[1] == 0);
1244 try expect(ov[1] == 0);
1245 }
1246}
1247
1248test "allow signed integer division/remainder when values are comptime-known and positive or exact" {
1249 try expect(5 / 3 == 1);
1250 try expect(-5 / -3 == 1);
1251 try expect(-6 / 3 == -2);
1252
1253 try expect(5 % 3 == 2);
1254 try expect(-6 % 3 == 0);
1255}
1256
1257test "quad hex float literal parsing accurate" {
1258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1261 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1262
1263 const a: f128 = 0x1.1111222233334444555566667777p+0;
1264
1265 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
1266 const expected: u128 = 0x3fff1111222233334444555566667777;
1267 try expect(@as(u128, @bitCast(a)) == expected);
1268
1269 // non-normalized
1270 const b: f128 = 0x11.111222233334444555566667777p-4;
1271 try expect(@as(u128, @bitCast(b)) == expected);
1272
1273 const S = struct {
1274 fn doTheTest() !void {
1275 {
1276 var f: f128 = 0x1.2eab345678439abcdefea56782346p+5;
1277 _ = &f;
1278 try expect(@as(u128, @bitCast(f)) == 0x40042eab345678439abcdefea5678234);
1279 }
1280 {
1281 var f: f128 = 0x1.edcb34a235253948765432134674fp-1;
1282 _ = &f;
1283 try expect(@as(u128, @bitCast(f)) == 0x3ffeedcb34a235253948765432134675); // round-to-even
1284 }
1285 {
1286 var f: f128 = 0x1.353e45674d89abacc3a2ebf3ff4ffp-50;
1287 _ = &f;
1288 try expect(@as(u128, @bitCast(f)) == 0x3fcd353e45674d89abacc3a2ebf3ff50);
1289 }
1290 {
1291 var f: f128 = 0x1.ed8764648369535adf4be3214567fp-9;
1292 _ = &f;
1293 try expect(@as(u128, @bitCast(f)) == 0x3ff6ed8764648369535adf4be3214568);
1294 }
1295 const exp2ft = [_]f64{
1296 0x1.6a09e667f3bcdp-1,
1297 0x1.7a11473eb0187p-1,
1298 0x1.8ace5422aa0dbp-1,
1299 0x1.9c49182a3f090p-1,
1300 0x1.ae89f995ad3adp-1,
1301 0x1.c199bdd85529cp-1,
1302 0x1.d5818dcfba487p-1,
1303 0x1.ea4afa2a490dap-1,
1304 0x1.0000000000000p+0,
1305 0x1.0b5586cf9890fp+0,
1306 0x1.172b83c7d517bp+0,
1307 0x1.2387a6e756238p+0,
1308 0x1.306fe0a31b715p+0,
1309 0x1.3dea64c123422p+0,
1310 0x1.4bfdad5362a27p+0,
1311 0x1.5ab07dd485429p+0,
1312 0x1.8p23,
1313 0x1.62e430p-1,
1314 0x1.ebfbe0p-3,
1315 0x1.c6b348p-5,
1316 0x1.3b2c9cp-7,
1317 0x1.0p127,
1318 -0x1.0p-149,
1319 };
1320
1321 const answers = [_]u64{
1322 0x3fe6a09e667f3bcd,
1323 0x3fe7a11473eb0187,
1324 0x3fe8ace5422aa0db,
1325 0x3fe9c49182a3f090,
1326 0x3feae89f995ad3ad,
1327 0x3fec199bdd85529c,
1328 0x3fed5818dcfba487,
1329 0x3feea4afa2a490da,
1330 0x3ff0000000000000,
1331 0x3ff0b5586cf9890f,
1332 0x3ff172b83c7d517b,
1333 0x3ff2387a6e756238,
1334 0x3ff306fe0a31b715,
1335 0x3ff3dea64c123422,
1336 0x3ff4bfdad5362a27,
1337 0x3ff5ab07dd485429,
1338 0x4168000000000000,
1339 0x3fe62e4300000000,
1340 0x3fcebfbe00000000,
1341 0x3fac6b3480000000,
1342 0x3f83b2c9c0000000,
1343 0x47e0000000000000,
1344 0xb6a0000000000000,
1345 };
1346
1347 for (exp2ft, 0..) |x, i| {
1348 try expect(@as(u64, @bitCast(x)) == answers[i]);
1349 }
1350 }
1351 };
1352 try S.doTheTest();
1353 try comptime S.doTheTest();
1354}
1355
1356test "truncating shift left" {
1357 try testShlTrunc(maxInt(u16));
1358 try comptime testShlTrunc(maxInt(u16));
1359}
1360fn testShlTrunc(x: u16) !void {
1361 const shifted = x << 1;
1362 try expect(shifted == 65534);
1363}
1364
1365test "exact shift left" {
1366 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1367
1368 try testShlExact(0b00110101);
1369 try comptime testShlExact(0b00110101);
1370
1371 if (@shlExact(1, 1) != 2) @compileError("should be 2");
1372}
1373fn testShlExact(x: u8) !void {
1374 const shifted = @shlExact(x, 2);
1375 try expect(shifted == 0b11010100);
1376}
1377
1378test "exact shift right" {
1379 try testShrExact(0b10110100);
1380 try comptime testShrExact(0b10110100);
1381}
1382fn testShrExact(x: u8) !void {
1383 const shifted = @shrExact(x, 2);
1384 try expect(shifted == 0b00101101);
1385}
1386
1387test "shift left/right on u0 operand" {
1388 const S = struct {
1389 fn doTheTest() !void {
1390 var x: u0 = 0;
1391 var y: u0 = 0;
1392 _ = .{ &x, &y };
1393 try expectEqual(@as(u0, 0), x << 0);
1394 try expectEqual(@as(u0, 0), x >> 0);
1395 try expectEqual(@as(u0, 0), x << y);
1396 try expectEqual(@as(u0, 0), x >> y);
1397 try expectEqual(@as(u0, 0), @shlExact(x, 0));
1398 try expectEqual(@as(u0, 0), @shrExact(x, 0));
1399 try expectEqual(@as(u0, 0), @shlExact(x, y));
1400 try expectEqual(@as(u0, 0), @shrExact(x, y));
1401 }
1402 };
1403 try S.doTheTest();
1404 try comptime S.doTheTest();
1405}
1406
1407test "comptime float rem int" {
1408 comptime {
1409 const x = @as(f32, 1) % 2;
1410 try expect(x == 1.0);
1411 }
1412}
1413
1414test "remainder division" {
1415 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1418 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1419 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1420 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1421
1422 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1423 // https://github.com/ziglang/zig/issues/12602
1424 return error.SkipZigTest;
1425 }
1426
1427 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
1428
1429 try comptime remdiv(f16);
1430 try comptime remdiv(f32);
1431 try comptime remdiv(f64);
1432 try comptime remdiv(f80);
1433 try comptime remdiv(f128);
1434 try remdiv(f16);
1435 try remdiv(f32);
1436 try remdiv(f64);
1437 try remdiv(f80);
1438 try remdiv(f128);
1439}
1440
1441fn remdiv(comptime T: type) !void {
1442 try expect(@as(T, 1) == @as(T, 1) % @as(T, 2));
1443 try remdivOne(T, 1, 1, 2);
1444
1445 try expect(@as(T, 1) == @as(T, 7) % @as(T, 3));
1446 try remdivOne(T, 1, 7, 3);
1447}
1448
1449fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {
1450 try expect(a == @rem(b, c));
1451 try expect(a == @mod(b, c));
1452}
1453
1454test "float remainder division using @rem" {
1455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1456 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1457 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1458 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1459
1460 try comptime frem(f16);
1461 try comptime frem(f32);
1462 try comptime frem(f64);
1463 try comptime frem(f80);
1464 try comptime frem(f128);
1465 try frem(f16);
1466 try frem(f32);
1467 try frem(f64);
1468 try frem(f80);
1469 try frem(f128);
1470}
1471
1472fn frem(comptime T: type) !void {
1473 const epsilon = switch (T) {
1474 f16 => 1.0,
1475 f32 => 0.001,
1476 f64 => 0.00001,
1477 f80 => 0.000001,
1478 f128 => 0.0000001,
1479 else => unreachable,
1480 };
1481
1482 try fremOne(T, 6.9, 4.0, 2.9, epsilon);
1483 try fremOne(T, -6.9, 4.0, -2.9, epsilon);
1484 try fremOne(T, -5.0, 3.0, -2.0, epsilon);
1485 try fremOne(T, 3.0, 2.0, 1.0, epsilon);
1486 try fremOne(T, 1.0, 2.0, 1.0, epsilon);
1487 try fremOne(T, 0.0, 1.0, 0.0, epsilon);
1488 try fremOne(T, -0.0, 1.0, -0.0, epsilon);
1489}
1490
1491fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
1492 try expect(@abs(@rem(a, b) - c) < epsilon);
1493}
1494
1495test "float modulo division using @mod" {
1496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1499 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1500 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1501
1502 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
1503
1504 try comptime fmod(f16);
1505 try comptime fmod(f32);
1506 try comptime fmod(f64);
1507 try comptime fmod(f80);
1508 try comptime fmod(f128);
1509 try fmod(f16);
1510 try fmod(f32);
1511 try fmod(f64);
1512 try fmod(f80);
1513 try fmod(f128);
1514}
1515
1516fn fmod(comptime T: type) !void {
1517 const epsilon = switch (T) {
1518 f16 => 1.0,
1519 f32 => 0.001,
1520 f64 => 0.00001,
1521 f80 => 0.000001,
1522 f128 => 0.0000001,
1523 else => unreachable,
1524 };
1525
1526 try fmodOne(T, 6.9, 4.0, 2.9, epsilon);
1527 try fmodOne(T, -6.9, 4.0, 1.1, epsilon);
1528 try fmodOne(T, -5.0, 3.0, 1.0, epsilon);
1529 try fmodOne(T, 3.0, 2.0, 1.0, epsilon);
1530 try fmodOne(T, 1.0, 2.0, 1.0, epsilon);
1531 try fmodOne(T, 0.0, 1.0, 0.0, epsilon);
1532 try fmodOne(T, -0.0, 1.0, -0.0, epsilon);
1533}
1534
1535fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
1536 try expect(@abs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon);
1537}
1538
1539test "@round f16" {
1540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1542 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1543
1544 try testRound(f16, 12.0);
1545 try comptime testRound(f16, 12.0);
1546}
1547
1548test "@round f32/f64" {
1549 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1550 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1551 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1552
1553 try testRound(f64, 12.0);
1554 try comptime testRound(f64, 12.0);
1555 try testRound(f32, 12.0);
1556 try comptime testRound(f32, 12.0);
1557
1558 const x = 14.0;
1559 const y = x + 0.4;
1560 const z = @round(y);
1561 comptime assert(x == z);
1562}
1563
1564test "@round f80" {
1565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1567 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1568 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1569 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1570
1571 try testRound(f80, 12.0);
1572 try comptime testRound(f80, 12.0);
1573}
1574
1575test "@round f128" {
1576 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1577 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1578 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1579 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1580 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1581
1582 try testRound(f128, 12.0);
1583 try comptime testRound(f128, 12.0);
1584}
1585
1586fn testRound(comptime T: type, x: T) !void {
1587 const y = x - 0.5;
1588 const z = @round(y);
1589 try expect(x == z);
1590}
1591
1592test "vector integer addition" {
1593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1594 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1596 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1597 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1598 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1599
1600 const S = struct {
1601 fn doTheTest() !void {
1602 var a: @Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
1603 var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
1604 _ = .{ &a, &b };
1605 const result = a + b;
1606 var result_array: [4]i32 = result;
1607 const expected = [_]i32{ 6, 8, 10, 12 };
1608 try expectEqualSlices(i32, &expected, &result_array);
1609 }
1610 };
1611 try S.doTheTest();
1612 try comptime S.doTheTest();
1613}
1614
1615test "NaN comparison" {
1616 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1617 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1618 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1619 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1620 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
1621
1622 try testNanEqNan(f16);
1623 try testNanEqNan(f32);
1624 try testNanEqNan(f64);
1625 try testNanEqNan(f128);
1626 try comptime testNanEqNan(f16);
1627 try comptime testNanEqNan(f32);
1628 try comptime testNanEqNan(f64);
1629 try comptime testNanEqNan(f128);
1630}
1631
1632test "NaN comparison f80" {
1633 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1634 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1635 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1636 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1637
1638 try testNanEqNan(f80);
1639 try comptime testNanEqNan(f80);
1640}
1641
1642fn testNanEqNan(comptime F: type) !void {
1643 var nan1 = math.nan(F);
1644 var nan2 = math.nan(F);
1645 _ = .{ &nan1, &nan2 };
1646 try expect(nan1 != nan2);
1647 try expect(!(nan1 == nan2));
1648 try expect(!(nan1 > nan2));
1649 try expect(!(nan1 >= nan2));
1650 try expect(!(nan1 < nan2));
1651 try expect(!(nan1 <= nan2));
1652}
1653
1654test "vector comparison" {
1655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1656 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1657 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1658 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1659 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1660 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1661
1662 const S = struct {
1663 fn doTheTest() !void {
1664 var a: @Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 };
1665 var b: @Vector(6, i32) = [_]i32{ -1, 3, 0, 6, 10, -10 };
1666 _ = .{ &a, &b };
1667 try expect(mem.eql(bool, &@as([6]bool, a < b), &[_]bool{ false, false, true, true, true, false }));
1668 try expect(mem.eql(bool, &@as([6]bool, a <= b), &[_]bool{ false, true, true, true, true, false }));
1669 try expect(mem.eql(bool, &@as([6]bool, a == b), &[_]bool{ false, true, false, false, false, false }));
1670 try expect(mem.eql(bool, &@as([6]bool, a != b), &[_]bool{ true, false, true, true, true, true }));
1671 try expect(mem.eql(bool, &@as([6]bool, a > b), &[_]bool{ true, false, false, false, false, true }));
1672 try expect(mem.eql(bool, &@as([6]bool, a >= b), &[_]bool{ true, true, false, false, false, true }));
1673 }
1674 };
1675 try S.doTheTest();
1676 try comptime S.doTheTest();
1677}
1678
1679test "compare undefined literal with comptime_int" {
1680 var x = undefined == 1;
1681 // x is now undefined with type bool
1682 x = true;
1683 try expect(x);
1684}
1685
1686test "signed zeros are represented properly" {
1687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1688 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1689 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1690 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1691
1692 const S = struct {
1693 fn doTheTest() !void {
1694 try testOne(f16);
1695 try testOne(f32);
1696 try testOne(f64);
1697 try testOne(f80);
1698 try testOne(f128);
1699 try testOne(c_longdouble);
1700 }
1701
1702 fn testOne(comptime T: type) !void {
1703 const ST = std.meta.Int(.unsigned, @typeInfo(T).float.bits);
1704 var as_fp_val = -@as(T, 0.0);
1705 _ = &as_fp_val;
1706 const as_uint_val: ST = @bitCast(as_fp_val);
1707 // Ensure the sign bit is set.
1708 try expect(as_uint_val >> (@typeInfo(T).float.bits - 1) == 1);
1709 }
1710 };
1711
1712 try S.doTheTest();
1713 try comptime S.doTheTest();
1714}
1715
1716test "absFloat" {
1717 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1718 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1719
1720 try testAbsFloat();
1721 try comptime testAbsFloat();
1722}
1723fn testAbsFloat() !void {
1724 try testAbsFloatOne(-10.05, 10.05);
1725 try testAbsFloatOne(10.05, 10.05);
1726}
1727fn testAbsFloatOne(in: f32, out: f32) !void {
1728 try expect(@abs(@as(f32, in)) == @as(f32, out));
1729}
1730
1731test "mod lazy values" {
1732 {
1733 const X = struct { x: u32 };
1734 const x = @sizeOf(X);
1735 const y = 1 % x;
1736 _ = y;
1737 }
1738 {
1739 const X = struct { x: u32 };
1740 const x = @sizeOf(X);
1741 const y = x % 1;
1742 _ = y;
1743 }
1744}
1745
1746test "@clz works on both vector and scalar inputs" {
1747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1748 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1749 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1750 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1751 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1752 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1753
1754 var x: u32 = 0x1;
1755 _ = &x;
1756 var y: @Vector(4, u32) = [_]u32{ 0x1, 0x1, 0x1, 0x1 };
1757 _ = &y;
1758 const a = @clz(x);
1759 const b = @clz(y);
1760 try std.testing.expectEqual(@as(u6, 31), a);
1761 try std.testing.expectEqual([_]u6{ 31, 31, 31, 31 }, b);
1762}
1763
1764test "runtime comparison to NaN is comptime-known" {
1765 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1766 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1767 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1768 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1769 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
1770
1771 const S = struct {
1772 fn doTheTest(comptime F: type, x: F) void {
1773 const nan = math.nan(F);
1774 if (!(nan != x)) comptime unreachable;
1775 if (nan == x) comptime unreachable;
1776 if (nan > x) comptime unreachable;
1777 if (nan < x) comptime unreachable;
1778 if (nan >= x) comptime unreachable;
1779 if (nan <= x) comptime unreachable;
1780 }
1781 };
1782
1783 S.doTheTest(f16, 123.0);
1784 S.doTheTest(f32, 123.0);
1785 S.doTheTest(f64, 123.0);
1786 S.doTheTest(f128, 123.0);
1787 comptime S.doTheTest(f16, 123.0);
1788 comptime S.doTheTest(f32, 123.0);
1789 comptime S.doTheTest(f64, 123.0);
1790 comptime S.doTheTest(f128, 123.0);
1791}
1792
1793test "runtime int comparison to inf is comptime-known" {
1794 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1795 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1796 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1797 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1798 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
1799
1800 const S = struct {
1801 fn doTheTest(comptime F: type, x: u32) void {
1802 const inf = math.inf(F);
1803 if (!(inf != x)) comptime unreachable;
1804 if (inf == x) comptime unreachable;
1805 if (x > inf) comptime unreachable;
1806 if (x >= inf) comptime unreachable;
1807 if (!(x < inf)) comptime unreachable;
1808 if (!(x <= inf)) comptime unreachable;
1809 }
1810 };
1811
1812 S.doTheTest(f16, 123);
1813 S.doTheTest(f32, 123);
1814 S.doTheTest(f64, 123);
1815 S.doTheTest(f128, 123);
1816 comptime S.doTheTest(f16, 123);
1817 comptime S.doTheTest(f32, 123);
1818 comptime S.doTheTest(f64, 123);
1819 comptime S.doTheTest(f128, 123);
1820}
1821
1822test "float divide by zero" {
1823 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1826 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1827 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1828
1829 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
1830
1831 const S = struct {
1832 fn doTheTest(comptime F: type, zero: F, one: F) !void {
1833 try expect(math.isPositiveInf(@divTrunc(one, zero)));
1834 try expect(math.isPositiveInf(@divFloor(one, zero)));
1835
1836 try expect(math.isNan(@rem(one, zero)));
1837 try expect(math.isNan(@mod(one, zero)));
1838 }
1839 };
1840
1841 try S.doTheTest(f16, 0, 1);
1842 comptime S.doTheTest(f16, 0, 1) catch unreachable;
1843
1844 try S.doTheTest(f32, 0, 1);
1845 comptime S.doTheTest(f32, 0, 1) catch unreachable;
1846
1847 try S.doTheTest(f64, 0, 1);
1848 comptime S.doTheTest(f64, 0, 1) catch unreachable;
1849
1850 try S.doTheTest(f80, 0, 1);
1851 comptime S.doTheTest(f80, 0, 1) catch unreachable;
1852
1853 try S.doTheTest(f128, 0, 1);
1854 comptime S.doTheTest(f128, 0, 1) catch unreachable;
1855}
1856
1857test "partially-runtime integer vector division would be illegal if vector elements were reordered" {
1858 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1859 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1860 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1861 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1862 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1863 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1864 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1865
1866 var lhs: @Vector(2, i8) = .{ -128, 5 };
1867 const rhs: @Vector(2, i8) = .{ 1, -1 };
1868
1869 const expected: @Vector(2, i8) = .{ -128, -5 };
1870
1871 lhs = lhs; // suppress error
1872
1873 const trunc = @divTrunc(lhs, rhs);
1874 try expect(trunc[0] == expected[0]);
1875 try expect(trunc[1] == expected[1]);
1876
1877 const floor = @divFloor(lhs, rhs);
1878 try expect(floor[0] == expected[0]);
1879 try expect(floor[1] == expected[1]);
1880
1881 const exact = @divExact(lhs, rhs);
1882 try expect(exact[0] == expected[0]);
1883 try expect(exact[1] == expected[1]);
1884}
1885
1886test "float vector division of comptime zero by runtime nan is nan" {
1887 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1888 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1890 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1891 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1892 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1893
1894 const ct_zero: @Vector(1, f32) = .{0};
1895 var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
1896
1897 rt_nan = rt_nan; // suppress error
1898
1899 try expect(math.isNan((@divTrunc(ct_zero, rt_nan))[0]));
1900 try expect(math.isNan((@divFloor(ct_zero, rt_nan))[0]));
1901 try expect(math.isNan((ct_zero / rt_nan)[0]));
1902}
1903
1904test "float vector multiplication of comptime zero by runtime nan is nan" {
1905 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1906 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1907 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1908 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1909 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1910 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1911
1912 const ct_zero: @Vector(1, f32) = .{0};
1913 var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
1914
1915 rt_nan = rt_nan; // suppress error
1916
1917 try expect(math.isNan((ct_zero * rt_nan)[0]));
1918 try expect(math.isNan((rt_nan * ct_zero)[0]));
1919}
1920
1921test "comptime float vector division of zero by nan is nan" {
1922 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1923 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1924 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1925 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1926 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1927
1928 const ct_zero: @Vector(1, f32) = .{0};
1929 const ct_nan: @Vector(1, f32) = .{math.nan(f32)};
1930
1931 comptime assert(math.isNan((@divTrunc(ct_zero, ct_nan))[0]));
1932 comptime assert(math.isNan((@divFloor(ct_zero, ct_nan))[0]));
1933 comptime assert(math.isNan((ct_zero / ct_nan)[0]));
1934}
1935
1936test "comptime float vector multiplication of zero by nan is nan" {
1937 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1939 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1940 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1941 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1942
1943 const ct_zero: @Vector(1, f32) = .{0};
1944 const ct_nan: @Vector(1, f32) = .{math.nan(f32)};
1945
1946 comptime assert(math.isNan((ct_zero * ct_nan)[0]));
1947 comptime assert(math.isNan((ct_nan * ct_zero)[0]));
1948}