140 Commits

Author SHA1 Message Date
Trevor Gross
375cb5402f Resolve small errors identified by recent clippy 2025-04-08 22:04:58 -05:00
Trevor Gross
725759602a Upgrade all dependencies to the latest
This is mostly done to get the latest version of `rand`, which includes
some breaking changes.
2025-03-18 19:46:34 -05:00
Trevor Gross
c01153d29b Make fma a trait method on Float 2025-02-12 10:27:11 +00:00
Trevor Gross
dea2ed3d1d Scale test iteration count at a later point
Currently the argument multiplier and large float multiplier happen
before selecting count based on generator. However, this means that
bivariate and trivariate functions don't get scaled at all (except for
the special cased fma).

Move this scaling to a later point.
2025-02-12 04:07:13 -06:00
Trevor Gross
e106d63516 Add a way to print inputs on failure
When there is a panic in an extensive test, tracing down where it came
from can be difficult since no information is provides (messeges are
e.g. "attempted to subtract with overflow"). Resolve this by calling the
functions within `panic::catch_unwind`, printing the input, and
continuing.
2025-02-11 22:33:08 -06:00
Trevor Gross
7db47c741c Check exact values for specified cases
Inputs in `case_list` shouldn't hit xfails or increased ULP tolerance.
Ensure that overrides are skipped when testing against MPFR or a
specified value and that NaNs, if any, are checked bitwise.
2025-02-11 02:27:13 -06:00
Trevor Gross
53a055049c Add roundeven{,f,f16,f128}
C23 specifies a new set of `roundeven` functions that round to the
nearest integral, with ties to even. It does not raise any floating
point exceptions.

This behavior is similar to two other functions:

1. `rint`, which rounds to the nearest integer respecting rounding mode
   and possibly raising exceptions.
2. `nearbyint`, which is identical to `rint` except it may not raise
   exceptions.

Technically `rint`, `nearbyint`, and `roundeven` all behave the same in
Rust because we assume default floating point environment. The backends
are allowed to lower to `roundeven`, however, so we should provide it in
case the fallback is needed.

Add the `roundeven` family here and convert `rint` to a function that
takes a rounding mode. This currently has no effect.
2025-02-11 00:55:22 -06:00
Trevor Gross
e79fb05b25 Increase allowed offset from infinity for ynf
Failed with

    called `Result::unwrap()` on an `Err` value: ynf

    Caused by:
        0:
               input:    (223, 116.89665)
               as hex:   (, 0x1.d3962cp+6)
               as bits:  (0x000000df, 0x42e9cb16)
               expected: -3.1836905e38          -0x1.df074cp+127 0xff6f83a6
               actual:   -inf                   -inf 0xff800000
        1: mismatched infinities
2025-02-10 16:17:33 -06:00
Trevor Gross
669731335e Add fminimum, fmaximum, fminimum_num, and fmaximum_num
These functions represent new operations from IEEE 754-2019. Introduce
them for all float sizes.
2025-02-10 16:17:33 -06:00
Trevor Gross
35f5731d62 Introduce a trait constant for the minimum positive normal value 2025-02-10 08:17:57 +00:00
Trevor Gross
2f0685a9a2 Implement u256 with two u128s rather than u64
This produces better assembly, e.g. on aarch64:

            .globl  libm::u128_wmul
            .p2align        2
    libm::u128_wmul:
    Lfunc_begin124:
            .cfi_startproc
            mul x9, x2, x0
            umulh x10, x2, x0
            umulh x11, x3, x0
            mul x12, x3, x0
            umulh x13, x2, x1
            mul x14, x2, x1
            umulh x15, x3, x1
            mul x16, x3, x1
            adds x10, x10, x14
            cinc x13, x13, hs
            adds x13, x13, x16
            cinc x14, x15, hs
            adds x10, x10, x12
            cinc x11, x11, hs
            adds x11, x13, x11
            stp x9, x10, [x8]
            cinc x9, x14, hs
            stp x11, x9, [x8, rust-lang/libm#16]
            ret

The original was ~70 instructions so the improvement is significant.
With these changes, the result is reasonably close to what LLVM
generates using `u256` operands [1].

[1]: https://llvm.godbolt.org/z/re1aGdaqY
2025-02-09 23:41:51 -06:00
Trevor Gross
1efdc96974 Increase the tolerance for jn and yn
These still fail random tests, e.g.:

    called `Result::unwrap()` on an `Err` value: jn

    Caused by:
        0:
               input:    (1068, -16013.98381387313)
               as hex:   (, -0x1.f46fded9ced39p+13)
               as bits:  (0x0000042c, 0xc0cf46fded9ced39)
               expected: 6.7603314308122506e-6  0x1.c5ad9c102d413p-18 0x3edc5ad9c102d413
               actual:   6.7603314308006335e-6  0x1.c5ad9c1029e80p-18 0x3edc5ad9c1029e80
        1: ulp 13715 > 4000

    Caused by:
        0:
               input:    (195, 42147.94)
               as hex:   (, 0x1.4947e2p+15)
               as bits:  (0x000000c3, 0x4724a3f1)
               expected: -2.13669e-7            -0x1.cad9c6p-23 0xb4656ce3
               actual:   -2.1376937e-7          -0x1.cb10f4p-23 0xb465887a
        1: ulp 7063 > 4000

    Caused by:
        0:
               input:    (194, 740.1916)
               as hex:   (, 0x1.721886p+9)
               as bits:  (0x000000c2, 0x44390c43)
               expected: 1.212096e-6            0x1.455e9ap-20 0x35a2af4d
               actual:   1.2172386e-6           0x1.46c000p-20 0x35a36000
        1: ulp 45235 > 10000

Increase allowed precision to avoid spurious failures.
2025-02-09 22:07:40 -06:00
Trevor Gross
900b61f363 Change how operators are black_boxed
For some reason, the upcoming limb changes in [1] seem to ignore the
black boxing when applied to the operator function. Changing to instead
black box the inputs appears to fix this.

[1]: https://github.com/rust-lang/libm/pull/503
2025-02-08 04:49:44 -06:00
Trevor Gross
0a43f24a30 Add simple icount benchmarks for u256 operations 2025-02-08 02:02:45 -06:00
Trevor Gross
35c201c37f Decrease the allowed error for cbrt
With the correctly rounded implementation, we can reduce the ULP
requirement for `cbrt` to zero. There is still an override required for
`i586` because of the imprecise FMA.
2025-02-07 23:04:53 +00:00
Trevor Gross
d35a443527 fmaf128: fix exponent calculation for subnormals
When `fmaf128` was introduced in [1], it included a bug where `self`
gets returned rather than the expected minimum positive value. Resolve
this and add a regression test.

[1]: https://github.com/rust-lang/libm/pull/494
2025-02-07 02:47:06 +00:00
Trevor Gross
f028611faf Check more subnormal values during edge cases tests
Add checks at the max subnormal value and a couple values scatted
throughout the subnormal range. This helped identifiy a bug in
`fmaf128`.

As part of this, slightly reduce the amount of edge cases checked
without optimizations because the change makes it become noticible.
2025-02-07 02:47:06 +00:00
Trevor Gross
aac4901953 Add better edge case testing for scalbn
Include integer values around the minimum and maximum exponents which
require different behavior in the scale functions.
2025-02-06 19:37:20 -06:00
Trevor Gross
9223d60dfa Add fmaf128
Resolve all remaining `f64`-specific items in the generic version of
`fma`, then expose `fmaf128`.
2025-02-06 18:41:45 -06:00
Trevor Gross
4bf116f146 Add an integration test that verifies a list of cases
We need someplace to collect known failures, previous regressions, edge
cases that are difficult to construct from generics, and similar.
Introduce this here.
2025-02-06 01:40:04 -06:00
Trevor Gross
23989245ce fma: Ensure zero has the correct sign
Currently, `fma(tiny, -tiny, 0.0)` returns 0.0 while the answer should
be -0.0. This is because `-0.0 + 0.0 = +0.0` in the default rounding
mode; however, the result should be negative. Musl has the same pattern
but that version worked because the C compiler was contracting `x*y + z`
to (ironically) `fmadd`.

Musl was fixed in 9683bd6241 ("math: fix fma(x,y,0) when x*y rounds to
-0"). Add the same fix here, which allows dropping the xfails.
2025-02-06 02:03:19 +00:00
Trevor Gross
3fbe59f850 Print the hex float format upon failure
Now that we have a hex float formatter, make use of it for test output.
This produces values that are easier to read than the bitwise hex
representation.

Example:

    thread 'mp_quickspace_fmaf128' panicked at crates/libm-test/tests/multiprecision.rs:17:48:
    called `Result::unwrap()` on an `Err` value:
        input:    (0xe38d71c71c71c71c71c71c71c71c71c8, 0xe38d71c71c71c71c71c71c71c71c71c8, 0xffff0000000000000000000000000000)
        as hex:   (-0x1.71c71c71c71c71c71c71c71c71c8p+9102, -0x1.71c71c71c71c71c71c71c71c71c8p+9102, -inf)
        as bits:  (0xe38d71c71c71c71c71c71c71c71c71c8, 0xe38d71c71c71c71c71c71c71c71c71c8, 0xffff0000000000000000000000000000)
        expected: 0xffff0000000000000000000000000000 -inf 0xffff0000000000000000000000000000
        actual:   0x7fff8000000000000000000000000000 NaN 0x7fff8000000000000000000000000000

    Caused by:
        real value != NaN
2025-02-05 18:30:30 -06:00
Trevor Gross
e01ce5d53a Commonize the signature for all instances of get_test_cases
In order to make these more interchangeable in more places, always
return `(impl Iterator, u64)`. This will facilitate using other
generators for extensive tests.
2025-02-05 16:30:11 -06:00
Trevor Gross
eee632ee1b Add checks via annotation that lists are sorted or exhaustive
This crate has a handful of lists that need to list all API and can't
easily be verified. Additionally, some longer lists should be kept
sorted so they are easier to look through. Resolve both of these by
adding a check in `update-api-list.py` that looks for annotations and
verifies the contents are as expected.

Annotations are `verify-apilist-start`, `verify-apilist-end`,
`verify-sorted-start`, and `verify-sorted-end`.

This includes fixes for anything that did not meet the criteria.
2025-02-05 15:18:05 +00:00
Trevor Gross
cc2874c9a9 Add scalbnf16, scalbnf128, ldexpf16, and ldexpf128
Use the generic `scalbn` to provide `f16` and `f128` versions, which
also work for `ldexp`.

This involves a new algorithm for `f16` because the default does not
converge fast enough with a limited number of rounds.
2025-02-05 13:37:54 +00:00
Trevor Gross
99c1080556 Support parsing NaN and infinities from the hf* functions
This isn't very useful for constants since the trait constants are
available, but does enable roundtripping via hex float syntax.
2025-01-29 00:12:31 +00:00
Trevor Gross
396725e146 Revert "Temporarily pin indicatif to 0.17.9"
This reverts commit 1dacdabdb6186f97144c50f8952575576deb3730.
2025-01-28 14:21:23 -06:00
Trevor Gross
176d22db12 Temporarily pin indicatif to 0.17.9
0.17.10 introduced a change that removes `Sync` from `ProgressStyle`,
which makes it more difficult to share in a callback. Pin the dependency
for now until we see if `indicatif` will change this back or if we need
to find a workaround.
2025-01-28 05:00:15 -06:00
Trevor Gross
b9bd107a67 Use remquo from Rug
Rug 1.27.0 exposes `remquo`; make use of it for our tests. Removing our
workaround also allows removing the direct dependency on `gmp-mpfr-sys`
2025-01-25 01:08:31 +00:00
Trevor Gross
edd1289341 Use frexp from Rug
Rug 1.27.0 exposes `frexp`. Make use of it for our tests.
2025-01-25 01:00:01 +00:00
Trevor Gross
62f0fd40d1 Use az exported from Rug
Since Rug 1.27.0, `az` is reexported. This means we no longer need to
track it as a separate dependency.
2025-01-25 00:55:03 +00:00
Trevor Gross
7c6c0c1b79 Upgrade all dependencies to the latest version
In particular, this includes updates to Rug that we can make use of [1],
[2], [3], [4].

[1]: https://gitlab.com/tspiteri/rug/-/issues/78
[2]: https://gitlab.com/tspiteri/rug/-/issues/80
[3]: https://gitlab.com/tspiteri/rug/-/issues/76
[4]: https://gitlab.com/tspiteri/rug/-/issues/73
2025-01-25 00:50:02 +00:00
Trevor Gross
173a48ce8c Enable missing icount benchmarks
A few new functions were added but this list did not get updated. Do so
here.
2025-01-24 03:39:49 -06:00
Trevor Gross
71200bc3ce Add fmodf128
This function is significantly slower than all others so includes an
override in `EXTREMELY_SLOW_TESTS`. Without it, PR CI takes ~1hour and
the extensive tests in CI take ~1day.
2025-01-24 08:23:15 +00:00
Trevor Gross
b863308979 Add way to override the number of iterations for specific tests
Certain functions (`fmodf128`) are significantly slower than others,
to the point that running the default number of tests adds tens of
minutes to PR CI and extensive test time increases to ~1day. It does not
make sense to do this by default; so, introduce `EXTREMELY_SLOW_TESTS`
to test configuration that allows setting specific tests that need to
have a reduced iteration count.
2025-01-24 08:23:15 +00:00
Trevor Gross
67218cbaa5 Add fmodf16 using the generic implementation 2025-01-24 06:03:59 +00:00
Trevor Gross
6d5105c006 Add fminf16, fmaxf16, fminf128, and fmaxf128 2025-01-24 03:01:36 +00:00
Trevor Gross
357ee34abb Remove an outdated note about precision 2025-01-24 01:59:10 +00:00
Trevor Gross
d20a5e82a5 Add roundf16 and roundf128 2025-01-24 01:59:10 +00:00
Trevor Gross
3aa2d1cfc2 Add a generic version of scalbn
This replaces the `f32` and `f64` versions of `scalbn` and `ldexp`.
2025-01-23 16:59:44 -06:00
Trevor Gross
ca8dccc5b6 Introduce XFAILs that assert failure
Currently our XFAILs are open ended; we do not check that it actually
fails, so we have no easy way of knowing that a previously-failing test
starts passing. Introduce a new enum that we return from overrides to
give us more flexibility here, including the ability to assert that
expected failures happen.

With the new enum, it is also possible to specify ULP via return value
rather than passing a `&mut u32` parameter.

This includes refactoring of `precision.rs` to be more accurate about
where errors come from, if possible.

Fixes: https://github.com/rust-lang/libm/issues/455
2025-01-23 01:15:21 -06:00
Trevor Gross
b22398d658 Add rintf16 and rintf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-22 11:04:39 +00:00
Trevor Gross
6a8bb0fa80 Add floorf16 and floorf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-22 08:50:06 +00:00
Trevor Gross
9064c42abe Add ceilf16 and ceilf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-22 07:22:32 +00:00
Trevor Gross
a7cd13b6a3 Make Float::exp return an unsigned integer
`exp` does not perform any form of unbiasing, so there isn't any reason
it should be signed. Change this.

Additionally, add `EPSILON` to the `Float` trait.
2025-01-22 07:15:39 +00:00
Trevor Gross
186eac9227 Add sqrtf16 and sqrtf128
Use the generic algorithms to provide implementations for these
routines.
2025-01-22 05:31:13 +00:00
Trevor Gross
b3d57f8c28 Remove trailing whitespace in scripts, run JuliaFormatter 2025-01-21 20:30:11 -05:00
Trevor Gross
3986206ce0 Add an xfail for recent ynf failures
This failed a couple of times recently in CI, once on i686 and once on
aarch64-apple:

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

    Caused by:
        0:
               input:    (681, 509.90924) (0x000002a9, 0x43fef462)
               expected: -3.2161271e38          0xff71f45b
               actual:   -inf                   0xff800000
        1: mismatched infinities

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

    Caused by:
        0:
               input:    (132, 50.46604) (0x00000084, 0x4249dd3a)
               expected: -3.3364996e38          0xff7b02a5
               actual:   -inf                   0xff800000
        1: mismatched infinities

Add a new override to account for this.
2025-01-16 09:47:00 +00:00
Trevor Gross
5139ba6f46 Reduce the warm up and measurement time for short-benchmarks
The icount benchmarks are what we will be relying on in CI more than the
existing benchmarks. There isn't much reason to keep these around, but
there isn't much point in dropping them either. So, just reduce the
runtime.
2025-01-16 09:07:46 +00:00
Trevor Gross
490ebbb187 Add benchmarks using iai-callgrind
Running walltime benchmarks in CI is notoriously unstable, Introduce
benchmarks that instead use instruction count and other more
reproducible metrics, using `iai-callgrind` [1], which we are able to
run in CI with a high degree of reproducibility.

Inputs to this benchmark are a logspace sweep, which gives an
approximation for real-world use, but may fail to indicate outlier
cases.

[1]: https://github.com/iai-callgrind/iai-callgrind
2025-01-16 09:07:19 +00:00