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    _ = &pi;
 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    _ = &pi;
 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    _ = &pi;
 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}