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