| author | |
| committer | |
| log | a35688b6135bf456609e64015bffd4d3edeac998 |
| tree | f19cfc5871e6e936e63da98f118122d67b1e22a2 |
| parent | e62e42f0d901fd1b053b22ecd14a42bdac7dbac4 |
| parent | 03dfd2ecc37cc99b15d4ce3ff19147230ddc8fd4 |
| signature |
Math tests simplified (exp and log functions) with bugfixes7 files changed, 473 insertions(+), 186 deletions(-)
lib/compiler_rt/exp.zig+89-20| ... | @@ -10,6 +10,7 @@ const arch = builtin.cpu.arch; | ... | @@ -10,6 +10,7 @@ const arch = builtin.cpu.arch; |
| 10 | const math = std.math; | 10 | const math = std.math; |
| 11 | const mem = std.mem; | 11 | const mem = std.mem; |
| 12 | const expect = std.testing.expect; | 12 | const expect = std.testing.expect; |
| 13 | const expectEqual = std.testing.expectEqual; | ||
| 13 | const common = @import("common.zig"); | 14 | const common = @import("common.zig"); |
| 14 | 15 | ||
| 15 | pub const panic = common.panic; | 16 | pub const panic = common.panic; |
| ... | @@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { | ... | @@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { |
| 211 | } | 212 | } |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 214 | test "exp32" { | 215 | test "expf() special" { |
| 215 | const epsilon = 0.000001; | 216 | try expectEqual(expf(0.0), 1.0); |
| 217 | try expectEqual(expf(-0.0), 1.0); | ||
| 218 | try expectEqual(expf(1.0), math.e); | ||
| 219 | try expectEqual(expf(math.ln2), 2.0); | ||
| 220 | try expectEqual(expf(math.inf(f32)), math.inf(f32)); | ||
| 221 | try expect(math.isPositiveZero(expf(-math.inf(f32)))); | ||
| 222 | try expect(math.isNan(expf(math.nan(f32)))); | ||
| 223 | try expect(math.isNan(expf(math.snan(f32)))); | ||
| 224 | } | ||
| 216 | 225 | ||
| 217 | try expect(expf(0.0) == 1.0); | 226 | test "expf() sanity" { |
| 218 | try expect(math.approxEqAbs(f32, expf(0.0), 1.0, epsilon)); | 227 | try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12); |
| 219 | try expect(math.approxEqAbs(f32, expf(0.2), 1.221403, epsilon)); | 228 | try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6); |
| 220 | try expect(math.approxEqAbs(f32, expf(0.8923), 2.440737, epsilon)); | 229 | try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13); |
| 221 | try expect(math.approxEqAbs(f32, expf(1.5), 4.481689, epsilon)); | 230 | try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10); |
| 231 | try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13); | ||
| 232 | try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0); | ||
| 233 | try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1); | ||
| 234 | try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0); | ||
| 235 | try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1); | ||
| 236 | try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1); | ||
| 237 | try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8); | ||
| 238 | try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20); | ||
| 239 | try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25); | ||
| 240 | try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20); | ||
| 241 | try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8); | ||
| 242 | try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2); | ||
| 243 | try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16); | ||
| 244 | try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24); | ||
| 245 | try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5); | ||
| 246 | try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28); | ||
| 222 | } | 247 | } |
| 223 | 248 | ||
| 224 | test "exp64" { | 249 | test "expf() boundary" { |
| 225 | const epsilon = 0.000001; | 250 | try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite |
| 251 | try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf | ||
| 252 | try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value | ||
| 253 | try expectEqual(expf(0x1p-149), 1.0); // Min positive input value | ||
| 254 | try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value | ||
| 255 | try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input | ||
| 256 | try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input | ||
| 257 | try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero | ||
| 258 | try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero | ||
| 259 | try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal | ||
| 260 | try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal | ||
| 226 | 261 | ||
| 227 | try expect(exp(0.0) == 1.0); | ||
| 228 | try expect(math.approxEqAbs(f64, exp(0.0), 1.0, epsilon)); | ||
| 229 | try expect(math.approxEqAbs(f64, exp(0.2), 1.221403, epsilon)); | ||
| 230 | try expect(math.approxEqAbs(f64, exp(0.8923), 2.440737, epsilon)); | ||
| 231 | try expect(math.approxEqAbs(f64, exp(1.5), 4.481689, epsilon)); | ||
| 232 | } | 262 | } |
| 233 | 263 | ||
| 234 | test "exp32.special" { | 264 | test "exp() special" { |
| 235 | try expect(math.isPositiveInf(expf(math.inf(f32)))); | 265 | try expectEqual(exp(0.0), 1.0); |
| 236 | try expect(math.isNan(expf(math.nan(f32)))); | 266 | try expectEqual(exp(-0.0), 1.0); |
| 267 | // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC | ||
| 268 | // try expectEqual(exp(1.0), math.e); | ||
| 269 | try expectEqual(exp(math.ln2), 2.0); | ||
| 270 | try expectEqual(exp(math.inf(f64)), math.inf(f64)); | ||
| 271 | try expect(math.isPositiveZero(exp(-math.inf(f64)))); | ||
| 272 | try expect(math.isNan(exp(math.nan(f64)))); | ||
| 273 | try expect(math.isNan(exp(math.snan(f64)))); | ||
| 237 | } | 274 | } |
| 238 | 275 | ||
| 239 | test "exp64.special" { | 276 | test "exp() sanity" { |
| 240 | try expect(math.isPositiveInf(exp(math.inf(f64)))); | 277 | try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); |
| 241 | try expect(math.isNan(exp(math.nan(f64)))); | 278 | try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); |
| 279 | try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); | ||
| 280 | try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); | ||
| 281 | try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); | ||
| 282 | try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); | ||
| 283 | try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); | ||
| 284 | try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); | ||
| 285 | try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); | ||
| 286 | try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); | ||
| 287 | try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); | ||
| 288 | try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); | ||
| 289 | try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); | ||
| 290 | try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); | ||
| 291 | try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); | ||
| 292 | try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); | ||
| 293 | try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); | ||
| 294 | try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); | ||
| 295 | try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); | ||
| 296 | try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); | ||
| 297 | } | ||
| 298 | |||
| 299 | test "exp() boundary" { | ||
| 300 | try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite | ||
| 301 | try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf | ||
| 302 | try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value | ||
| 303 | try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value | ||
| 304 | try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value | ||
| 305 | try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input | ||
| 306 | try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input | ||
| 307 | try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero | ||
| 308 | try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero | ||
| 309 | try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal | ||
| 310 | try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal | ||
| 242 | } | 311 | } |
lib/compiler_rt/exp2.zig+68-23| ... | @@ -10,6 +10,7 @@ const arch = builtin.cpu.arch; | ... | @@ -10,6 +10,7 @@ const arch = builtin.cpu.arch; |
| 10 | const math = std.math; | 10 | const math = std.math; |
| 11 | const mem = std.mem; | 11 | const mem = std.mem; |
| 12 | const expect = std.testing.expect; | 12 | const expect = std.testing.expect; |
| 13 | const expectEqual = std.testing.expectEqual; | ||
| 13 | const common = @import("common.zig"); | 14 | const common = @import("common.zig"); |
| 14 | 15 | ||
| 15 | pub const panic = common.panic; | 16 | pub const panic = common.panic; |
| ... | @@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 { | ... | @@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 { |
| 58 | if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x); | 59 | if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x); |
| 59 | } | 60 | } |
| 60 | // x <= -150 | 61 | // x <= -150 |
| 61 | if (u >= 0x3160000) { | 62 | if (u >= 0xC3160000) { |
| 62 | return 0; | 63 | return 0; |
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| ... | @@ -457,34 +458,78 @@ const exp2dt = [_]f64{ | ... | @@ -457,34 +458,78 @@ const exp2dt = [_]f64{ |
| 457 | 0x1.690f4b19e9471p+0, -0x1.9780p-45, | 458 | 0x1.690f4b19e9471p+0, -0x1.9780p-45, |
| 458 | }; | 459 | }; |
| 459 | 460 | ||
| 460 | test "exp2_32" { | 461 | test "exp2f() special" { |
| 461 | const epsilon = 0.000001; | 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 expect(math.isPositiveZero(exp2f(-math.inf(f32)))); | ||
| 468 | try expect(math.isNan(exp2f(math.nan(f32)))); | ||
| 469 | try expect(math.isNan(exp2f(math.snan(f32)))); | ||
| 470 | } | ||
| 462 | 471 | ||
| 463 | try expect(exp2f(0.0) == 1.0); | 472 | test "exp2f() sanity" { |
| 464 | try expect(math.approxEqAbs(f32, exp2f(0.2), 1.148698, epsilon)); | 473 | try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9); |
| 465 | try expect(math.approxEqAbs(f32, exp2f(0.8923), 1.856133, epsilon)); | 474 | try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4); |
| 466 | try expect(math.approxEqAbs(f32, exp2f(1.5), 2.828427, epsilon)); | 475 | try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9); |
| 467 | try expect(math.approxEqAbs(f32, exp2f(37.45), 187747237888, epsilon)); | 476 | try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7); |
| 468 | try expect(math.approxEqAbs(f32, exp2f(-1), 0.5, epsilon)); | 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); | ||
| 469 | } | 483 | } |
| 470 | 484 | ||
| 471 | test "exp2_64" { | 485 | test "exp2f() boundary" { |
| 472 | const epsilon = 0.000001; | 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 | } | ||
| 473 | 498 | ||
| 474 | try expect(exp2(0.0) == 1.0); | 499 | test "exp2() special" { |
| 475 | try expect(math.approxEqAbs(f64, exp2(0.2), 1.148698, epsilon)); | 500 | try expectEqual(exp2(0.0), 1.0); |
| 476 | try expect(math.approxEqAbs(f64, exp2(0.8923), 1.856133, epsilon)); | 501 | try expectEqual(exp2(-0.0), 1.0); |
| 477 | try expect(math.approxEqAbs(f64, exp2(1.5), 2.828427, epsilon)); | 502 | try expectEqual(exp2(1.0), 2.0); |
| 478 | try expect(math.approxEqAbs(f64, exp2(-1), 0.5, epsilon)); | 503 | try expectEqual(exp2(-1.0), 0.5); |
| 479 | try expect(math.approxEqAbs(f64, exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon)); | 504 | try expectEqual(exp2(math.inf(f64)), math.inf(f64)); |
| 505 | try expect(math.isPositiveZero(exp2(-math.inf(f64)))); | ||
| 506 | try expect(math.isNan(exp2(math.nan(f64)))); | ||
| 507 | try expect(math.isNan(exp2(math.snan(f64)))); | ||
| 480 | } | 508 | } |
| 481 | 509 | ||
| 482 | test "exp2_32.special" { | 510 | test "exp2() sanity" { |
| 483 | try expect(math.isPositiveInf(exp2f(math.inf(f32)))); | 511 | try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); |
| 484 | try expect(math.isNan(exp2f(math.nan(f32)))); | 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); | ||
| 485 | } | 521 | } |
| 486 | 522 | ||
| 487 | test "exp2_64.special" { | 523 | test "exp2() boundary" { |
| 488 | try expect(math.isPositiveInf(exp2(math.inf(f64)))); | 524 | try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite |
| 489 | try expect(math.isNan(exp2(math.nan(f64)))); | 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 | ||
| 490 | } | 535 | } |
lib/compiler_rt/log.zig+64-29| ... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const testing = std.testing; | 10 | const expect = std.testing.expect; |
| 11 | const expectEqual = std.testing.expectEqual; | ||
| 11 | const arch = builtin.cpu.arch; | 12 | const arch = builtin.cpu.arch; |
| 12 | const common = @import("common.zig"); | 13 | const common = @import("common.zig"); |
| 13 | 14 | ||
| ... | @@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 { | ... | @@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 { |
| 110 | 111 | ||
| 111 | // subnormal, scale x | 112 | // subnormal, scale x |
| 112 | k -= 54; | 113 | k -= 54; |
| 113 | x *= 0x1.0p54; | 114 | x *= 0x1p54; |
| 114 | hx = @intCast(@as(u64, @bitCast(ix)) >> 32); | 115 | hx = @intCast(@as(u64, @bitCast(x)) >> 32); |
| 115 | } else if (hx >= 0x7FF00000) { | 116 | } else if (hx >= 0x7FF00000) { |
| 116 | return x; | 117 | return x; |
| 117 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { | 118 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { |
| ... | @@ -159,38 +160,72 @@ pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { | ... | @@ -159,38 +160,72 @@ pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { |
| 159 | } | 160 | } |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | test "ln32" { | 163 | test "logf() special" { |
| 163 | const epsilon = 0.000001; | 164 | try expectEqual(logf(0.0), -math.inf(f32)); |
| 165 | try expectEqual(logf(-0.0), -math.inf(f32)); | ||
| 166 | try expect(math.isPositiveZero(logf(1.0))); | ||
| 167 | try expectEqual(logf(math.e), 1.0); | ||
| 168 | try expectEqual(logf(math.inf(f32)), math.inf(f32)); | ||
| 169 | try expect(math.isNan(logf(-1.0))); | ||
| 170 | try expect(math.isNan(logf(-math.inf(f32)))); | ||
| 171 | try expect(math.isNan(logf(math.nan(f32)))); | ||
| 172 | try expect(math.isNan(logf(math.snan(f32)))); | ||
| 173 | } | ||
| 164 | 174 | ||
| 165 | try testing.expect(math.approxEqAbs(f32, logf(0.2), -1.609438, epsilon)); | 175 | test "logf() sanity" { |
| 166 | try testing.expect(math.approxEqAbs(f32, logf(0.8923), -0.113953, epsilon)); | 176 | try expect(math.isNan(logf(-0x1.0223a0p+3))); |
| 167 | try testing.expect(math.approxEqAbs(f32, logf(1.5), 0.405465, epsilon)); | 177 | try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0); |
| 168 | try testing.expect(math.approxEqAbs(f32, logf(37.45), 3.623007, epsilon)); | 178 | try expect(math.isNan(logf(-0x1.0c34b4p+3))); |
| 169 | try testing.expect(math.approxEqAbs(f32, logf(89.123), 4.490017, epsilon)); | 179 | try expect(math.isNan(logf(-0x1.a206f0p+2))); |
| 170 | try testing.expect(math.approxEqAbs(f32, logf(123123.234375), 11.720941, epsilon)); | 180 | try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1); |
| 181 | try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2); | ||
| 182 | try expect(math.isNan(logf(-0x1.a05cc8p-2))); | ||
| 183 | try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1); | ||
| 184 | try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2); | ||
| 185 | try expect(math.isNan(logf(-0x1.5b86eap-1))); | ||
| 171 | } | 186 | } |
| 172 | 187 | ||
| 173 | test "ln64" { | 188 | test "logf() boundary" { |
| 174 | const epsilon = 0.000001; | 189 | try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value |
| 190 | try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value | ||
| 191 | try expect(math.isNan(logf(-0x1p-149))); // Min negative input value | ||
| 192 | try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 | ||
| 193 | try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 | ||
| 194 | try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal | ||
| 195 | try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal | ||
| 196 | } | ||
| 175 | 197 | ||
| 176 | try testing.expect(math.approxEqAbs(f64, log(0.2), -1.609438, epsilon)); | 198 | test "log() special" { |
| 177 | try testing.expect(math.approxEqAbs(f64, log(0.8923), -0.113953, epsilon)); | 199 | try expectEqual(log(0.0), -math.inf(f64)); |
| 178 | try testing.expect(math.approxEqAbs(f64, log(1.5), 0.405465, epsilon)); | 200 | try expectEqual(log(-0.0), -math.inf(f64)); |
| 179 | try testing.expect(math.approxEqAbs(f64, log(37.45), 3.623007, epsilon)); | 201 | try expect(math.isPositiveZero(log(1.0))); |
| 180 | try testing.expect(math.approxEqAbs(f64, log(89.123), 4.490017, epsilon)); | 202 | try expectEqual(log(math.e), 1.0); |
| 181 | try testing.expect(math.approxEqAbs(f64, log(123123.234375), 11.720941, epsilon)); | 203 | try expectEqual(log(math.inf(f64)), math.inf(f64)); |
| 204 | try expect(math.isNan(log(-1.0))); | ||
| 205 | try expect(math.isNan(log(-math.inf(f64)))); | ||
| 206 | try expect(math.isNan(log(math.nan(f64)))); | ||
| 207 | try expect(math.isNan(log(math.snan(f64)))); | ||
| 182 | } | 208 | } |
| 183 | 209 | ||
| 184 | test "ln32.special" { | 210 | test "log() sanity" { |
| 185 | try testing.expect(math.isPositiveInf(logf(math.inf(f32)))); | 211 | try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3))); |
| 186 | try testing.expect(math.isNegativeInf(logf(0.0))); | 212 | try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); |
| 187 | try testing.expect(math.isNan(logf(-1.0))); | 213 | try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3))); |
| 188 | try testing.expect(math.isNan(logf(math.nan(f32)))); | 214 | try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2))); |
| 215 | try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); | ||
| 216 | try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); | ||
| 217 | try expect(math.isNan(log(-0x1.a05cc754481d1p-2))); | ||
| 218 | try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); | ||
| 219 | try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); | ||
| 220 | try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1))); | ||
| 189 | } | 221 | } |
| 190 | 222 | ||
| 191 | test "ln64.special" { | 223 | test "log() boundary" { |
| 192 | try testing.expect(math.isPositiveInf(log(math.inf(f64)))); | 224 | try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value |
| 193 | try testing.expect(math.isNegativeInf(log(0.0))); | 225 | try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value |
| 194 | try testing.expect(math.isNan(log(-1.0))); | 226 | try expect(math.isNan(log(-0x1p-1074))); // Min negative input value |
| 195 | try testing.expect(math.isNan(log(math.nan(f64)))); | 227 | try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 |
| 228 | try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 | ||
| 229 | try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal | ||
| 230 | try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal | ||
| 196 | } | 231 | } |
lib/compiler_rt/log10.zig+64-27| ... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const testing = std.testing; | 10 | const expect = std.testing.expect; |
| 11 | const expectEqual = std.testing.expectEqual; | ||
| 11 | const maxInt = std.math.maxInt; | 12 | const maxInt = std.math.maxInt; |
| 12 | const arch = builtin.cpu.arch; | 13 | const arch = builtin.cpu.arch; |
| 13 | const common = @import("common.zig"); | 14 | const common = @import("common.zig"); |
| ... | @@ -187,38 +188,74 @@ pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { | ... | @@ -187,38 +188,74 @@ pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { |
| 187 | } | 188 | } |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | test "log10_32" { | 191 | test "log10f() special" { |
| 191 | const epsilon = 0.000001; | 192 | try expectEqual(log10f(0.0), -math.inf(f32)); |
| 193 | try expectEqual(log10f(-0.0), -math.inf(f32)); | ||
| 194 | try expect(math.isPositiveZero(log10f(1.0))); | ||
| 195 | try expectEqual(log10f(10.0), 1.0); | ||
| 196 | try expectEqual(log10f(0.1), -1.0); | ||
| 197 | try expectEqual(log10f(math.inf(f32)), math.inf(f32)); | ||
| 198 | try expect(math.isNan(log10f(-1.0))); | ||
| 199 | try expect(math.isNan(log10f(-math.inf(f32)))); | ||
| 200 | try expect(math.isNan(log10f(math.nan(f32)))); | ||
| 201 | try expect(math.isNan(log10f(math.snan(f32)))); | ||
| 202 | } | ||
| 192 | 203 | ||
| 193 | try testing.expect(math.approxEqAbs(f32, log10f(0.2), -0.698970, epsilon)); | 204 | test "log10f() sanity" { |
| 194 | try testing.expect(math.approxEqAbs(f32, log10f(0.8923), -0.049489, epsilon)); | 205 | try expect(math.isNan(log10f(-0x1.0223a0p+3))); |
| 195 | try testing.expect(math.approxEqAbs(f32, log10f(1.5), 0.176091, epsilon)); | 206 | try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1); |
| 196 | try testing.expect(math.approxEqAbs(f32, log10f(37.45), 1.573452, epsilon)); | 207 | try expect(math.isNan(log10f(-0x1.0c34b4p+3))); |
| 197 | try testing.expect(math.approxEqAbs(f32, log10f(89.123), 1.94999, epsilon)); | 208 | try expect(math.isNan(log10f(-0x1.a206f0p+2))); |
| 198 | try testing.expect(math.approxEqAbs(f32, log10f(123123.234375), 5.09034, epsilon)); | 209 | try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1); |
| 210 | try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit | ||
| 211 | try expect(math.isNan(log10f(-0x1.a05cc8p-2))); | ||
| 212 | try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2); | ||
| 213 | try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4); | ||
| 214 | try expect(math.isNan(log10f(-0x1.5b86eap-1))); | ||
| 199 | } | 215 | } |
| 200 | 216 | ||
| 201 | test "log10_64" { | 217 | test "log10f() boundary" { |
| 202 | const epsilon = 0.000001; | 218 | try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value |
| 219 | try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value | ||
| 220 | try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value | ||
| 221 | try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 | ||
| 222 | try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 | ||
| 223 | try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal | ||
| 224 | try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal | ||
| 225 | } | ||
| 203 | 226 | ||
| 204 | try testing.expect(math.approxEqAbs(f64, log10(0.2), -0.698970, epsilon)); | 227 | test "log10() special" { |
| 205 | try testing.expect(math.approxEqAbs(f64, log10(0.8923), -0.049489, epsilon)); | 228 | try expectEqual(log10(0.0), -math.inf(f64)); |
| 206 | try testing.expect(math.approxEqAbs(f64, log10(1.5), 0.176091, epsilon)); | 229 | try expectEqual(log10(-0.0), -math.inf(f64)); |
| 207 | try testing.expect(math.approxEqAbs(f64, log10(37.45), 1.573452, epsilon)); | 230 | try expect(math.isPositiveZero(log10(1.0))); |
| 208 | try testing.expect(math.approxEqAbs(f64, log10(89.123), 1.94999, epsilon)); | 231 | try expectEqual(log10(10.0), 1.0); |
| 209 | try testing.expect(math.approxEqAbs(f64, log10(123123.234375), 5.09034, epsilon)); | 232 | try expectEqual(log10(0.1), -1.0); |
| 233 | try expectEqual(log10(math.inf(f64)), math.inf(f64)); | ||
| 234 | try expect(math.isNan(log10(-1.0))); | ||
| 235 | try expect(math.isNan(log10(-math.inf(f64)))); | ||
| 236 | try expect(math.isNan(log10(math.nan(f64)))); | ||
| 237 | try expect(math.isNan(log10(math.snan(f64)))); | ||
| 210 | } | 238 | } |
| 211 | 239 | ||
| 212 | test "log10_32.special" { | 240 | test "log10() sanity" { |
| 213 | try testing.expect(math.isPositiveInf(log10f(math.inf(f32)))); | 241 | try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3))); |
| 214 | try testing.expect(math.isNegativeInf(log10f(0.0))); | 242 | try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); |
| 215 | try testing.expect(math.isNan(log10f(-1.0))); | 243 | try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3))); |
| 216 | try testing.expect(math.isNan(log10f(math.nan(f32)))); | 244 | try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2))); |
| 245 | try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); | ||
| 246 | try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); | ||
| 247 | try expect(math.isNan(log10(-0x1.a05cc754481d1p-2))); | ||
| 248 | try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); | ||
| 249 | try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); | ||
| 250 | try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1))); | ||
| 217 | } | 251 | } |
| 218 | 252 | ||
| 219 | test "log10_64.special" { | 253 | test "log10() boundary" { |
| 220 | try testing.expect(math.isPositiveInf(log10(math.inf(f64)))); | 254 | try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value |
| 221 | try testing.expect(math.isNegativeInf(log10(0.0))); | 255 | try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value |
| 222 | try testing.expect(math.isNan(log10(-1.0))); | 256 | try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value |
| 223 | try testing.expect(math.isNan(log10(math.nan(f64)))); | 257 | try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 |
| 258 | try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 | ||
| 259 | try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal | ||
| 260 | try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal | ||
| 224 | } | 261 | } |
lib/compiler_rt/log2.zig+62-24| ... | @@ -8,6 +8,7 @@ const std = @import("std"); | ... | @@ -8,6 +8,7 @@ const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const expect = std.testing.expect; | 10 | const expect = std.testing.expect; |
| 11 | const expectEqual = std.testing.expectEqual; | ||
| 11 | const maxInt = std.math.maxInt; | 12 | const maxInt = std.math.maxInt; |
| 12 | const arch = builtin.cpu.arch; | 13 | const arch = builtin.cpu.arch; |
| 13 | const common = @import("common.zig"); | 14 | const common = @import("common.zig"); |
| ... | @@ -179,36 +180,73 @@ pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { | ... | @@ -179,36 +180,73 @@ pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { |
| 179 | } | 180 | } |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 182 | test "log2_32" { | 183 | test "log2f() special" { |
| 183 | const epsilon = 0.000001; | 184 | try expectEqual(log2f(0.0), -math.inf(f32)); |
| 184 | 185 | try expectEqual(log2f(-0.0), -math.inf(f32)); | |
| 185 | try expect(math.approxEqAbs(f32, log2f(0.2), -2.321928, epsilon)); | 186 | try expect(math.isPositiveZero(log2f(1.0))); |
| 186 | try expect(math.approxEqAbs(f32, log2f(0.8923), -0.164399, epsilon)); | 187 | try expectEqual(log2f(2.0), 1.0); |
| 187 | try expect(math.approxEqAbs(f32, log2f(1.5), 0.584962, epsilon)); | 188 | try expectEqual(log2f(math.inf(f32)), math.inf(f32)); |
| 188 | try expect(math.approxEqAbs(f32, log2f(37.45), 5.226894, epsilon)); | 189 | try expect(math.isNan(log2f(-1.0))); |
| 189 | try expect(math.approxEqAbs(f32, log2f(123123.234375), 16.909744, epsilon)); | 190 | try expect(math.isNan(log2f(-math.inf(f32)))); |
| 191 | try expect(math.isNan(log2f(math.nan(f32)))); | ||
| 192 | try expect(math.isNan(log2f(math.snan(f32)))); | ||
| 190 | } | 193 | } |
| 191 | 194 | ||
| 192 | test "log2_64" { | 195 | test "log2f() sanity" { |
| 193 | const epsilon = 0.000001; | 196 | try expect(math.isNan(log2f(-0x1.0223a0p+3))); |
| 194 | 197 | try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1); | |
| 195 | try expect(math.approxEqAbs(f64, log2(0.2), -2.321928, epsilon)); | 198 | try expect(math.isNan(log2f(-0x1.0c34b4p+3))); |
| 196 | try expect(math.approxEqAbs(f64, log2(0.8923), -0.164399, epsilon)); | 199 | try expect(math.isNan(log2f(-0x1.a206f0p+2))); |
| 197 | try expect(math.approxEqAbs(f64, log2(1.5), 0.584962, epsilon)); | 200 | try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1); |
| 198 | try expect(math.approxEqAbs(f64, log2(37.45), 5.226894, epsilon)); | 201 | try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit |
| 199 | try expect(math.approxEqAbs(f64, log2(123123.234375), 16.909744, epsilon)); | 202 | try expect(math.isNan(log2f(-0x1.a05cc8p-2))); |
| 203 | try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1); | ||
| 204 | try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2); | ||
| 205 | try expect(math.isNan(log2f(-0x1.5b86eap-1))); | ||
| 200 | } | 206 | } |
| 201 | 207 | ||
| 202 | test "log2_32.special" { | 208 | test "log2f() boundary" { |
| 203 | try expect(math.isPositiveInf(log2f(math.inf(f32)))); | 209 | try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value |
| 204 | try expect(math.isNegativeInf(log2f(0.0))); | 210 | try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value |
| 205 | try expect(math.isNan(log2f(-1.0))); | 211 | try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value |
| 206 | try expect(math.isNan(log2f(math.nan(f32)))); | 212 | try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 |
| 213 | try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 | ||
| 214 | try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal | ||
| 215 | try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal | ||
| 216 | |||
| 207 | } | 217 | } |
| 208 | 218 | ||
| 209 | test "log2_64.special" { | 219 | test "log2() special" { |
| 210 | try expect(math.isPositiveInf(log2(math.inf(f64)))); | 220 | try expectEqual(log2(0.0), -math.inf(f64)); |
| 211 | try expect(math.isNegativeInf(log2(0.0))); | 221 | try expectEqual(log2(-0.0), -math.inf(f64)); |
| 222 | try expect(math.isPositiveZero(log2(1.0))); | ||
| 223 | try expectEqual(log2(2.0), 1.0); | ||
| 224 | try expectEqual(log2(math.inf(f64)), math.inf(f64)); | ||
| 212 | try expect(math.isNan(log2(-1.0))); | 225 | try expect(math.isNan(log2(-1.0))); |
| 226 | try expect(math.isNan(log2(-math.inf(f64)))); | ||
| 213 | try expect(math.isNan(log2(math.nan(f64)))); | 227 | try expect(math.isNan(log2(math.nan(f64)))); |
| 228 | try expect(math.isNan(log2(math.snan(f64)))); | ||
| 229 | } | ||
| 230 | |||
| 231 | test "log2() sanity" { | ||
| 232 | try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3))); | ||
| 233 | try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); | ||
| 234 | try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3))); | ||
| 235 | try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2))); | ||
| 236 | try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); | ||
| 237 | try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); | ||
| 238 | try expect(math.isNan(log2(-0x1.a05cc754481d1p-2))); | ||
| 239 | try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); | ||
| 240 | try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); | ||
| 241 | try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1))); | ||
| 242 | } | ||
| 243 | |||
| 244 | test "log2() boundary" { | ||
| 245 | try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value | ||
| 246 | try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value | ||
| 247 | try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value | ||
| 248 | try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 | ||
| 249 | try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 | ||
| 250 | try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal | ||
| 251 | try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal | ||
| 214 | } | 252 | } |
lib/std/math/expm1.zig+67-28| ... | @@ -10,6 +10,7 @@ const std = @import("../std.zig"); | ... | @@ -10,6 +10,7 @@ const std = @import("../std.zig"); |
| 10 | const math = std.math; | 10 | const math = std.math; |
| 11 | const mem = std.mem; | 11 | const mem = std.mem; |
| 12 | const expect = std.testing.expect; | 12 | const expect = std.testing.expect; |
| 13 | const expectEqual = std.testing.expectEqual; | ||
| 13 | 14 | ||
| 14 | /// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1 | 15 | /// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1 |
| 15 | /// when x is near 0. | 16 | /// when x is near 0. |
| ... | @@ -39,9 +40,9 @@ fn expm1_32(x_: f32) f32 { | ... | @@ -39,9 +40,9 @@ fn expm1_32(x_: f32) f32 { |
| 39 | const Q2: f32 = 1.5807170421e-3; | 40 | const Q2: f32 = 1.5807170421e-3; |
| 40 | 41 | ||
| 41 | var x = x_; | 42 | var x = x_; |
| 42 | const ux = @as(u32, @bitCast(x)); | 43 | const ux: u32 = @bitCast(x); |
| 43 | const hx = ux & 0x7FFFFFFF; | 44 | const hx = ux & 0x7FFFFFFF; |
| 44 | const sign = hx >> 31; | 45 | const sign = ux >> 31; |
| 45 | 46 | ||
| 46 | // TODO: Shouldn't need this check explicitly. | 47 | // TODO: Shouldn't need this check explicitly. |
| 47 | if (math.isNegativeInf(x)) { | 48 | if (math.isNegativeInf(x)) { |
| ... | @@ -147,7 +148,7 @@ fn expm1_32(x_: f32) f32 { | ... | @@ -147,7 +148,7 @@ fn expm1_32(x_: f32) f32 { |
| 147 | return y - 1.0; | 148 | return y - 1.0; |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | const uf = @as(f32, @bitCast(@as(u32, @intCast(0x7F -% k)) << 23)); | 151 | const uf: f32 = @bitCast(@as(u32, @intCast(0x7F -% k)) << 23); |
| 151 | if (k < 23) { | 152 | if (k < 23) { |
| 152 | return (x - e + (1 - uf)) * twopk; | 153 | return (x - e + (1 - uf)) * twopk; |
| 153 | } else { | 154 | } else { |
| ... | @@ -286,39 +287,77 @@ fn expm1_64(x_: f64) f64 { | ... | @@ -286,39 +287,77 @@ fn expm1_64(x_: f64) f64 { |
| 286 | } | 287 | } |
| 287 | } | 288 | } |
| 288 | 289 | ||
| 289 | test expm1 { | 290 | test "expm1_32() special" { |
| 290 | try expect(expm1(@as(f32, 0.0)) == expm1_32(0.0)); | 291 | try expect(math.isPositiveZero(expm1_32(0.0))); |
| 291 | try expect(expm1(@as(f64, 0.0)) == expm1_64(0.0)); | 292 | try expect(math.isNegativeZero(expm1_32(-0.0))); |
| 293 | try expectEqual(expm1_32(math.ln2), 1.0); | ||
| 294 | try expectEqual(expm1_32(math.inf(f32)), math.inf(f32)); | ||
| 295 | try expectEqual(expm1_32(-math.inf(f32)), -1.0); | ||
| 296 | try expect(math.isNan(expm1_32(math.nan(f32)))); | ||
| 297 | try expect(math.isNan(expm1_32(math.snan(f32)))); | ||
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | test expm1_32 { | 300 | test "expm1_32() sanity" { |
| 295 | const epsilon = 0.000001; | 301 | try expectEqual(expm1_32(-0x1.0223a0p+3), -0x1.ffd6e0p-1); |
| 296 | 302 | try expectEqual(expm1_32(0x1.161868p+2), 0x1.30712ap+6); | |
| 297 | try expect(math.isPositiveZero(expm1_32(0.0))); | 303 | try expectEqual(expm1_32(-0x1.0c34b4p+3), -0x1.ffe1fap-1); |
| 298 | try expect(math.approxEqAbs(f32, expm1_32(0.0), 0.0, epsilon)); | 304 | try expectEqual(expm1_32(-0x1.a206f0p+2), -0x1.ff4116p-1); |
| 299 | try expect(math.approxEqAbs(f32, expm1_32(0.2), 0.221403, epsilon)); | 305 | try expectEqual(expm1_32(0x1.288bbcp+3), 0x1.4ab480p+13); // Disagrees with GCC in last bit |
| 300 | try expect(math.approxEqAbs(f32, expm1_32(0.8923), 1.440737, epsilon)); | 306 | try expectEqual(expm1_32(0x1.52efd0p-1), 0x1.e09536p-1); |
| 301 | try expect(math.approxEqAbs(f32, expm1_32(1.5), 3.481689, epsilon)); | 307 | try expectEqual(expm1_32(-0x1.a05cc8p-2), -0x1.561c3ep-2); |
| 308 | try expectEqual(expm1_32(0x1.1f9efap-1), 0x1.81ec4ep-1); | ||
| 309 | try expectEqual(expm1_32(0x1.8c5db0p-1), 0x1.2b3364p+0); | ||
| 310 | try expectEqual(expm1_32(-0x1.5b86eap-1), -0x1.f8951ap-2); | ||
| 302 | } | 311 | } |
| 303 | 312 | ||
| 304 | test expm1_64 { | 313 | test "expm1_32() boundary" { |
| 305 | const epsilon = 0.000001; | 314 | // TODO: The last value before inf is actually 0x1.62e300p+6 -> 0x1.ff681ep+127 |
| 315 | // try expectEqual(expm1_32(0x1.62e42ep+6), 0x1.ffff08p+127); // Last value before result is inf | ||
| 316 | try expectEqual(expm1_32(0x1.62e430p+6), math.inf(f32)); // First value that gives inf | ||
| 317 | try expectEqual(expm1_32(0x1.fffffep+127), math.inf(f32)); // Max input value | ||
| 318 | try expectEqual(expm1_32(0x1p-149), 0x1p-149); // Min positive input value | ||
| 319 | try expectEqual(expm1_32(-0x1p-149), -0x1p-149); // Min negative input value | ||
| 320 | try expectEqual(expm1_32(0x1p-126), 0x1p-126); // First positive subnormal input | ||
| 321 | try expectEqual(expm1_32(-0x1p-126), -0x1p-126); // First negative subnormal input | ||
| 322 | try expectEqual(expm1_32(0x1.fffffep-125), 0x1.fffffep-125); // Last positive value before subnormal | ||
| 323 | try expectEqual(expm1_32(-0x1.fffffep-125), -0x1.fffffep-125); // Last negative value before subnormal | ||
| 324 | try expectEqual(expm1_32(-0x1.154244p+4), -0x1.fffffep-1); // Last value before result is -1 | ||
| 325 | try expectEqual(expm1_32(-0x1.154246p+4), -1); // First value where result is -1 | ||
| 326 | } | ||
| 306 | 327 | ||
| 328 | test "expm1_64() special" { | ||
| 307 | try expect(math.isPositiveZero(expm1_64(0.0))); | 329 | try expect(math.isPositiveZero(expm1_64(0.0))); |
| 308 | try expect(math.approxEqAbs(f64, expm1_64(0.0), 0.0, epsilon)); | 330 | try expect(math.isNegativeZero(expm1_64(-0.0))); |
| 309 | try expect(math.approxEqAbs(f64, expm1_64(0.2), 0.221403, epsilon)); | 331 | try expectEqual(expm1_64(math.ln2), 1.0); |
| 310 | try expect(math.approxEqAbs(f64, expm1_64(0.8923), 1.440737, epsilon)); | 332 | try expectEqual(expm1_64(math.inf(f64)), math.inf(f64)); |
| 311 | try expect(math.approxEqAbs(f64, expm1_64(1.5), 3.481689, epsilon)); | 333 | try expectEqual(expm1_64(-math.inf(f64)), -1.0); |
| 334 | try expect(math.isNan(expm1_64(math.nan(f64)))); | ||
| 335 | try expect(math.isNan(expm1_64(math.snan(f64)))); | ||
| 312 | } | 336 | } |
| 313 | 337 | ||
| 314 | test "expm1_32.special" { | 338 | test "expm1_64() sanity" { |
| 315 | try expect(math.isPositiveInf(expm1_32(math.inf(f32)))); | 339 | try expectEqual(expm1_64(-0x1.02239f3c6a8f1p+3), -0x1.ffd6df9b02b3ep-1); |
| 316 | try expect(expm1_32(-math.inf(f32)) == -1.0); | 340 | try expectEqual(expm1_64(0x1.161868e18bc67p+2), 0x1.30712ed238c04p+6); |
| 317 | try expect(math.isNan(expm1_32(math.nan(f32)))); | 341 | try expectEqual(expm1_64(-0x1.0c34b3e01e6e7p+3), -0x1.ffe1f94e493e7p-1); |
| 342 | try expectEqual(expm1_64(-0x1.a206f0a19dcc4p+2), -0x1.ff4115c03f78dp-1); | ||
| 343 | try expectEqual(expm1_64(0x1.288bbb0d6a1e6p+3), 0x1.4ab477496e07ep+13); | ||
| 344 | try expectEqual(expm1_64(0x1.52efd0cd80497p-1), 0x1.e095382100a01p-1); | ||
| 345 | try expectEqual(expm1_64(-0x1.a05cc754481d1p-2), -0x1.561c3e0582be6p-2); | ||
| 346 | try expectEqual(expm1_64(0x1.1f9ef934745cbp-1), 0x1.81ec4cd4d4a8fp-1); | ||
| 347 | try expectEqual(expm1_64(0x1.8c5db097f7442p-1), 0x1.2b3363a944bf7p+0); | ||
| 348 | try expectEqual(expm1_64(-0x1.5b86ea8118a0ep-1), -0x1.f8951aebffbafp-2); | ||
| 318 | } | 349 | } |
| 319 | 350 | ||
| 320 | test "expm1_64.special" { | 351 | test "expm1_64() boundary" { |
| 321 | try expect(math.isPositiveInf(expm1_64(math.inf(f64)))); | 352 | try expectEqual(expm1_64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // Last value before result is inf |
| 322 | try expect(expm1_64(-math.inf(f64)) == -1.0); | 353 | try expectEqual(expm1_64(0x1.62e42fefa39f0p+9), math.inf(f64)); // First value that gives inf |
| 323 | try expect(math.isNan(expm1_64(math.nan(f64)))); | 354 | try expectEqual(expm1_64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value |
| 355 | try expectEqual(expm1_64(0x1p-1074), 0x1p-1074); // Min positive input value | ||
| 356 | try expectEqual(expm1_64(-0x1p-1074), -0x1p-1074); // Min negative input value | ||
| 357 | try expectEqual(expm1_64(0x1p-1022), 0x1p-1022); // First positive subnormal input | ||
| 358 | try expectEqual(expm1_64(-0x1p-1022), -0x1p-1022); // First negative subnormal input | ||
| 359 | try expectEqual(expm1_64(0x1.fffffffffffffp-1021), 0x1.fffffffffffffp-1021); // Last positive value before subnormal | ||
| 360 | try expectEqual(expm1_64(-0x1.fffffffffffffp-1021), -0x1.fffffffffffffp-1021); // Last negative value before subnormal | ||
| 361 | try expectEqual(expm1_64(-0x1.2b708872320e1p+5), -0x1.fffffffffffffp-1); // Last value before result is -1 | ||
| 362 | try expectEqual(expm1_64(-0x1.2b708872320e2p+5), -1); // First value where result is -1 | ||
| 324 | } | 363 | } |
lib/std/math/log1p.zig+59-35| ... | @@ -8,6 +8,7 @@ const std = @import("../std.zig"); | ... | @@ -8,6 +8,7 @@ const std = @import("../std.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const mem = std.mem; | 9 | const mem = std.mem; |
| 10 | const expect = std.testing.expect; | 10 | const expect = std.testing.expect; |
| 11 | const expectEqual = std.testing.expectEqual; | ||
| 11 | 12 | ||
| 12 | /// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero. | 13 | /// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero. |
| 13 | /// | 14 | /// |
| ... | @@ -182,49 +183,72 @@ fn log1p_64(x: f64) f64 { | ... | @@ -182,49 +183,72 @@ fn log1p_64(x: f64) f64 { |
| 182 | return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi; | 183 | return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi; |
| 183 | } | 184 | } |
| 184 | 185 | ||
| 185 | test log1p { | 186 | test "log1p_32() special" { |
| 186 | try expect(log1p(@as(f32, 0.0)) == log1p_32(0.0)); | ||
| 187 | try expect(log1p(@as(f64, 0.0)) == log1p_64(0.0)); | ||
| 188 | } | ||
| 189 | |||
| 190 | test log1p_32 { | ||
| 191 | const epsilon = 0.000001; | ||
| 192 | |||
| 193 | try expect(math.approxEqAbs(f32, log1p_32(0.0), 0.0, epsilon)); | ||
| 194 | try expect(math.approxEqAbs(f32, log1p_32(0.2), 0.182322, epsilon)); | ||
| 195 | try expect(math.approxEqAbs(f32, log1p_32(0.8923), 0.637793, epsilon)); | ||
| 196 | try expect(math.approxEqAbs(f32, log1p_32(1.5), 0.916291, epsilon)); | ||
| 197 | try expect(math.approxEqAbs(f32, log1p_32(37.45), 3.649359, epsilon)); | ||
| 198 | try expect(math.approxEqAbs(f32, log1p_32(89.123), 4.501175, epsilon)); | ||
| 199 | try expect(math.approxEqAbs(f32, log1p_32(123123.234375), 11.720949, epsilon)); | ||
| 200 | } | ||
| 201 | |||
| 202 | test log1p_64 { | ||
| 203 | const epsilon = 0.000001; | ||
| 204 | |||
| 205 | try expect(math.approxEqAbs(f64, log1p_64(0.0), 0.0, epsilon)); | ||
| 206 | try expect(math.approxEqAbs(f64, log1p_64(0.2), 0.182322, epsilon)); | ||
| 207 | try expect(math.approxEqAbs(f64, log1p_64(0.8923), 0.637793, epsilon)); | ||
| 208 | try expect(math.approxEqAbs(f64, log1p_64(1.5), 0.916291, epsilon)); | ||
| 209 | try expect(math.approxEqAbs(f64, log1p_64(37.45), 3.649359, epsilon)); | ||
| 210 | try expect(math.approxEqAbs(f64, log1p_64(89.123), 4.501175, epsilon)); | ||
| 211 | try expect(math.approxEqAbs(f64, log1p_64(123123.234375), 11.720949, epsilon)); | ||
| 212 | } | ||
| 213 | |||
| 214 | test "log1p_32.special" { | ||
| 215 | try expect(math.isPositiveInf(log1p_32(math.inf(f32)))); | ||
| 216 | try expect(math.isPositiveZero(log1p_32(0.0))); | 187 | try expect(math.isPositiveZero(log1p_32(0.0))); |
| 217 | try expect(math.isNegativeZero(log1p_32(-0.0))); | 188 | try expect(math.isNegativeZero(log1p_32(-0.0))); |
| 218 | try expect(math.isNegativeInf(log1p_32(-1.0))); | 189 | try expectEqual(log1p_32(-1.0), -math.inf(f32)); |
| 190 | try expectEqual(log1p_32(1.0), math.ln2); | ||
| 191 | try expectEqual(log1p_32(math.inf(f32)), math.inf(f32)); | ||
| 219 | try expect(math.isNan(log1p_32(-2.0))); | 192 | try expect(math.isNan(log1p_32(-2.0))); |
| 193 | try expect(math.isNan(log1p_32(-math.inf(f32)))); | ||
| 220 | try expect(math.isNan(log1p_32(math.nan(f32)))); | 194 | try expect(math.isNan(log1p_32(math.nan(f32)))); |
| 195 | try expect(math.isNan(log1p_32(math.snan(f32)))); | ||
| 221 | } | 196 | } |
| 222 | 197 | ||
| 223 | test "log1p_64.special" { | 198 | test "log1p_32() sanity" { |
| 224 | try expect(math.isPositiveInf(log1p_64(math.inf(f64)))); | 199 | try expect(math.isNan(log1p_32(-0x1.0223a0p+3))); |
| 200 | try expectEqual(log1p_32(0x1.161868p+2), 0x1.ad1bdcp+0); | ||
| 201 | try expect(math.isNan(log1p_32(-0x1.0c34b4p+3))); | ||
| 202 | try expect(math.isNan(log1p_32(-0x1.a206f0p+2))); | ||
| 203 | try expectEqual(log1p_32(0x1.288bbcp+3), 0x1.2a1ab8p+1); | ||
| 204 | try expectEqual(log1p_32(0x1.52efd0p-1), 0x1.041a4ep-1); | ||
| 205 | try expectEqual(log1p_32(-0x1.a05cc8p-2), -0x1.0b3596p-1); | ||
| 206 | try expectEqual(log1p_32(0x1.1f9efap-1), 0x1.c88344p-2); | ||
| 207 | try expectEqual(log1p_32(0x1.8c5db0p-1), 0x1.258a8ep-1); | ||
| 208 | try expectEqual(log1p_32(-0x1.5b86eap-1), -0x1.22b542p+0); | ||
| 209 | } | ||
| 210 | |||
| 211 | test "log1p_32() boundary" { | ||
| 212 | try expectEqual(log1p_32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value | ||
| 213 | try expectEqual(log1p_32(0x1p-149), 0x1p-149); // Min positive input value | ||
| 214 | try expectEqual(log1p_32(-0x1p-149), -0x1p-149); // Min negative input value | ||
| 215 | try expectEqual(log1p_32(0x1p-126), 0x1p-126); // First subnormal | ||
| 216 | try expectEqual(log1p_32(-0x1p-126), -0x1p-126); // First negative subnormal | ||
| 217 | try expectEqual(log1p_32(-0x1.fffffep-1), -0x1.0a2b24p+4); // Last value before result is -inf | ||
| 218 | try expect(math.isNan(log1p_32(-0x1.000002p+0))); // First value where result is nan | ||
| 219 | } | ||
| 220 | |||
| 221 | test "log1p_64() special" { | ||
| 225 | try expect(math.isPositiveZero(log1p_64(0.0))); | 222 | try expect(math.isPositiveZero(log1p_64(0.0))); |
| 226 | try expect(math.isNegativeZero(log1p_64(-0.0))); | 223 | try expect(math.isNegativeZero(log1p_64(-0.0))); |
| 227 | try expect(math.isNegativeInf(log1p_64(-1.0))); | 224 | try expectEqual(log1p_64(-1.0), -math.inf(f64)); |
| 225 | try expectEqual(log1p_64(1.0), math.ln2); | ||
| 226 | try expectEqual(log1p_64(math.inf(f64)), math.inf(f64)); | ||
| 228 | try expect(math.isNan(log1p_64(-2.0))); | 227 | try expect(math.isNan(log1p_64(-2.0))); |
| 228 | try expect(math.isNan(log1p_64(-math.inf(f64)))); | ||
| 229 | try expect(math.isNan(log1p_64(math.nan(f64)))); | 229 | try expect(math.isNan(log1p_64(math.nan(f64)))); |
| 230 | try expect(math.isNan(log1p_64(math.snan(f64)))); | ||
| 231 | } | ||
| 232 | |||
| 233 | test "log1p_64() sanity" { | ||
| 234 | try expect(math.isNan(log1p_64(-0x1.02239f3c6a8f1p+3))); | ||
| 235 | try expectEqual(log1p_64(0x1.161868e18bc67p+2), 0x1.ad1bdd1e9e686p+0); // Disagrees with GCC in last bit | ||
| 236 | try expect(math.isNan(log1p_64(-0x1.0c34b3e01e6e7p+3))); | ||
| 237 | try expect(math.isNan(log1p_64(-0x1.a206f0a19dcc4p+2))); | ||
| 238 | try expectEqual(log1p_64(0x1.288bbb0d6a1e6p+3), 0x1.2a1ab8365b56fp+1); | ||
| 239 | try expectEqual(log1p_64(0x1.52efd0cd80497p-1), 0x1.041a4ec2a680ap-1); | ||
| 240 | try expectEqual(log1p_64(-0x1.a05cc754481d1p-2), -0x1.0b3595423aec1p-1); | ||
| 241 | try expectEqual(log1p_64(0x1.1f9ef934745cbp-1), 0x1.c8834348a846ep-2); | ||
| 242 | try expectEqual(log1p_64(0x1.8c5db097f7442p-1), 0x1.258a8e8a35bbfp-1); | ||
| 243 | try expectEqual(log1p_64(-0x1.5b86ea8118a0ep-1), -0x1.22b5426327502p+0); | ||
| 244 | } | ||
| 245 | |||
| 246 | test "log1p_64() boundary" { | ||
| 247 | try expectEqual(log1p_64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value | ||
| 248 | try expectEqual(log1p_64(0x1p-1074), 0x1p-1074); // Min positive input value | ||
| 249 | try expectEqual(log1p_64(-0x1p-1074), -0x1p-1074); // Min negative input value | ||
| 250 | try expectEqual(log1p_64(0x1p-1022), 0x1p-1022); // First subnormal | ||
| 251 | try expectEqual(log1p_64(-0x1p-1022), -0x1p-1022); // First negative subnormal | ||
| 252 | try expectEqual(log1p_64(-0x1.fffffffffffffp-1), -0x1.25e4f7b2737fap+5); // Last value before result is -inf | ||
| 253 | try expect(math.isNan(log1p_64(-0x1.0000000000001p+0))); // First value where result is nan | ||
| 230 | } | 254 | } |