Import "next" branch of rust-num/num

This commit is contained in:
Toshiki Teramura 2018-01-12 23:39:58 +09:00
parent 42a610d323
commit 0b1169c17b
11 changed files with 386 additions and 89 deletions

View File

@ -12,3 +12,7 @@ version = "0.1.41"
readme = "README.md" readme = "README.md"
[dependencies] [dependencies]
[features]
default = ["std"]
std = []

View File

@ -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 {

View File

@ -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);

View File

@ -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 {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_nan() {
Self::nan()
} else if self.is_sign_negative() {
-Self::one()
} else {
Self::one()
}
}
/// Returns `true` if `self` is positive, including `+0.0`, /// Returns `true` if `self` is positive, including `+0.0`,
/// `Float::infinity()`, and with newer versions of Rust `f64::NAN`. /// `Float::infinity()`, and with newer versions of Rust `f64::NAN`.
@ -339,7 +385,10 @@ pub trait Float
/// assert!(!g.is_sign_positive()); /// assert!(!g.is_sign_positive());
/// assert!(!neg_nan.is_sign_positive()); /// assert!(!neg_nan.is_sign_positive());
/// ``` /// ```
fn is_sign_positive(self) -> bool; #[inline]
fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
/// Returns `true` if `self` is negative, including `-0.0`, /// Returns `true` if `self` is negative, including `-0.0`,
/// `Float::neg_infinity()`, and with newer versions of Rust `-f64::NAN`. /// `Float::neg_infinity()`, and with newer versions of Rust `-f64::NAN`.
@ -357,7 +406,11 @@ pub trait Float
/// assert!(g.is_sign_negative()); /// assert!(g.is_sign_negative());
/// assert!(!nan.is_sign_negative()); /// assert!(!nan.is_sign_negative());
/// ``` /// ```
fn is_sign_negative(self) -> bool; #[inline]
fn is_sign_negative(self) -> bool {
let (_, _, sign) = self.integer_decode();
sign < 0
}
/// 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
@ -375,7 +428,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`.
/// ///
/// ``` /// ```
@ -386,7 +441,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.
/// ///
@ -400,7 +458,35 @@ pub trait Float
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
fn powi(self, n: i32) -> Self; #[inline]
fn powi(self, mut exp: i32) -> Self {
let mut base = self;
if exp == 0 {
return Self::one();
} else if exp < 0 {
base = base.recip();
exp = exp.wrapping_neg();
}
let mut exp = exp as u32;
// duplicated from `::pow`, but using `Mul` by value instead of by reference.
while exp & 1 == 0 {
base = base * base;
exp >>= 1;
}
if exp == 1 { return base; }
let mut acc = base;
while exp > 1 {
exp >>= 1;
base = base * base;
if exp & 1 == 1 {
acc = acc * base;
}
}
acc
}
/// Raise a number to a floating point power. /// Raise a number to a floating point power.
/// ///
@ -412,6 +498,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.
@ -429,6 +516,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).
@ -445,6 +533,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)`.
@ -459,6 +548,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.
@ -475,6 +565,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.
@ -494,6 +585,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.
@ -508,6 +600,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.
@ -522,6 +615,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.
@ -535,6 +629,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();
@ -542,6 +637,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.
/// ///
/// ``` /// ```
@ -553,15 +681,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;
/// ///
@ -570,10 +696,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;
/// ///
@ -582,7 +719,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.
/// ///
@ -601,6 +747,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.
@ -615,6 +762,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
@ -631,6 +779,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).
@ -645,6 +794,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).
@ -659,6 +809,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).
@ -672,6 +823,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
@ -689,6 +841,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
@ -706,6 +859,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
@ -721,6 +875,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`).
@ -750,6 +905,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
@ -768,6 +924,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
@ -783,6 +940,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
@ -799,6 +957,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.
@ -817,6 +976,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.
@ -835,6 +995,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.
@ -853,6 +1014,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.
@ -867,6 +1029,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.
@ -881,6 +1044,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.
@ -896,6 +1060,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;
@ -924,21 +1089,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]
@ -948,264 +1113,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)
@ -1237,6 +1464,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 {
@ -1255,8 +1497,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,)+) => (
@ -1272,7 +1529,7 @@ macro_rules! float_const_impl {
$( $(
#[inline] #[inline]
fn $constant() -> Self { fn $constant() -> Self {
::std::$T::consts::$constant ::core::$T::consts::$constant
} }
)+ )+
} }
@ -1317,10 +1574,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.),
@ -1332,6 +1586,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);

View File

@ -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> {
@ -79,6 +79,10 @@ pub trait One: Sized + Mul<Self, Output = Self> {
/// `static mut`s. /// `static mut`s.
// FIXME (#5527): This should be an associated constant // FIXME (#5527): This should be an associated constant
fn one() -> Self; fn one() -> Self;
/// Returns `true` if `self` is equal to the multiplicative identity.
#[inline]
fn is_one(&self) -> bool;
} }
macro_rules! one_impl { macro_rules! one_impl {
@ -86,6 +90,9 @@ macro_rules! one_impl {
impl One for $t { impl One for $t {
#[inline] #[inline]
fn one() -> $t { $v } fn one() -> $t { $v }
#[inline]
fn is_one(&self) -> bool { *self == $v }
} }
} }
} }
@ -109,6 +116,10 @@ impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
fn one() -> Self { fn one() -> Self {
Wrapping(T::one()) Wrapping(T::one())
} }
fn is_one(&self) -> bool {
self.0.is_one()
}
} }
// Some helper functions provided for backwards compatibility. // Some helper functions provided for backwards compatibility.

View File

@ -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;

View File

@ -9,12 +9,20 @@
// except according to those terms. // except according to those terms.
//! Numeric traits for generic mathematics //! Numeric traits for generic mathematics
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
html_root_url = "https://rust-num.github.io/num/",
html_playground_url = "http://play.integer32.com/")]
#![doc(html_root_url = "https://docs.rs/num-traits/0.1")] #![deny(unconditional_recursion)]
use std::ops::{Add, Sub, Mul, Div, Rem}; #![cfg_attr(not(feature = "std"), no_std)]
use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; #[cfg(feature = "std")]
use std::num::Wrapping; 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};
@ -127,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)
} }
@ -156,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 {
@ -303,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 }),
} }
}, },

View File

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

View File

@ -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) => {

View File

@ -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.
@ -12,11 +12,14 @@ use {One, CheckedMul};
/// assert_eq!(pow(6u8, 3), 216); /// assert_eq!(pow(6u8, 3), 216);
/// ``` /// ```
#[inline] #[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T { pub fn pow<T: Clone + One>(mut base: T, mut exp: usize) -> T
where
for<'a> &'a T: Mul<&'a T, Output = T>,
{
if exp == 0 { return T::one() } if exp == 0 { return T::one() }
while exp & 1 == 0 { while exp & 1 == 0 {
base = base.clone() * base; base = &base * &base;
exp >>= 1; exp >>= 1;
} }
if exp == 1 { return base } if exp == 1 { return base }
@ -24,9 +27,9 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
let mut acc = base.clone(); let mut acc = base.clone();
while exp > 1 { while exp > 1 {
exp >>= 1; exp >>= 1;
base = base.clone() * base; base = &base * &base;
if exp & 1 == 1 { if exp & 1 == 1 {
acc = acc * base.clone(); acc = &acc * &base;
} }
} }
acc acc

View File

@ -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`