authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-17 18:44:51+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-17 18:44:51+02:00
loga35688b6135bf456609e64015bffd4d3edeac998
treef19cfc5871e6e936e63da98f118122d67b1e22a2
parente62e42f0d901fd1b053b22ecd14a42bdac7dbac4
parent03dfd2ecc37cc99b15d4ce3ff19147230ddc8fd4
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20069 from LewisGaul/math-tests-simplified

Math tests simplified (exp and log functions) with bugfixes

7 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;
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
13const common = @import("common.zig");14const common = @import("common.zig");
1415
15pub const panic = common.panic;16pub 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}
213214
214test "exp32" {215test "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}
216225
217 try expect(expf(0.0) == 1.0);226test "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}
223248
224test "exp64" {249test "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
226261
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}
233263
234test "exp32.special" {264test "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}
238275
239test "exp64.special" {276test "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
299test "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;
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
13const common = @import("common.zig");14const common = @import("common.zig");
1415
15pub const panic = common.panic;16pub 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 <= -15061 // 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};
459460
460test "exp2_32" {461test "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}
462471
463 try expect(exp2f(0.0) == 1.0);472test "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}
470484
471test "exp2_64" {485test "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}
473498
474 try expect(exp2(0.0) == 1.0);499test "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}
481509
482test "exp2_32.special" {510test "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}
486522
487test "exp2_64.special" {523test "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 @@
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const testing = std.testing;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const arch = builtin.cpu.arch;12const arch = builtin.cpu.arch;
12const common = @import("common.zig");13const common = @import("common.zig");
1314
...@@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 {...@@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 {
110111
111 // subnormal, scale x112 // 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}
161162
162test "ln32" {163test "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}
164174
165 try testing.expect(math.approxEqAbs(f32, logf(0.2), -1.609438, epsilon));175test "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}
172187
173test "ln64" {188test "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}
175197
176 try testing.expect(math.approxEqAbs(f64, log(0.2), -1.609438, epsilon));198test "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}
183209
184test "ln32.special" {210test "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}
190222
191test "ln64.special" {223test "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 @@
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const testing = std.testing;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;13const arch = builtin.cpu.arch;
13const common = @import("common.zig");14const 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}
189190
190test "log10_32" {191test "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}
192203
193 try testing.expect(math.approxEqAbs(f32, log10f(0.2), -0.698970, epsilon));204test "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}
200216
201test "log10_64" {217test "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}
203226
204 try testing.expect(math.approxEqAbs(f64, log10(0.2), -0.698970, epsilon));227test "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}
211239
212test "log10_32.special" {240test "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}
218252
219test "log10_64.special" {253test "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");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const expect = std.testing.expect;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;13const arch = builtin.cpu.arch;
13const common = @import("common.zig");14const 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}
181182
182test "log2_32" {183test "log2f() special" {
183 const epsilon = 0.000001;184 try expectEqual(log2f(0.0), -math.inf(f32));
184185 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}
191194
192test "log2_64" {195test "log2f() sanity" {
193 const epsilon = 0.000001;196 try expect(math.isNan(log2f(-0x1.0223a0p+3)));
194197 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}
201207
202test "log2_32.special" {208test "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}
208218
209test "log2_64.special" {219test "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
231test "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
244test "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");
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
1314
14/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 115/// 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;
4041
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;
4546
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 }
149150
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}
288289
289test expm1 {290test "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}
293299
294test expm1_32 {300test "expm1_32() sanity" {
295 const epsilon = 0.000001;301 try expectEqual(expm1_32(-0x1.0223a0p+3), -0x1.ffd6e0p-1);
296302 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}
303312
304test expm1_64 {313test "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}
306327
328test "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}
313337
314test "expm1_32.special" {338test "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}
319350
320test "expm1_64.special" {351test "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");
8const math = std.math;8const math = std.math;
9const mem = std.mem;9const mem = std.mem;
10const expect = std.testing.expect;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
1112
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}
184185
185test log1p {186test "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
190test 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
202test 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
214test "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}
222197
223test "log1p_64.special" {198test "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
211test "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
221test "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
233test "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
246test "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}