3.3 KiB
How to contribute
- Pick your favorite math function from the issue tracker.
- Look for the C implementation of the function in the MUSL source code.
- Copy paste the C code into a Rust file in the
src/math
directory and adjustsrc/math/mod.rs
accordingly. Also, uncomment the corresponding trait method insrc/lib.rs
. - Write some simple tests in your module (using
#[test]
) - Run
cargo test
to make sure it works - Run
cargo test --features musl-reference-tests
to compare your implementation against musl's - Send us a pull request! Make sure to run
cargo fmt
on your code before sending the PR. Also include "closes #42" in the PR description to close the corresponding issue. - 🎉
Check PR #65 for an example.
Tips and tricks
-
IMPORTANT The code in this crate will end up being used in the
core
crate so it can not have any external dependencies (other thancore
itself). -
Only use relative imports within the
math
directory / module, e.g.use self::fabs::fabs
oruse 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 theGET_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 theSET_FLOAT_WORD
macro, or a union, to do this operation. -
You may use other methods from core like
f64::is_nan
, etc. as appropriate. -
If you're implementing one of the private double-underscore functions, take a look at the "source" name in the comment at the top for an idea for alternate naming. For example,
__sin
was renamed tok_sin
after the FreeBSD source code naming. Douse
these private functions inmod.rs
. -
You may encounter weird literals like
0x1p127f
in the MUSL code. These are hexadecimal floating point literals. Rust (the language) doesn't support these kind of literals. The best way I have found to deal with these literals is to turn them into their integer representation using thehexf!
macro and then turn them back into floats. See below:
// Step 1: write a program to convert the float into its integer representation
#[macro_use]
extern crate hexf;
fn main() {
println!("{:#x}", hexf32!("0x1.0p127").to_bits());
}
$ # Step 2: run the program
$ cargo run
0x7f000000
// Step 3: copy paste the output into libm
let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 12
- Rust code panics on arithmetic overflows when not optimized. You may need to use the
Wrapping
newtype to avoid this problem.
Testing
Normal tests can be executed with:
cargo test
If you'd like to run tests with randomized inputs that get compared against musl itself, you'll need to be on a Linux system and then you can execute:
cargo test --features musl-reference-tests
Note that you may need to pass --release
to Cargo if there are errors related
to integer overflow.