116 Commits

Author SHA1 Message Date
Trevor Gross
2d857e1c21 Replace HasDomain to enable multi-argument edge case and domain tests
This also allows reusing the same generator logic between logspace tests
and extensive tests, so comes with a nice bit of cleanup.

Changes:

* Make the generator part of `CheckCtx` since a `Generator` and
  `CheckCtx` are almost always passed together.
* Rename `domain_logspace` to `spaced` since this no longer only
  operates within a domain and we may want to handle integer spacing.
* Domain is now calculated at runtime rather than using traits, which is
  much easier to work with.
* With the above, domains for multidimensional functions are added.
* The extensive test generator code tests has been combined with the
  domain_logspace generator code. With this, the domain tests have just
  become a subset of extensive tests. These were renamed to "quickspace"
  since, technically, the extensive tests are also "domain" or "domain
  logspace" tests.
* Edge case generators now handle functions with multiple inputs.
* The test runners can be significantly cleaned up and deduplicated.
2025-01-16 01:10:26 +00:00
Trevor Gross
45e3b98165 Add an override for a recent failure
Failed on i686:

    ──── STDERR:             libm-test::bench/random y1f/crate

    thread 'main' panicked at crates/libm-test/benches/random.rs:76:65:
    called `Result::unwrap()` on an `Err` value: ynf

    Caused by:
        0:
               input:    (213, 109.15641) (0x000000d5, 0x42da5015)
               expected: -3.3049217e38          0xff78a27a
               actual:   -inf                   0xff800000
        1: mismatched infinities
2025-01-15 01:05:38 +00:00
Trevor Gross
13b5bf3959 Add fdimf16 and fdimf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-13 14:04:54 +00:00
Trevor Gross
23dfe62a9d Format the MPFR manual implementation list 2025-01-13 06:22:25 -05:00
Trevor Gross
b558b365d3 Add truncf16 and truncf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-13 10:12:09 +00:00
Trevor Gross
dfa694a8e4 Add a utility crate for quick evaluation
Introduce a simple binary that can run arbitrary input against any of
the available implementations (musl, MPFR, our libm). This provides an
easy way to check results, or run specific cases against a debugger.

Examples:

    $ cargo run -p util -- eval libm pow 1.6 2.4
    3.089498284311124
    $ cargo run -p util -- eval mpfr pow 1.6 2.4
    3.089498284311124
    $ cargo run -p util -- eval musl tgamma 1.2344597839132
    0.9097442657960874
    $ cargo run -p util -- eval mpfr tgamma 1.2344597839132
    0.9097442657960874
    $ cargo run -p util -- eval libm tgamma 1.2344597839132
    0.9097442657960871
    $ cargo run -p util -- eval musl sincos 3.1415926535
    (8.979318433952318e-11, -1.0)
2025-01-13 04:43:48 -05:00
Trevor Gross
3de783c40f Enable build-mpfr and build-musl by default
Most users who are developing this crate are likely running on a Unix
system, since there isn't much to test against otherwise. For
convenience, enable the features required to run these tests by default.
2025-01-13 03:53:46 +00:00
Trevor Gross
504616d5a0 Rename the test-multiprecision feature to build-mpfr
Currently the features that control what we test against are
`build-musl` and `test-multiprecision`. I didn't name them very
consistently and there isn't really any reason for that.

Rename `test-multiprecision` to `build-mpfr` to better reflect what it
actually does and to be more consistent with `build-musl`.
2025-01-13 03:25:19 +00:00
Trevor Gross
b50ea809ff Add a new precision adjustment for i586 exp2f
There was a recent failure from the random tests:

     ---- mp_random_exp2f stdout ----
    Random Mpfr exp2f arg 1/1: 10000 iterations (10000 total) using `LIBM_SEED=fqgMuzs6eqH1VZSEmQpLnThnaIyRUOWe`

    thread 'mp_random_exp2f' panicked at crates/libm-test/tests/multiprecision.rs:41:49:
    called `Result::unwrap()` on an `Err` value:
        input:    (127.97238,) (0x42fff1dc,)
        expected: 3.3383009e38           0x7f7b2556
        actual:   inf                    0x7f800000

    Caused by:
        mismatched infinities

Add an xfail for mismatched infinities on i586.
2025-01-12 03:48:13 -05:00
Trevor Gross
228c716a43 Add a new precision adjustment for i586 rint
`rint` had a couple recent failures from the random tests:

    ---- mp_random_rint stdout ----
    Random Mpfr rint arg 1/1: 10000 iterations (10000 total) using `LIBM_SEED=Fl1f69DaJnwkHN2FeuCXaBFRvJYsPvEY`

    thread 'mp_random_rint' panicked at crates/libm-test/tests/multiprecision.rs:41:49:
    called `Result::unwrap()` on an `Err` value:
        input:    (-849751480.5001163,) (0xc1c95316dc4003d0,)
        expected: -849751481.0           0xc1c95316dc800000
        actual:   -849751480.0           0xc1c95316dc000000

    Caused by:
        ulp 8388608 > 100000

And:

    ---- mp_random_rint stdout ----
    Random Mpfr rint arg 1/1: 10000 iterations (10000 total) using `LIBM_SEED=XN7VCGhX3Wu6Mzn8COvJPITyZlGP7gN7`

    thread 'mp_random_rint' panicked at crates/libm-test/tests/multiprecision.rs:41:49:
    called `Result::unwrap()` on an `Err` value:
        input:    (-12493089.499809155,) (0xc167d4242ffe6fc5,)
        expected: -12493089.0            0xc167d42420000000
        actual:   -12493090.0            0xc167d42440000000

    Caused by:
        ulp 536870912 > 100000

It seems we just implement an incorrect rounding mode. Replace the
existing `rint` override with an xfail if the difference is 0.0 <= ε <=
1.0.
2025-01-12 03:48:13 -05:00
Trevor Gross
5b1c1fca03 Expose C versions of libm functions in the cb crate
`compiler_builtins` exposes an `extern "C"` version of `libm` routines,
so add the same here. There really isn't much to test here (unless we
later add tests against C `libm` suites), but one nice benefit is this
gives us a library with unmangled names that is easy to `objdump`. In
accordance with that, also update `cb` to be a `staticlib`.

Unfortunately this also means we have to remove it from the workspace,
since Cargo doesn't allow setting `panic = "abort"` for a single crate.
2025-01-12 03:29:40 -05:00
Trevor Gross
721960c172 Remove ExpInt from Float, always use i32 instead
`ExpInt` is likely to only have performance benefits on 16-bit
platforms, but makes working with the exponent more difficult. It seems
like a worthwhile tradeoff to instead just use `i32`, so do that here.
2025-01-11 19:22:01 -05:00
Trevor Gross
a0c03b2537 Add tests against MPFR for remquo and remquof
Rug does not yet expose this function, but it is possible to use the
MPFR bindings directly.
2025-01-10 16:04:16 -05:00
beetrees
76714a5657 Make extensive tests exhaustive if there are enough iterations available 2025-01-07 17:44:06 -05:00
Trevor Gross
0359db23c7 Increase the allowed ULP for tgammaf
Extensive tests report that the precision isn't actually 0:

    ---- mp_extensive_tgammaf ----

        input:    (-0.00063536887,) (0xba268ee2,)
        expected: -1574.4668             0xc4c4cef0
        actual:   -1574.4667             0xc4c4ceef

    Caused by:
        ulp 1 > 0

Update ULP to reflect this. After this change, `tgammaf` extensive tests
pass.
2025-01-06 22:19:49 -05:00
Trevor Gross
05b87887f4 Increase the allowed precision for failing tests on i586
These will need to be fixed, for now just xfail them so this doesn't
block better test coverage.
2025-01-06 15:41:39 -05:00
Trevor Gross
a9407010b4 Enable MPFR tests on i586
MPFR does build and run correctly without SSE, but requires
`force-cross` be enabled.
2025-01-06 15:41:39 -05:00
Trevor Gross
449d41a24f Loosen precision on i586 based on new tests 2025-01-06 11:46:01 +00:00
Trevor Gross
4b014bff40 Add an override for failing ceil/floor tests on i586 2025-01-06 11:44:28 +00:00
Trevor Gross
a3363785ea Add domain and edge case tests to musl
This provides an increase in test coverage on platforms that cannot test
against MPFR.
2025-01-06 09:30:41 +00:00
Trevor Gross
6b5e8b20f0 Add test infrastructure for f16 and f128
Update test traits to support `f16` and `f128`, as applicable. Add the
new routines (`fabs` and `copysign` for `f16` and `f128`) to the list of
all operations.
2025-01-06 04:10:51 -05:00
Trevor Gross
05a1f4a982 Update precision based on failures from extensive tests 2025-01-06 08:22:13 +00:00
Trevor Gross
1bbf8b12da Add extensive and exhaustive tests
Add a generator that will test all inputs for input spaces `u32::MAX` or
smaller (e.g. single-argument `f32` routines).  For anything larger,
still run approximately `u32::MAX` tests, but distribute inputs evenly
across the function domain.

Since we often only want to run one of these tests at a time, this
implementation parallelizes within each test using `rayon`. A custom
test runner is used so a progress bar is possible.

Specific tests must be enabled by setting the `LIBM_EXTENSIVE_TESTS`
environment variable, e.g.

    LIBM_EXTENSIVE_TESTS=all_f16,cos,cosf cargo run ...

Testing on a recent machine, most tests take about two minutes or less.
The Bessel functions are quite slow and take closer to 10 minutes, and
FMA is increased to run for about the same.
2025-01-06 08:22:13 +00:00
Trevor Gross
f453f5e5b5 Add tests against MPFR for ilogb and ilogbf 2025-01-06 01:29:22 -05:00
Trevor Gross
206bf326d5 Increase the precision for jn and jnf
New random seeds seem to indicate that this test does have some more
failures, this is a recent failure on i586:

    ---- musl_random_jnf stdout ----
    Random Musl jnf arg 1/2: 100 iterations (10000 total) using `LIBM_SEED=nLfzQ3U1OBVvqWaMBcto84UTMsC5FIaC`
    Random Musl jnf arg 2/2: 100 iterations (10000 total) using `LIBM_SEED=nLfzQ3U1OBVvqWaMBcto84UTMsC5FIaC`

    thread 'musl_random_jnf' panicked at crates/libm-test/tests/compare_built_musl.rs:43:51:
    called `Result::unwrap()` on an `Err` value:
        input:    (205, 5497.891) (0x000000cd, 0x45abcf21)
        expected: 7.3291517e-6           0x36f5ecef
        actual:   7.331668e-6            0x36f6028c

    Caused by:
        ulp 5533 > 4000

It seems unlikely that `jn` would somehow have better precision than
`j0`/`j1`, so just use the same precision.
2025-01-05 23:37:12 -05:00
Trevor Gross
ea21b6045f Rename unstable-test-support to unstable-public-internals
The `support` module that this feature makes public will be useful for
implementations in `compiler-builtins`, not only for testing. Give this
feature a more accurate name.
2025-01-05 22:13:11 -05:00
Trevor Gross
cc6a84bf43 Update precision based on new test results 2025-01-06 01:51:37 +00:00
Trevor Gross
37dbc534cb Rewrite the random test generator
Currently, all inputs are generated and then cached. This works
reasonably well but it isn't very configurable or extensible (adding
`f16` and `f128` is awkward).

Replace this with a trait for generating random sequences of tuples.
This also removes possible storage limitations of caching all inputs.
2025-01-06 00:32:21 +00:00
Trevor Gross
b78f7b7b48 Add an iterator that ensures known size
Introduce the `KnownSize` iterator wrapper, which allows providing the
size at construction time. This provides an `ExactSizeIterator`
implemenation so we can check a generator's value count during testing.
2025-01-06 00:32:21 +00:00
Trevor Gross
9a7a519370 Streamline the way that test iteration count is determined
Currently, tests use a handful of constants to determine how many
iterations to perform: `NTESTS`, `AROUND`, and `MAX_CHECK_POINTS`. This
configuration is not very straightforward to adjust and needs to be
repeated everywhere it is used.

Replace this with new functions in the `run_cfg` module that determine
iteration counts in a more reusable and documented way.

This only updates `edge_cases` and `domain_logspace`, `random` is
refactored in a later commit.
2025-01-06 00:32:21 +00:00
Trevor Gross
b7b22b54c0 Add a way for tests to log to a file
Occasionally it is useful to see some information from running tests
without making everything noisy from `--nocapture`. Add a function to
log this kind of output to a file, and print the file as part of CI.
2025-01-06 00:32:21 +00:00
Trevor Gross
4b15d9e5e3 Add tests against MPFR for scalbn{f} and ldexp{f} 2025-01-05 18:49:54 -05:00
Trevor Gross
e9bc33e8d3 Add tests against MPFR for frexp and frexpf
This implementation comes from `rug::Float::to_f32_exp` [1].

[1]: https://docs.rs/rug/1.26.1/rug/struct.Float.html#method.to_f32_exp
2025-01-05 18:33:20 -05:00
Trevor Gross
59964fbbca Add tests against MPFR for modf and modff
Rug provides `trunc_fract_round`, which implements `modf`, use it to add
a test.
2025-01-05 18:17:27 -05:00
Trevor Gross
f99d8acc20 Clean up integers stored in MpTy
There isn't any need to cache the integer since it gets provided as an
argument anyway. Simplify this in `jn` and `yn`.
2025-01-04 21:25:22 -05:00
Trevor Gross
d50c12b219 precision: Sort ilogb with other precise operations
This is a nonfunctional change.
2025-01-04 06:32:38 -05:00
Trevor Gross
3030182c66 Change to exhaustive matching for default_ulp
Make it more obvious what the expected ULP for a given routine is. This
also narrows ULP to 0 for operations that require exact results.
2025-01-03 18:47:34 -05:00
Trevor Gross
14e6d05dfb Use intrinsics for abs and copysign when available
Currently our implementations for `abs` and `copysign` are defined on
the trait, and these are then called from `generic`. It would be better
to call core's `.abs()` / `.copysign(y)`, but we can't do this in the
generic because calling the standalone function could become recursive
(`fabsf` becomes `intrinsics::fabsf32`, that may lower to a call to
`fabsf`).

Change this so the traits uses the call to `core` if available, falling
back to a call to the standalone generic function.

In practice the recursion isn't likely to be a problem since LLVM
probably always lowers `abs`/`copysign` to assembly, but this pattern
should be more correct for functions that we will add in the future
(e.g. `fma`).

This should eventually be followed by a change to call the trait methods
rather than `fabs`/`copysign` directly.
2025-01-03 07:50:56 -05:00
Trevor Gross
3fb16fbdbe macros: Always emit f16_enabled and f128_enabled attributes
Once we start addinf `f16` and `f128` routines, we will need to have
this cfg for almost all uses of `for_each_function`. Rather than needing
to specify this each time, always emit `#[cfg(f16_enabled)]` or
`#[cfg(f128_enabled)]` for each function that uses `f16` or `f128`,
respectively.
2025-01-02 17:38:09 -05:00
Trevor Gross
e754ecb6d9 Add missing functions to the macro list
Now that we are using rustdoc output to locate public functions, the
test is indicating a few that were missed since they don't have their
own function. Update everything to now include the following routines:

* `erfc`
* `erfcf`
* `y0`
* `y0f`
* `y1`
* `y1f`
* `yn`
* `ynf`
2025-01-01 11:15:48 +00:00
Trevor Gross
ed72c4ec69 Use rustdoc output to create a list of public API
Rather than collecting a list of file names in `libm-test/build.rs`,
just use a script to parse rustdoc's JSON output.
2025-01-01 11:01:50 +00:00
Trevor Gross
cf58a7ce90 Remove lossy casting in logspace
Currently `logspace` does a lossy cast from `F::Int` to `usize`. This
could be problematic in the rare cases that this is called with a step
count exceeding what is representable in `usize`.

Resolve this by instead adding bounds so the float's integer type itself
can be iterated.
2024-12-30 01:11:59 -05:00
Trevor Gross
e8c501861a Set the allowed FMA ULP to 0
It is currently getting the default of 1 or 2. Since this operation
should always be infinite precision, no deviation is allowed.
2024-12-29 21:10:57 -05:00
Trevor Gross
7082f9baf7 Use CheckCtx in more places
Rather than passing names or identifiers, just pass `CheckCtx` in a few
more places.
2024-12-29 03:23:57 -05:00
Trevor Gross
86aeee818b Move CheckBasis and CheckCtx to a new run_cfg module
These are used more places than just test traits, so this new module
should be a better home. `run_cfg` will also be expanded in the near
future.
2024-12-29 03:23:57 -05:00
Trevor Gross
6e97fef9c9 Add ALL, from_str and math_op to Identifier
Introduce new API to iterate the function list and associate items with
their `MathOp`.
2024-12-29 08:07:40 +00:00
Trevor Gross
b9ecacf03b Add new trait implementations for Identifier and BaseName
These allow for more convenient printing, as well as storage in map
types.
2024-12-29 08:07:21 +00:00
Trevor Gross
fc4b88aecd Include shared.rs in libm_test::op
These types from `libm-macros` provide a way to get information about an
operation at runtime, rather than only being encoded in the type system.
Include the file and reexport relevant types.
2024-12-29 08:06:46 +00:00
Trevor Gross
1069346b6d Move the macro's input function list to a new module shared
This will enable us to `include!` the file to access these types in
`libm-test`, rather than somehow reproducing the types as part of the
macro. Ideally `libm-test` would just `use` the types from `libm-macros`
but proc macro crates cannot currently export anything else.

This also adjusts naming to closer match the scheme described in
`libm_test::op`.
2024-12-29 08:03:19 +00:00
Trevor Gross
d86f8bee8b Add a way to plot the output from generators
For visualization, add a simple script for generating scatter plots and
a binary (via examples) to plot the inputs given various domains.
2024-12-29 07:47:21 +00:00