Commit graph

777 commits

Author SHA1 Message Date
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
2a3ef8b9a2 Fix parsing of negative hex float literals in util 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
86ee1f99c9 Combine fmin{,f,f16,f128} and fmax{,f,f16,128} into a single file
These don't have much content since they now use the generic
implementation. There will be more similar functions in the near future
(fminimum, fmaximum, fminimum_num, fmaximum_num); start the pattern of
combining similar functions now so we don't have to eventually maintain
similar docs across 24 different files.
2025-02-10 14:54:53 -06:00
Trevor Gross
a6dd7980f1 Small refactor of bigint tests
Print errors immediately rather than deferring to the end, so any debug
output shows up immediately before the relevant failed test.
2025-02-10 14:20:37 -06:00
Trevor Gross
8e7c83ea2d Merge pull request rust-lang/libm#510 from tgross35/replace-fenv
Migrate away from nonfunctional `fenv` stubs
2025-02-10 07:25:58 -06:00
Trevor Gross
e94e987399 Eliminate the use of force_eval! in ceil, floor, and trunc 2025-02-10 12:37:25 +00:00
Trevor Gross
105cd79578 Migrate away from nonfunctional fenv stubs
Many routines have some form of handling for rounding mode and floating
point exceptions, which are implemented via a combination of stubs and
`force_eval!` use. This is suboptimal, however, because:

1. Rust does not interact with the floating point environment, so most
   of this code does nothing.
2. The parts of the code that are not dead are not testable.
3. `force_eval!` blocks optimizations, which is unnecessary because we
   do not rely on its side effects.

We cannot ensure correct rounding and exception handling in all cases
without some form of arithmetic operations that are aware of this
behavior. However, the cases where rounding mode is explicitly handled
or exceptions are explicitly raised are testable. Make this possible
here for functions that depend on `math::fenv` by moving the
implementation to a nonpublic function that takes a `Round` and returns
a `Status`.

Link: https://github.com/rust-lang/libm/issues/480
2025-02-10 12:29:59 +00: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
b7fdce0505 ci: Pin the nightly toolchain for i686-pc-windows-gnu
Pin i686-pc-windows-gnu to nightly-2025-02-07 until [1] is resolved.

[1]: https://github.com/rust-lang/rust/issues/136795
2025-02-09 22:07:40 -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
017f1035f1 Replace an assert! with debug_assert! in u256::shr
The implementation came from the `compiler_builtins` port but this
should be weakened to match other integer types.
2025-02-08 05:55:03 -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
e35c5c8970 Merge pull request rust-lang/libm#475 from tgross35/core-cbrt
Port the CORE-MATH version of `cbrt`
2025-02-07 17:56:03 -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
2fa2b10ba4 Port the CORE-MATH version of cbrt
Replace our current implementation with one that is correctly rounded.

Source: 81d447bb1c/src/binary64/cbrt/cbrt.c
2025-02-07 23:04:53 +00:00
Trevor Gross
f1afc26b8a Add an enum representation of rounding mode
We only round using nearest, but some incoming code has more handling of
rounding modes that would be nice to `match` on. Rather than checking
integer values, add an enum representation.
2025-02-07 23:04:53 +00:00
Trevor Gross
f45cc66e8e Work arouind iai-callgrind apt failures
Usually `cargo binstall iai-callgrind-runner` handles apt dependencies.
However, the following has been happening:

    Err:11 mirror+file:/etc/apt/apt-mirrors.txt noble-updates/main amd64 libc6-dbg amd64 2.39-0ubuntu8.3
      404  Not Found [IP: 40.81.13.82 80]
    E: Failed to fetch mirror+file:/etc/apt/apt-mirrors.txt/pool/main/g/glibc/libc6-dbg_2.39-0ubuntu8.3_amd64.deb  404  Not Found [IP: 40.81.13.82 80]
    Fetched 19.8 MB in 6s (3138 kB/s)
    E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

Installing the dependencies manually seems to resolve the issue.
2025-02-07 17:04:26 -06:00
Trevor Gross
9169216f41 Uncomment some hex float tests that should work now 2025-02-07 17:04:26 -06:00
Trevor Gross
aa4ae487d4 Convert fmaf to a generic implementation
Introduce a version of generic `fma` that works when there is a larger
hardware-backed float type available to compute the result with more
precision. This is currently used only for `f32`, but with some minor
adjustments it should work for `f16` as well.
2025-02-06 22:51:42 -06:00
Trevor Gross
3e2de21344 Remove or reduce the scope of allow(unused) where possible
Now that we have more in this crate making use of traits, try to be more
specific about what is actually unused.
2025-02-06 21:57:17 -06:00
Trevor Gross
bd0c2cbd97 Merge pull request rust-lang/libm#497 from tgross35/edge-case-max-subnorm
fmaf128: fix exponent calculation for subnormals
2025-02-06 21:22:59 -06: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
69ebd750cc Run standard tests before running integration tests
To ensure we don't waste time running extensive tests when there is an
easily identifiable failure, run the normal test suite for relevant
functions before starting extensive tests.
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
bbdcc7ef89 Make it possible to use hf32! and similar macros outside of libm
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.
2025-02-06 18:41:45 -06:00
Trevor Gross
3aa4da2756 Improve tidy output
Print a better diff when lists are unsorted, and always check tidy lists
even if `--check` is not passed.
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
f070e65e4f Merge pull request rust-lang/libm#493 from tgross35/fma-sign
fma: Ensure zero has the correct sign
2025-02-05 20:32:11 -06:00
Trevor Gross
ada2d9ae1d Switch musl to track master
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.
2025-02-06 02:03:41 +00: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
9458abd204 Start converting fma to a generic function
This is the first step toward making `fma` usable for `f128`, and
possibly `f32` on platforms where growing to `f64` is not fast. This
does not yet work for anything other than `f64`.
2025-02-05 15:10:47 -06:00
Trevor Gross
466cd81ff5 Merge pull request rust-lang/libm#489 from tgross35/sort-everything
Add checks via annotation that lists are sorted or exhaustive
2025-02-05 09:47:04 -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
f7765fae89 Do not add libm_helper.rs to the sources list
This is just a collection of all functions and should not trigger
extensive tests when changed.
2025-02-05 15:13:53 +00:00
Trevor Gross
cc1a55a77e Add a check in the shared.rs that the function list is sorted 2025-02-05 15:13:53 +00:00
Trevor Gross
0e6d93f67d Merge pull request rust-lang/libm#391 from rust-lang/tgross35/f16-f128-scalbn
Add `ldexpf16`, `ldexpf128`, `scalbnf16`, and `scalbnf128`
2025-02-05 09:00:53 -06: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
98bee053ef Fix hex float trait recursion problem 2025-02-05 13:37:15 +00:00
Trevor Gross
8db5ff73e6 Rename EXP_MAX to EXP_SAT
`EXP_MAX` sounds like it would be the maximum value representable by
that float type's exponent, rather than the maximum unsigned value of
its bits. Clarify this by renaming to `EXP_SAT`, the "saturated"
exponent representation.
2025-01-31 07:15:14 -06:00
Manish Goregaokar
7d674145ae Specify license as just MIT
Simplify the SPDX string to the user-facing version to make it easier for
users and tooling to understand. Contributions must still be `MIT OR Apache-2.0`. 

[ add commit body with context - Trevor ]
2025-01-30 15:06:41 -06:00
Trevor Gross
9d62bd0636 Merge pull request rust-lang/libm#483 from tgross35/hex-print
Add support for printing hex float syntax
2025-01-29 23:58:57 -06:00
Trevor Gross
e283c25602 Util: also print the hex float format for outputs 2025-01-29 00:17:19 +00:00