//! Operations and constants for 64-bits floats (`f64` type)
-use default::Default;
-use intrinsics;
-use num::{Zero, One, Bounded, Signed, Num, Primitive};
+#![doc(primitive = "f64")]
+// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
+#![allow(type_overflow)]
-#[cfg(not(test))] use cmp::{Eq, Ord};
-#[cfg(not(test))] use ops::{Add, Sub, Mul, Div, Rem, Neg};
+use intrinsics;
+use mem;
+use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
+use num::Float;
+use option::Option;
// FIXME(#5527): These constants should be deprecated once associated
// constants are implemented in favour of referencing the respective
pub static LN_10: f64 = 2.30258509299404568401799145468436421_f64;
}
-#[cfg(not(test))]
-impl Ord for f64 {
+impl Float for f64 {
#[inline]
- fn lt(&self, other: &f64) -> bool { (*self) < (*other) }
+ fn nan() -> f64 { NAN }
+
#[inline]
- fn le(&self, other: &f64) -> bool { (*self) <= (*other) }
+ fn infinity() -> f64 { INFINITY }
+
#[inline]
- fn ge(&self, other: &f64) -> bool { (*self) >= (*other) }
+ fn neg_infinity() -> f64 { NEG_INFINITY }
+
#[inline]
- fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
-}
-#[cfg(not(test))]
-impl Eq for f64 {
+ fn neg_zero() -> f64 { -0.0 }
+
+ /// Returns `true` if the number is NaN.
#[inline]
- fn eq(&self, other: &f64) -> bool { (*self) == (*other) }
-}
+ fn is_nan(self) -> bool { self != self }
-impl Default for f64 {
+ /// Returns `true` if the number is infinite.
#[inline]
- fn default() -> f64 { 0.0 }
-}
+ fn is_infinite(self) -> bool {
+ self == Float::infinity() || self == Float::neg_infinity()
+ }
-impl Primitive for f64 {}
+ /// Returns `true` if the number is neither infinite or NaN.
+ #[inline]
+ fn is_finite(self) -> bool {
+ !(self.is_nan() || self.is_infinite())
+ }
-impl Num for f64 {}
+ /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
+ #[inline]
+ fn is_normal(self) -> bool {
+ self.classify() == FPNormal
+ }
+
+ /// 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 {
+ static EXP_MASK: u64 = 0x7ff0000000000000;
+ static MAN_MASK: u64 = 0x000fffffffffffff;
+
+ let bits: u64 = unsafe { mem::transmute(self) };
+ match (bits & MAN_MASK, bits & EXP_MASK) {
+ (0, 0) => FPZero,
+ (_, 0) => FPSubnormal,
+ (0, EXP_MASK) => FPInfinite,
+ (_, EXP_MASK) => FPNaN,
+ _ => FPNormal,
+ }
+ }
-impl Zero for f64 {
#[inline]
- fn zero() -> f64 { 0.0 }
+ fn mantissa_digits(_: Option<f64>) -> uint { MANTISSA_DIGITS }
- /// Returns true if the number is equal to either `0.0` or `-0.0`
#[inline]
- fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
-}
+ fn digits(_: Option<f64>) -> uint { DIGITS }
-impl One for f64 {
#[inline]
- fn one() -> f64 { 1.0 }
-}
+ fn epsilon() -> f64 { EPSILON }
-#[cfg(not(test))]
-impl Add<f64,f64> for f64 {
#[inline]
- fn add(&self, other: &f64) -> f64 { *self + *other }
-}
-#[cfg(not(test))]
-impl Sub<f64,f64> for f64 {
+ fn min_exp(_: Option<f64>) -> int { MIN_EXP }
+
#[inline]
- fn sub(&self, other: &f64) -> f64 { *self - *other }
-}
-#[cfg(not(test))]
-impl Mul<f64,f64> for f64 {
+ fn max_exp(_: Option<f64>) -> int { MAX_EXP }
+
#[inline]
- fn mul(&self, other: &f64) -> f64 { *self * *other }
-}
-#[cfg(not(test))]
-impl Div<f64,f64> for f64 {
+ fn min_10_exp(_: Option<f64>) -> int { MIN_10_EXP }
+
#[inline]
- fn div(&self, other: &f64) -> f64 { *self / *other }
-}
-#[cfg(not(test))]
-impl Rem<f64,f64> for f64 {
+ fn max_10_exp(_: Option<f64>) -> int { MAX_10_EXP }
+
#[inline]
- fn rem(&self, other: &f64) -> f64 {
- extern { fn fmod(a: f64, b: f64) -> f64; }
- unsafe { fmod(*self, *other) }
+ fn min_pos_value(_: Option<f64>) -> f64 { MIN_POS_VALUE }
+
+ /// Returns the mantissa, exponent and sign as integers.
+ fn integer_decode(self) -> (u64, i16, i8) {
+ let bits: u64 = unsafe { mem::transmute(self) };
+ let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+ let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+ let mantissa = if exponent == 0 {
+ (bits & 0xfffffffffffff) << 1
+ } else {
+ (bits & 0xfffffffffffff) | 0x10000000000000
+ };
+ // Exponent bias + mantissa shift
+ exponent -= 1023 + 52;
+ (mantissa, exponent, sign)
}
-}
-#[cfg(not(test))]
-impl Neg<f64> for f64 {
+
+ /// Rounds towards minus infinity.
#[inline]
- fn neg(&self) -> f64 { -*self }
-}
+ fn floor(self) -> f64 {
+ unsafe { intrinsics::floorf64(self) }
+ }
+
+ /// Rounds towards plus infinity.
+ #[inline]
+ fn ceil(self) -> f64 {
+ unsafe { intrinsics::ceilf64(self) }
+ }
-impl Signed for f64 {
- /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
+ /// Rounds to nearest integer. Rounds half-way cases away from zero.
#[inline]
- fn abs(&self) -> f64 {
- unsafe { intrinsics::fabsf64(*self) }
+ fn round(self) -> f64 {
+ unsafe { intrinsics::roundf64(self) }
}
- /// The positive difference of two numbers. Returns `0.0` if the number is less than or
- /// equal to `other`, otherwise the difference between`self` and `other` is returned.
+ /// Returns the integer part of the number (rounds towards zero).
#[inline]
- fn abs_sub(&self, other: &f64) -> f64 {
- extern { fn fdim(a: f64, b: f64) -> f64; }
- unsafe { fdim(*self, *other) }
+ fn trunc(self) -> f64 {
+ unsafe { intrinsics::truncf64(self) }
}
- /// # Returns
+ /// The fractional part of the number, satisfying:
///
- /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
- /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
- /// - `NAN` if the number is NaN
+ /// ```rust
+ /// let x = 1.65f64;
+ /// assert!(x == x.trunc() + x.fract())
+ /// ```
#[inline]
- fn signum(&self) -> f64 {
- if self != self { NAN } else {
- unsafe { intrinsics::copysignf64(1.0, *self) }
- }
+ fn fract(self) -> f64 { self - self.trunc() }
+
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+ /// error. This produces a more accurate result with better performance than
+ /// a separate multiplication operation followed by an add.
+ #[inline]
+ fn mul_add(self, a: f64, b: f64) -> f64 {
+ unsafe { intrinsics::fmaf64(self, a, b) }
}
- /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
+ /// Returns the reciprocal (multiplicative inverse) of the number.
#[inline]
- fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == INFINITY }
+ fn recip(self) -> f64 { 1.0 / self }
- /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
#[inline]
- fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == NEG_INFINITY }
-}
+ fn powf(self, n: f64) -> f64 {
+ unsafe { intrinsics::powf64(self, n) }
+ }
-impl Bounded for f64 {
- // NOTE: this is the smallest non-infinite f32 value, *not* MIN_VALUE
#[inline]
- fn min_value() -> f64 { -MAX_VALUE }
+ fn powi(self, n: i32) -> f64 {
+ unsafe { intrinsics::powif64(self, n) }
+ }
+ /// sqrt(2.0)
#[inline]
- fn max_value() -> f64 { MAX_VALUE }
+ fn sqrt2() -> f64 { consts::SQRT2 }
+
+ /// 1.0 / sqrt(2.0)
+ #[inline]
+ fn frac_1_sqrt2() -> f64 { consts::FRAC_1_SQRT2 }
+
+ #[inline]
+ fn sqrt(self) -> f64 {
+ unsafe { intrinsics::sqrtf64(self) }
+ }
+
+ #[inline]
+ fn rsqrt(self) -> f64 { self.sqrt().recip() }
+
+ /// Archimedes' constant
+ #[inline]
+ fn pi() -> f64 { consts::PI }
+
+ /// 2.0 * pi
+ #[inline]
+ fn two_pi() -> f64 { consts::PI_2 }
+
+ /// pi / 2.0
+ #[inline]
+ fn frac_pi_2() -> f64 { consts::FRAC_PI_2 }
+
+ /// pi / 3.0
+ #[inline]
+ fn frac_pi_3() -> f64 { consts::FRAC_PI_3 }
+
+ /// pi / 4.0
+ #[inline]
+ fn frac_pi_4() -> f64 { consts::FRAC_PI_4 }
+
+ /// pi / 6.0
+ #[inline]
+ fn frac_pi_6() -> f64 { consts::FRAC_PI_6 }
+
+ /// pi / 8.0
+ #[inline]
+ fn frac_pi_8() -> f64 { consts::FRAC_PI_8 }
+
+ /// 1.0 / pi
+ #[inline]
+ fn frac_1_pi() -> f64 { consts::FRAC_1_PI }
+
+ /// 2.0 / pi
+ #[inline]
+ fn frac_2_pi() -> f64 { consts::FRAC_2_PI }
+
+ /// 2.0 / sqrt(pi)
+ #[inline]
+ fn frac_2_sqrtpi() -> f64 { consts::FRAC_2_SQRTPI }
+
+ /// Euler's number
+ #[inline]
+ fn e() -> f64 { consts::E }
+
+ /// log2(e)
+ #[inline]
+ fn log2_e() -> f64 { consts::LOG2_E }
+
+ /// log10(e)
+ #[inline]
+ fn log10_e() -> f64 { consts::LOG10_E }
+
+ /// ln(2.0)
+ #[inline]
+ fn ln_2() -> f64 { consts::LN_2 }
+
+ /// ln(10.0)
+ #[inline]
+ fn ln_10() -> f64 { consts::LN_10 }
+
+ /// Returns the exponential of the number.
+ #[inline]
+ fn exp(self) -> f64 {
+ unsafe { intrinsics::expf64(self) }
+ }
+
+ /// Returns 2 raised to the power of the number.
+ #[inline]
+ fn exp2(self) -> f64 {
+ unsafe { intrinsics::exp2f64(self) }
+ }
+
+ /// Returns the natural logarithm of the number.
+ #[inline]
+ fn ln(self) -> f64 {
+ unsafe { intrinsics::logf64(self) }
+ }
+
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ #[inline]
+ fn log(self, base: f64) -> f64 { self.ln() / base.ln() }
+
+ /// Returns the base 2 logarithm of the number.
+ #[inline]
+ fn log2(self) -> f64 {
+ unsafe { intrinsics::log2f64(self) }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ #[inline]
+ fn log10(self) -> f64 {
+ unsafe { intrinsics::log10f64(self) }
+ }
+
+ /// Converts to degrees, assuming the number is in radians.
+ #[inline]
+ fn to_degrees(self) -> f64 { self * (180.0f64 / Float::pi()) }
+
+ /// Converts to radians, assuming the number is in degrees.
+ #[inline]
+ fn to_radians(self) -> f64 {
+ let value: f64 = Float::pi();
+ self * (value / 180.0)
+ }
}
+