1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const math = std.math;
5
6const epsilon_16 = 0.002;
7const epsilon = 0.000001;
8
9fn epsForType(comptime T: type) T {
10 return switch (T) {
11 f16 => @as(f16, epsilon_16),
12 else => @as(T, epsilon),
13 };
14}
15
16test "add f16" {
17 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18
19 try testAdd(f16);
20 try comptime testAdd(f16);
21}
22
23test "add f32/f64" {
24 try testAdd(f32);
25 try comptime testAdd(f32);
26 try testAdd(f64);
27 try comptime testAdd(f64);
28}
29
30test "add f80/f128/c_longdouble" {
31 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
33
34 try testAdd(f80);
35 try comptime testAdd(f80);
36 try testAdd(f128);
37 try comptime testAdd(f128);
38 try testAdd(c_longdouble);
39 try comptime testAdd(c_longdouble);
40}
41
42fn testAdd(comptime T: type) !void {
43 var one_point_two_five: T = 1.25;
44 var two_point_seven_five: T = 2.75;
45 _ = &one_point_two_five;
46 _ = &two_point_seven_five;
47 try expect(one_point_two_five + two_point_seven_five == 4);
48}
49
50test "sub f16" {
51 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
52
53 try testSub(f16);
54 try comptime testSub(f16);
55}
56
57test "sub f32/f64" {
58 try testSub(f32);
59 try comptime testSub(f32);
60 try testSub(f64);
61 try comptime testSub(f64);
62}
63
64test "sub f80/f128/c_longdouble" {
65 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
67
68 try testSub(f80);
69 try comptime testSub(f80);
70 try testSub(f128);
71 try comptime testSub(f128);
72 try testSub(c_longdouble);
73 try comptime testSub(c_longdouble);
74}
75
76fn testSub(comptime T: type) !void {
77 var one_point_two_five: T = 1.25;
78 var two_point_seven_five: T = 2.75;
79 _ = &one_point_two_five;
80 _ = &two_point_seven_five;
81 try expect(one_point_two_five - two_point_seven_five == -1.5);
82}
83
84test "mul f16" {
85 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
86
87 try testMul(f16);
88 try comptime testMul(f16);
89}
90
91test "mul f32/f64" {
92 try testMul(f32);
93 try comptime testMul(f32);
94 try testMul(f64);
95 try comptime testMul(f64);
96}
97
98test "mul f80/f128/c_longdouble" {
99 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
100 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
101
102 try testMul(f80);
103 try comptime testMul(f80);
104 try testMul(f128);
105 try comptime testMul(f128);
106 try testMul(c_longdouble);
107 try comptime testMul(c_longdouble);
108}
109
110fn testMul(comptime T: type) !void {
111 var one_point_two_five: T = 1.25;
112 var two_point_seven_five: T = 2.75;
113 _ = &one_point_two_five;
114 _ = &two_point_seven_five;
115 try expect(one_point_two_five * two_point_seven_five == 3.4375);
116}
117
118test "cmp f16" {
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
121
122 try testCmp(f16);
123 try comptime testCmp(f16);
124}
125
126test "cmp f32" {
127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
130 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
131
132 try testCmp(f32);
133 try comptime testCmp(f32);
134}
135
136test "cmp f64" {
137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
139 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
140
141 try testCmp(f64);
142 try comptime testCmp(f64);
143}
144
145test "cmp f128" {
146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
149
150 try testCmp(f128);
151 try comptime testCmp(f128);
152}
153
154test "cmp f80/c_longdouble" {
155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158
159 try testCmp(f80);
160 try comptime testCmp(f80);
161 try testCmp(c_longdouble);
162 try comptime testCmp(c_longdouble);
163}
164
165fn testCmp(comptime T: type) !void {
166 {
167 // No decimal part
168 var x: T = 1.0;
169 _ = &x;
170 try expect(x == 1.0);
171 try expect(x != 0.0);
172 try expect(x > 0.0);
173 try expect(x < 2.0);
174 try expect(x >= 1.0);
175 try expect(x <= 1.0);
176 }
177 {
178 // Non-zero decimal part
179 var x: T = 1.5;
180 _ = &x;
181 try expect(x != 1.0);
182 try expect(x != 2.0);
183 try expect(x > 1.0);
184 try expect(x < 2.0);
185 try expect(x >= 1.0);
186 try expect(x <= 2.0);
187 }
188
189 @setEvalBranchQuota(2_000);
190 var edges = [_]T{
191 -math.inf(T),
192 -math.floatMax(T),
193 -math.floatMin(T),
194 -math.floatTrueMin(T),
195 -0.0,
196 math.nan(T),
197 0.0,
198 math.floatTrueMin(T),
199 math.floatMin(T),
200 math.floatMax(T),
201 math.inf(T),
202 };
203 _ = &edges;
204 for (edges, 0..) |rhs, rhs_i| {
205 for (edges, 0..) |lhs, lhs_i| {
206 const no_nan = lhs_i != 5 and rhs_i != 5;
207 const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;
208 const rhs_order = if (rhs_i < 5) rhs_i else rhs_i - 2;
209 try expect((lhs == rhs) == (no_nan and lhs_order == rhs_order));
210 try expect((lhs != rhs) == !(no_nan and lhs_order == rhs_order));
211 try expect((lhs < rhs) == (no_nan and lhs_order < rhs_order));
212 try expect((lhs > rhs) == (no_nan and lhs_order > rhs_order));
213 try expect((lhs <= rhs) == (no_nan and lhs_order <= rhs_order));
214 try expect((lhs >= rhs) == (no_nan and lhs_order >= rhs_order));
215 }
216 }
217}
218
219test "vector cmp f16" {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
224
225 try testCmpVector(f16);
226 try comptime testCmpVector(f16);
227}
228
229test "vector cmp f32" {
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
232 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
233 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
236 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
237 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
238 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
239
240 try testCmpVector(f32);
241 try comptime testCmpVector(f32);
242}
243
244test "vector cmp f64" {
245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
248 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
249 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
250 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
251
252 try testCmpVector(f64);
253 try comptime testCmpVector(f64);
254}
255
256test "vector cmp f128" {
257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
259 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
260 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
261 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
262 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
263
264 try testCmpVector(f128);
265 try comptime testCmpVector(f128);
266}
267
268test "vector cmp f80/c_longdouble" {
269 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
270 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
271 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
272 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
274
275 try testCmpVector(f80);
276 try comptime testCmpVector(f80);
277 try testCmpVector(c_longdouble);
278 try comptime testCmpVector(c_longdouble);
279}
280
281fn testCmpVector(comptime T: type) !void {
282 @setEvalBranchQuota(2_000);
283 var edges = [_]T{
284 -math.inf(T),
285 -math.floatMax(T),
286 -math.floatMin(T),
287 -math.floatTrueMin(T),
288 -0.0,
289 math.nan(T),
290 0.0,
291 math.floatTrueMin(T),
292 math.floatMin(T),
293 math.floatMax(T),
294 math.inf(T),
295 };
296 _ = &edges;
297 for (edges, 0..) |rhs, rhs_i| {
298 const rhs_v: @Vector(4, T) = .{ rhs, rhs, rhs, rhs };
299 for (edges, 0..) |lhs, lhs_i| {
300 const no_nan = lhs_i != 5 and rhs_i != 5;
301 const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;
302 const rhs_order = if (rhs_i < 5) rhs_i else rhs_i - 2;
303 const lhs_v: @Vector(4, T) = .{ lhs, lhs, lhs, lhs };
304 try expect(@reduce(.And, (lhs_v == rhs_v)) == (no_nan and lhs_order == rhs_order));
305 try expect(@reduce(.And, (lhs_v != rhs_v)) == !(no_nan and lhs_order == rhs_order));
306 try expect(@reduce(.And, (lhs_v < rhs_v)) == (no_nan and lhs_order < rhs_order));
307 try expect(@reduce(.And, (lhs_v > rhs_v)) == (no_nan and lhs_order > rhs_order));
308 try expect(@reduce(.And, (lhs_v <= rhs_v)) == (no_nan and lhs_order <= rhs_order));
309 try expect(@reduce(.And, (lhs_v >= rhs_v)) == (no_nan and lhs_order >= rhs_order));
310 }
311 }
312}
313
314test "different sized float comparisons" {
315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
318
319 try testDifferentSizedFloatComparisons();
320 try comptime testDifferentSizedFloatComparisons();
321}
322
323fn testDifferentSizedFloatComparisons() !void {
324 var a: f16 = 1;
325 var b: f64 = 2;
326 _ = .{ &a, &b };
327 try expect(a < b);
328}
329
330// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
331//test "@nearbyint" {
332// comptime testNearbyInt();
333// testNearbyInt();
334//}
335
336//fn testNearbyInt() void {
337// // TODO test f16, f128, and c_longdouble
338// // https://github.com/ziglang/zig/issues/4026
339// {
340// var a: f32 = 2.1;
341// try expect(@nearbyint(a) == 2);
342// }
343// {
344// var a: f64 = -3.75;
345// try expect(@nearbyint(a) == -4);
346// }
347//}
348
349test "negative f128 intFromFloat at compile-time" {
350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
353
354 const a: f128 = -2;
355 var b: i64 = @intFromFloat(a);
356 _ = &b;
357 try expect(@as(i64, -2) == b);
358}
359
360test "@sqrt f16" {
361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
363 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
365
366 try testSqrt(f16);
367 try comptime testSqrt(f16);
368}
369
370test "@sqrt f32/f64" {
371 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
373 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
374
375 try testSqrt(f32);
376 try comptime testSqrt(f32);
377 try testSqrt(f64);
378 try comptime testSqrt(f64);
379}
380
381test "@sqrt f80/f128/c_longdouble" {
382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
383 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
385 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
386 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
387
388 try testSqrt(f80);
389 try comptime testSqrt(f80);
390 try testSqrt(f128);
391 try comptime testSqrt(f128);
392 try testSqrt(c_longdouble);
393 try comptime testSqrt(c_longdouble);
394}
395
396fn testSqrt(comptime T: type) !void {
397 const eps = epsForType(T);
398 var four: T = 4.0;
399 try expect(@sqrt(four) == 2.0);
400 var nine: T = 9.0;
401 try expect(@sqrt(nine) == 3.0);
402 var twenty_five: T = 25.0;
403 try expect(@sqrt(twenty_five) == 5.0);
404 var sixty_four: T = 64.0;
405 try expect(@sqrt(sixty_four) == 8.0);
406 var one_point_one: T = 1.1;
407
408 try expect(math.approxEqAbs(T, @sqrt(one_point_one), 1.0488088481701516, eps));
409 var two: T = 2.0;
410 try expect(math.approxEqAbs(T, @sqrt(two), 1.4142135623730950, eps));
411 var three_point_six: T = 3.6;
412 try expect(math.approxEqAbs(T, @sqrt(three_point_six), 1.8973665961010276, eps));
413 var sixty_four_point_one: T = 64.1;
414 try expect(math.approxEqAbs(T, @sqrt(sixty_four_point_one), 8.00624756049923802, eps));
415 var twelve: T = 12.0;
416 try expect(math.approxEqAbs(T, @sqrt(twelve), 3.46410161513775459, eps));
417 var thirteen: T = 13.0;
418 try expect(math.approxEqAbs(T, @sqrt(thirteen), 3.60555127546398929, eps));
419 var fourteen: T = 14.0;
420 try expect(math.approxEqAbs(T, @sqrt(fourteen), 3.74165738677394139, eps));
421 var a: T = 7.539840;
422 try expect(math.approxEqAbs(T, @sqrt(a), 2.74587690911300684, eps));
423 var b: T = 19.230934;
424 try expect(math.approxEqAbs(T, @sqrt(b), 4.38530888307767894, eps));
425 var c: T = 8942.230469;
426 try expect(math.approxEqAbs(T, @sqrt(c), 94.5633674791671111, eps));
427
428 // special cases
429 var inf: T = math.inf(T);
430 try expect(math.isPositiveInf(@sqrt(inf)));
431 var zero: T = 0.0;
432 try expect(math.isPositiveZero(@sqrt(zero)));
433 var neg_zero: T = -0.0;
434 try expect(math.isNegativeZero(@sqrt(neg_zero)));
435 var neg_one: T = -1.0;
436 try expect(math.isNan(@sqrt(neg_one)));
437 var nan: T = math.nan(T);
438 try expect(math.isNan(@sqrt(nan)));
439
440 _ = .{
441 &four,
442 &nine,
443 &twenty_five,
444 &sixty_four,
445 &one_point_one,
446 &two,
447 &three_point_six,
448 &sixty_four_point_one,
449 &twelve,
450 &thirteen,
451 &fourteen,
452 &a,
453 &b,
454 &c,
455 &inf,
456 &zero,
457 &neg_zero,
458 &neg_one,
459 &nan,
460 };
461}
462
463test "@sqrt with vectors" {
464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
467 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
468
469 try testSqrtWithVectors();
470 try comptime testSqrtWithVectors();
471}
472
473fn testSqrtWithVectors() !void {
474 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
475 _ = &v;
476 const result = @sqrt(v);
477 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
478 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
479 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
480 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
481}
482
483test "@sin f16" {
484 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
486 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
487 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
488
489 try testSin(f16);
490 try comptime testSin(f16);
491}
492
493test "@sin f32/f64" {
494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
497 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
498
499 try testSin(f32);
500 comptime try testSin(f32);
501 try testSin(f64);
502 comptime try testSin(f64);
503}
504
505test "@sin f80/f128/c_longdouble" {
506 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
509 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
510
511 try testSin(f80);
512 comptime try testSin(f80);
513 try testSin(f128);
514 comptime try testSin(f128);
515 try testSin(c_longdouble);
516 comptime try testSin(c_longdouble);
517}
518
519fn testSin(comptime T: type) !void {
520 const eps = epsForType(T);
521 var zero: T = 0;
522 _ = &zero;
523 try expect(@sin(zero) == 0);
524 var pi: T = math.pi;
525 _ = &pi;
526 try expect(math.approxEqAbs(T, @sin(pi), 0, eps));
527 try expect(math.approxEqAbs(T, @sin(pi / 2.0), 1, eps));
528 try expect(math.approxEqAbs(T, @sin(pi / 4.0), 0.7071067811865475, eps));
529}
530
531test "@sin with vectors" {
532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
535 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
536
537 try testSinWithVectors();
538 try comptime testSinWithVectors();
539}
540
541fn testSinWithVectors() !void {
542 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
543 _ = &v;
544 const result = @sin(v);
545 try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
546 try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
547 try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
548 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
549}
550
551test "@cos f16" {
552 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
554 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
555 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
556
557 try testCos(f16);
558 try comptime testCos(f16);
559}
560
561test "@cos f32/f64" {
562 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
563 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
564 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
565 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
566
567 try testCos(f32);
568 try comptime testCos(f32);
569 try testCos(f64);
570 try comptime testCos(f64);
571}
572
573test "@cos f80/f128/c_longdouble" {
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
577 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
578
579 try testCos(f80);
580 try comptime testCos(f80);
581 try testCos(f128);
582 try comptime testCos(f128);
583 try testCos(c_longdouble);
584 try comptime testCos(c_longdouble);
585}
586
587fn testCos(comptime T: type) !void {
588 const eps = epsForType(T);
589 var zero: T = 0;
590 _ = &zero;
591 try expect(@cos(zero) == 1);
592 var pi: T = math.pi;
593 _ = &pi;
594 try expect(math.approxEqAbs(T, @cos(pi), -1, eps));
595 try expect(math.approxEqAbs(T, @cos(pi / 2.0), 0, eps));
596 try expect(math.approxEqAbs(T, @cos(pi / 4.0), 0.7071067811865475, eps));
597}
598
599test "@cos with vectors" {
600 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
601 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
602 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
603 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
604
605 try testCosWithVectors();
606 try comptime testCosWithVectors();
607}
608
609fn testCosWithVectors() !void {
610 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
611 _ = &v;
612 const result = @cos(v);
613 try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
614 try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
615 try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
616 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
617}
618
619test "@tan f16" {
620 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
621 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
622 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
623 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
624
625 try testTan(f16);
626 try comptime testTan(f16);
627}
628
629test "@tan f32/f64" {
630 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
632 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
633 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
634
635 try testTan(f32);
636 try comptime testTan(f32);
637 try testTan(f64);
638 try comptime testTan(f64);
639}
640
641test "@tan f80/f128/c_longdouble" {
642 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
643 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
644 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
645 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
646
647 try testTan(f80);
648 try comptime testTan(f80);
649 try testTan(f128);
650 try comptime testTan(f128);
651 try testTan(c_longdouble);
652 try comptime testTan(c_longdouble);
653}
654
655fn testTan(comptime T: type) !void {
656 const eps = epsForType(T);
657 var zero: T = 0;
658 _ = &zero;
659 try expect(@tan(zero) == 0);
660 var pi: T = math.pi;
661 _ = &pi;
662 try expect(math.approxEqAbs(T, @tan(pi), 0, eps));
663 try expect(math.approxEqAbs(T, @tan(pi / 3.0), 1.732050807568878, eps));
664 try expect(math.approxEqAbs(T, @tan(pi / 4.0), 1, eps));
665}
666
667test "@tan with vectors" {
668 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
669 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
670 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
671 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
672
673 try testTanWithVectors();
674 try comptime testTanWithVectors();
675}
676
677fn testTanWithVectors() !void {
678 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
679 _ = &v;
680 const result = @tan(v);
681 try expect(math.approxEqAbs(f32, @tan(@as(f32, 1.1)), result[0], epsilon));
682 try expect(math.approxEqAbs(f32, @tan(@as(f32, 2.2)), result[1], epsilon));
683 try expect(math.approxEqAbs(f32, @tan(@as(f32, 3.3)), result[2], epsilon));
684 try expect(math.approxEqAbs(f32, @tan(@as(f32, 4.4)), result[3], epsilon));
685}
686
687test "@exp f16" {
688 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
690 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
691 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
692
693 try testExp(f16);
694 try comptime testExp(f16);
695}
696
697test "@exp f32/f64" {
698 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
700 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
701 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
702
703 try testExp(f32);
704 try comptime testExp(f32);
705 try testExp(f64);
706 try comptime testExp(f64);
707}
708
709test "@exp f80/f128/c_longdouble" {
710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
713 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
714
715 try testExp(f80);
716 try comptime testExp(f80);
717 try testExp(f128);
718 try comptime testExp(f128);
719 try testExp(c_longdouble);
720 try comptime testExp(c_longdouble);
721}
722
723fn testExp(comptime T: type) !void {
724 const eps = epsForType(T);
725
726 var zero: T = 0;
727 _ = &zero;
728 try expect(@exp(zero) == 1);
729
730 var two: T = 2;
731 _ = &two;
732 try expect(math.approxEqAbs(T, @exp(two), 7.389056098930650, eps));
733
734 var five: T = 5;
735 _ = &five;
736 try expect(math.approxEqAbs(T, @exp(five), 148.4131591025766, eps));
737}
738
739test "@exp with vectors" {
740 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
741 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
742 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
743 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
744
745 try testExpWithVectors();
746 try comptime testExpWithVectors();
747}
748
749fn testExpWithVectors() !void {
750 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
751 _ = &v;
752 const result = @exp(v);
753 try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
754 try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
755 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
756 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
757}
758
759test "@exp2 f16" {
760 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
761 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
762 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
763 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
764
765 try testExp2(f16);
766 try comptime testExp2(f16);
767}
768
769test "@exp2 f32/f64" {
770 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
771 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
772 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
773 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
774
775 try testExp2(f32);
776 try comptime testExp2(f32);
777 try testExp2(f64);
778 try comptime testExp2(f64);
779}
780
781test "@exp2 f80/f128/c_longdouble" {
782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
784 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
785 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
786
787 try testExp2(f80);
788 try comptime testExp2(f80);
789 try testExp2(f128);
790 try comptime testExp2(f128);
791 try testExp2(c_longdouble);
792 try comptime testExp2(c_longdouble);
793}
794
795fn testExp2(comptime T: type) !void {
796 const eps = epsForType(T);
797 var two: T = 2;
798 try expect(@exp2(two) == 4);
799 var one_point_five: T = 1.5;
800 try expect(math.approxEqAbs(T, @exp2(one_point_five), 2.8284271247462, eps));
801 var four_point_five: T = 4.5;
802 try expect(math.approxEqAbs(T, @exp2(four_point_five), 22.627416997969, eps));
803 _ = .{ &two, &one_point_five, &four_point_five };
804}
805
806test "@exp2 with @vectors" {
807 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
808 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
809 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
810 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
811
812 try testExp2WithVectors();
813 try comptime testExp2WithVectors();
814}
815
816fn testExp2WithVectors() !void {
817 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
818 _ = &v;
819 const result = @exp2(v);
820 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
821 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
822 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
823 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
824}
825
826test "@log f16" {
827 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
828 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
829 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
830 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
831
832 try testLog(f16);
833 try comptime testLog(f16);
834}
835
836test "@log f32/f64" {
837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
838 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
839 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
840 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
841
842 try testLog(f32);
843 try comptime testLog(f32);
844 try testLog(f64);
845 try comptime testLog(f64);
846}
847
848test "@log f80/f128/c_longdouble" {
849 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
850 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
851 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
853
854 try testLog(f80);
855 try comptime testLog(f80);
856 try testLog(f128);
857 try comptime testLog(f128);
858 try testLog(c_longdouble);
859 try comptime testLog(c_longdouble);
860}
861
862fn testLog(comptime T: type) !void {
863 const eps = epsForType(T);
864 var e: T = math.e;
865 try expect(math.approxEqAbs(T, @log(e), 1, eps));
866 var two: T = 2;
867 try expect(math.approxEqAbs(T, @log(two), 0.6931471805599, eps));
868 var five: T = 5;
869 try expect(math.approxEqAbs(T, @log(five), 1.6094379124341, eps));
870 _ = .{ &e, &two, &five };
871}
872
873test "@log with @vectors" {
874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
877 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
878 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
879
880 {
881 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
882 _ = &v;
883 const result = @log(v);
884 try expect(@log(@as(f32, 1.1)) == result[0]);
885 try expect(@log(@as(f32, 2.2)) == result[1]);
886 try expect(@log(@as(f32, 0.3)) == result[2]);
887 try expect(@log(@as(f32, 0.4)) == result[3]);
888 }
889}
890
891test "@log2 f16" {
892 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
893 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
894 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
895 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
896
897 try testLog2(f16);
898 try comptime testLog2(f16);
899}
900
901test "@log2 f32/f64" {
902 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
903 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
904 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
905 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
906
907 try testLog2(f32);
908 try comptime testLog2(f32);
909 try testLog2(f64);
910 try comptime testLog2(f64);
911}
912
913test "@log2 f80/f128/c_longdouble" {
914 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
915 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
916 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
917 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
918
919 try testLog2(f80);
920 try comptime testLog2(f80);
921 try testLog2(f128);
922 try comptime testLog2(f128);
923 try testLog2(c_longdouble);
924 try comptime testLog2(c_longdouble);
925}
926
927fn testLog2(comptime T: type) !void {
928 const eps = epsForType(T);
929 var four: T = 4;
930 try expect(@log2(four) == 2);
931 var six: T = 6;
932 try expect(math.approxEqAbs(T, @log2(six), 2.5849625007212, eps));
933 var ten: T = 10;
934 try expect(math.approxEqAbs(T, @log2(ten), 3.3219280948874, eps));
935 _ = .{ &four, &six, &ten };
936}
937
938test "@log2 with vectors" {
939 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
940 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
941 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
942 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
943 // https://github.com/ziglang/zig/issues/13681
944 if (builtin.zig_backend == .stage2_llvm and
945 builtin.cpu.arch == .aarch64 and
946 builtin.os.tag == .windows) return error.SkipZigTest;
947
948 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) {
949 // https://codeberg.org/ziglang/zig/issues/35518
950 return error.SkipZigTest;
951 }
952
953 try testLog2WithVectors();
954 try comptime testLog2WithVectors();
955}
956
957fn testLog2WithVectors() !void {
958 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
959 _ = &v;
960 const result = @log2(v);
961 try expect(@log2(@as(f32, 1.1)) == result[0]);
962 try expect(@log2(@as(f32, 2.2)) == result[1]);
963 try expect(@log2(@as(f32, 0.3)) == result[2]);
964 try expect(@log2(@as(f32, 0.4)) == result[3]);
965}
966
967test "@log10 f16" {
968 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
970 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
971 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
972
973 try testLog10(f16);
974 try comptime testLog10(f16);
975}
976
977test "@log10 f32/f64" {
978 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
979 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
980 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
981 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
982
983 try testLog10(f32);
984 try comptime testLog10(f32);
985 try testLog10(f64);
986 try comptime testLog10(f64);
987}
988
989test "@log10 f80/f128/c_longdouble" {
990 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
992 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
993 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
994
995 try testLog10(f80);
996 try comptime testLog10(f80);
997 try testLog10(f128);
998 try comptime testLog10(f128);
999 try testLog10(c_longdouble);
1000 try comptime testLog10(c_longdouble);
1001}
1002
1003fn testLog10(comptime T: type) !void {
1004 const eps = epsForType(T);
1005 var hundred: T = 100;
1006 try expect(@log10(hundred) == 2);
1007 var fifteen: T = 15;
1008 try expect(math.approxEqAbs(T, @log10(fifteen), 1.176091259056, eps));
1009 var fifty: T = 50;
1010 try expect(math.approxEqAbs(T, @log10(fifty), 1.698970004336, eps));
1011 _ = .{ &hundred, &fifteen, &fifty };
1012}
1013
1014test "@log10 with vectors" {
1015 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1016 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1017 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1019
1020 try testLog10WithVectors();
1021 try comptime testLog10WithVectors();
1022}
1023
1024fn testLog10WithVectors() !void {
1025 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
1026 _ = &v;
1027 const result = @log10(v);
1028 try expect(@log10(@as(f32, 1.1)) == result[0]);
1029 try expect(@log10(@as(f32, 2.2)) == result[1]);
1030 try expect(@log10(@as(f32, 0.3)) == result[2]);
1031 try expect(@log10(@as(f32, 0.4)) == result[3]);
1032}
1033
1034test "@abs f16" {
1035 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1036 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1038
1039 try testFabs(f16);
1040 try comptime testFabs(f16);
1041}
1042
1043test "@abs f32/f64" {
1044 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1045 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1046
1047 try testFabs(f32);
1048 try comptime testFabs(f32);
1049 try testFabs(f64);
1050 try comptime testFabs(f64);
1051}
1052
1053test "@abs f80/f128/c_longdouble" {
1054 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1055 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1056 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1057 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1058
1059 try testFabs(f80);
1060 try comptime testFabs(f80);
1061 try testFabs(f128);
1062 try comptime testFabs(f128);
1063 try testFabs(c_longdouble);
1064 try comptime testFabs(c_longdouble);
1065}
1066
1067fn testFabs(comptime T: type) !void {
1068 var two_point_five: T = 2.5;
1069 try expect(@abs(two_point_five) == 2.5);
1070 var neg_two_point_five: T = -2.5;
1071 try expect(@abs(neg_two_point_five) == 2.5);
1072
1073 var twelve: T = 12.0;
1074 try expect(@abs(twelve) == 12.0);
1075 var neg_fourteen: T = -14.0;
1076 try expect(@abs(neg_fourteen) == 14.0);
1077
1078 // normals
1079 var one: T = 1.0;
1080 try expect(@abs(one) == 1.0);
1081 var neg_one: T = -1.0;
1082 try expect(@abs(neg_one) == 1.0);
1083 var min: T = math.floatMin(T);
1084 try expect(@abs(min) == math.floatMin(T));
1085 var neg_min: T = -math.floatMin(T);
1086 try expect(@abs(neg_min) == math.floatMin(T));
1087 var max: T = math.floatMax(T);
1088 try expect(@abs(max) == math.floatMax(T));
1089 var neg_max: T = -math.floatMax(T);
1090 try expect(@abs(neg_max) == math.floatMax(T));
1091
1092 // subnormals
1093 var zero: T = 0.0;
1094 try expect(@abs(zero) == 0.0);
1095 var neg_zero: T = -0.0;
1096 try expect(@abs(neg_zero) == 0.0);
1097 var true_min: T = math.floatTrueMin(T);
1098 try expect(@abs(true_min) == math.floatTrueMin(T));
1099 var neg_true_min: T = -math.floatTrueMin(T);
1100 try expect(@abs(neg_true_min) == math.floatTrueMin(T));
1101
1102 // non-finite numbers
1103 var inf: T = math.inf(T);
1104 try expect(math.isPositiveInf(@abs(inf)));
1105 var neg_inf: T = -math.inf(T);
1106 try expect(math.isPositiveInf(@abs(neg_inf)));
1107 var nan: T = math.nan(T);
1108 try expect(math.isNan(@abs(nan)));
1109
1110 _ = .{
1111 &two_point_five,
1112 &neg_two_point_five,
1113 &twelve,
1114 &neg_fourteen,
1115 &one,
1116 &neg_one,
1117 &min,
1118 &neg_min,
1119 &max,
1120 &neg_max,
1121 &zero,
1122 &neg_zero,
1123 &true_min,
1124 &neg_true_min,
1125 &inf,
1126 &neg_inf,
1127 &nan,
1128 };
1129}
1130
1131test "@abs with vectors" {
1132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1134 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1135
1136 try testFabsWithVectors();
1137 try comptime testFabsWithVectors();
1138}
1139
1140fn testFabsWithVectors() !void {
1141 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
1142 _ = &v;
1143 const result = @abs(v);
1144 try expect(math.approxEqAbs(f32, @abs(@as(f32, 1.1)), result[0], epsilon));
1145 try expect(math.approxEqAbs(f32, @abs(@as(f32, -2.2)), result[1], epsilon));
1146 try expect(math.approxEqAbs(f32, @abs(@as(f32, 0.3)), result[2], epsilon));
1147 try expect(math.approxEqAbs(f32, @abs(@as(f32, -0.4)), result[3], epsilon));
1148}
1149
1150test "@floor f16" {
1151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1152 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1154
1155 try testFloor(f16);
1156 try comptime testFloor(f16);
1157}
1158
1159test "@floor f32/f64" {
1160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1163
1164 try testFloor(f32);
1165 try comptime testFloor(f32);
1166 try testFloor(f64);
1167 try comptime testFloor(f64);
1168}
1169
1170test "@floor f80/f128/c_longdouble" {
1171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1174 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1175
1176 try testFloor(f80);
1177 try comptime testFloor(f80);
1178 try testFloor(f128);
1179 try comptime testFloor(f128);
1180 try testFloor(c_longdouble);
1181 try comptime testFloor(c_longdouble);
1182}
1183
1184fn testFloor(comptime T: type) !void {
1185 var two_point_one: T = 2.1;
1186 try expect(@floor(two_point_one) == 2.0);
1187 var neg_two_point_one: T = -2.1;
1188 try expect(@floor(neg_two_point_one) == -3.0);
1189 var three_point_five: T = 3.5;
1190 try expect(@floor(three_point_five) == 3.0);
1191 var neg_three_point_five: T = -3.5;
1192 try expect(@floor(neg_three_point_five) == -4.0);
1193 var twelve: T = 12.0;
1194 try expect(@floor(twelve) == 12.0);
1195 var neg_twelve: T = -12.0;
1196 try expect(@floor(neg_twelve) == -12.0);
1197 var fourteen_point_seven: T = 14.7;
1198 try expect(@floor(fourteen_point_seven) == 14.0);
1199 var neg_fourteen_point_seven: T = -14.7;
1200 try expect(@floor(neg_fourteen_point_seven) == -15.0);
1201
1202 _ = .{
1203 &two_point_one,
1204 &neg_two_point_one,
1205 &three_point_five,
1206 &neg_three_point_five,
1207 &twelve,
1208 &neg_twelve,
1209 &fourteen_point_seven,
1210 &neg_fourteen_point_seven,
1211 };
1212}
1213
1214test "@floor with vectors" {
1215 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1217 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1218
1219 try testFloorWithVectors();
1220 try comptime testFloorWithVectors();
1221}
1222
1223fn testFloorWithVectors() !void {
1224 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
1225 _ = &v;
1226 const result = @floor(v);
1227 try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
1228 try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
1229 try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
1230 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
1231}
1232
1233test "@ceil f16" {
1234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1236 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1237
1238 try testCeil(f16);
1239 try comptime testCeil(f16);
1240}
1241
1242test "@ceil f32/f64" {
1243 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1244 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1245 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1246
1247 try testCeil(f32);
1248 try comptime testCeil(f32);
1249 try testCeil(f64);
1250 try comptime testCeil(f64);
1251}
1252
1253test "@ceil f80/f128/c_longdouble" {
1254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1256 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1257 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1258
1259 try testCeil(f80);
1260 try comptime testCeil(f80);
1261 try testCeil(f128);
1262 try comptime testCeil(f128);
1263 try testCeil(c_longdouble);
1264 try comptime testCeil(c_longdouble);
1265}
1266
1267test "@ceil f80 maxInt(u64)" {
1268 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1269 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1270 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1271 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1272
1273 var x: u64 = std.math.maxInt(u64);
1274 x = x;
1275 const float: f80 = @floatFromInt(x);
1276 try std.testing.expect(float == @ceil(float));
1277}
1278
1279fn testCeil(comptime T: type) !void {
1280 var two_point_one: T = 2.1;
1281 try expect(@ceil(two_point_one) == 3.0);
1282 var neg_two_point_one: T = -2.1;
1283 try expect(@ceil(neg_two_point_one) == -2.0);
1284 var three_point_five: T = 3.5;
1285 try expect(@ceil(three_point_five) == 4.0);
1286 var neg_three_point_five: T = -3.5;
1287 try expect(@ceil(neg_three_point_five) == -3.0);
1288 var twelve: T = 12.0;
1289 try expect(@ceil(twelve) == 12.0);
1290 var neg_twelve: T = -12.0;
1291 try expect(@ceil(neg_twelve) == -12.0);
1292 var fourteen_point_seven: T = 14.7;
1293 try expect(@ceil(fourteen_point_seven) == 15.0);
1294 var neg_fourteen_point_seven: T = -14.7;
1295 try expect(@ceil(neg_fourteen_point_seven) == -14.0);
1296
1297 _ = .{
1298 &two_point_one,
1299 &neg_two_point_one,
1300 &three_point_five,
1301 &neg_three_point_five,
1302 &twelve,
1303 &neg_twelve,
1304 &fourteen_point_seven,
1305 &neg_fourteen_point_seven,
1306 };
1307}
1308
1309test "@ceil with vectors" {
1310 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1311 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1312 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1313
1314 try testCeilWithVectors();
1315 try comptime testCeilWithVectors();
1316}
1317
1318fn testCeilWithVectors() !void {
1319 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
1320 _ = &v;
1321 const result = @ceil(v);
1322 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
1323 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
1324 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
1325 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
1326}
1327
1328test "@trunc f16" {
1329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1330 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1331 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1332
1333 try testTrunc(f16);
1334 try comptime testTrunc(f16);
1335}
1336
1337test "@trunc f32/f64" {
1338 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1339 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1340 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1341
1342 try testTrunc(f32);
1343 try comptime testTrunc(f32);
1344 try testTrunc(f64);
1345 try comptime testTrunc(f64);
1346}
1347
1348test "@trunc f80/f128/c_longdouble" {
1349 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1350 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1351 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1352 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1353
1354 try testTrunc(f80);
1355 try comptime testTrunc(f80);
1356 try testTrunc(f128);
1357 try comptime testTrunc(f128);
1358 try testTrunc(c_longdouble);
1359 try comptime testTrunc(c_longdouble);
1360}
1361
1362fn testTrunc(comptime T: type) !void {
1363 var two_point_one: T = 2.1;
1364 try expect(@trunc(two_point_one) == 2.0);
1365 var neg_two_point_one: T = -2.1;
1366 try expect(@trunc(neg_two_point_one) == -2.0);
1367 var three_point_five: T = 3.5;
1368 try expect(@trunc(three_point_five) == 3.0);
1369 var neg_three_point_five: T = -3.5;
1370 try expect(@trunc(neg_three_point_five) == -3.0);
1371 var twelve: T = 12.0;
1372 try expect(@trunc(twelve) == 12.0);
1373 var neg_twelve: T = -12.0;
1374 try expect(@trunc(neg_twelve) == -12.0);
1375 var fourteen_point_seven: T = 14.7;
1376 try expect(@trunc(fourteen_point_seven) == 14.0);
1377 var neg_fourteen_point_seven: T = -14.7;
1378 try expect(@trunc(neg_fourteen_point_seven) == -14.0);
1379
1380 _ = .{
1381 &two_point_one,
1382 &neg_two_point_one,
1383 &three_point_five,
1384 &neg_three_point_five,
1385 &twelve,
1386 &neg_twelve,
1387 &fourteen_point_seven,
1388 &neg_fourteen_point_seven,
1389 };
1390}
1391
1392test "@trunc with vectors" {
1393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1394 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1395 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1396
1397 try testTruncWithVectors();
1398 try comptime testTruncWithVectors();
1399}
1400
1401fn testTruncWithVectors() !void {
1402 var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
1403 _ = &v;
1404 const result = @trunc(v);
1405 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
1406 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
1407 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
1408 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
1409}
1410
1411test "neg f16" {
1412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1413 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1415
1416 try testNeg(f16);
1417 try comptime testNeg(f16);
1418}
1419
1420test "neg f32/f64" {
1421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1422 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1423 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1424
1425 try testNeg(f32);
1426 try comptime testNeg(f32);
1427 try testNeg(f64);
1428 try comptime testNeg(f64);
1429}
1430
1431test "neg f80/f128/c_longdouble" {
1432 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1433 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1434 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1435 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1436
1437 try testNeg(f80);
1438 try comptime testNeg(f80);
1439 try testNeg(f128);
1440 try comptime testNeg(f128);
1441 try testNeg(c_longdouble);
1442 try comptime testNeg(c_longdouble);
1443}
1444
1445fn testNeg(comptime T: type) !void {
1446 var two_point_five: T = 2.5;
1447 try expect(-two_point_five == -2.5);
1448 var neg_two_point_five: T = -2.5;
1449 try expect(-neg_two_point_five == 2.5);
1450
1451 var twelve: T = 12.0;
1452 try expect(-twelve == -12.0);
1453 var neg_fourteen: T = -14.0;
1454 try expect(-neg_fourteen == 14.0);
1455
1456 // normals
1457 var one: T = 1.0;
1458 try expect(-one == -1.0);
1459 var neg_one: T = -1.0;
1460 try expect(-neg_one == 1.0);
1461 var min: T = math.floatMin(T);
1462 try expect(-min == -math.floatMin(T));
1463 var neg_min: T = -math.floatMin(T);
1464 try expect(-neg_min == math.floatMin(T));
1465 var max: T = math.floatMax(T);
1466 try expect(-max == -math.floatMax(T));
1467 var neg_max: T = -math.floatMax(T);
1468 try expect(-neg_max == math.floatMax(T));
1469
1470 // subnormals
1471 var zero: T = 0.0;
1472 try expect(math.isNegativeZero(-zero));
1473 var neg_zero: T = -0.0;
1474 try expect(math.isPositiveZero(-neg_zero));
1475 var true_min: T = math.floatTrueMin(T);
1476 try expect(-true_min == -math.floatTrueMin(T));
1477 var neg_true_min: T = -math.floatTrueMin(T);
1478 try expect(-neg_true_min == math.floatTrueMin(T));
1479
1480 // non-finite numbers
1481 var inf: T = math.inf(T);
1482 try expect(math.isNegativeInf(-inf));
1483 var neg_inf: T = -math.inf(T);
1484 try expect(math.isPositiveInf(-neg_inf));
1485 var nan: T = math.nan(T);
1486 try expect(math.isNan(-nan));
1487 try expect(math.signbit(-nan));
1488 var neg_nan: T = -math.nan(T);
1489 try expect(math.isNan(-neg_nan));
1490 try expect(!math.signbit(-neg_nan));
1491
1492 _ = .{
1493 &two_point_five,
1494 &neg_two_point_five,
1495 &twelve,
1496 &neg_fourteen,
1497 &one,
1498 &neg_one,
1499 &min,
1500 &neg_min,
1501 &max,
1502 &neg_max,
1503 &zero,
1504 &neg_zero,
1505 &true_min,
1506 &neg_true_min,
1507 &inf,
1508 &neg_inf,
1509 &nan,
1510 &neg_nan,
1511 };
1512}
1513
1514test "negate f80" {
1515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1516
1517 var f: f80 = 0.0;
1518 const a: u80 = @bitCast(f);
1519 try expect(a == 0);
1520 f = -f;
1521 const b: u80 = @bitCast(f);
1522 try expect(b == 0x8000_00000000_00000000);
1523}
1524
1525test "eval @setFloatMode at compile-time" {
1526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1527
1528 const result = comptime fnWithFloatMode();
1529 try expect(result == 1234.0);
1530}
1531
1532fn fnWithFloatMode() f32 {
1533 @setFloatMode(std.builtin.FloatMode.strict);
1534 return 1234.0;
1535}
1536
1537test "float literal at compile time not lossy" {
1538 try expect(16777216.0 + 1.0 == 16777217.0);
1539 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
1540}
1541
1542test "f128 at compile time is lossy" {
1543 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
1544}
1545
1546test "comptime fixed-width float zero divided by zero produces NaN" {
1547 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1548 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1549 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1550 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1551
1552 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
1553 try expect(math.isNan(@as(F, 0) / @as(F, 0)));
1554 }
1555}
1556
1557test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
1558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1559 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1560 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1561
1562 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
1563 const pos = @as(F, 1) / @as(F, 0);
1564 const neg = @as(F, -1) / @as(F, 0);
1565 try expect(math.isInf(pos));
1566 try expect(math.isInf(neg));
1567 try expect(pos > 0);
1568 try expect(neg < 0);
1569 }
1570}
1571
1572test "comptime float compared with runtime int" {
1573 const f = 10.0;
1574 var i: usize = 0;
1575 _ = &i;
1576 try std.testing.expect(i < f);
1577}
1578test "comptime nan < runtime 0" {
1579 const f = comptime std.math.nan(f64);
1580 var i: usize = 0;
1581 _ = &i;
1582 try std.testing.expect(!(f < i));
1583}
1584test "comptime inf > runtime 0" {
1585 const f = comptime std.math.inf(f64);
1586 var i: usize = 0;
1587 _ = &i;
1588 try std.testing.expect(f > i);
1589}
1590test "comptime -inf < runtime 0" {
1591 const f = comptime -std.math.inf(f64);
1592 var i: usize = 0;
1593 _ = &i;
1594 try std.testing.expect(f < i);
1595}
1596test "comptime inf >= runtime 1" {
1597 const f = comptime std.math.inf(f64);
1598 var i: usize = 1;
1599 _ = &i;
1600 try std.testing.expect(f >= i);
1601}
1602test "comptime isNan(nan * 1)" {
1603 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1604
1605 const nan_times_one = comptime std.math.nan(f64) * 1;
1606 try std.testing.expect(std.math.isNan(nan_times_one));
1607}
1608test "runtime isNan(nan * 1)" {
1609 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1610
1611 const nan_times_one = std.math.nan(f64) * 1;
1612 try std.testing.expect(std.math.isNan(nan_times_one));
1613}
1614test "comptime isNan(nan * 0)" {
1615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1616
1617 const nan_times_zero = comptime std.math.nan(f64) * 0;
1618 try std.testing.expect(std.math.isNan(nan_times_zero));
1619 const zero_times_nan = 0 * comptime std.math.nan(f64);
1620 try std.testing.expect(std.math.isNan(zero_times_nan));
1621}
1622test "runtime isNan(nan * 0)" {
1623 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1624
1625 const nan_times_zero = std.math.nan(f64) * 0;
1626 try std.testing.expect(std.math.isNan(nan_times_zero));
1627 const zero_times_nan = 0 * std.math.nan(f64);
1628 try std.testing.expect(std.math.isNan(zero_times_nan));
1629}
1630test "comptime isNan(inf * 0)" {
1631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1632
1633 const inf_times_zero = comptime std.math.inf(f64) * 0;
1634 try std.testing.expect(std.math.isNan(inf_times_zero));
1635 const zero_times_inf = 0 * comptime std.math.inf(f64);
1636 try std.testing.expect(std.math.isNan(zero_times_inf));
1637}
1638test "runtime isNan(inf * 0)" {
1639 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1640
1641 const inf_times_zero = std.math.inf(f64) * 0;
1642 try std.testing.expect(std.math.isNan(inf_times_zero));
1643 const zero_times_inf = 0 * std.math.inf(f64);
1644 try std.testing.expect(std.math.isNan(zero_times_inf));
1645}
1646
1647test "optimized float mode" {
1648 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
1649 if (builtin.mode == .debug) return error.SkipZigTest;
1650
1651 const big = 0x1p40;
1652 const small = 0.001;
1653 const tiny = 0x1p-10;
1654
1655 const S = struct {
1656 fn strict(x: f64) f64 {
1657 @setFloatMode(.strict);
1658 return x + big - big;
1659 }
1660 fn optimized(x: f64) f64 {
1661 @setFloatMode(.optimized);
1662 return x + big - big;
1663 }
1664 };
1665 try expect(S.optimized(small) == small);
1666 try expect(S.strict(small) == tiny);
1667}
1668
1669fn MakeType(comptime x: anytype) type {
1670 return struct {
1671 fn get() @TypeOf(x) {
1672 return x;
1673 }
1674 };
1675}
1676
1677const nan_a: f32 = @bitCast(@as(u32, 0xffc00000));
1678const nan_b: f32 = @bitCast(@as(u32, 0xffe00000));
1679
1680fn testMemoization() !void {
1681 try expect(MakeType(nan_a) == MakeType(nan_a));
1682 try expect(MakeType(nan_b) == MakeType(nan_b));
1683 try expect(MakeType(nan_a) != MakeType(nan_b));
1684}
1685
1686fn testVectorMemoization(comptime T: type) !void {
1687 const nan_a_v: T = @splat(nan_a);
1688 const nan_b_v: T = @splat(nan_b);
1689 try expect(MakeType(nan_a_v) == MakeType(nan_a_v));
1690 try expect(MakeType(nan_b_v) == MakeType(nan_b_v));
1691 try expect(MakeType(nan_a_v) != MakeType(nan_b_v));
1692}
1693
1694test "comptime calls are only memoized when float arguments are bit-for-bit equal" {
1695 try comptime testMemoization();
1696 try comptime testVectorMemoization(@Vector(4, f32));
1697}
1698
1699test "result location forwarded through unary float builtins" {
1700 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1701 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1702 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1703
1704 const S = struct {
1705 var x: u32 = 10;
1706 };
1707
1708 var y: f64 = 0.0;
1709 y = @sqrt(@floatFromInt(S.x));
1710 y = @sin(@floatFromInt(S.x));
1711 y = @cos(@floatFromInt(S.x));
1712 y = @tan(@floatFromInt(S.x));
1713 y = @exp(@floatFromInt(S.x));
1714 y = @exp2(@floatFromInt(S.x));
1715 y = @log(@floatFromInt(S.x));
1716 y = @log2(@floatFromInt(S.x));
1717 y = @log10(@floatFromInt(S.x));
1718 y = @floor(@floatFromInt(S.x));
1719 y = @ceil(@floatFromInt(S.x));
1720 y = @trunc(@floatFromInt(S.x));
1721 y = @round(@floatFromInt(S.x));
1722}