zig icon indicating copy to clipboard operation
zig copied to clipboard

Maths tests resurrected (exp and log functions) with bugfixes

Open LewisGaul opened this issue 3 years ago • 3 comments

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/
    • Sanity tests, taken from libc-test (e.g. exp.h)
    • Special cases (inf, nan, 0, ...)
    • Boundary cases (last value before inf, first subnormal, ...)
  • 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

  1. 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.
  1. 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

LewisGaul avatar Aug 07 '22 12:08 LewisGaul

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).

LewisGaul avatar Aug 07 '22 23:08 LewisGaul

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?

LewisGaul avatar Aug 09 '22 19:08 LewisGaul

Your code.

Vexu avatar Aug 09 '22 20:08 Vexu

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

andrewrk avatar Oct 20 '22 02:10 andrewrk

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.

LewisGaul avatar Oct 20 '22 13:10 LewisGaul