Skip to content

Commit afa81f8

Browse files
committed
Merge #30
30: Re-introduce the std feature r=vks a=cuviper This is a port of @vks's rust-num/num#296, but without the feature-toggled changes to `Float`. Now `Float` and the newer `Real` are completely dependent on having `std` enabled. In the future we can consider adding separate more-limited float/real traits that can work without `std`, like the `BaseFloat` that was originally proposed in the former PR. This is a breaking change with a bump to 0.2, since anyone currently using `default-features = false` will lose functionality. The actual API is otherwise unchanged, so my plan is to employ the "semver trick" -- publishing a new num-traits-0.1 that re-exports everything from 0.2 (with `std`). Thus all `num-traits` users should remain compatible even if they mix 0.1 and 0.2. Closes #16.
2 parents 3716330 + ffa67c8 commit afa81f8

14 files changed

+140
-55
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ categories = [ "algorithms", "science" ]
88
license = "MIT/Apache-2.0"
99
repository = "https://github.com/rust-num/num-traits"
1010
name = "num-traits"
11-
version = "0.1.42"
11+
version = "0.2.0-pre"
1212
readme = "README.md"
1313

1414
[dependencies]
15+
16+
[features]
17+
default = ["std"]
18+
std = []

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Add this to your `Cargo.toml`:
1212

1313
```toml
1414
[dependencies]
15-
num-traits = "0.1"
15+
num-traits = "0.2"
1616
```
1717

1818
and this to your crate root:
@@ -21,6 +21,19 @@ and this to your crate root:
2121
extern crate num_traits;
2222
```
2323

24+
## Features
25+
26+
This crate can be used without the standard library (`#![no_std]`) by disabling
27+
the default `std` feature. Use this in `Cargo.toml`:
28+
29+
```toml
30+
[dependencies.num-traits]
31+
version = "0.2"
32+
default-features = false
33+
```
34+
35+
The `Float` and `Real` traits are only available when `std` is enabled.
36+
2437
## Releases
2538

2639
Release notes are available in [RELEASES.md](RELEASES.md).

ci/test_full.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ set -ex
44

55
echo Testing num-traits on rustc ${TRAVIS_RUST_VERSION}
66

7-
# num-integer should build and test everywhere.
7+
# num-traits should build and test everywhere.
88
cargo build --verbose
99
cargo test --verbose
1010

11-
# We have no features to test...
11+
# test `no_std`
12+
cargo build --verbose --no-default-features
13+
cargo test --verbose --no-default-features

src/bounds.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use std::{usize, u8, u16, u32, u64};
2-
use std::{isize, i8, i16, i32, i64};
3-
use std::{f32, f64};
4-
use std::num::Wrapping;
1+
use core::{usize, u8, u16, u32, u64};
2+
use core::{isize, i8, i16, i32, i64};
3+
use core::{f32, f64};
4+
use core::num::Wrapping;
55

66
/// Numbers which have upper and lower bounds
77
pub trait Bounded {

src/cast.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use std::mem::size_of;
2-
use std::num::Wrapping;
1+
use core::f64;
2+
use core::mem::size_of;
3+
use core::num::Wrapping;
34

45
use identities::Zero;
56
use bounds::Bounded;
@@ -226,8 +227,10 @@ macro_rules! impl_to_primitive_float_to_float {
226227
// Make sure the value is in range for the cast.
227228
// NaN and +-inf are cast as they are.
228229
let n = $slf as f64;
229-
let max_value: $DstT = ::std::$DstT::MAX;
230-
if !n.is_finite() || (-max_value as f64 <= n && n <= max_value as f64) {
230+
let max_value: $DstT = ::core::$DstT::MAX;
231+
if n != n || n == f64::INFINITY || n == f64::NEG_INFINITY
232+
|| (-max_value as f64 <= n && n <= max_value as f64)
233+
{
231234
Some($slf as $DstT)
232235
} else {
233236
None
@@ -522,8 +525,8 @@ impl_as_primitive!(bool => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64);
522525

523526
#[test]
524527
fn to_primitive_float() {
525-
use std::f32;
526-
use std::f64;
528+
use core::f32;
529+
use core::f64;
527530

528531
let f32_toolarge = 1e39f64;
529532
assert_eq!(f32_toolarge.to_f32(), None);

src/float.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1+
#[cfg(feature = "std")]
12
use std::mem;
3+
#[cfg(feature = "std")]
24
use std::ops::Neg;
5+
#[cfg(feature = "std")]
36
use std::num::FpCategory;
47

58
// Used for default implementation of `epsilon`
9+
#[cfg(feature = "std")]
610
use std::f32;
711

12+
#[cfg(feature = "std")]
813
use {Num, NumCast};
914

1015
// FIXME: these doctests aren't actually helpful, because they're using and
1116
// testing the inherent methods directly, not going through `Float`.
1217

18+
/// Generic trait for floating point numbers
19+
///
20+
/// This trait is only available with the `std` feature.
21+
#[cfg(feature = "std")]
1322
pub trait Float
1423
: Num
1524
+ Copy
@@ -923,6 +932,7 @@ pub trait Float
923932
fn integer_decode(self) -> (u64, i16, i8);
924933
}
925934

935+
#[cfg(feature = "std")]
926936
macro_rules! float_impl {
927937
($T:ident $decode:ident) => (
928938
impl Float for $T {
@@ -1219,6 +1229,7 @@ macro_rules! float_impl {
12191229
)
12201230
}
12211231

1232+
#[cfg(feature = "std")]
12221233
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
12231234
let bits: u32 = unsafe { mem::transmute(f) };
12241235
let sign: i8 = if bits >> 31 == 0 {
@@ -1237,6 +1248,7 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
12371248
(mantissa as u64, exponent, sign)
12381249
}
12391250

1251+
#[cfg(feature = "std")]
12401252
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
12411253
let bits: u64 = unsafe { mem::transmute(f) };
12421254
let sign: i8 = if bits >> 63 == 0 {
@@ -1255,7 +1267,9 @@ fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
12551267
(mantissa, exponent, sign)
12561268
}
12571269

1270+
#[cfg(feature = "std")]
12581271
float_impl!(f32 integer_decode_f32);
1272+
#[cfg(feature = "std")]
12591273
float_impl!(f64 integer_decode_f64);
12601274

12611275
macro_rules! float_const_impl {
@@ -1272,7 +1286,7 @@ macro_rules! float_const_impl {
12721286
$(
12731287
#[inline]
12741288
fn $constant() -> Self {
1275-
::std::$T::consts::$constant
1289+
::core::$T::consts::$constant
12761290
}
12771291
)+
12781292
}
@@ -1314,13 +1328,13 @@ float_const_impl! {
13141328
SQRT_2,
13151329
}
13161330

1317-
#[cfg(test)]
1331+
#[cfg(all(test, feature = "std"))]
13181332
mod tests {
13191333
use Float;
13201334

13211335
#[test]
13221336
fn convert_deg_rad() {
1323-
use std::f64::consts;
1337+
use core::f64::consts;
13241338

13251339
const DEG_RAD_PAIRS: [(f64, f64); 7] = [
13261340
(0.0, 0.),

src/identities.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::ops::{Add, Mul};
2-
use std::num::Wrapping;
1+
use core::ops::{Add, Mul};
2+
use core::num::Wrapping;
33

44
/// Defines an additive identity element for `Self`.
55
pub trait Zero: Sized + Add<Self, Output = Self> {

src/int.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
1+
use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
22

33
use {Num, NumCast};
44
use bounds::Bounded;

src/lib.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,30 @@
1010

1111
//! Numeric traits for generic mathematics
1212
13-
#![doc(html_root_url = "https://docs.rs/num-traits/0.1")]
13+
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
1414

15-
use std::ops::{Add, Sub, Mul, Div, Rem};
16-
use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
17-
use std::num::Wrapping;
18-
use std::fmt;
15+
#![deny(unconditional_recursion)]
16+
17+
#![cfg_attr(not(feature = "std"), no_std)]
18+
#[cfg(feature = "std")]
19+
extern crate core;
20+
21+
use core::ops::{Add, Sub, Mul, Div, Rem};
22+
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
23+
use core::num::Wrapping;
24+
use core::fmt;
1925

2026
pub use bounds::Bounded;
21-
pub use float::{Float, FloatConst};
27+
#[cfg(feature = "std")]
28+
pub use float::Float;
29+
pub use float::FloatConst;
2230
// pub use real::Real; // NOTE: Don't do this, it breaks `use num_traits::*;`.
2331
pub use identities::{Zero, One, zero, one};
24-
pub use ops::checked::*;
25-
pub use ops::wrapping::*;
32+
pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr};
33+
pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub};
2634
pub use ops::saturating::Saturating;
2735
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
28-
pub use cast::*;
36+
pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
2937
pub use int::PrimInt;
3038
pub use pow::{pow, checked_pow};
3139

@@ -34,6 +42,7 @@ pub mod sign;
3442
pub mod ops;
3543
pub mod bounds;
3644
pub mod float;
45+
#[cfg(feature = "std")]
3746
pub mod real;
3847
pub mod cast;
3948
pub mod int;
@@ -130,10 +139,10 @@ impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
130139
macro_rules! int_trait_impl {
131140
($name:ident for $($t:ty)*) => ($(
132141
impl $name for $t {
133-
type FromStrRadixErr = ::std::num::ParseIntError;
142+
type FromStrRadixErr = ::core::num::ParseIntError;
134143
#[inline]
135144
fn from_str_radix(s: &str, radix: u32)
136-
-> Result<Self, ::std::num::ParseIntError>
145+
-> Result<Self, ::core::num::ParseIntError>
137146
{
138147
<$t>::from_str_radix(s, radix)
139148
}
@@ -159,7 +168,7 @@ pub enum FloatErrorKind {
159168
Empty,
160169
Invalid,
161170
}
162-
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
171+
// FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
163172
// so there's not really any way for us to reuse it.
164173
#[derive(Debug)]
165174
pub struct ParseFloatError {
@@ -181,7 +190,7 @@ impl fmt::Display for ParseFloatError {
181190
// with this implementation ourselves until we want to make a breaking change.
182191
// (would have to drop it from `Num` though)
183192
macro_rules! float_trait_impl {
184-
($name:ident for $($t:ty)*) => ($(
193+
($name:ident for $($t:ident)*) => ($(
185194
impl $name for $t {
186195
type FromStrRadixErr = ParseFloatError;
187196

@@ -193,9 +202,9 @@ macro_rules! float_trait_impl {
193202

194203
// Special values
195204
match src {
196-
"inf" => return Ok(Float::infinity()),
197-
"-inf" => return Ok(Float::neg_infinity()),
198-
"NaN" => return Ok(Float::nan()),
205+
"inf" => return Ok(core::$t::INFINITY),
206+
"-inf" => return Ok(core::$t::NEG_INFINITY),
207+
"NaN" => return Ok(core::$t::NAN),
199208
_ => {},
200209
}
201210

@@ -236,15 +245,15 @@ macro_rules! float_trait_impl {
236245
// if we've not seen any non-zero digits.
237246
if prev_sig != 0.0 {
238247
if is_positive && sig <= prev_sig
239-
{ return Ok(Float::infinity()); }
248+
{ return Ok(core::$t::INFINITY); }
240249
if !is_positive && sig >= prev_sig
241-
{ return Ok(Float::neg_infinity()); }
250+
{ return Ok(core::$t::NEG_INFINITY); }
242251

243252
// Detect overflow by reversing the shift-and-add process
244253
if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
245-
{ return Ok(Float::infinity()); }
254+
{ return Ok(core::$t::INFINITY); }
246255
if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
247-
{ return Ok(Float::neg_infinity()); }
256+
{ return Ok(core::$t::NEG_INFINITY); }
248257
}
249258
prev_sig = sig;
250259
},
@@ -280,9 +289,9 @@ macro_rules! float_trait_impl {
280289
};
281290
// Detect overflow by comparing to last value
282291
if is_positive && sig < prev_sig
283-
{ return Ok(Float::infinity()); }
292+
{ return Ok(core::$t::INFINITY); }
284293
if !is_positive && sig > prev_sig
285-
{ return Ok(Float::neg_infinity()); }
294+
{ return Ok(core::$t::NEG_INFINITY); }
286295
prev_sig = sig;
287296
},
288297
None => match c {
@@ -316,9 +325,15 @@ macro_rules! float_trait_impl {
316325
None => return Err(PFE { kind: Invalid }),
317326
};
318327

328+
#[cfg(feature = "std")]
329+
fn pow(base: $t, exp: usize) -> $t {
330+
Float::powi(base, exp as i32)
331+
}
332+
// otherwise uses the generic `pow` from the root
333+
319334
match (is_positive, exp) {
320-
(true, Ok(exp)) => base.powi(exp as i32),
321-
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
335+
(true, Ok(exp)) => pow(base, exp),
336+
(false, Ok(exp)) => 1.0 / pow(base, exp),
322337
(_, Err(_)) => return Err(PFE { kind: Invalid }),
323338
}
324339
},

src/ops/checked.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::ops::{Add, Sub, Mul, Div, Shl, Shr};
1+
use core::ops::{Add, Sub, Mul, Div, Shl, Shr};
22

33
/// Performs addition that returns `None` instead of wrapping around on
44
/// overflow.

src/ops/wrapping.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::ops::{Add, Sub, Mul};
2-
use std::num::Wrapping;
1+
use core::ops::{Add, Sub, Mul};
2+
use core::num::Wrapping;
33

44
macro_rules! wrapping_impl {
55
($trait_name:ident, $method:ident, $t:ty) => {

src/pow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::ops::Mul;
1+
use core::ops::Mul;
22
use {One, CheckedMul};
33

44
/// Raises a value to the power of exp, using exponentiation by squaring.

src/real.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use {Num, NumCast, Float};
1010
///
1111
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
1212
/// for a list of data types that could meaningfully implement this trait.
13+
///
14+
/// This trait is only available with the `std` feature.
1315
pub trait Real
1416
: Num
1517
+ Copy

0 commit comments

Comments
 (0)