compiler-rt
and, if applicable, their tests. Note that this crate has generic implementations for a lot of routines, which may be usable without porting the entire implementation.builtins-test
, comparing the behavior of the ported intrinsic(s) with their implementation on the testing host.builtins-test-intrinsics/src/main.rs
to verify it can be linked on all targets.== !=
) before bitwise operations (& | ^
), while Rust evaluates the other way.IMPORTANT The code in this crate will end up being used in the core
crate so it can not have any external dependencies (other than a subset of core
itself).
Only use relative imports within the math
directory / module, e.g. use self::fabs::fabs
or use super::k_cos
. Absolute imports from core are OK, e.g. use core::u64
.
To reinterpret a float as an integer use the to_bits
method. The MUSL code uses the GET_FLOAT_WORD
macro, or a union, to do this operation.
To reinterpret an integer as a float use the f32::from_bits
constructor. The MUSL code uses the SET_FLOAT_WORD
macro, or a union, to do this operation.
You may use other methods from core like f64::is_nan
, etc. as appropriate.
Rust does not have hex float literals. This crate provides two hf16!
, hf32!
, hf64!
, and hf128!
which convert string literals to floats at compile time.
assert_eq!(hf32!("0x1.ffep+8").to_bits(), 0x43fff000); assert_eq!(hf64!("0x1.ffep+8").to_bits(), 0x407ffe0000000000);
Rust code panics on arithmetic overflows when not optimized. You may need to use the Wrapping
newtype to avoid this problem, or individual methods like wrapping_add
.
Testing for these crates can be somewhat complex, so feel free to rely on CI.
The easiest way replicate CI testing is using Docker. This can be done by running ./ci/run-docker.sh [target]
. If no target is specified, all targets will be run.
Tests can also be run without Docker:
# Run basic tests # # --no-default-features always needs to be passed, an unfortunate limitation # since the `#![compiler_builtins]` feature is enabled by default. cargo test --workspace --no-default-features # Test with all interesting features cargo test --workspace --no-default-features \ --features arch,unstable-float,unstable-intrinsics,mem # Run with more detailed tests for libm cargo test --workspace --no-default-features \ --features arch,unstable-float,unstable-intrinsics,mem \ --features build-mpfr,build-musl \ --profile release-checked
The multiprecision tests use the rug
crate for bindings to MPFR. MPFR can be difficult to build on non-Unix systems, refer to gmp_mpfr_sys
for help.
build-musl
does not build with MSVC, Wasm, or Thumb.
In order to run all tests, some dependencies may be required:
# Allow testing compiler-builtins ./ci/download-compiler-rt.sh # Optional, initialize musl for `--features build-musl` git submodule init git submodule update # `--release` ables more test cases cargo test --release
Libm also has tests that are exhaustive (for single-argument f32
and 1- or 2- argument f16
) or extensive (for all other float and argument combinations). These take quite a long time to run, but are launched in CI when relevant files are changed.
Exhaustive tests can be selected by passing an environment variable:
LIBM_EXTENSIVE_TESTS=sqrt,sqrtf cargo test --features build-mpfr \ --test z_extensive \ --profile release-checked # Run all tests for one type LIBM_EXTENSIVE_TESTS=all_f16 cargo test ... # Ensure `f64` tests can run exhaustively. Estimated completion test for a # single test is 57306 years on my machine so this may be worth skipping. LIBM_EXTENSIVE_TESTS=all LIBM_EXTENSIVE_ITERATIONS=18446744073709551615 cargo test ...
Regular walltime benchmarks can be run with cargo bench
:
cargo bench --no-default-features \ --features arch,unstable-float,unstable-intrinsics,mem \ --features benchmarking-reports
There are also benchmarks that check instruction count behind the icount
feature. These require iai-callgrind-runner
(via Cargo) and Valgrind to be installed, which means these only run on limited platforms.
Instruction count benchmarks are run as part of CI to flag performance regresions.
cargo bench --no-default-features \ --features arch,unstable-float,unstable-intrinsics,mem \ --features icount \ --bench icount --bench mem_icount