authorgravatar for lewis.gaul@gmail.comLewis Gaul <lewis.gaul@gmail.com> 2024-05-25 21:54:05+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-17 05:04:59+02:00
log9da19e51ea1da7cf6746dbdf8340248a77ce362f
treea8131709b907372c81bcd3e060dd1402d934ae73
parent680358767e30ac386e6727ffc9295820c598d6b9

Add tests for exp2(), with bugfix for 64-bit boundary case


1 files changed, 68 insertions(+), 23 deletions(-)

lib/compiler_rt/exp2.zig+68-23
......@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
1010const math = std.math;
1111const mem = std.mem;
1212const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
1314const common = @import("common.zig");
1415
1516pub const panic = common.panic;
......@@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
5859 if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x);
5960 }
6061 // x <= -150
61 if (u >= 0x3160000) {
62 if (u >= 0xC3160000) {
6263 return 0;
6364 }
6465 }
......@@ -457,34 +458,78 @@ const exp2dt = [_]f64{
457458 0x1.690f4b19e9471p+0, -0x1.9780p-45,
458459};
459460
460test "exp2_32" {
461 const epsilon = 0.000001;
461test "exp2f() special" {
462 try expectEqual(exp2f(0.0), 1.0);
463 try expectEqual(exp2f(-0.0), 1.0);
464 try expectEqual(exp2f(1.0), 2.0);
465 try expectEqual(exp2f(-1.0), 0.5);
466 try expectEqual(exp2f(math.inf(f32)), math.inf(f32));
467 try expectEqual(exp2f(-math.inf(f32)), 0.0);
468 try expect(math.isNan(exp2f(math.nan(f32))));
469 try expect(math.isNan(exp2f(math.snan(f32))));
470}
462471
463 try expect(exp2f(0.0) == 1.0);
464 try expect(math.approxEqAbs(f32, exp2f(0.2), 1.148698, epsilon));
465 try expect(math.approxEqAbs(f32, exp2f(0.8923), 1.856133, epsilon));
466 try expect(math.approxEqAbs(f32, exp2f(1.5), 2.828427, epsilon));
467 try expect(math.approxEqAbs(f32, exp2f(37.45), 187747237888, epsilon));
468 try expect(math.approxEqAbs(f32, exp2f(-1), 0.5, epsilon));
472test "exp2f() sanity" {
473 try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);
474 try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);
475 try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);
476 try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);
477 try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);
478 try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);
479 try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);
480 try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);
481 try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);
482 try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);
469483}
470484
471test "exp2_64" {
472 const epsilon = 0.000001;
485test "exp2f() boundary" {
486 try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
487 try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result
488 try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
489 try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
490 try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
491 try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
492 try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value
493 try expectEqual(exp2f(0x1p-149), 1); // Min positive input value
494 try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value
495 try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input
496 try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input
497}
473498
474 try expect(exp2(0.0) == 1.0);
475 try expect(math.approxEqAbs(f64, exp2(0.2), 1.148698, epsilon));
476 try expect(math.approxEqAbs(f64, exp2(0.8923), 1.856133, epsilon));
477 try expect(math.approxEqAbs(f64, exp2(1.5), 2.828427, epsilon));
478 try expect(math.approxEqAbs(f64, exp2(-1), 0.5, epsilon));
479 try expect(math.approxEqAbs(f64, exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon));
499test "exp2() special" {
500 try expectEqual(exp2(0.0), 1.0);
501 try expectEqual(exp2(-0.0), 1.0);
502 try expectEqual(exp2(1.0), 2.0);
503 try expectEqual(exp2(-1.0), 0.5);
504 try expectEqual(exp2(math.inf(f64)), math.inf(f64));
505 try expectEqual(exp2(-math.inf(f64)), 0.0);
506 try expect(math.isNan(exp2(math.nan(f64))));
507 try expect(math.isNan(exp2(math.snan(f64))));
480508}
481509
482test "exp2_32.special" {
483 try expect(math.isPositiveInf(exp2f(math.inf(f32))));
484 try expect(math.isNan(exp2f(math.nan(f32))));
510test "exp2() sanity" {
511 try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
512 try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
513 try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
514 try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
515 try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
516 try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
517 try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
518 try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
519 try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
520 try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
485521}
486522
487test "exp2_64.special" {
488 try expect(math.isPositiveInf(exp2(math.inf(f64))));
489 try expect(math.isNan(exp2(math.nan(f64))));
523test "exp2() boundary" {
524 try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
525 try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result
526 try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
527 try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
528 try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
529 try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
530 try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
531 try expectEqual(exp2(0x1p-1074), 1); // Min positive input value
532 try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value
533 try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input
534 try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input
490535}