|  | @@ -1,16 +1,237 @@
 | 
	
		
			
				|  |  | -#[cfg(feature = "std")]
 | 
	
		
			
				|  |  | -use std::mem;
 | 
	
		
			
				|  |  | -#[cfg(feature = "std")]
 | 
	
		
			
				|  |  | -use std::ops::Neg;
 | 
	
		
			
				|  |  | -#[cfg(feature = "std")]
 | 
	
		
			
				|  |  | -use std::num::FpCategory;
 | 
	
		
			
				|  |  | +use core::mem;
 | 
	
		
			
				|  |  | +use core::ops::Neg;
 | 
	
		
			
				|  |  | +use core::num::FpCategory;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Used for default implementation of `epsilon`
 | 
	
		
			
				|  |  |  #[cfg(feature = "std")]
 | 
	
		
			
				|  |  |  use std::f32;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +use {Num, ToPrimitive};
 | 
	
		
			
				|  |  |  #[cfg(feature = "std")]
 | 
	
		
			
				|  |  | -use {Num, NumCast};
 | 
	
		
			
				|  |  | +use NumCast;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/// Generic trait for floating point numbers that works with `no_std`.
 | 
	
		
			
				|  |  | +///
 | 
	
		
			
				|  |  | +/// This trait implements a subset of the `Float` trait.
 | 
	
		
			
				|  |  | +pub trait FloatCore: Num + Neg<Output = Self> + PartialOrd + Copy {
 | 
	
		
			
				|  |  | +    /// Returns positive infinity.
 | 
	
		
			
				|  |  | +    fn infinity() -> Self;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns negative infinity.
 | 
	
		
			
				|  |  | +    fn neg_infinity() -> Self;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns NaN.
 | 
	
		
			
				|  |  | +    fn nan() -> Self;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns `true` if the number is NaN.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn is_nan(self) -> bool {
 | 
	
		
			
				|  |  | +        self != self
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns `true` if the number is infinite.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn is_infinite(self) -> bool {
 | 
	
		
			
				|  |  | +        self == Self::infinity() || self == Self::neg_infinity()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns `true` if the number is neither infinite or NaN.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn is_finite(self) -> bool {
 | 
	
		
			
				|  |  | +        !(self.is_nan() || self.is_infinite())
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn is_normal(self) -> bool {
 | 
	
		
			
				|  |  | +        self.classify() == FpCategory::Normal
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// 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
 | 
	
		
			
				|  |  | +    /// predicate instead.
 | 
	
		
			
				|  |  | +    fn classify(self) -> FpCategory;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Computes the absolute value of `self`. Returns `FloatCore::nan()` if the
 | 
	
		
			
				|  |  | +    /// number is `FloatCore::nan()`.
 | 
	
		
			
				|  |  | +    #[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`.
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// - `1.0` if the number is positive, `+0.0` or `FloatCore::infinity()`
 | 
	
		
			
				|  |  | +    /// - `-1.0` if the number is negative, `-0.0` or `FloatCore::neg_infinity()`
 | 
	
		
			
				|  |  | +    /// - `FloatCore::nan()` if the number is `FloatCore::nan()`
 | 
	
		
			
				|  |  | +    #[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
 | 
	
		
			
				|  |  | +    /// `FloatCore::infinity()`.
 | 
	
		
			
				|  |  | +    #[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
 | 
	
		
			
				|  |  | +    /// `FloatCore::neg_infinity()`.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn is_sign_negative(self) -> bool {
 | 
	
		
			
				|  |  | +        self < Self::zero() || (Self::one() / self) == Self::neg_infinity()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns the minimum of the two numbers.
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// If one of the arguments is NaN, then the other argument is returned.
 | 
	
		
			
				|  |  | +    #[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 }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns the maximum of the two numbers.
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// If one of the arguments is NaN, then the other argument is returned.
 | 
	
		
			
				|  |  | +    #[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 reciprocal (multiplicative inverse) of the number.
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn recip(self) -> Self {
 | 
	
		
			
				|  |  | +        Self::one() / self
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Raise a number to an integer power.
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// Using this function is generally faster than using `powf`
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn powi(mut self, mut exp: i32) -> Self {
 | 
	
		
			
				|  |  | +        if exp < 0 {
 | 
	
		
			
				|  |  | +            exp = -exp;
 | 
	
		
			
				|  |  | +            self = self.recip();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // It should always be possible to convert a positive `i32` to a `usize`.
 | 
	
		
			
				|  |  | +        super::pow(self, exp.to_usize().unwrap())
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Converts to degrees, assuming the number is in radians.
 | 
	
		
			
				|  |  | +    fn to_degrees(self) -> Self;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Converts to radians, assuming the number is in degrees.
 | 
	
		
			
				|  |  | +    fn to_radians(self) -> Self;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl FloatCore for f32 {
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn infinity() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f32::INFINITY
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn neg_infinity() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f32::NEG_INFINITY
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn nan() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f32::NAN
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn classify(self) -> FpCategory {
 | 
	
		
			
				|  |  | +        const EXP_MASK: u32 = 0x7f800000;
 | 
	
		
			
				|  |  | +        const MAN_MASK: u32 = 0x007fffff;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let bits: u32 = unsafe { mem::transmute(self) };
 | 
	
		
			
				|  |  | +        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,
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn to_degrees(self) -> Self {
 | 
	
		
			
				|  |  | +        self * (180.0 / ::core::f32::consts::PI)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn to_radians(self) -> Self {
 | 
	
		
			
				|  |  | +        self * (::core::f32::consts::PI / 180.0)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl FloatCore for f64 {
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn infinity() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f64::INFINITY
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn neg_infinity() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f64::NEG_INFINITY
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn nan() -> Self {
 | 
	
		
			
				|  |  | +        ::core::f64::NAN
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn classify(self) -> FpCategory {
 | 
	
		
			
				|  |  | +        const EXP_MASK: u64 = 0x7ff0000000000000;
 | 
	
		
			
				|  |  | +        const MAN_MASK: u64 = 0x000fffffffffffff;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let bits: u64 = unsafe { mem::transmute(self) };
 | 
	
		
			
				|  |  | +        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,
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn to_degrees(self) -> Self {
 | 
	
		
			
				|  |  | +        self * (180.0 / ::core::f64::consts::PI)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[inline]
 | 
	
		
			
				|  |  | +    fn to_radians(self) -> Self {
 | 
	
		
			
				|  |  | +        self * (::core::f64::consts::PI / 180.0)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // FIXME: these doctests aren't actually helpful, because they're using and
 | 
	
		
			
				|  |  |  // testing the inherent methods directly, not going through `Float`.
 | 
	
	
		
			
				|  | @@ -1328,25 +1549,40 @@ float_const_impl! {
 | 
	
		
			
				|  |  |      SQRT_2,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#[cfg(all(test, feature = "std"))]
 | 
	
		
			
				|  |  | +#[cfg(test)]
 | 
	
		
			
				|  |  |  mod tests {
 | 
	
		
			
				|  |  | -    use Float;
 | 
	
		
			
				|  |  | +    use core::f64::consts;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const DEG_RAD_PAIRS: [(f64, f64); 7] = [
 | 
	
		
			
				|  |  | +        (0.0, 0.),
 | 
	
		
			
				|  |  | +        (22.5, consts::FRAC_PI_8),
 | 
	
		
			
				|  |  | +        (30.0, consts::FRAC_PI_6),
 | 
	
		
			
				|  |  | +        (45.0, consts::FRAC_PI_4),
 | 
	
		
			
				|  |  | +        (60.0, consts::FRAC_PI_3),
 | 
	
		
			
				|  |  | +        (90.0, consts::FRAC_PI_2),
 | 
	
		
			
				|  |  | +        (180.0, consts::PI),
 | 
	
		
			
				|  |  | +    ];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[test]
 | 
	
		
			
				|  |  |      fn convert_deg_rad() {
 | 
	
		
			
				|  |  | -        use core::f64::consts;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        const DEG_RAD_PAIRS: [(f64, f64); 7] = [
 | 
	
		
			
				|  |  | -            (0.0, 0.),
 | 
	
		
			
				|  |  | -            (22.5, consts::FRAC_PI_8),
 | 
	
		
			
				|  |  | -            (30.0, consts::FRAC_PI_6),
 | 
	
		
			
				|  |  | -            (45.0, consts::FRAC_PI_4),
 | 
	
		
			
				|  |  | -            (60.0, consts::FRAC_PI_3),
 | 
	
		
			
				|  |  | -            (90.0, consts::FRAC_PI_2),
 | 
	
		
			
				|  |  | -            (180.0, consts::PI),
 | 
	
		
			
				|  |  | -        ];
 | 
	
		
			
				|  |  | +        use float::FloatCore;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          for &(deg, rad) in &DEG_RAD_PAIRS {
 | 
	
		
			
				|  |  | +            assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
 | 
	
		
			
				|  |  | +            assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let (deg, rad) = (deg as f32, rad as f32);
 | 
	
		
			
				|  |  | +            assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
 | 
	
		
			
				|  |  | +            assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[cfg(feature = "std")]
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn convert_deg_rad_std() {
 | 
	
		
			
				|  |  | +        for &(deg, rad) in &DEG_RAD_PAIRS {
 | 
	
		
			
				|  |  | +            use Float;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
 | 
	
		
			
				|  |  |              assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
 | 
	
		
			
				|  |  |  
 |