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.
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.
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.
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.
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
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
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.
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
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.
Adjust paths such that these macros don't go through the private `math`
module. `feature = "private-test-deps"` is still needed.
Additionally, ensure that `cargo check` for this crate gets run in CI
because `cargo test` does not seem to identify this problem.
`compiler_builtins` will need to reexport the `support` module.
We need someplace to collect known failures, previous regressions, edge
cases that are difficult to construct from generics, and similar.
Introduce this here.
A few bugs have been fixed, including the sign of `fma(tiny, -tiny,
0.0)`. Switch to tracking `master` rather than the latest tag so we
don't need to xfail these tests.
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.
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
In order to make these more interchangeable in more places, always
return `(impl Iterator, u64)`. This will facilitate using other
generators for extensive tests.
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.
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.
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.
The Cargo feature `checked` was added in 410b0633a6b9 ("Overhaul tests")
and later removed in e4ac1399062c ("swap stable to be unstable, checked
is now debug_assertions"). However, there are a few remaining uses of
`feature = "checked"` that did not get removed. Clean these up here.
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.
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.
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