Skip to content

Commit da8974e

Browse files
LewisGaulandrewrk
authored andcommitted
Add tests for exp(), noting last-bit discrepancy for exp(1.0) with math.e
1 parent 9da19e5 commit da8974e

File tree

1 file changed

+89
-20
lines changed

1 file changed

+89
-20
lines changed

lib/compiler_rt/exp.zig

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
1010
const math = std.math;
1111
const mem = std.mem;
1212
const expect = std.testing.expect;
13+
const expectEqual = std.testing.expectEqual;
1314
const common = @import("common.zig");
1415

1516
pub const panic = common.panic;
@@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
211212
}
212213
}
213214

214-
test "exp32" {
215-
const epsilon = 0.000001;
215+
test "expf() special" {
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 expectEqual(expf(-math.inf(f32)), 0.0);
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);
218-
try expect(math.approxEqAbs(f32, expf(0.0), 1.0, epsilon));
219-
try expect(math.approxEqAbs(f32, expf(0.2), 1.221403, epsilon));
220-
try expect(math.approxEqAbs(f32, expf(0.8923), 2.440737, epsilon));
221-
try expect(math.approxEqAbs(f32, expf(1.5), 4.481689, epsilon));
226+
test "expf() sanity" {
227+
try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);
228+
try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);
229+
try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
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);
222247
}
223248

224-
test "exp64" {
225-
const epsilon = 0.000001;
249+
test "expf() boundary" {
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));
232262
}
233263

234-
test "exp32.special" {
235-
try expect(math.isPositiveInf(expf(math.inf(f32))));
236-
try expect(math.isNan(expf(math.nan(f32))));
264+
test "exp() special" {
265+
try expectEqual(exp(0.0), 1.0);
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 expectEqual(exp(-math.inf(f64)), 0.0);
272+
try expect(math.isNan(exp(math.nan(f64))));
273+
try expect(math.isNan(exp(math.snan(f64))));
237274
}
238275

239-
test "exp64.special" {
240-
try expect(math.isPositiveInf(exp(math.inf(f64))));
241-
try expect(math.isNan(exp(math.nan(f64))));
276+
test "exp() sanity" {
277+
try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
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
242311
}

0 commit comments

Comments
 (0)