Skip to content

Commit 87eac33

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 48d56ba + a666d85 commit 87eac33

17 files changed

+844
-168
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Change Log
2+
3+
All notable changes to this project will be documented in this file.
4+
This project adheres to [Semantic Versioning](http://semver.org/).
5+
6+
## [Unreleased]
7+
8+
## v0.1.0 - 2018-07-13
9+
10+
- Initial release
11+
12+
[Unreleased]: https://github.com/japaric/libm/compare/v0.1.0...HEAD

CONTRIBUTING.md

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# How to contribute
2+
3+
- Pick your favorite math function from the [issue tracker].
4+
- Look for the C implementation of the function in the [MUSL source code][src].
5+
- Copy paste the C code into a Rust file in the `src/math` directory and adjust `src/math/mod.rs`
6+
accordingly. Also, uncomment the corresponding trait method in `src/lib.rs`.
7+
- Run `cargo watch check` and fix the compiler errors.
8+
- Tweak the bottom of `test-generator/src/main.rs` to add your function to the test suite.
9+
- If you can, run the full test suite locally (see the [testing](#testing) section below). If you
10+
can't, no problem! Your PR will be fully tested automatically. Though you may still want to add
11+
and run some unit tests. See the bottom of [`src/math/truncf.rs`] for an example of such tests;
12+
you can run unit tests with the `cargo test --lib` command.
13+
- Send us a pull request!
14+
- :tada:
15+
16+
[issue tracker]: https://github.com/japaric/libm/issues
17+
[src]: https://git.musl-libc.org/cgit/musl/tree/src/math
18+
[`src/math/truncf.rs`]: https://github.com/japaric/libm/blob/master/src/math/truncf.rs
19+
20+
Check [PR #65] for an example.
21+
22+
[PR #65]: https://github.com/japaric/libm/pull/65
23+
24+
## Tips and tricks
25+
26+
- *IMPORTANT* The code in this crate will end up being used in the `core` crate so it can **not**
27+
have any external dependencies (other than `core` itself).
28+
29+
- Only use relative imports within the `math` directory / module, e.g. `use self::fabs::fabs` or
30+
`use super::isnanf`. Absolute imports from core are OK, e.g. `use core::u64`.
31+
32+
- To reinterpret a float as an integer use the `to_bits` method. The MUSL code uses the
33+
`GET_FLOAT_WORD` macro, or a union, to do this operation.
34+
35+
- To reinterpret an integer as a float use the `f32::from_bits` constructor. The MUSL code uses the
36+
`SET_FLOAT_WORD` macro, or a union, to do this operation.
37+
38+
- You may encounter weird literals like `0x1p127f` in the MUSL code. These are hexadecimal floating
39+
point literals. Rust (the language) doesn't support these kind of literals. The best way I have
40+
found to deal with these literals is to turn them into their integer representation using the
41+
[`hexf!`] macro and then turn them back into floats. See below:
42+
43+
[`hexf!`]: https://crates.io/crates/hexf
44+
45+
``` rust
46+
// Step 1: write a program to convert the float into its integer representation
47+
#[macro_use]
48+
extern crate hexf;
49+
50+
fn main() {
51+
println!("{:#x}", hexf32!("0x1.0p127").to_bits());
52+
}
53+
```
54+
55+
``` console
56+
$ # Step 2: run the program
57+
$ cargo run
58+
0x7f000000
59+
```
60+
61+
``` rust
62+
// Step 3: copy paste the output into libm
63+
let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 12
64+
```
65+
66+
- Rust code panics on arithmetic overflows when not optimized. You may need to use the [`Wrapping`]
67+
newtype to avoid this problem.
68+
69+
[`Wrapping`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html
70+
71+
## Testing
72+
73+
The test suite of this crate can only be run on x86_64 Linux systems using the following commands:
74+
75+
``` console
76+
$ # The test suite depends on the `cross` tool so install it if you don't have it
77+
$ cargo install cross
78+
79+
$ # and the `cross` tool requires docker to be running
80+
$ systemctl start docker
81+
82+
$ # execute the test suite for the x86_64 target
83+
$ TARGET=x86_64-unknown-linux-gnu bash ci/script.sh
84+
85+
$ # execute the test suite for the ARMv7 target
86+
$ TARGET=armv7-unknown-linux-gnueabihf bash ci/script.sh
87+
```

Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
[package]
2+
authors = ["Jorge Aparicio <[email protected]>"]
3+
categories = ["no-std"]
4+
description = "libm in pure Rust"
5+
documentation = "https://docs.rs/libm"
6+
keywords = ["libm", "math"]
7+
license = "MIT OR Apache-2.0"
28
name = "libm"
9+
repository = "https://github.com/japaric/libm"
310
version = "0.1.0"
4-
authors = ["Jorge Aparicio <[email protected]>"]
511

612
[workspace]
713
members = ["cb", "test-generator"]

README.md

+23-44
Original file line numberDiff line numberDiff line change
@@ -6,62 +6,41 @@ A port of [MUSL]'s libm to Rust.
66

77
## Goals
88

9-
The short term goal of this library is to enable math support (e.g. `sin`, `atan2`) for the
10-
`wasm32-unknown-unknown` target. The longer term goal is to enable math support in the `core` crate.
9+
The short term goal of this library is to [enable math support (e.g. `sin`, `atan2`) for the
10+
`wasm32-unknown-unknown` target][wasm] (cf. [rust-lang-nursery/compiler-builtins][pr]). The longer
11+
term goal is to enable [math support in the `core` crate][core].
1112

12-
## Testing
13+
[wasm]: https://github.com/japaric/libm/milestone/1
14+
[pr]: https://github.com/rust-lang-nursery/compiler-builtins/pull/248
15+
[core]: https://github.com/japaric/libm/milestone/2
1316

14-
The test suite of this crate can only be run on x86_64 Linux systems.
17+
## Already usable
1518

16-
```
17-
$ # The test suite depends on the `cross` tool so install it if you don't have it
18-
$ cargo install cross
19-
20-
$ # and the `cross` tool requires docker to be running
21-
$ systemctl start docker
22-
23-
$ # execute the test suite for the x86_64 target
24-
$ TARGET=x86_64-unknown-linux-gnu bash ci/script.sh
25-
26-
$ # execute the test suite for the ARMv7 target
27-
$ TARGET=armv7-unknown-linux-gnueabihf bash ci/script.sh
28-
```
19+
This crate is [on crates.io] and can be used today in stable `#![no_std]` programs like this:
2920

30-
## Contributing
31-
32-
- Pick your favorite math function from the [issue tracker].
33-
- Look for the C implementation of the function in the [MUSL source code][src].
34-
- Copy paste the C code into a Rust file in the `src/math` directory and adjust `src/math/mod.rs`
35-
accordingly. Also, uncomment the corresponding trait method in `src/lib.rs`.
36-
- Run `cargo watch check` and fix the compiler errors.
37-
- Tweak the bottom of `test-generator/src/main.rs` to add your function to the test suite.
38-
- If you can, run the test suite locally. If you can't, no problem! Your PR will be tested
39-
automatically.
40-
- Send us a pull request!
41-
- :tada:
42-
43-
[issue tracker]: https://github.com/japaric/libm/issues
44-
[src]: https://git.musl-libc.org/cgit/musl/tree/src/math
21+
[on crates.io]: https://crates.io/crates/libm
4522

46-
Check [PR #2] for an example.
23+
``` rust
24+
#![no_std]
4725

48-
[PR #2]: https://github.com/japaric/libm/pull/2
26+
extern crate libm;
4927

50-
### Notes
28+
use libm::F32Ext; // adds methods to `f32`
5129

52-
- Only use relative imports within the `math` directory / module, e.g. `use self::fabs::fabs` or
53-
`use super::isnanf`. Absolute imports from core are OK, e.g. `use core::u64`.
30+
fn foo(x: f32) {
31+
let y = x.sqrt();
32+
let z = libm::truncf(x);
33+
}
34+
```
5435

55-
- To reinterpret a float as an integer use the `to_bits` method. The MUSL code uses the
56-
`GET_FLOAT_WORD` macro, or a union, to do this operation.
36+
Not all the math functions are available at the moment. Check the [API docs] to learn what's
37+
currently supported.
5738

58-
- To reinterpret an integer as a float use the `f32::from_bits` constructor. The MUSL code uses the
59-
`SET_FLOAT_WORD` macro, or a union, to do this operation.
39+
[API docs]: https://docs.rs/libm
6040

61-
- Rust code panics on arithmetic overflows when not optimized. You may need to use the [`Wrapping`]
62-
newtype to avoid this problem.
41+
## Contributing
6342

64-
[`Wrapping`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html
43+
Please check [CONTRIBUTING.md](CONTRIBUTING.md)
6544

6645
## License
6746

src/lib.rs

+12-25
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ pub fn _eq(a: u64, b: u64) -> bool {
3232

3333
/// Math support for `f32`
3434
///
35-
/// NOTE this meant to be a closed extension trait. The only stable way to use this trait is to
36-
/// import it to access its methods.
37-
pub trait F32Ext {
35+
/// This trait is sealed and cannot be implemented outside of `libm`.
36+
pub trait F32Ext: private::Sealed {
3837
#[cfg(todo)]
3938
fn floor(self) -> Self;
4039

@@ -43,7 +42,6 @@ pub trait F32Ext {
4342

4443
fn round(self) -> Self;
4544

46-
#[cfg(todo)]
4745
fn trunc(self) -> Self;
4846

4947
#[cfg(todo)]
@@ -70,16 +68,13 @@ pub trait F32Ext {
7068

7169
fn sqrt(self) -> Self;
7270

73-
#[cfg(todo)]
7471
fn exp(self) -> Self;
7572

7673
#[cfg(todo)]
7774
fn exp2(self) -> Self;
7875

79-
#[cfg(todo)]
8076
fn ln(self) -> Self;
8177

82-
#[cfg(todo)]
8378
fn log(self, base: Self) -> Self;
8479

8580
#[cfg(todo)]
@@ -91,7 +86,6 @@ pub trait F32Ext {
9186
#[cfg(todo)]
9287
fn cbrt(self) -> Self;
9388

94-
#[cfg(todo)]
9589
fn hypot(self, other: Self) -> Self;
9690

9791
#[cfg(todo)]
@@ -164,7 +158,6 @@ impl F32Ext for f32 {
164158
roundf(self)
165159
}
166160

167-
#[cfg(todo)]
168161
#[inline]
169162
fn trunc(self) -> Self {
170163
truncf(self)
@@ -218,7 +211,6 @@ impl F32Ext for f32 {
218211
sqrtf(self)
219212
}
220213

221-
#[cfg(todo)]
222214
#[inline]
223215
fn exp(self) -> Self {
224216
expf(self)
@@ -230,13 +222,11 @@ impl F32Ext for f32 {
230222
exp2f(self)
231223
}
232224

233-
#[cfg(todo)]
234225
#[inline]
235226
fn ln(self) -> Self {
236227
logf(self)
237228
}
238229

239-
#[cfg(todo)]
240230
#[inline]
241231
fn log(self, base: Self) -> Self {
242232
self.ln() / base.ln()
@@ -260,7 +250,6 @@ impl F32Ext for f32 {
260250
cbrtf(self)
261251
}
262252

263-
#[cfg(todo)]
264253
#[inline]
265254
fn hypot(self, other: Self) -> Self {
266255
hypotf(self, other)
@@ -364,20 +353,17 @@ impl F32Ext for f32 {
364353
}
365354
}
366355

367-
/// Math support for `f32`
356+
/// Math support for `f64`
368357
///
369-
/// NOTE this meant to be a closed extension trait. The only stable way to use this trait is to
370-
/// import it to access its methods.
371-
pub trait F64Ext {
372-
#[cfg(todo)]
358+
/// This trait is sealed and cannot be implemented outside of `libm`.
359+
pub trait F64Ext: private::Sealed {
373360
fn floor(self) -> Self;
374361

375362
#[cfg(todo)]
376363
fn ceil(self) -> Self;
377364

378365
fn round(self) -> Self;
379366

380-
#[cfg(todo)]
381367
fn trunc(self) -> Self;
382368

383369
#[cfg(todo)]
@@ -403,7 +389,6 @@ pub trait F64Ext {
403389
#[cfg(todo)]
404390
fn powf(self, n: Self) -> Self;
405391

406-
#[cfg(todo)]
407392
fn sqrt(self) -> Self;
408393

409394
#[cfg(todo)]
@@ -427,7 +412,6 @@ pub trait F64Ext {
427412
#[cfg(todo)]
428413
fn cbrt(self) -> Self;
429414

430-
#[cfg(todo)]
431415
fn hypot(self, other: Self) -> Self;
432416

433417
#[cfg(todo)]
@@ -483,7 +467,6 @@ pub trait F64Ext {
483467
}
484468

485469
impl F64Ext for f64 {
486-
#[cfg(todo)]
487470
#[inline]
488471
fn floor(self) -> Self {
489472
floor(self)
@@ -500,7 +483,6 @@ impl F64Ext for f64 {
500483
round(self)
501484
}
502485

503-
#[cfg(todo)]
504486
#[inline]
505487
fn trunc(self) -> Self {
506488
trunc(self)
@@ -550,7 +532,6 @@ impl F64Ext for f64 {
550532
pow(self, n)
551533
}
552534

553-
#[cfg(todo)]
554535
#[inline]
555536
fn sqrt(self) -> Self {
556537
sqrt(self)
@@ -598,7 +579,6 @@ impl F64Ext for f64 {
598579
cbrt(self)
599580
}
600581

601-
#[cfg(todo)]
602582
#[inline]
603583
fn hypot(self, other: Self) -> Self {
604584
hypot(self, other)
@@ -701,3 +681,10 @@ impl F64Ext for f64 {
701681
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
702682
}
703683
}
684+
685+
mod private {
686+
pub trait Sealed {}
687+
688+
impl Sealed for f32 {}
689+
impl Sealed for f64 {}
690+
}

0 commit comments

Comments
 (0)