ba0a984a86
The Float trait in libstd is quite a large trait which has dependencies on cmath (libm) and such, which libcore cannot satisfy. It also has many functions that libcore can implement, however, as LLVM has intrinsics or they're just bit twiddling. This commit moves what it can of the Float trait from the standard library into libcore to allow floats to be usable in the core library. The remaining functions are now resident in a FloatMath trait in the standard library (in the prelude now). Previous code which was generic over just the Float trait may now need to be generic over the FloatMath trait. [breaking-change]
498 lines
13 KiB
Rust
498 lines
13 KiB
Rust
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! Operations and constants for 32-bits floats (`f32` type)
|
|
|
|
use default::Default;
|
|
use intrinsics;
|
|
use mem;
|
|
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
|
|
use num::{Zero, One, Bounded, Signed, Num, Primitive, Float};
|
|
use option::Option;
|
|
|
|
#[cfg(not(test))] use cmp::{Eq, Ord};
|
|
#[cfg(not(test))] use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
|
|
|
pub static RADIX: uint = 2u;
|
|
|
|
pub static MANTISSA_DIGITS: uint = 24u;
|
|
pub static DIGITS: uint = 6u;
|
|
|
|
pub static EPSILON: f32 = 1.19209290e-07_f32;
|
|
|
|
/// Smallest finite f32 value
|
|
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
|
|
/// Smallest positive, normalized f32 value
|
|
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
|
|
/// Largest finite f32 value
|
|
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;
|
|
|
|
pub static MIN_EXP: int = -125;
|
|
pub static MAX_EXP: int = 128;
|
|
|
|
pub static MIN_10_EXP: int = -37;
|
|
pub static MAX_10_EXP: int = 38;
|
|
|
|
pub static NAN: f32 = 0.0_f32/0.0_f32;
|
|
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
|
|
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
|
|
|
|
/// Various useful constants.
|
|
pub mod consts {
|
|
// FIXME: replace with mathematical constants from cmath.
|
|
|
|
// FIXME(#5527): These constants should be deprecated once associated
|
|
// constants are implemented in favour of referencing the respective members
|
|
// of `Float`.
|
|
|
|
/// Archimedes' constant
|
|
pub static PI: f32 = 3.14159265358979323846264338327950288_f32;
|
|
|
|
/// pi * 2.0
|
|
pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;
|
|
|
|
/// pi/2.0
|
|
pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
|
|
|
|
/// pi/3.0
|
|
pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
|
|
|
|
/// pi/4.0
|
|
pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
|
|
|
|
/// pi/6.0
|
|
pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
|
|
|
|
/// pi/8.0
|
|
pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
|
|
|
|
/// 1.0/pi
|
|
pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
|
|
|
|
/// 2.0/pi
|
|
pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
|
|
|
|
/// 2.0/sqrt(pi)
|
|
pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
|
|
|
|
/// sqrt(2.0)
|
|
pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
|
|
|
|
/// 1.0/sqrt(2.0)
|
|
pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
|
|
|
|
/// Euler's number
|
|
pub static E: f32 = 2.71828182845904523536028747135266250_f32;
|
|
|
|
/// log2(e)
|
|
pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;
|
|
|
|
/// log10(e)
|
|
pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;
|
|
|
|
/// ln(2.0)
|
|
pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;
|
|
|
|
/// ln(10.0)
|
|
pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Ord for f32 {
|
|
#[inline]
|
|
fn lt(&self, other: &f32) -> bool { (*self) < (*other) }
|
|
#[inline]
|
|
fn le(&self, other: &f32) -> bool { (*self) <= (*other) }
|
|
#[inline]
|
|
fn ge(&self, other: &f32) -> bool { (*self) >= (*other) }
|
|
#[inline]
|
|
fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
|
|
}
|
|
#[cfg(not(test))]
|
|
impl Eq for f32 {
|
|
#[inline]
|
|
fn eq(&self, other: &f32) -> bool { (*self) == (*other) }
|
|
}
|
|
|
|
impl Num for f32 {}
|
|
|
|
impl Default for f32 {
|
|
#[inline]
|
|
fn default() -> f32 { 0.0 }
|
|
}
|
|
|
|
impl Primitive for f32 {}
|
|
|
|
impl Zero for f32 {
|
|
#[inline]
|
|
fn zero() -> f32 { 0.0 }
|
|
|
|
/// 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 }
|
|
}
|
|
|
|
impl One for f32 {
|
|
#[inline]
|
|
fn one() -> f32 { 1.0 }
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Add<f32,f32> for f32 {
|
|
#[inline]
|
|
fn add(&self, other: &f32) -> f32 { *self + *other }
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Sub<f32,f32> for f32 {
|
|
#[inline]
|
|
fn sub(&self, other: &f32) -> f32 { *self - *other }
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Mul<f32,f32> for f32 {
|
|
#[inline]
|
|
fn mul(&self, other: &f32) -> f32 { *self * *other }
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Div<f32,f32> for f32 {
|
|
#[inline]
|
|
fn div(&self, other: &f32) -> f32 { *self / *other }
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Rem<f32,f32> for f32 {
|
|
#[inline]
|
|
fn rem(&self, other: &f32) -> f32 {
|
|
extern { fn fmodf(a: f32, b: f32) -> f32; }
|
|
unsafe { fmodf(*self, *other) }
|
|
}
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
impl Neg<f32> for f32 {
|
|
#[inline]
|
|
fn neg(&self) -> f32 { -*self }
|
|
}
|
|
|
|
impl Signed for f32 {
|
|
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
|
#[inline]
|
|
fn abs(&self) -> f32 {
|
|
unsafe { intrinsics::fabsf32(*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.
|
|
#[inline]
|
|
fn abs_sub(&self, other: &f32) -> f32 {
|
|
extern { fn fdimf(a: f32, b: f32) -> f32; }
|
|
unsafe { fdimf(*self, *other) }
|
|
}
|
|
|
|
/// # Returns
|
|
///
|
|
/// - `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
|
|
#[inline]
|
|
fn signum(&self) -> f32 {
|
|
if self != self { NAN } else {
|
|
unsafe { intrinsics::copysignf32(1.0, *self) }
|
|
}
|
|
}
|
|
|
|
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
|
#[inline]
|
|
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == INFINITY }
|
|
|
|
/// 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 }
|
|
}
|
|
|
|
impl Bounded for f32 {
|
|
// NOTE: this is the smallest non-infinite f32 value, *not* MIN_VALUE
|
|
#[inline]
|
|
fn min_value() -> f32 { -MAX_VALUE }
|
|
|
|
#[inline]
|
|
fn max_value() -> f32 { MAX_VALUE }
|
|
}
|
|
|
|
impl Float for f32 {
|
|
#[inline]
|
|
fn nan() -> f32 { NAN }
|
|
|
|
#[inline]
|
|
fn infinity() -> f32 { INFINITY }
|
|
|
|
#[inline]
|
|
fn neg_infinity() -> f32 { NEG_INFINITY }
|
|
|
|
#[inline]
|
|
fn neg_zero() -> f32 { -0.0 }
|
|
|
|
/// 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 == Float::infinity() || self == Float::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() == 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: u32 = 0x7f800000;
|
|
static MAN_MASK: u32 = 0x007fffff;
|
|
|
|
let bits: u32 = unsafe { mem::transmute(self) };
|
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
|
(0, 0) => FPZero,
|
|
(_, 0) => FPSubnormal,
|
|
(0, EXP_MASK) => FPInfinite,
|
|
(_, EXP_MASK) => FPNaN,
|
|
_ => FPNormal,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }
|
|
|
|
#[inline]
|
|
fn digits(_: Option<f32>) -> uint { DIGITS }
|
|
|
|
#[inline]
|
|
fn epsilon() -> f32 { EPSILON }
|
|
|
|
#[inline]
|
|
fn min_exp(_: Option<f32>) -> int { MIN_EXP }
|
|
|
|
#[inline]
|
|
fn max_exp(_: Option<f32>) -> int { MAX_EXP }
|
|
|
|
#[inline]
|
|
fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }
|
|
|
|
#[inline]
|
|
fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }
|
|
|
|
#[inline]
|
|
fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }
|
|
|
|
/// Returns the mantissa, exponent and sign as integers.
|
|
fn integer_decode(self) -> (u64, i16, i8) {
|
|
let bits: u32 = unsafe { mem::transmute(self) };
|
|
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
|
|
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
|
let mantissa = if exponent == 0 {
|
|
(bits & 0x7fffff) << 1
|
|
} else {
|
|
(bits & 0x7fffff) | 0x800000
|
|
};
|
|
// Exponent bias + mantissa shift
|
|
exponent -= 127 + 23;
|
|
(mantissa as u64, exponent, sign)
|
|
}
|
|
|
|
/// Round half-way cases toward `NEG_INFINITY`
|
|
#[inline]
|
|
fn floor(self) -> f32 {
|
|
unsafe { intrinsics::floorf32(self) }
|
|
}
|
|
|
|
/// Round half-way cases toward `INFINITY`
|
|
#[inline]
|
|
fn ceil(self) -> f32 {
|
|
unsafe { intrinsics::ceilf32(self) }
|
|
}
|
|
|
|
/// Round half-way cases away from `0.0`
|
|
#[inline]
|
|
fn round(self) -> f32 {
|
|
unsafe { intrinsics::roundf32(self) }
|
|
}
|
|
|
|
/// The integer part of the number (rounds towards `0.0`)
|
|
#[inline]
|
|
fn trunc(self) -> f32 {
|
|
unsafe { intrinsics::truncf32(self) }
|
|
}
|
|
|
|
/// The fractional part of the number, satisfying:
|
|
///
|
|
/// ```rust
|
|
/// let x = 1.65f32;
|
|
/// assert!(x == x.trunc() + x.fract())
|
|
/// ```
|
|
#[inline]
|
|
fn fract(self) -> f32 { 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: f32, b: f32) -> f32 {
|
|
unsafe { intrinsics::fmaf32(self, a, b) }
|
|
}
|
|
|
|
/// The reciprocal (multiplicative inverse) of the number
|
|
#[inline]
|
|
fn recip(self) -> f32 { 1.0 / self }
|
|
|
|
fn powi(self, n: i32) -> f32 {
|
|
unsafe { intrinsics::powif32(self, n) }
|
|
}
|
|
|
|
#[inline]
|
|
fn powf(self, n: f32) -> f32 {
|
|
unsafe { intrinsics::powf32(self, n) }
|
|
}
|
|
|
|
/// sqrt(2.0)
|
|
#[inline]
|
|
fn sqrt2() -> f32 { consts::SQRT2 }
|
|
|
|
/// 1.0 / sqrt(2.0)
|
|
#[inline]
|
|
fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }
|
|
|
|
#[inline]
|
|
fn sqrt(self) -> f32 {
|
|
unsafe { intrinsics::sqrtf32(self) }
|
|
}
|
|
|
|
#[inline]
|
|
fn rsqrt(self) -> f32 { self.sqrt().recip() }
|
|
|
|
/// Archimedes' constant
|
|
#[inline]
|
|
fn pi() -> f32 { consts::PI }
|
|
|
|
/// 2.0 * pi
|
|
#[inline]
|
|
fn two_pi() -> f32 { consts::PI_2 }
|
|
|
|
/// pi / 2.0
|
|
#[inline]
|
|
fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }
|
|
|
|
/// pi / 3.0
|
|
#[inline]
|
|
fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }
|
|
|
|
/// pi / 4.0
|
|
#[inline]
|
|
fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }
|
|
|
|
/// pi / 6.0
|
|
#[inline]
|
|
fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }
|
|
|
|
/// pi / 8.0
|
|
#[inline]
|
|
fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }
|
|
|
|
/// 1 .0/ pi
|
|
#[inline]
|
|
fn frac_1_pi() -> f32 { consts::FRAC_1_PI }
|
|
|
|
/// 2.0 / pi
|
|
#[inline]
|
|
fn frac_2_pi() -> f32 { consts::FRAC_2_PI }
|
|
|
|
/// 2.0 / sqrt(pi)
|
|
#[inline]
|
|
fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }
|
|
|
|
/// Euler's number
|
|
#[inline]
|
|
fn e() -> f32 { consts::E }
|
|
|
|
/// log2(e)
|
|
#[inline]
|
|
fn log2_e() -> f32 { consts::LOG2_E }
|
|
|
|
/// log10(e)
|
|
#[inline]
|
|
fn log10_e() -> f32 { consts::LOG10_E }
|
|
|
|
/// ln(2.0)
|
|
#[inline]
|
|
fn ln_2() -> f32 { consts::LN_2 }
|
|
|
|
/// ln(10.0)
|
|
#[inline]
|
|
fn ln_10() -> f32 { consts::LN_10 }
|
|
|
|
/// Returns the exponential of the number
|
|
#[inline]
|
|
fn exp(self) -> f32 {
|
|
unsafe { intrinsics::expf32(self) }
|
|
}
|
|
|
|
/// Returns 2 raised to the power of the number
|
|
#[inline]
|
|
fn exp2(self) -> f32 {
|
|
unsafe { intrinsics::exp2f32(self) }
|
|
}
|
|
|
|
/// Returns the natural logarithm of the number
|
|
#[inline]
|
|
fn ln(self) -> f32 {
|
|
unsafe { intrinsics::logf32(self) }
|
|
}
|
|
|
|
/// Returns the logarithm of the number with respect to an arbitrary base
|
|
#[inline]
|
|
fn log(self, base: f32) -> f32 { self.ln() / base.ln() }
|
|
|
|
/// Returns the base 2 logarithm of the number
|
|
#[inline]
|
|
fn log2(self) -> f32 {
|
|
unsafe { intrinsics::log2f32(self) }
|
|
}
|
|
|
|
/// Returns the base 10 logarithm of the number
|
|
#[inline]
|
|
fn log10(self) -> f32 {
|
|
unsafe { intrinsics::log10f32(self) }
|
|
}
|
|
|
|
/// Converts to degrees, assuming the number is in radians
|
|
#[inline]
|
|
fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }
|
|
|
|
/// Converts to radians, assuming the number is in degrees
|
|
#[inline]
|
|
fn to_radians(self) -> f32 {
|
|
let value: f32 = Float::pi();
|
|
self * (value / 180.0f32)
|
|
}
|
|
}
|