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 adjust src/math/mod.rs accordingly. Also, uncomment the corresponding trait method in src/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.
  • :tada:

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 than 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.

  • 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 to k_sin after the FreeBSD source code naming. Do use these private functions in mod.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 the hexf! 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.