diff options
Diffstat (limited to 'src/libstd/num/f64.rs')
| -rw-r--r-- | src/libstd/num/f64.rs | 203 |
1 files changed, 91 insertions, 112 deletions
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index fc8c5f47073..69328a5ecdc 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -10,86 +10,66 @@ //! Operations and constants for 64-bits floats (`f64` type) -#[allow(missing_doc)]; +#![allow(missing_doc)] use prelude::*; -use cmath; use default::Default; use from_str::FromStr; -use libc::{c_double, c_int}; +use libc::{c_int}; use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal}; use num::{Zero, One, Bounded, strconv}; use num; use intrinsics; -macro_rules! delegate( - ( - $( - fn $name:ident( - $( - $arg:ident : $arg_ty:ty - ),* - ) -> $rv:ty = $bound_name:path - ),* - ) => ( - $( - #[inline] - pub fn $name($( $arg : $arg_ty ),*) -> $rv { - unsafe { - $bound_name($( $arg ),*) - } - } - )* - ) -) - -delegate!( - // intrinsics - fn sqrt(n: f64) -> f64 = intrinsics::sqrtf64, - fn powi(n: f64, e: i32) -> f64 = intrinsics::powif64, - fn sin(n: f64) -> f64 = intrinsics::sinf64, - fn cos(n: f64) -> f64 = intrinsics::cosf64, - fn pow(n: f64, e: f64) -> f64 = intrinsics::powf64, - fn exp(n: f64) -> f64 = intrinsics::expf64, - fn exp2(n: f64) -> f64 = intrinsics::exp2f64, - fn ln(n: f64) -> f64 = intrinsics::logf64, - fn log10(n: f64) -> f64 = intrinsics::log10f64, - fn log2(n: f64) -> f64 = intrinsics::log2f64, - fn mul_add(a: f64, b: f64, c: f64) -> f64 = intrinsics::fmaf64, - fn abs(n: f64) -> f64 = intrinsics::fabsf64, - fn copysign(x: f64, y: f64) -> f64 = intrinsics::copysignf64, - fn floor(x: f64) -> f64 = intrinsics::floorf64, - fn ceil(n: f64) -> f64 = intrinsics::ceilf64, - fn trunc(n: f64) -> f64 = intrinsics::truncf64, - fn rint(n: f64) -> f64 = intrinsics::rintf64, - fn nearbyint(n: f64) -> f64 = intrinsics::nearbyintf64, - fn round(n: f64) -> f64 = intrinsics::roundf64, - - // cmath - fn acos(n: c_double) -> c_double = cmath::c_double::acos, - fn asin(n: c_double) -> c_double = cmath::c_double::asin, - fn atan(n: c_double) -> c_double = cmath::c_double::atan, - fn atan2(a: c_double, b: c_double) -> c_double = cmath::c_double::atan2, - fn cbrt(n: c_double) -> c_double = cmath::c_double::cbrt, - fn cosh(n: c_double) -> c_double = cmath::c_double::cosh, - // fn erf(n: c_double) -> c_double = cmath::c_double::erf, - // fn erfc(n: c_double) -> c_double = cmath::c_double::erfc, - fn exp_m1(n: c_double) -> c_double = cmath::c_double::exp_m1, - fn abs_sub(a: c_double, b: c_double) -> c_double = cmath::c_double::abs_sub, - fn next_after(x: c_double, y: c_double) -> c_double = cmath::c_double::next_after, - fn frexp(n: c_double, value: &mut c_int) -> c_double = cmath::c_double::frexp, - fn hypot(x: c_double, y: c_double) -> c_double = cmath::c_double::hypot, - fn ldexp(x: c_double, n: c_int) -> c_double = cmath::c_double::ldexp, - // fn log_radix(n: c_double) -> c_double = cmath::c_double::log_radix, - fn ln_1p(n: c_double) -> c_double = cmath::c_double::ln_1p, - // fn ilog_radix(n: c_double) -> c_int = cmath::c_double::ilog_radix, - // fn modf(n: c_double, iptr: &mut c_double) -> c_double = cmath::c_double::modf, - // fn ldexp_radix(n: c_double, i: c_int) -> c_double = cmath::c_double::ldexp_radix, - fn sinh(n: c_double) -> c_double = cmath::c_double::sinh, - fn tan(n: c_double) -> c_double = cmath::c_double::tan, - fn tanh(n: c_double) -> c_double = cmath::c_double::tanh -) +#[allow(dead_code)] +mod cmath { + use libc::{c_double, c_int}; + + #[link_name = "m"] + extern { + pub fn acos(n: c_double) -> c_double; + pub fn asin(n: c_double) -> c_double; + pub fn atan(n: c_double) -> c_double; + pub fn atan2(a: c_double, b: c_double) -> c_double; + pub fn cbrt(n: c_double) -> c_double; + pub fn cosh(n: c_double) -> c_double; + pub fn erf(n: c_double) -> c_double; + pub fn erfc(n: c_double) -> c_double; + pub fn expm1(n: c_double) -> c_double; + pub fn fdim(a: c_double, b: c_double) -> c_double; + pub fn fmax(a: c_double, b: c_double) -> c_double; + pub fn fmin(a: c_double, b: c_double) -> c_double; + pub fn nextafter(x: c_double, y: c_double) -> c_double; + pub fn frexp(n: c_double, value: &mut c_int) -> c_double; + pub fn hypot(x: c_double, y: c_double) -> c_double; + pub fn ldexp(x: c_double, n: c_int) -> c_double; + pub fn logb(n: c_double) -> c_double; + pub fn log1p(n: c_double) -> c_double; + pub fn ilogb(n: c_double) -> c_int; + pub fn modf(n: c_double, iptr: &mut c_double) -> c_double; + pub fn sinh(n: c_double) -> c_double; + pub fn tan(n: c_double) -> c_double; + pub fn tanh(n: c_double) -> c_double; + pub fn tgamma(n: c_double) -> c_double; + + // These are commonly only available for doubles + + pub fn j0(n: c_double) -> c_double; + pub fn j1(n: c_double) -> c_double; + pub fn jn(i: c_int, n: c_double) -> c_double; + + pub fn y0(n: c_double) -> c_double; + pub fn y1(n: c_double) -> c_double; + pub fn yn(i: c_int, n: c_double) -> c_double; + + #[cfg(unix)] + pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double; + #[cfg(windows)] + #[link_name="__lgamma_r"] + pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double; + } +} // FIXME (#1433): obtain these in a different way @@ -241,12 +221,12 @@ impl Neg<f64> for f64 { impl Signed for f64 { /// Computes the absolute value. Returns `NAN` if the number is `NAN`. #[inline] - fn abs(&self) -> f64 { abs(*self) } + fn abs(&self) -> f64 { unsafe{intrinsics::fabsf64(*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: &f64) -> f64 { abs_sub(*self, *other) } + fn abs_sub(&self, other: &f64) -> f64 { unsafe{cmath::fdim(*self, *other)} } /// # Returns /// @@ -255,7 +235,7 @@ impl Signed for f64 { /// - `NAN` if the number is NaN #[inline] fn signum(&self) -> f64 { - if self.is_nan() { NAN } else { copysign(1.0, *self) } + if self.is_nan() { NAN } else { unsafe{intrinsics::copysignf64(1.0, *self)} } } /// Returns `true` if the number is positive, including `+0.0` and `INFINITY` @@ -270,19 +250,19 @@ impl Signed for f64 { impl Round for f64 { /// Round half-way cases toward `NEG_INFINITY` #[inline] - fn floor(&self) -> f64 { floor(*self) } + fn floor(&self) -> f64 { unsafe{intrinsics::floorf64(*self)} } /// Round half-way cases toward `INFINITY` #[inline] - fn ceil(&self) -> f64 { ceil(*self) } + fn ceil(&self) -> f64 { unsafe{intrinsics::ceilf64(*self)} } /// Round half-way cases away from `0.0` #[inline] - fn round(&self) -> f64 { round(*self) } + fn round(&self) -> f64 { unsafe{intrinsics::roundf64(*self)} } /// The integer part of the number (rounds towards `0.0`) #[inline] - fn trunc(&self) -> f64 { trunc(*self) } + fn trunc(&self) -> f64 { unsafe{intrinsics::truncf64(*self)} } /// The fractional part of the number, satisfying: /// @@ -307,12 +287,12 @@ impl Primitive for f64 {} impl Float for f64 { #[inline] fn max(self, other: f64) -> f64 { - unsafe { cmath::c_double::fmax(self, other) } + unsafe { cmath::fmax(self, other) } } #[inline] fn min(self, other: f64) -> f64 { - unsafe { cmath::c_double::fmin(self, other) } + unsafe { cmath::fmin(self, other) } } #[inline] @@ -388,9 +368,7 @@ impl Float for f64 { /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` #[inline] - fn ldexp(x: f64, exp: int) -> f64 { - ldexp(x, exp as c_int) - } + fn ldexp(x: f64, exp: int) -> f64 { unsafe{cmath::ldexp(x, exp as c_int)} } /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying: /// @@ -398,34 +376,32 @@ impl Float for f64 { /// - `0.5 <= abs(x) < 1.0` #[inline] fn frexp(&self) -> (f64, int) { - let mut exp = 0; - let x = frexp(*self, &mut exp); - (x, exp as int) + unsafe { + let mut exp = 0; + let x = cmath::frexp(*self, &mut exp); + (x, exp as int) + } } /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero #[inline] - fn exp_m1(&self) -> f64 { exp_m1(*self) } + fn exp_m1(&self) -> f64 { unsafe{cmath::expm1(*self)} } /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately #[inline] - fn ln_1p(&self) -> f64 { ln_1p(*self) } + fn ln_1p(&self) -> f64 { unsafe{cmath::log1p(*self)} } /// 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 { - mul_add(*self, a, b) - } + fn mul_add(&self, a: f64, b: f64) -> f64 { unsafe{intrinsics::fmaf64(*self, a, b)} } /// Returns the next representable floating-point value in the direction of `other` #[inline] - fn next_after(&self, other: f64) -> f64 { - next_after(*self, other) - } + fn next_after(&self, other: f64) -> f64 { unsafe{cmath::nextafter(*self, other)} } /// Returns the mantissa, exponent and sign as integers. fn integer_decode(&self) -> (u64, i16, i8) { @@ -517,40 +493,43 @@ impl Float for f64 { fn recip(&self) -> f64 { 1.0 / *self } #[inline] - fn powf(&self, n: &f64) -> f64 { pow(*self, *n) } + fn powf(&self, n: &f64) -> f64 { unsafe{intrinsics::powf64(*self, *n)} } + + #[inline] + fn powi(&self, n: i32) -> f64 { unsafe{intrinsics::powif64(*self, n)} } #[inline] - fn sqrt(&self) -> f64 { sqrt(*self) } + fn sqrt(&self) -> f64 { unsafe{intrinsics::sqrtf64(*self)} } #[inline] fn rsqrt(&self) -> f64 { self.sqrt().recip() } #[inline] - fn cbrt(&self) -> f64 { cbrt(*self) } + fn cbrt(&self) -> f64 { unsafe{cmath::cbrt(*self)} } #[inline] - fn hypot(&self, other: &f64) -> f64 { hypot(*self, *other) } + fn hypot(&self, other: &f64) -> f64 { unsafe{cmath::hypot(*self, *other)} } #[inline] - fn sin(&self) -> f64 { sin(*self) } + fn sin(&self) -> f64 { unsafe{intrinsics::sinf64(*self)} } #[inline] - fn cos(&self) -> f64 { cos(*self) } + fn cos(&self) -> f64 { unsafe{intrinsics::cosf64(*self)} } #[inline] - fn tan(&self) -> f64 { tan(*self) } + fn tan(&self) -> f64 { unsafe{cmath::tan(*self)} } #[inline] - fn asin(&self) -> f64 { asin(*self) } + fn asin(&self) -> f64 { unsafe{cmath::asin(*self)} } #[inline] - fn acos(&self) -> f64 { acos(*self) } + fn acos(&self) -> f64 { unsafe{cmath::acos(*self)} } #[inline] - fn atan(&self) -> f64 { atan(*self) } + fn atan(&self) -> f64 { unsafe{cmath::atan(*self)} } #[inline] - fn atan2(&self, other: &f64) -> f64 { atan2(*self, *other) } + fn atan2(&self, other: &f64) -> f64 { unsafe{cmath::atan2(*self, *other)} } /// Simultaneously computes the sine and cosine of the number #[inline] @@ -560,15 +539,15 @@ impl Float for f64 { /// Returns the exponential of the number #[inline] - fn exp(&self) -> f64 { exp(*self) } + fn exp(&self) -> f64 { unsafe{intrinsics::expf64(*self)} } /// Returns 2 raised to the power of the number #[inline] - fn exp2(&self) -> f64 { exp2(*self) } + fn exp2(&self) -> f64 { unsafe{intrinsics::exp2f64(*self)} } /// Returns the natural logarithm of the number #[inline] - fn ln(&self) -> f64 { ln(*self) } + fn ln(&self) -> f64 { unsafe{intrinsics::logf64(*self)} } /// Returns the logarithm of the number with respect to an arbitrary base #[inline] @@ -576,20 +555,20 @@ impl Float for f64 { /// Returns the base 2 logarithm of the number #[inline] - fn log2(&self) -> f64 { log2(*self) } + fn log2(&self) -> f64 { unsafe{intrinsics::log2f64(*self)} } /// Returns the base 10 logarithm of the number #[inline] - fn log10(&self) -> f64 { log10(*self) } + fn log10(&self) -> f64 { unsafe{intrinsics::log10f64(*self)} } #[inline] - fn sinh(&self) -> f64 { sinh(*self) } + fn sinh(&self) -> f64 { unsafe{cmath::sinh(*self)} } #[inline] - fn cosh(&self) -> f64 { cosh(*self) } + fn cosh(&self) -> f64 { unsafe{cmath::cosh(*self)} } #[inline] - fn tanh(&self) -> f64 { tanh(*self) } + fn tanh(&self) -> f64 { unsafe{cmath::tanh(*self)} } /// Inverse hyperbolic sine /// |
