658 Commits

Author SHA1 Message Date
Trevor Gross
cd7c76aab3 Migrate all crates except libm to edition 2024
Unfortunately this means we lose use of the convenient name `gen`, so
this includes a handful of renaming.

We can't increase the edition for `libm` yet due to MSRV, but we can
enable `unsafe_op_in_unsafe_fn` to help make that change smoother in the
future.
2025-04-18 19:00:45 -04:00
Trevor Gross
3a0b9c9f51 refactor: Introduce a virtual manifest
Move the workspace configuration to a virtual manifest. This
reorganization makes a more clear separation between package contents
and support files that don't get distributed. It will also make it
easier to merge this repository with `compiler-builtins` which is
planned (builtins had a similar update done in [1]).

LICENSE.txt and README.md are symlinkedinto the new directory to ensure
they get included in the package.

[1]: https://github.com/rust-lang/compiler-builtins/pull/702
2025-04-18 17:49:25 -04:00
Trevor Gross
7077daa6ad refactor: Move the libm crate to a subdirectory
In preparation for switching to a virtual manifest, move the `libm`
crate into a subdirectory and update paths to match.

Updating `Cargo.toml` is done in the next commit so git tracks the moved
file correctly.
2025-04-18 17:49:25 -04:00
Trevor Gross
88dcaf20b5 Mark generic functions #[inline]
Benchmarks for [1] seemed to indicate that repository organization for
some reason had an effect on performance, even though the exact same
rustc commands were running (though some with a different order). After
investigating more, it appears that dependencies may have an affect on
inlining thresholds for generic functions.

It is surprising that this happens, we more or less expect that public
functions will be standalone but everything they call will be inlined.
To help ensure this, mark all generic functions `#[inline]` if they
should be merged into the public function.

Zulip discussion at [2].

[1]: https://github.com/rust-lang/libm/pull/533
[2]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Dependencies.20affecting.20codegen/with/513079387
2025-04-18 16:29:27 -04:00
Trevor Gross
3cecf22e0c Combine the source files for fmod
Since `fmod` is generic, there isn't any need to have the small wrappers
in separate files. Most operations was done in [1] but `fmod` was
omitted until now.

[1]: https://github.com/rust-lang/libm/pull/537
2025-04-18 15:14:55 -04:00
Trevor Gross
8da1290f04 Ensure all public functions are marked no_panic
Fixes: https://github.com/rust-lang/libm/issues/201
2025-04-18 04:23:00 -04:00
Trevor Gross
2db05de8fd ci: Account for PR_NUMBER being set to an empty string
This is the case for CI after merge that is no longer associated with a
pull request.
2025-04-18 03:26:38 -04:00
Trevor Gross
2585a57dc7 Ensure configure.rs changes trigger rebuilds 2025-04-18 02:47:03 -04:00
Trevor Gross
1cb17773f6 ci: Increase the timeout for extensive tests
The reorganization PR has caused this to fail once before because every
file shows up as changed. Increase the timeout so this doesn't happen.

We now cancel the job if too many extensive tests are run unless `ci:
allow-many-extensive` is in the PR description, so this helps prevent
the limit being hit by accident.
2025-04-17 23:31:06 -05:00
Trevor Gross
a0e5a7a636 ci: Require ci: allow-many-extensive if a threshold is exceeded
Error out when too many extensive tests would be run unless `ci:
allow-many-extensive` is in the PR description. This allows us to set a
much higher CI timeout with less risk that a 4+ hour job gets started by
accident.
2025-04-17 23:31:06 -05:00
Trevor Gross
cad0d6f187 ci: Allow skipping extensive tests with ci: skip-extensive
Sometimes we do refactoring that moves things around and triggers an
extensive test, even though the implementation didn't change. There
isn't any need to run full extensive CI in these cases, so add a way to
skip it from the PR message.
2025-04-17 23:31:06 -05:00
Trevor Gross
014c3e4ccb ci: Cancel jobs when a new push happens
Jobs should just cancel automatically, it isn't ideal that extensive
jobs can continue running for multiple hours after code has been
updated. Use a solution from [1] to do this.

[1]: https://stackoverflow.com/a/72408109/5380651
2025-04-17 22:57:24 -05:00
Trevor Gross
a15c8c9a3d Combine the source files for more generic implementations
Splitting into different source files by float size doesn't have any
benefit when the only content is a small function that forwards to the
generic implementation. Combine the source files for all width versions
of:

* ceil
* copysign
* fabs
* fdim
* floor
* fmaximum
* fmaximum_num
* fminimum
* fminimum_num
* ldexp
* scalbn
* sqrt
* truc

fmod is excluded to avoid conflicts with an open PR.

As part of this change move unit tests out of the generic module,
instead testing the type-specific functions (e.g. `ceilf16` rather than
`ceil::<f16>()`). This ensures that unit tests are validating whatever
we expose, such as arch-specific implementations via
`select_implementation!`, which would otherwise be skipped. (They are
still covered by integration tests).
2025-04-17 22:00:42 -05:00
Trevor Gross
579627ddd5 Make assert_biteq! not rely on having Int in scope 2025-04-17 22:00:42 -05:00
Trevor Gross
f88b7c8a46 Add NEG_NAN to Float
Introduce a constant representing NaN with a negative sign bit for use
with testing. There isn't really any guarantee that `F::NAN` is positive
but in practice it always is, which is good enough for testing purposes.
2025-04-17 22:00:42 -05:00
Trevor Gross
e4d716c848 fmod: Correct the normalization of subnormals
Discussed at [1], there was an off-by-one mistake when converting from
the loop routine to using `leading_zeros` for normalization.

Currently, using `EXP_BITS` has the effect that `ix` after the branch
has its MSB _one bit to the left_ of the implicit bit's position,
whereas a shift by `EXP_BITS + 1` ensures that the MSB is exactly at the
implicit bit's position, matching what is done for normals (where the
implicit bit is set to be explicit). This doesn't seem to have any
effect in our implementation since the failing test cases from [1]
appear to still have correct results.

Since the result of using `EXP_BITS + 1` is more consistent with what is
done for normals, apply this here.

[1]: https://github.com/rust-lang/libm/pull/469#discussion_r2012473920
2025-04-16 15:28:10 -05:00
Trevor Gross
14ab2453f2 fmod: Add regression tests for subnormal issue
From discussion at [1] our loop count calculation is incorrect, causing
an issue with subnormal numbers. Add test cases for known failures.

[1]: https://github.com/rust-lang/libm/pull/469#discussion_r2012473920
2025-04-16 15:28:10 -05:00
quaternic
b955cc691e Implement rounding for the hex float parsing and prepare to improve error handling
Parsing errors are now bubbled up part of the way, but that needs some
more work.

Rounding should be correct, and the `Status` returned by `parse_any`
should have the correct bits set. These are used for the current (unchanged)
behavior of the surface level functions like `hf64`: panic on invalid inputs, or
values that aren't exactly representable.
2025-04-15 00:46:12 +00:00
Trevor Gross
28b6df8603 Add assembly version of simple operations on aarch64
Replace `core::arch` versions of the following with handwritten
assembly, which avoids recursion issues (cg_gcc using `rint` as a
fallback) as well as problems with `aarch64be`.

* `rint`
* `rintf`

Additionally, add assembly versions of the following:

* `fma`
* `fmaf`
* `sqrt`
* `sqrtf`

If the `fp16` target feature is available, which implies `neon`, also
include the following:

* `rintf16`
* `sqrtf16`

`sqrt` is added to match the implementation for `x86`. `fma` is included
since it is used by many other routines.

There are a handful of other operations that have assembly
implementations. They are omitted here because we should have basic
float math routines available in `core` in the near future, which will
allow us to defer to LLVM for assembly lowering rather than implementing
these ourselves.
2025-04-09 00:46:53 -05:00
Trevor Gross
375cb5402f Resolve small errors identified by recent clippy 2025-04-08 22:04:58 -05:00
Trevor Gross
4e5cbbeda1 Replace calls to core::arch intrinsics with assembly
Some backends may replace calls to `core::arch` with multiple calls to
`sqrt` [1], which becomes recursive. Help mitigate this by replacing the
call with assembly.

Results in the same assembly as the current implementation when built
with optimizations.

[1]: https://github.com/rust-lang/compiler-builtins/issues/649
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
1774882738 Gate another assertion behind compiler-builtins
This is causing link errors on Windows.
2025-02-24 02:25:17 -05:00
Trevor Gross
2615971f55 Configure out remaining formatting when compiler-builtins is set
These are still causing errors in the compiler-builtins CI.
2025-02-24 01:22:26 -05:00
Trevor Gross
3f6b08ac1e Ignore unused variables when compiler-builtins is set 2025-02-24 00:28:14 -05:00
Trevor Gross
9021b2820c Resolve monomorphization errors in compiler-builtins
`compiler-builtins` is not allowed to call anything from `core`;
however, there are a couple of cases where we do so in `libm` for debug
output. Gate relevant locations behind the `compiler-builtins` Cargo
feature.
2025-02-23 23:42:28 -05:00
Trevor Gross
ba8f07282e Make the compiler-builtins test more accurately mirror compiler-builtins
In `compiler-builtins`, `libm` is contained within a `math` module. The
smoke test in this repo has a slightly different layout so some things
were passing that shouldn't be.

Change module layouts in `compiler-builtins-smoke-test` to match
`compiler-builtins` and update a few instances of broken paths.
2025-02-23 21:10:11 -05:00
Trevor Gross
c32bc8398a ci: Pin the nightly toolchain for aarch64 jobs
Pin aarch64-unknown-linux-gnu and aarch64-apple-darwin to
nightly-2025-02-07 until [1] makes it to a Rust nightly.

[1]: https://github.com/llvm/llvm-project/issues/127804
2025-02-23 21:10:11 -05:00
Trevor Gross
bd41642818 Use git ls-files rather than manually globbing for tidy
This avoids matching build directories, ignored files, and submodules.
2025-02-12 15:38:46 -06:00
Trevor Gross
c01153d29b Make fma a trait method on Float 2025-02-12 10:27:11 +00:00
Trevor Gross
720ba18931 fma refactor 3/3: combine fma public API with its implementation
Similar to other recent changes, just put public API in the same file as
its generic implementation. To keep things slightly cleaner, split the
default implementation from the `_wide` implementation.

Also introduces a stub `fmaf16`.
2025-02-12 10:27:11 +00:00
Trevor Gross
bcbdb0b74f fma refactor 2/3: move math/generic/fma.rs to math/fma.rs
Done in stages so git tracks the moved file correctly.
2025-02-12 10:18:48 +00:00
Trevor Gross
212d463e89 fma refactor 1/3: remove math/fma.rs
Done in stages so git tracks the moved file correctly.
2025-02-12 10:18:48 +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
aa26cab257 Rename Float::exp to Float::ex
Our function to get the exponent conflicts with the inherent `exp`
function for `e^x`. Rename `exp` to `ex` to avoid confusion and usage
problems.
2025-02-11 10:41:43 -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
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
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