Maths tests resurrected (exp and log functions) with bugfixes
Reviving https://github.com/ziglang/zig/pull/10415.
- Add test framework (at
lib/std/math/test.zig) for maths functions that take in a float and output a float of the same type, e.g.exp() - Create tests for all exp/log functions under
lib/std/math/test/ - Remove special case tests from function implementation modules to avoid duplication (leave the basic tests intact)
- Bugfixes uncovered by improved testing:
-
exp2_32()flushing to zero too soon -
expm1_32()giving incorrect results for a certain range of small negative inputs -
ln64()giving incorrect results for positive subnormal inputs - Some functions returning canonical NaN instead of passing through input NaNs unchanged (as per Musl and GCC)
-
log10_64()returning 32-bit inf and NaN, which would be fine as it's cast up, except casting NaN results in failure to pass through the input unchanged
-
Example output with 'log_level = .info' for debugging (failing test added for illustration):
$./zig test --zig-lib-dir lib lib/std/math/test.zig --test-filter 'exp32() boundary'
Test [1/1] test.exp.test "math.exp32() boundary"... [default] (info):
[default] (info): IN: 0x42B97217 0x1.72e42ep6 9.27228317e+01
[default] (info): OUT: 0x7F800000 inf inf
[default] (info): EXP: 0x7F7FFF84 0x1.ffff08p127 3.40279851e+38
FAILURE: expected exp(0x1.72e42ep6)->0x1.ffff08p127, got inf (32-bit)
[default] (info):
[default] (info): IN: 0x42B17218 0x1.62e43p6 8.87228393e+01
[default] (info): OUT: 0x7F800000 inf inf
[default] (info):
[default] (info): IN: 0x7F7FFFFF 0x1.fffffep127 3.40282346e+38
[default] (info): OUT: 0x7F800000 inf inf
[default] (info):
[default] (info): IN: 0x00000001 0x0.000002p-126 1.40129846e-45
[default] (info): OUT: 0x3F800000 0x1p0 1.0e+00
[default] (info):
[default] (info): IN: 0x80000001 -0x0.000002p-126 -1.40129846e-45
[default] (info): OUT: 0x3F800000 0x1p0 1.0e+00
[default] (info):
[default] (info): IN: 0x00800000 0x1p-126 1.17549435e-38
[default] (info): OUT: 0x3F800000 0x1p0 1.0e+00
[default] (info):
[default] (info): IN: 0x80800000 -0x1p-126 -1.17549435e-38
[default] (info): OUT: 0x3F800000 0x1p0 1.0e+00
[default] (info):
[default] (info): IN: 0xC2CFF1B4 -0x1.9fe368p6 -1.03972076e+02
[default] (info): OUT: 0x00000001 0x0.000002p-126 1.40129846e-45
[default] (info):
[default] (info): IN: 0xC2CFF1B5 -0x1.9fe36ap6 -1.03972084e+02
[default] (info): OUT: 0x00000000 0x0.0p0 0.0e+00
[default] (info):
[default] (info): IN: 0xC2AEAC4F -0x1.5d589ep6 -8.73365402e+01
[default] (info): OUT: 0x00800026 0x1.00004cp-126 1.17549967e-38
[default] (info):
[default] (info): IN: 0xC2AEAC50 -0x1.5d58ap6 -8.73365478e+01
[default] (info): OUT: 0x007FFFE6 0x0.ffffccp-126 1.17549070e-38
[default] (info):
[default] (info): Subtest summary: 10 passed; 1 failed
Test [1/1] test.exp.test "math.exp32() boundary"... FAIL (Failure)
/mnt/c/Users/legaul/repos/zig/lib/std/math/test.zig:96:17: 0x21906a in Testcase(std.math.exp,"exp",f32).run (test)
return error.TestExpectedEqual;
^
/mnt/c/Users/legaul/repos/zig/lib/std/math/test.zig:120:23: 0x217ecd in runTests (test)
if (failures > 0) return error.Failure;
^
/mnt/c/Users/legaul/repos/zig/lib/std/math/test/exp.zig:78:5: 0x217398 in test.exp.test "math.exp32() boundary" (test)
try runTests(cases);
^
0 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
lib/std/math/zig-cache/o/7af2224de94b200df723802d7c69b7dc/test /mnt/c/Users/legaul/repos/zig/build/zig
Previous suggestions from @matu3ba that I'm considering out of scope of this PR:
-
Adding tests for all extreme values (e.g. +/- inf) rather than targeted boundary cases (see https://github.com/ziglang/zig/pull/10415#discussion_r775308449)
-
Taking on all Musl tests
2 ideas for discussion
- port libc-test to zig
- 1.1. Port the test running functions from libc-test, which is the test library of musl.
- 1.2. Use scripts to generate the test code from the musl test macros.
- more code to write, but less dependency on C/clang
- caveat, but actually a feature: Include the comments in the generated test code.
- vendor libc-test
- 2.1 use zig stubs for the build scripts and test calls
- less code to write, but more dependency on C/clang
If anyone has any suggestions on how to debug the tests failing in the CI that would be welcome... Seems possibly something to do with wasi and windows (I'm developing on WSL1 where the tests all pass).
The ci.ziglang.org failures are caused by your code not being compatible with stage3. Azure failure I have no clue about.
What's the resolution to the code that's not compatible with stage3? Is that an issue with stage3 or with my code?
Your code.
I'm afraid we have found ourselves in the same situation again. Despite this PR looking extremely valuable, all CI checks are failing, and there have been no changes made to this PR in over 30 days. I hope you'll give it another shot...
For posterity, here is the freebsd CI failure copy pasted:
/usr/home/build/zig/lib/std/math/test/exp.zig:62:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/exp.zig:62:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/exp.zig:114:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/exp.zig:114:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/exp2.zig:51:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/exp2.zig:51:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/exp2.zig:93:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/exp2.zig:93:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/expm1.zig:50:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/expm1.zig:50:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/expm1.zig:93:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/expm1.zig:93:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/ln.zig:54:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/ln.zig:54:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/ln.zig:92:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/ln.zig:92:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log2.zig:53:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log2.zig:53:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log2.zig:91:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log2.zig:91:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log10.zig:54:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log10.zig:54:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log10.zig:92:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log10.zig:92:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log1p.zig:53:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log1p.zig:53:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test/log1p.zig:91:38: error: unable to resolve comptime value
/usr/home/build/zig/lib/std/math/test/log1p.zig:91:38: note: slice value being concatenated must be comptime-known
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
/usr/home/build/zig/lib/std/math/test.zig:149:31: error: cannot store runtime value in compile time variable
The problem is I didn't know how to reproduce or debug the issue. I can try again in the development environment that's available to me with latest stage3 (I have time available next week where I'd been planning on having another go). If I still can't reproduce I'm afraid I think I'll need some help to be able to get anywhere with it! Still keen to work on it and push it through.