Auto merge of #296 - vks:no_std, r=cuviper
traits: Introduce std feature This makes it possible to build `traits` without `std`. For this a new trait `BasicFloat` was introduced, implementing some basic functionality that works with `core`. Most notably this is lacking functions like `cos`, `sin`, etc. `Float` is not available without `std`. Refs #216.
This commit is contained in:
commit
8b5d4ac24e
|
@ -10,6 +10,10 @@ for package in bigint complex integer iter rational traits; do
|
||||||
cargo test --manifest-path $package/Cargo.toml
|
cargo test --manifest-path $package/Cargo.toml
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Only num-traits supports no_std at the moment.
|
||||||
|
cargo build --manifest-path traits/Cargo.toml --no-default-features
|
||||||
|
cargo test --manifest-path traits/Cargo.toml --no-default-features
|
||||||
|
|
||||||
# Each isolated feature should also work everywhere.
|
# Each isolated feature should also work everywhere.
|
||||||
for feature in '' bigint rational complex; do
|
for feature in '' bigint rational complex; do
|
||||||
cargo build --verbose --no-default-features --features="$feature"
|
cargo build --verbose --no-default-features --features="$feature"
|
||||||
|
|
|
@ -10,3 +10,7 @@ name = "num-traits"
|
||||||
version = "0.1.37"
|
version = "0.1.37"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = []
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{usize, u8, u16, u32, u64};
|
use core::{usize, u8, u16, u32, u64};
|
||||||
use std::{isize, i8, i16, i32, i64};
|
use core::{isize, i8, i16, i32, i64};
|
||||||
use std::{f32, f64};
|
use core::{f32, f64};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
/// Numbers which have upper and lower bounds
|
/// Numbers which have upper and lower bounds
|
||||||
pub trait Bounded {
|
pub trait Bounded {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use std::mem::size_of;
|
use core::mem::size_of;
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
use identities::Zero;
|
use identities::Zero;
|
||||||
use bounds::Bounded;
|
use bounds::Bounded;
|
||||||
|
use float::Float;
|
||||||
|
|
||||||
/// A generic trait for converting a value to a number.
|
/// A generic trait for converting a value to a number.
|
||||||
pub trait ToPrimitive {
|
pub trait ToPrimitive {
|
||||||
|
@ -226,8 +227,8 @@ macro_rules! impl_to_primitive_float_to_float {
|
||||||
// Make sure the value is in range for the cast.
|
// Make sure the value is in range for the cast.
|
||||||
// NaN and +-inf are cast as they are.
|
// NaN and +-inf are cast as they are.
|
||||||
let n = $slf as f64;
|
let n = $slf as f64;
|
||||||
let max_value: $DstT = ::std::$DstT::MAX;
|
let max_value: $DstT = ::core::$DstT::MAX;
|
||||||
if !n.is_finite() || (-max_value as f64 <= n && n <= max_value as f64) {
|
if !Float::is_finite(n) || (-max_value as f64 <= n && n <= max_value as f64) {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -454,8 +455,8 @@ impl<T: NumCast> NumCast for Wrapping<T> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_primitive_float() {
|
fn to_primitive_float() {
|
||||||
use std::f32;
|
use core::f32;
|
||||||
use std::f64;
|
use core::f64;
|
||||||
|
|
||||||
let f32_toolarge = 1e39f64;
|
let f32_toolarge = 1e39f64;
|
||||||
assert_eq!(f32_toolarge.to_f32(), None);
|
assert_eq!(f32_toolarge.to_f32(), None);
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
use std::mem;
|
use core::mem;
|
||||||
use std::ops::Neg;
|
use core::ops::Neg;
|
||||||
use std::num::FpCategory;
|
use core::num::FpCategory;
|
||||||
|
|
||||||
// Used for default implementation of `epsilon`
|
// Used for default implementation of `epsilon`
|
||||||
use std::f32;
|
use core::f32;
|
||||||
|
|
||||||
use {Num, NumCast};
|
use {ToPrimitive, Num, NumCast};
|
||||||
|
|
||||||
// FIXME: these doctests aren't actually helpful, because they're using and
|
// FIXME: these doctests aren't actually helpful, because they're using and
|
||||||
// testing the inherent methods directly, not going through `Float`.
|
// testing the inherent methods directly, not going through `Float`.
|
||||||
|
|
||||||
|
/// Floating point operations.
|
||||||
|
///
|
||||||
|
/// Please note that some methods are disabled for `no_std`. If you implement it
|
||||||
|
/// only for `no_std`, the build will fail if anyone else in the dependency
|
||||||
|
/// graph enables `num-traits/std`.
|
||||||
pub trait Float
|
pub trait Float
|
||||||
: Num
|
: Num
|
||||||
+ Copy
|
+ Copy
|
||||||
|
@ -27,6 +32,7 @@ pub trait Float
|
||||||
/// assert!(nan.is_nan());
|
/// assert!(nan.is_nan());
|
||||||
/// ```
|
/// ```
|
||||||
fn nan() -> Self;
|
fn nan() -> Self;
|
||||||
|
|
||||||
/// Returns the infinite value.
|
/// Returns the infinite value.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -40,6 +46,7 @@ pub trait Float
|
||||||
/// assert!(infinity > f32::MAX);
|
/// assert!(infinity > f32::MAX);
|
||||||
/// ```
|
/// ```
|
||||||
fn infinity() -> Self;
|
fn infinity() -> Self;
|
||||||
|
|
||||||
/// Returns the negative infinite value.
|
/// Returns the negative infinite value.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -53,6 +60,7 @@ pub trait Float
|
||||||
/// assert!(neg_infinity < f32::MIN);
|
/// assert!(neg_infinity < f32::MIN);
|
||||||
/// ```
|
/// ```
|
||||||
fn neg_infinity() -> Self;
|
fn neg_infinity() -> Self;
|
||||||
|
|
||||||
/// Returns `-0.0`.
|
/// Returns `-0.0`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -66,7 +74,10 @@ pub trait Float
|
||||||
/// assert_eq!(7.0f32/inf, zero);
|
/// assert_eq!(7.0f32/inf, zero);
|
||||||
/// assert_eq!(zero * 10.0, zero);
|
/// assert_eq!(zero * 10.0, zero);
|
||||||
/// ```
|
/// ```
|
||||||
fn neg_zero() -> Self;
|
#[inline]
|
||||||
|
fn neg_zero() -> Self {
|
||||||
|
-Self::zero()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the smallest finite value that this type can represent.
|
/// Returns the smallest finite value that this type can represent.
|
||||||
///
|
///
|
||||||
|
@ -134,7 +145,10 @@ pub trait Float
|
||||||
/// assert!(nan.is_nan());
|
/// assert!(nan.is_nan());
|
||||||
/// assert!(!f.is_nan());
|
/// assert!(!f.is_nan());
|
||||||
/// ```
|
/// ```
|
||||||
fn is_nan(self) -> bool;
|
#[inline]
|
||||||
|
fn is_nan(self) -> bool {
|
||||||
|
self != self
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if this value is positive infinity or negative infinity and
|
/// Returns `true` if this value is positive infinity or negative infinity and
|
||||||
/// false otherwise.
|
/// false otherwise.
|
||||||
|
@ -154,7 +168,10 @@ pub trait Float
|
||||||
/// assert!(inf.is_infinite());
|
/// assert!(inf.is_infinite());
|
||||||
/// assert!(neg_inf.is_infinite());
|
/// assert!(neg_inf.is_infinite());
|
||||||
/// ```
|
/// ```
|
||||||
fn is_infinite(self) -> bool;
|
#[inline]
|
||||||
|
fn is_infinite(self) -> bool {
|
||||||
|
self == Self::infinity() || self == Self::neg_infinity()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if this number is neither infinite nor `NaN`.
|
/// Returns `true` if this number is neither infinite nor `NaN`.
|
||||||
///
|
///
|
||||||
|
@ -173,7 +190,10 @@ pub trait Float
|
||||||
/// assert!(!inf.is_finite());
|
/// assert!(!inf.is_finite());
|
||||||
/// assert!(!neg_inf.is_finite());
|
/// assert!(!neg_inf.is_finite());
|
||||||
/// ```
|
/// ```
|
||||||
fn is_finite(self) -> bool;
|
#[inline]
|
||||||
|
fn is_finite(self) -> bool {
|
||||||
|
!(self.is_nan() || self.is_infinite())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the number is neither zero, infinite,
|
/// Returns `true` if the number is neither zero, infinite,
|
||||||
/// [subnormal][subnormal], or `NaN`.
|
/// [subnormal][subnormal], or `NaN`.
|
||||||
|
@ -197,7 +217,10 @@ pub trait Float
|
||||||
/// assert!(!lower_than_min.is_normal());
|
/// assert!(!lower_than_min.is_normal());
|
||||||
/// ```
|
/// ```
|
||||||
/// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
|
/// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
|
||||||
fn is_normal(self) -> bool;
|
#[inline]
|
||||||
|
fn is_normal(self) -> bool {
|
||||||
|
self.classify() == FpCategory::Normal
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the floating point category of the number. If only one property
|
/// Returns the floating point category of the number. If only one property
|
||||||
/// is going to be tested, it is generally faster to use the specific
|
/// is going to be tested, it is generally faster to use the specific
|
||||||
|
@ -227,6 +250,7 @@ pub trait Float
|
||||||
/// assert_eq!(f.floor(), 3.0);
|
/// assert_eq!(f.floor(), 3.0);
|
||||||
/// assert_eq!(g.floor(), 3.0);
|
/// assert_eq!(g.floor(), 3.0);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn floor(self) -> Self;
|
fn floor(self) -> Self;
|
||||||
|
|
||||||
/// Returns the smallest integer greater than or equal to a number.
|
/// Returns the smallest integer greater than or equal to a number.
|
||||||
|
@ -240,6 +264,7 @@ pub trait Float
|
||||||
/// assert_eq!(f.ceil(), 4.0);
|
/// assert_eq!(f.ceil(), 4.0);
|
||||||
/// assert_eq!(g.ceil(), 4.0);
|
/// assert_eq!(g.ceil(), 4.0);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn ceil(self) -> Self;
|
fn ceil(self) -> Self;
|
||||||
|
|
||||||
/// Returns the nearest integer to a number. Round half-way cases away from
|
/// Returns the nearest integer to a number. Round half-way cases away from
|
||||||
|
@ -254,6 +279,7 @@ pub trait Float
|
||||||
/// assert_eq!(f.round(), 3.0);
|
/// assert_eq!(f.round(), 3.0);
|
||||||
/// assert_eq!(g.round(), -3.0);
|
/// assert_eq!(g.round(), -3.0);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn round(self) -> Self;
|
fn round(self) -> Self;
|
||||||
|
|
||||||
/// Return the integer part of a number.
|
/// Return the integer part of a number.
|
||||||
|
@ -267,6 +293,7 @@ pub trait Float
|
||||||
/// assert_eq!(f.trunc(), 3.0);
|
/// assert_eq!(f.trunc(), 3.0);
|
||||||
/// assert_eq!(g.trunc(), -3.0);
|
/// assert_eq!(g.trunc(), -3.0);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn trunc(self) -> Self;
|
fn trunc(self) -> Self;
|
||||||
|
|
||||||
/// Returns the fractional part of a number.
|
/// Returns the fractional part of a number.
|
||||||
|
@ -282,6 +309,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference_x < 1e-10);
|
/// assert!(abs_difference_x < 1e-10);
|
||||||
/// assert!(abs_difference_y < 1e-10);
|
/// assert!(abs_difference_y < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn fract(self) -> Self;
|
fn fract(self) -> Self;
|
||||||
|
|
||||||
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
|
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
|
||||||
|
@ -302,7 +330,16 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(f64::NAN.abs().is_nan());
|
/// assert!(f64::NAN.abs().is_nan());
|
||||||
/// ```
|
/// ```
|
||||||
fn abs(self) -> Self;
|
#[inline]
|
||||||
|
fn abs(self) -> Self {
|
||||||
|
if self.is_sign_positive() {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if self.is_sign_negative() {
|
||||||
|
return -self;
|
||||||
|
}
|
||||||
|
Self::nan()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a number that represents the sign of `self`.
|
/// Returns a number that represents the sign of `self`.
|
||||||
///
|
///
|
||||||
|
@ -321,7 +358,16 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(f64::NAN.signum().is_nan());
|
/// assert!(f64::NAN.signum().is_nan());
|
||||||
/// ```
|
/// ```
|
||||||
fn signum(self) -> Self;
|
#[inline]
|
||||||
|
fn signum(self) -> Self {
|
||||||
|
if self.is_sign_positive() {
|
||||||
|
return Self::one();
|
||||||
|
}
|
||||||
|
if self.is_sign_negative() {
|
||||||
|
return -Self::one();
|
||||||
|
}
|
||||||
|
Self::nan()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if `self` is positive, including `+0.0` and
|
/// Returns `true` if `self` is positive, including `+0.0` and
|
||||||
/// `Float::infinity()`.
|
/// `Float::infinity()`.
|
||||||
|
@ -340,7 +386,10 @@ pub trait Float
|
||||||
/// // Requires both tests to determine if is `NaN`
|
/// // Requires both tests to determine if is `NaN`
|
||||||
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
|
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
|
||||||
/// ```
|
/// ```
|
||||||
fn is_sign_positive(self) -> bool;
|
#[inline]
|
||||||
|
fn is_sign_positive(self) -> bool {
|
||||||
|
self > Self::zero() || (Self::one() / self) == Self::infinity()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if `self` is negative, including `-0.0` and
|
/// Returns `true` if `self` is negative, including `-0.0` and
|
||||||
/// `Float::neg_infinity()`.
|
/// `Float::neg_infinity()`.
|
||||||
|
@ -359,7 +408,10 @@ pub trait Float
|
||||||
/// // Requires both tests to determine if is `NaN`.
|
/// // Requires both tests to determine if is `NaN`.
|
||||||
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
|
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
|
||||||
/// ```
|
/// ```
|
||||||
fn is_sign_negative(self) -> bool;
|
#[inline]
|
||||||
|
fn is_sign_negative(self) -> bool {
|
||||||
|
self < Self::zero() || (Self::one() / self) == Self::neg_infinity()
|
||||||
|
}
|
||||||
|
|
||||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||||
/// error. This produces a more accurate result with better performance than
|
/// error. This produces a more accurate result with better performance than
|
||||||
|
@ -377,7 +429,9 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn mul_add(self, a: Self, b: Self) -> Self;
|
fn mul_add(self, a: Self, b: Self) -> Self;
|
||||||
|
|
||||||
/// Take the reciprocal (inverse) of a number, `1/x`.
|
/// Take the reciprocal (inverse) of a number, `1/x`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -388,7 +442,10 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn recip(self) -> Self;
|
#[inline]
|
||||||
|
fn recip(self) -> Self {
|
||||||
|
Self::one() / self
|
||||||
|
}
|
||||||
|
|
||||||
/// Raise a number to an integer power.
|
/// Raise a number to an integer power.
|
||||||
///
|
///
|
||||||
|
@ -402,7 +459,15 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn powi(self, n: i32) -> Self;
|
#[inline]
|
||||||
|
fn powi(mut self, mut exp: i32) -> Self {
|
||||||
|
if exp < 0 {
|
||||||
|
self = self.recip();
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
// It should always be possible to convert a positive `i32` to a `usize`.
|
||||||
|
super::pow(self, exp.to_usize().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
/// Raise a number to a floating point power.
|
/// Raise a number to a floating point power.
|
||||||
///
|
///
|
||||||
|
@ -414,6 +479,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn powf(self, n: Self) -> Self;
|
fn powf(self, n: Self) -> Self;
|
||||||
|
|
||||||
/// Take the square root of a number.
|
/// Take the square root of a number.
|
||||||
|
@ -431,6 +497,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// assert!(negative.sqrt().is_nan());
|
/// assert!(negative.sqrt().is_nan());
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn sqrt(self) -> Self;
|
fn sqrt(self) -> Self;
|
||||||
|
|
||||||
/// Returns `e^(self)`, (the exponential function).
|
/// Returns `e^(self)`, (the exponential function).
|
||||||
|
@ -447,6 +514,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn exp(self) -> Self;
|
fn exp(self) -> Self;
|
||||||
|
|
||||||
/// Returns `2^(self)`.
|
/// Returns `2^(self)`.
|
||||||
|
@ -461,6 +529,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn exp2(self) -> Self;
|
fn exp2(self) -> Self;
|
||||||
|
|
||||||
/// Returns the natural logarithm of the number.
|
/// Returns the natural logarithm of the number.
|
||||||
|
@ -477,6 +546,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn ln(self) -> Self;
|
fn ln(self) -> Self;
|
||||||
|
|
||||||
/// Returns the logarithm of the number with respect to an arbitrary base.
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
||||||
|
@ -496,6 +566,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference_10 < 1e-10);
|
/// assert!(abs_difference_10 < 1e-10);
|
||||||
/// assert!(abs_difference_2 < 1e-10);
|
/// assert!(abs_difference_2 < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn log(self, base: Self) -> Self;
|
fn log(self, base: Self) -> Self;
|
||||||
|
|
||||||
/// Returns the base 2 logarithm of the number.
|
/// Returns the base 2 logarithm of the number.
|
||||||
|
@ -510,6 +581,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn log2(self) -> Self;
|
fn log2(self) -> Self;
|
||||||
|
|
||||||
/// Returns the base 10 logarithm of the number.
|
/// Returns the base 10 logarithm of the number.
|
||||||
|
@ -524,6 +596,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn log10(self) -> Self;
|
fn log10(self) -> Self;
|
||||||
|
|
||||||
/// Converts radians to degrees.
|
/// Converts radians to degrees.
|
||||||
|
@ -537,6 +610,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_degrees(self) -> Self {
|
fn to_degrees(self) -> Self {
|
||||||
let halfpi = Self::zero().acos();
|
let halfpi = Self::zero().acos();
|
||||||
|
@ -544,6 +618,39 @@ pub trait Float
|
||||||
self * ninety / halfpi
|
self * ninety / halfpi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts radians to degrees.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::f64::consts;
|
||||||
|
///
|
||||||
|
/// let angle = consts::PI;
|
||||||
|
///
|
||||||
|
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
fn to_degrees(self) -> Self;
|
||||||
|
|
||||||
|
/// Converts degrees to radians.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::f64::consts;
|
||||||
|
///
|
||||||
|
/// let angle = 180.0_f64;
|
||||||
|
///
|
||||||
|
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[inline]
|
||||||
|
fn to_radians(self) -> Self {
|
||||||
|
let halfpi = Self::zero().acos();
|
||||||
|
let ninety = Self::from(90u8).unwrap();
|
||||||
|
self * halfpi / ninety
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts degrees to radians.
|
/// Converts degrees to radians.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -555,15 +662,13 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[cfg(not(feature = "std"))]
|
||||||
fn to_radians(self) -> Self {
|
fn to_radians(self) -> Self;
|
||||||
let halfpi = Self::zero().acos();
|
|
||||||
let ninety = Self::from(90u8).unwrap();
|
|
||||||
self * halfpi / ninety
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the maximum of the two numbers.
|
/// Returns the maximum of the two numbers.
|
||||||
///
|
///
|
||||||
|
/// If one of the arguments is NaN, then the other argument is returned.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::Float;
|
/// use num_traits::Float;
|
||||||
///
|
///
|
||||||
|
@ -572,10 +677,21 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert_eq!(x.max(y), y);
|
/// assert_eq!(x.max(y), y);
|
||||||
/// ```
|
/// ```
|
||||||
fn max(self, other: Self) -> Self;
|
#[inline]
|
||||||
|
fn max(self, other: Self) -> Self {
|
||||||
|
if self.is_nan() {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
if other.is_nan() {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if self > other { self } else { other }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the minimum of the two numbers.
|
/// Returns the minimum of the two numbers.
|
||||||
///
|
///
|
||||||
|
/// If one of the arguments is NaN, then the other argument is returned.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::Float;
|
/// use num_traits::Float;
|
||||||
///
|
///
|
||||||
|
@ -584,7 +700,16 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert_eq!(x.min(y), x);
|
/// assert_eq!(x.min(y), x);
|
||||||
/// ```
|
/// ```
|
||||||
fn min(self, other: Self) -> Self;
|
#[inline]
|
||||||
|
fn min(self, other: Self) -> Self {
|
||||||
|
if self.is_nan() {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
if other.is_nan() {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if self < other { self } else { other }
|
||||||
|
}
|
||||||
|
|
||||||
/// The positive difference of two numbers.
|
/// The positive difference of two numbers.
|
||||||
///
|
///
|
||||||
|
@ -603,6 +728,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference_x < 1e-10);
|
/// assert!(abs_difference_x < 1e-10);
|
||||||
/// assert!(abs_difference_y < 1e-10);
|
/// assert!(abs_difference_y < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn abs_sub(self, other: Self) -> Self;
|
fn abs_sub(self, other: Self) -> Self;
|
||||||
|
|
||||||
/// Take the cubic root of a number.
|
/// Take the cubic root of a number.
|
||||||
|
@ -617,6 +743,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn cbrt(self) -> Self;
|
fn cbrt(self) -> Self;
|
||||||
|
|
||||||
/// Calculate the length of the hypotenuse of a right-angle triangle given
|
/// Calculate the length of the hypotenuse of a right-angle triangle given
|
||||||
|
@ -633,6 +760,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn hypot(self, other: Self) -> Self;
|
fn hypot(self, other: Self) -> Self;
|
||||||
|
|
||||||
/// Computes the sine of a number (in radians).
|
/// Computes the sine of a number (in radians).
|
||||||
|
@ -647,6 +775,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn sin(self) -> Self;
|
fn sin(self) -> Self;
|
||||||
|
|
||||||
/// Computes the cosine of a number (in radians).
|
/// Computes the cosine of a number (in radians).
|
||||||
|
@ -661,6 +790,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn cos(self) -> Self;
|
fn cos(self) -> Self;
|
||||||
|
|
||||||
/// Computes the tangent of a number (in radians).
|
/// Computes the tangent of a number (in radians).
|
||||||
|
@ -674,6 +804,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-14);
|
/// assert!(abs_difference < 1e-14);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn tan(self) -> Self;
|
fn tan(self) -> Self;
|
||||||
|
|
||||||
/// Computes the arcsine of a number. Return value is in radians in
|
/// Computes the arcsine of a number. Return value is in radians in
|
||||||
|
@ -691,6 +822,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn asin(self) -> Self;
|
fn asin(self) -> Self;
|
||||||
|
|
||||||
/// Computes the arccosine of a number. Return value is in radians in
|
/// Computes the arccosine of a number. Return value is in radians in
|
||||||
|
@ -708,6 +840,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn acos(self) -> Self;
|
fn acos(self) -> Self;
|
||||||
|
|
||||||
/// Computes the arctangent of a number. Return value is in radians in the
|
/// Computes the arctangent of a number. Return value is in radians in the
|
||||||
|
@ -723,6 +856,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn atan(self) -> Self;
|
fn atan(self) -> Self;
|
||||||
|
|
||||||
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
||||||
|
@ -752,6 +886,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference_1 < 1e-10);
|
/// assert!(abs_difference_1 < 1e-10);
|
||||||
/// assert!(abs_difference_2 < 1e-10);
|
/// assert!(abs_difference_2 < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn atan2(self, other: Self) -> Self;
|
fn atan2(self, other: Self) -> Self;
|
||||||
|
|
||||||
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
||||||
|
@ -770,6 +905,7 @@ pub trait Float
|
||||||
/// assert!(abs_difference_0 < 1e-10);
|
/// assert!(abs_difference_0 < 1e-10);
|
||||||
/// assert!(abs_difference_0 < 1e-10);
|
/// assert!(abs_difference_0 < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn sin_cos(self) -> (Self, Self);
|
fn sin_cos(self) -> (Self, Self);
|
||||||
|
|
||||||
/// Returns `e^(self) - 1` in a way that is accurate even if the
|
/// Returns `e^(self) - 1` in a way that is accurate even if the
|
||||||
|
@ -785,6 +921,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn exp_m1(self) -> Self;
|
fn exp_m1(self) -> Self;
|
||||||
|
|
||||||
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
|
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
|
||||||
|
@ -801,6 +938,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn ln_1p(self) -> Self;
|
fn ln_1p(self) -> Self;
|
||||||
|
|
||||||
/// Hyperbolic sine function.
|
/// Hyperbolic sine function.
|
||||||
|
@ -819,6 +957,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn sinh(self) -> Self;
|
fn sinh(self) -> Self;
|
||||||
|
|
||||||
/// Hyperbolic cosine function.
|
/// Hyperbolic cosine function.
|
||||||
|
@ -837,6 +976,7 @@ pub trait Float
|
||||||
/// // Same result
|
/// // Same result
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn cosh(self) -> Self;
|
fn cosh(self) -> Self;
|
||||||
|
|
||||||
/// Hyperbolic tangent function.
|
/// Hyperbolic tangent function.
|
||||||
|
@ -855,6 +995,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn tanh(self) -> Self;
|
fn tanh(self) -> Self;
|
||||||
|
|
||||||
/// Inverse hyperbolic sine function.
|
/// Inverse hyperbolic sine function.
|
||||||
|
@ -869,6 +1010,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn asinh(self) -> Self;
|
fn asinh(self) -> Self;
|
||||||
|
|
||||||
/// Inverse hyperbolic cosine function.
|
/// Inverse hyperbolic cosine function.
|
||||||
|
@ -883,6 +1025,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn acosh(self) -> Self;
|
fn acosh(self) -> Self;
|
||||||
|
|
||||||
/// Inverse hyperbolic tangent function.
|
/// Inverse hyperbolic tangent function.
|
||||||
|
@ -898,6 +1041,7 @@ pub trait Float
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn atanh(self) -> Self;
|
fn atanh(self) -> Self;
|
||||||
|
|
||||||
|
|
||||||
|
@ -926,21 +1070,21 @@ pub trait Float
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! float_impl {
|
macro_rules! float_impl {
|
||||||
($T:ident $decode:ident) => (
|
($T:ident $decode:ident $classify:ident) => (
|
||||||
impl Float for $T {
|
impl Float for $T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn nan() -> Self {
|
fn nan() -> Self {
|
||||||
::std::$T::NAN
|
::core::$T::NAN
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn infinity() -> Self {
|
fn infinity() -> Self {
|
||||||
::std::$T::INFINITY
|
::core::$T::INFINITY
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg_infinity() -> Self {
|
fn neg_infinity() -> Self {
|
||||||
::std::$T::NEG_INFINITY
|
::core::$T::NEG_INFINITY
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -950,264 +1094,326 @@ macro_rules! float_impl {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn min_value() -> Self {
|
fn min_value() -> Self {
|
||||||
::std::$T::MIN
|
::core::$T::MIN
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn min_positive_value() -> Self {
|
fn min_positive_value() -> Self {
|
||||||
::std::$T::MIN_POSITIVE
|
::core::$T::MIN_POSITIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn epsilon() -> Self {
|
fn epsilon() -> Self {
|
||||||
::std::$T::EPSILON
|
::core::$T::EPSILON
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max_value() -> Self {
|
fn max_value() -> Self {
|
||||||
::std::$T::MAX
|
::core::$T::MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_nan(self) -> bool {
|
fn is_nan(self) -> bool {
|
||||||
<$T>::is_nan(self)
|
<$T>::is_nan(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_infinite(self) -> bool {
|
fn is_infinite(self) -> bool {
|
||||||
<$T>::is_infinite(self)
|
<$T>::is_infinite(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_finite(self) -> bool {
|
fn is_finite(self) -> bool {
|
||||||
<$T>::is_finite(self)
|
<$T>::is_finite(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_normal(self) -> bool {
|
fn is_normal(self) -> bool {
|
||||||
<$T>::is_normal(self)
|
<$T>::is_normal(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn classify(self) -> FpCategory {
|
fn classify(self) -> FpCategory {
|
||||||
<$T>::classify(self)
|
<$T>::classify(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
#[inline]
|
||||||
|
fn classify(self) -> FpCategory {
|
||||||
|
$classify(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn floor(self) -> Self {
|
fn floor(self) -> Self {
|
||||||
<$T>::floor(self)
|
<$T>::floor(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ceil(self) -> Self {
|
fn ceil(self) -> Self {
|
||||||
<$T>::ceil(self)
|
<$T>::ceil(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn round(self) -> Self {
|
fn round(self) -> Self {
|
||||||
<$T>::round(self)
|
<$T>::round(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn trunc(self) -> Self {
|
fn trunc(self) -> Self {
|
||||||
<$T>::trunc(self)
|
<$T>::trunc(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fract(self) -> Self {
|
fn fract(self) -> Self {
|
||||||
<$T>::fract(self)
|
<$T>::fract(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs(self) -> Self {
|
fn abs(self) -> Self {
|
||||||
<$T>::abs(self)
|
<$T>::abs(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn signum(self) -> Self {
|
fn signum(self) -> Self {
|
||||||
<$T>::signum(self)
|
<$T>::signum(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_sign_positive(self) -> bool {
|
fn is_sign_positive(self) -> bool {
|
||||||
<$T>::is_sign_positive(self)
|
<$T>::is_sign_positive(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_sign_negative(self) -> bool {
|
fn is_sign_negative(self) -> bool {
|
||||||
<$T>::is_sign_negative(self)
|
<$T>::is_sign_negative(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_add(self, a: Self, b: Self) -> Self {
|
fn mul_add(self, a: Self, b: Self) -> Self {
|
||||||
<$T>::mul_add(self, a, b)
|
<$T>::mul_add(self, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn recip(self) -> Self {
|
fn recip(self) -> Self {
|
||||||
<$T>::recip(self)
|
<$T>::recip(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn powi(self, n: i32) -> Self {
|
fn powi(self, n: i32) -> Self {
|
||||||
<$T>::powi(self, n)
|
<$T>::powi(self, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn powf(self, n: Self) -> Self {
|
fn powf(self, n: Self) -> Self {
|
||||||
<$T>::powf(self, n)
|
<$T>::powf(self, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sqrt(self) -> Self {
|
fn sqrt(self) -> Self {
|
||||||
<$T>::sqrt(self)
|
<$T>::sqrt(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn exp(self) -> Self {
|
fn exp(self) -> Self {
|
||||||
<$T>::exp(self)
|
<$T>::exp(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn exp2(self) -> Self {
|
fn exp2(self) -> Self {
|
||||||
<$T>::exp2(self)
|
<$T>::exp2(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ln(self) -> Self {
|
fn ln(self) -> Self {
|
||||||
<$T>::ln(self)
|
<$T>::ln(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn log(self, base: Self) -> Self {
|
fn log(self, base: Self) -> Self {
|
||||||
<$T>::log(self, base)
|
<$T>::log(self, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn log2(self) -> Self {
|
fn log2(self) -> Self {
|
||||||
<$T>::log2(self)
|
<$T>::log2(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn log10(self) -> Self {
|
fn log10(self) -> Self {
|
||||||
<$T>::log10(self)
|
<$T>::log10(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_degrees(self) -> Self {
|
fn to_degrees(self) -> Self {
|
||||||
// NB: `f32` didn't stabilize this until 1.7
|
<$T>::to_degrees(self)
|
||||||
// <$T>::to_degrees(self)
|
|
||||||
self * (180. / ::std::$T::consts::PI)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_radians(self) -> Self {
|
fn to_radians(self) -> Self {
|
||||||
// NB: `f32` didn't stabilize this until 1.7
|
<$T>::to_radians(self)
|
||||||
// <$T>::to_radians(self)
|
|
||||||
self * (::std::$T::consts::PI / 180.)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
#[inline]
|
||||||
|
fn to_degrees(self) -> Self {
|
||||||
|
self * (180. / ::core::$T::consts::PI)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
#[inline]
|
||||||
|
fn to_radians(self) -> Self {
|
||||||
|
self * (::core::$T::consts::PI / 180.)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max(self, other: Self) -> Self {
|
fn max(self, other: Self) -> Self {
|
||||||
<$T>::max(self, other)
|
<$T>::max(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn min(self, other: Self) -> Self {
|
fn min(self, other: Self) -> Self {
|
||||||
<$T>::min(self, other)
|
<$T>::min(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn abs_sub(self, other: Self) -> Self {
|
fn abs_sub(self, other: Self) -> Self {
|
||||||
<$T>::abs_sub(self, other)
|
<$T>::abs_sub(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cbrt(self) -> Self {
|
fn cbrt(self) -> Self {
|
||||||
<$T>::cbrt(self)
|
<$T>::cbrt(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hypot(self, other: Self) -> Self {
|
fn hypot(self, other: Self) -> Self {
|
||||||
<$T>::hypot(self, other)
|
<$T>::hypot(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sin(self) -> Self {
|
fn sin(self) -> Self {
|
||||||
<$T>::sin(self)
|
<$T>::sin(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cos(self) -> Self {
|
fn cos(self) -> Self {
|
||||||
<$T>::cos(self)
|
<$T>::cos(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tan(self) -> Self {
|
fn tan(self) -> Self {
|
||||||
<$T>::tan(self)
|
<$T>::tan(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn asin(self) -> Self {
|
fn asin(self) -> Self {
|
||||||
<$T>::asin(self)
|
<$T>::asin(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn acos(self) -> Self {
|
fn acos(self) -> Self {
|
||||||
<$T>::acos(self)
|
<$T>::acos(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn atan(self) -> Self {
|
fn atan(self) -> Self {
|
||||||
<$T>::atan(self)
|
<$T>::atan(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn atan2(self, other: Self) -> Self {
|
fn atan2(self, other: Self) -> Self {
|
||||||
<$T>::atan2(self, other)
|
<$T>::atan2(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sin_cos(self) -> (Self, Self) {
|
fn sin_cos(self) -> (Self, Self) {
|
||||||
<$T>::sin_cos(self)
|
<$T>::sin_cos(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn exp_m1(self) -> Self {
|
fn exp_m1(self) -> Self {
|
||||||
<$T>::exp_m1(self)
|
<$T>::exp_m1(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ln_1p(self) -> Self {
|
fn ln_1p(self) -> Self {
|
||||||
<$T>::ln_1p(self)
|
<$T>::ln_1p(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sinh(self) -> Self {
|
fn sinh(self) -> Self {
|
||||||
<$T>::sinh(self)
|
<$T>::sinh(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cosh(self) -> Self {
|
fn cosh(self) -> Self {
|
||||||
<$T>::cosh(self)
|
<$T>::cosh(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tanh(self) -> Self {
|
fn tanh(self) -> Self {
|
||||||
<$T>::tanh(self)
|
<$T>::tanh(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn asinh(self) -> Self {
|
fn asinh(self) -> Self {
|
||||||
<$T>::asinh(self)
|
<$T>::asinh(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn acosh(self) -> Self {
|
fn acosh(self) -> Self {
|
||||||
<$T>::acosh(self)
|
<$T>::acosh(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn atanh(self) -> Self {
|
fn atanh(self) -> Self {
|
||||||
<$T>::atanh(self)
|
<$T>::atanh(self)
|
||||||
|
@ -1239,6 +1445,21 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
(mantissa as u64, exponent, sign)
|
(mantissa as u64, exponent, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
fn classify_f32(f: f32) -> FpCategory {
|
||||||
|
const EXP_MASK: u32 = 0x7f800000;
|
||||||
|
const MAN_MASK: u32 = 0x007fffff;
|
||||||
|
|
||||||
|
let bits: u32 = unsafe { mem::transmute(f) };
|
||||||
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||||
|
(0, 0) => FpCategory::Zero,
|
||||||
|
(_, 0) => FpCategory::Subnormal,
|
||||||
|
(0, EXP_MASK) => FpCategory::Infinite,
|
||||||
|
(_, EXP_MASK) => FpCategory::Nan,
|
||||||
|
_ => FpCategory::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
let bits: u64 = unsafe { mem::transmute(f) };
|
let bits: u64 = unsafe { mem::transmute(f) };
|
||||||
let sign: i8 = if bits >> 63 == 0 {
|
let sign: i8 = if bits >> 63 == 0 {
|
||||||
|
@ -1257,8 +1478,23 @@ fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
(mantissa, exponent, sign)
|
(mantissa, exponent, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
float_impl!(f32 integer_decode_f32);
|
#[cfg(not(feature = "std"))]
|
||||||
float_impl!(f64 integer_decode_f64);
|
fn classify_f64(f: f64) -> FpCategory {
|
||||||
|
const EXP_MASK: u64 = 0x7ff0000000000000;
|
||||||
|
const MAN_MASK: u64 = 0x000fffffffffffff;
|
||||||
|
|
||||||
|
let bits: u64 = unsafe { mem::transmute(f) };
|
||||||
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||||
|
(0, 0) => FpCategory::Zero,
|
||||||
|
(_, 0) => FpCategory::Subnormal,
|
||||||
|
(0, EXP_MASK) => FpCategory::Infinite,
|
||||||
|
(_, EXP_MASK) => FpCategory::Nan,
|
||||||
|
_ => FpCategory::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float_impl!(f32 integer_decode_f32 classify_f32);
|
||||||
|
float_impl!(f64 integer_decode_f64 classify_f64);
|
||||||
|
|
||||||
macro_rules! float_const_impl {
|
macro_rules! float_const_impl {
|
||||||
($(#[$doc:meta] $constant:ident,)+) => (
|
($(#[$doc:meta] $constant:ident,)+) => (
|
||||||
|
@ -1274,7 +1510,7 @@ macro_rules! float_const_impl {
|
||||||
$(
|
$(
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $constant() -> Self {
|
fn $constant() -> Self {
|
||||||
::std::$T::consts::$constant
|
::core::$T::consts::$constant
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
@ -1319,10 +1555,7 @@ float_const_impl! {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use Float;
|
use Float;
|
||||||
|
use core::f64::consts;
|
||||||
#[test]
|
|
||||||
fn convert_deg_rad() {
|
|
||||||
use std::f64::consts;
|
|
||||||
|
|
||||||
const DEG_RAD_PAIRS: [(f64, f64); 7] = [
|
const DEG_RAD_PAIRS: [(f64, f64); 7] = [
|
||||||
(0.0, 0.),
|
(0.0, 0.),
|
||||||
|
@ -1334,6 +1567,23 @@ mod tests {
|
||||||
(180.0, consts::PI),
|
(180.0, consts::PI),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_deg_rad_core() {
|
||||||
|
for &(deg, rad) in &DEG_RAD_PAIRS {
|
||||||
|
assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
|
||||||
|
assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
|
||||||
|
|
||||||
|
let (deg, rad) = (deg as f32, rad as f32);
|
||||||
|
assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
|
||||||
|
assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[test]
|
||||||
|
fn convert_deg_rad_std() {
|
||||||
|
use Float;
|
||||||
|
|
||||||
for &(deg, rad) in &DEG_RAD_PAIRS {
|
for &(deg, rad) in &DEG_RAD_PAIRS {
|
||||||
assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
|
assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
|
||||||
assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
|
assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ops::{Add, Mul};
|
use core::ops::{Add, Mul};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
/// Defines an additive identity element for `Self`.
|
/// Defines an additive identity element for `Self`.
|
||||||
pub trait Zero: Sized + Add<Self, Output = Self> {
|
pub trait Zero: Sized + Add<Self, Output = Self> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||||
|
|
||||||
use {Num, NumCast};
|
use {Num, NumCast};
|
||||||
use bounds::Bounded;
|
use bounds::Bounded;
|
||||||
|
|
|
@ -14,9 +14,15 @@
|
||||||
html_root_url = "https://rust-num.github.io/num/",
|
html_root_url = "https://rust-num.github.io/num/",
|
||||||
html_playground_url = "http://play.integer32.com/")]
|
html_playground_url = "http://play.integer32.com/")]
|
||||||
|
|
||||||
use std::ops::{Add, Sub, Mul, Div, Rem};
|
#![deny(unconditional_recursion)]
|
||||||
use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
|
||||||
use std::num::Wrapping;
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
|
use core::ops::{Add, Sub, Mul, Div, Rem};
|
||||||
|
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||||
|
use core::num::Wrapping;
|
||||||
|
|
||||||
pub use bounds::Bounded;
|
pub use bounds::Bounded;
|
||||||
pub use float::{Float, FloatConst};
|
pub use float::{Float, FloatConst};
|
||||||
|
@ -129,10 +135,10 @@ impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
|
||||||
macro_rules! int_trait_impl {
|
macro_rules! int_trait_impl {
|
||||||
($name:ident for $($t:ty)*) => ($(
|
($name:ident for $($t:ty)*) => ($(
|
||||||
impl $name for $t {
|
impl $name for $t {
|
||||||
type FromStrRadixErr = ::std::num::ParseIntError;
|
type FromStrRadixErr = ::core::num::ParseIntError;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str_radix(s: &str, radix: u32)
|
fn from_str_radix(s: &str, radix: u32)
|
||||||
-> Result<Self, ::std::num::ParseIntError>
|
-> Result<Self, ::core::num::ParseIntError>
|
||||||
{
|
{
|
||||||
<$t>::from_str_radix(s, radix)
|
<$t>::from_str_radix(s, radix)
|
||||||
}
|
}
|
||||||
|
@ -158,7 +164,7 @@ pub enum FloatErrorKind {
|
||||||
Empty,
|
Empty,
|
||||||
Invalid,
|
Invalid,
|
||||||
}
|
}
|
||||||
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
|
// FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
|
||||||
// so there's not really any way for us to reuse it.
|
// so there's not really any way for us to reuse it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseFloatError {
|
pub struct ParseFloatError {
|
||||||
|
@ -305,8 +311,8 @@ macro_rules! float_trait_impl {
|
||||||
};
|
};
|
||||||
|
|
||||||
match (is_positive, exp) {
|
match (is_positive, exp) {
|
||||||
(true, Ok(exp)) => base.powi(exp as i32),
|
(true, Ok(exp)) => Float::powi(base, exp as i32),
|
||||||
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
|
(false, Ok(exp)) => 1.0 / Float::powi(base, exp as i32),
|
||||||
(_, Err(_)) => return Err(PFE { kind: Invalid }),
|
(_, Err(_)) => return Err(PFE { kind: Invalid }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::{Add, Sub, Mul, Div};
|
use core::ops::{Add, Sub, Mul, Div};
|
||||||
|
|
||||||
/// Performs addition that returns `None` instead of wrapping around on
|
/// Performs addition that returns `None` instead of wrapping around on
|
||||||
/// overflow.
|
/// overflow.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ops::{Add, Sub, Mul};
|
use core::ops::{Add, Sub, Mul};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
macro_rules! wrapping_impl {
|
macro_rules! wrapping_impl {
|
||||||
($trait_name:ident, $method:ident, $t:ty) => {
|
($trait_name:ident, $method:ident, $t:ty) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::Mul;
|
use core::ops::Mul;
|
||||||
use {One, CheckedMul};
|
use {One, CheckedMul};
|
||||||
|
|
||||||
/// Raises a value to the power of exp, using exponentiation by squaring.
|
/// Raises a value to the power of exp, using exponentiation by squaring.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::ops::Neg;
|
use core::ops::Neg;
|
||||||
use std::{f32, f64};
|
use core::{f32, f64};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
use Num;
|
use {Num, Float};
|
||||||
|
|
||||||
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
||||||
pub trait Signed: Sized + Num + Neg<Output = Self> {
|
pub trait Signed: Sized + Num + Neg<Output = Self> {
|
||||||
|
@ -104,16 +104,15 @@ macro_rules! signed_float_impl {
|
||||||
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs(&self) -> $t {
|
fn abs(&self) -> $t {
|
||||||
<$t>::abs(*self)
|
(*self).abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The positive difference of two numbers. Returns `0.0` if the number is
|
/// The positive difference of two numbers. Returns `0.0` if the number is
|
||||||
/// less than or equal to `other`, otherwise the difference between`self`
|
/// less than or equal to `other`, otherwise the difference between`self`
|
||||||
/// and `other` is returned.
|
/// and `other` is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(deprecated)]
|
|
||||||
fn abs_sub(&self, other: &$t) -> $t {
|
fn abs_sub(&self, other: &$t) -> $t {
|
||||||
<$t>::abs_sub(*self, *other)
|
if *self <= *other { 0. } else { *self - *other }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -123,7 +122,7 @@ macro_rules! signed_float_impl {
|
||||||
/// - `NAN` if the number is NaN
|
/// - `NAN` if the number is NaN
|
||||||
#[inline]
|
#[inline]
|
||||||
fn signum(&self) -> $t {
|
fn signum(&self) -> $t {
|
||||||
<$t>::signum(*self)
|
Float::signum(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
||||||
|
|
Loading…
Reference in New Issue