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