diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index d0e6d4fa49c..883f9abf917 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -222,63 +222,6 @@ impl Float for f32 { (mantissa as u64, exponent, sign) } - /// Rounds towards minus infinity. - #[inline] - fn floor(self) -> f32 { - return floorf(self); - - // On MSVC LLVM will lower many math intrinsics to a call to the - // corresponding function. On MSVC, however, many of these functions - // aren't actually available as symbols to call, but rather they are all - // `static inline` functions in header files. This means that from a C - // perspective it's "compatible", but not so much from an ABI - // perspective (which we're worried about). - // - // The inline header functions always just cast to a f64 and do their - // operation, so we do that here as well, but only for MSVC targets. - // - // Note that there are many MSVC-specific float operations which - // redirect to this comment, so `floorf` is just one case of a missing - // function on MSVC, but there are many others elsewhere. - #[cfg(target_env = "msvc")] - fn floorf(f: f32) -> f32 { (f as f64).floor() as f32 } - #[cfg(not(target_env = "msvc"))] - fn floorf(f: f32) -> f32 { unsafe { intrinsics::floorf32(f) } } - } - - /// Rounds towards plus infinity. - #[inline] - fn ceil(self) -> f32 { - return ceilf(self); - - // see notes above in `floor` - #[cfg(target_env = "msvc")] - fn ceilf(f: f32) -> f32 { (f as f64).ceil() as f32 } - #[cfg(not(target_env = "msvc"))] - fn ceilf(f: f32) -> f32 { unsafe { intrinsics::ceilf32(f) } } - } - - /// Rounds to nearest integer. Rounds half-way cases away from zero. - #[inline] - fn round(self) -> f32 { - unsafe { intrinsics::roundf32(self) } - } - - /// Returns the integer part of the number (rounds towards zero). - #[inline] - fn trunc(self) -> f32 { - unsafe { intrinsics::truncf32(self) } - } - - /// The fractional part of the number, satisfying: - /// - /// ``` - /// let x = 1.65f32; - /// assert!(x == x.trunc() + x.fract()) - /// ``` - #[inline] - fn fract(self) -> f32 { self - self.trunc() } - /// Computes the absolute value of `self`. Returns `Float::nan()` if the /// number is `Float::nan()`. #[inline] @@ -314,14 +257,6 @@ impl Float for f32 { self < 0.0 || (1.0 / self) == Float::neg_infinity() } - /// 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) } - } - /// Returns the reciprocal (multiplicative inverse) of the number. #[inline] fn recip(self) -> f32 { 1.0 / self } @@ -331,81 +266,6 @@ impl Float for f32 { unsafe { intrinsics::powif32(self, n) } } - #[inline] - fn powf(self, n: f32) -> f32 { - return powf(self, n); - - // see notes above in `floor` - #[cfg(target_env = "msvc")] - fn powf(f: f32, n: f32) -> f32 { (f as f64).powf(n as f64) as f32 } - #[cfg(not(target_env = "msvc"))] - fn powf(f: f32, n: f32) -> f32 { unsafe { intrinsics::powf32(f, n) } } - } - - #[inline] - fn sqrt(self) -> f32 { - if self < 0.0 { - NAN - } else { - unsafe { intrinsics::sqrtf32(self) } - } - } - - #[inline] - fn rsqrt(self) -> f32 { self.sqrt().recip() } - - /// Returns the exponential of the number. - #[inline] - fn exp(self) -> f32 { - return expf(self); - - // see notes above in `floor` - #[cfg(target_env = "msvc")] - fn expf(f: f32) -> f32 { (f as f64).exp() as f32 } - #[cfg(not(target_env = "msvc"))] - fn expf(f: f32) -> f32 { unsafe { intrinsics::expf32(f) } } - } - - /// 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 { - return logf(self); - - // see notes above in `floor` - #[cfg(target_env = "msvc")] - fn logf(f: f32) -> f32 { (f as f64).ln() as f32 } - #[cfg(not(target_env = "msvc"))] - fn logf(f: f32) -> f32 { unsafe { intrinsics::logf32(f) } } - } - - /// 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 { - return log10f(self); - - // see notes above in `floor` - #[cfg(target_env = "msvc")] - fn log10f(f: f32) -> f32 { (f as f64).log10() as f32 } - #[cfg(not(target_env = "msvc"))] - fn log10f(f: f32) -> f32 { unsafe { intrinsics::log10f32(f) } } - } - /// Converts to degrees, assuming the number is in radians. #[inline] fn to_degrees(self) -> f32 { self * (180.0f32 / consts::PI) } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index bf7da04f995..248137f5229 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -222,39 +222,6 @@ impl Float for f64 { (mantissa, exponent, sign) } - /// Rounds towards minus infinity. - #[inline] - fn floor(self) -> f64 { - unsafe { intrinsics::floorf64(self) } - } - - /// Rounds towards plus infinity. - #[inline] - fn ceil(self) -> f64 { - unsafe { intrinsics::ceilf64(self) } - } - - /// Rounds to nearest integer. Rounds half-way cases away from zero. - #[inline] - fn round(self) -> f64 { - unsafe { intrinsics::roundf64(self) } - } - - /// Returns the integer part of the number (rounds towards zero). - #[inline] - fn trunc(self) -> f64 { - unsafe { intrinsics::truncf64(self) } - } - - /// The fractional part of the number, satisfying: - /// - /// ``` - /// let x = 1.65f64; - /// assert!(x == x.trunc() + x.fract()) - /// ``` - #[inline] - fn fract(self) -> f64 { self - self.trunc() } - /// Computes the absolute value of `self`. Returns `Float::nan()` if the /// number is `Float::nan()`. #[inline] @@ -290,74 +257,15 @@ impl Float for f64 { self < 0.0 || (1.0 / self) == Float::neg_infinity() } - /// 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 the reciprocal (multiplicative inverse) of the number. #[inline] fn recip(self) -> f64 { 1.0 / self } - #[inline] - 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 { - if self < 0.0 { - NAN - } else { - unsafe { intrinsics::sqrtf64(self) } - } - } - - #[inline] - fn rsqrt(self) -> f64 { self.sqrt().recip() } - - /// 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 / consts::PI) } diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index a292ffa2e9d..6265691bde9 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -53,20 +53,15 @@ pub enum FullDecoded { /// A floating point type which can be `decode`d. pub trait DecodableFloat: Float + Copy { - /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`. - /// This is used for testing. - fn ldexpi(f: i64, exp: isize) -> Self; /// The minimum positive normalized value. fn min_pos_norm_value() -> Self; } impl DecodableFloat for f32 { - fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } fn min_pos_norm_value() -> Self { f32::MIN_POSITIVE } } impl DecodableFloat for f64 { - fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } fn min_pos_norm_value() -> Self { f64::MIN_POSITIVE } } diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 40fa2a5563d..1277decf5e2 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -131,7 +131,6 @@ functions. use prelude::v1::*; use i16; -use num::Float; use slice::bytes; pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded}; diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index cdc23c45fa0..ab610f28e9e 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -17,7 +17,6 @@ Almost direct (but slightly optimized) Rust translation of Figure 3 of [1]. use prelude::v1::*; -use num::Float; use cmp::Ordering; use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index 52eafcec184..b0822ca76c7 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -18,8 +18,6 @@ Rust adaptation of Grisu3 algorithm described in [1]. It uses about use prelude::v1::*; -use num::Float; - use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; /// A custom 64-bit floating point type, representing `f * 2^e`. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 19ca83b6ea4..60675a61868 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1296,18 +1296,6 @@ pub trait Float { /// Returns the mantissa, exponent and sign as integers, respectively. fn integer_decode(self) -> (u64, i16, i8); - /// Return the largest integer less than or equal to a number. - fn floor(self) -> Self; - /// Return the smallest integer greater than or equal to a number. - fn ceil(self) -> Self; - /// Return the nearest integer to a number. Round half-way cases away from - /// `0.0`. - fn round(self) -> Self; - /// Return the integer part of a number. - fn trunc(self) -> Self; - /// Return the fractional part of a number. - fn fract(self) -> Self; - /// Computes the absolute value of `self`. Returns `Float::nan()` if the /// number is `Float::nan()`. fn abs(self) -> Self; @@ -1324,10 +1312,6 @@ pub trait Float { /// `Float::neg_infinity()`. fn is_negative(self) -> bool; - /// 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. - fn mul_add(self, a: Self, b: Self) -> Self; /// Take the reciprocal (inverse) of a number, `1/x`. fn recip(self) -> Self; @@ -1335,28 +1319,6 @@ pub trait Float { /// /// Using this function is generally faster than using `powf` fn powi(self, n: i32) -> Self; - /// Raise a number to a floating point power. - fn powf(self, n: Self) -> Self; - - /// Take the square root of a number. - /// - /// Returns NaN if `self` is a negative number. - fn sqrt(self) -> Self; - /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. - fn rsqrt(self) -> Self; - - /// Returns `e^(self)`, (the exponential function). - fn exp(self) -> Self; - /// Returns 2 raised to the power of the number, `2^(self)`. - fn exp2(self) -> Self; - /// Returns the natural logarithm of the number. - fn ln(self) -> Self; - /// Returns the logarithm of the number with respect to an arbitrary base. - fn log(self, base: Self) -> Self; - /// Returns the base 2 logarithm of the number. - fn log2(self) -> Self; - /// Returns the base 10 logarithm of the number. - fn log10(self) -> Self; /// Convert radians to degrees. fn to_degrees(self) -> Self; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index c1cf2230ac4..061eba8a75e 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -445,7 +445,9 @@ rem_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } impl Rem for f32 { type Output = f32; - // see notes in `core::f32::Float::floor` + // The builtin f32 rem operator is broken when targeting + // MSVC; see comment in std::f32::floor. + // FIXME: See also #27859. #[inline] #[cfg(target_env = "msvc")] fn rem(self, other: f32) -> f32 { diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs index 488cd3a779c..8ae33a44202 100644 --- a/src/libcoretest/num/flt2dec/mod.rs +++ b/src/libcoretest/num/flt2dec/mod.rs @@ -164,12 +164,26 @@ fn check_exact(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16 } } +trait TestableFloat : DecodableFloat + fmt::Display { + /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`. + /// This is used for testing. + fn ldexpi(f: i64, exp: isize) -> Self; +} + +impl TestableFloat for f32 { + fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } +} + +impl TestableFloat for f64 { + fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } +} + fn check_exact_one(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16) - where T: DecodableFloat + fmt::Display, + where T: TestableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { // use a large enough buffer let mut buf = [b'_'; 1024]; - let v: T = DecodableFloat::ldexpi(x, e); + let v: T = TestableFloat::ldexpi(x, e); let decoded = decode_finite(v); try_exact!(f(&decoded) => &mut buf, &expected, expectedk; diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index c3a02ec5aab..ce72fa08a73 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -10,7 +10,7 @@ //! The exponential distribution. -use core::num::Float; +use FloatMath; use {Rng, Rand}; use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 2951563934b..2a5d4bbd2ec 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -13,7 +13,7 @@ use self::GammaRepr::*; use self::ChiSquaredRepr::*; -use core::num::Float; +use FloatMath; use {Rng, Open01}; use super::normal::StandardNormal; diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index ac3fe6510eb..cc70a695c8d 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -10,7 +10,7 @@ //! The normal and derived distributions. -use core::num::Float; +use FloatMath; use {Rng, Rand, Open01}; use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 56104064a72..aa4b93f06b4 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -29,6 +29,7 @@ #![unstable(feature = "rand", reason = "use `rand` from crates.io")] #![feature(core_float)] +#![feature(core_intrinsics)] #![feature(core_slice_ext)] #![feature(no_std)] #![feature(num_bits_bytes)] @@ -42,6 +43,8 @@ #[cfg(test)] #[macro_use] extern crate std; #[cfg(test)] #[macro_use] extern crate log; +use core::f64; +use core::intrinsics; use core::marker::PhantomData; pub use isaac::{IsaacRng, Isaac64Rng}; @@ -59,6 +62,43 @@ pub mod chacha; pub mod reseeding; mod rand_impls; +// Temporary trait to implement a few floating-point routines +// needed by librand; this is necessary because librand doesn't +// depend on libstd. This will go away when librand is integrated +// into libstd. +trait FloatMath : Sized { + fn exp(self) -> Self; + fn ln(self) -> Self; + fn sqrt(self) -> Self; + fn powf(self, n: Self) -> Self; +} + +impl FloatMath for f64 { + #[inline] + fn exp(self) -> f64 { + unsafe { intrinsics::expf64(self) } + } + + #[inline] + fn ln(self) -> f64 { + unsafe { intrinsics::logf64(self) } + } + + #[inline] + fn powf(self, n: f64) -> f64 { + unsafe { intrinsics::powf64(self, n) } + } + + #[inline] + fn sqrt(self) -> f64 { + if self < 0.0 { + f64::NAN + } else { + unsafe { intrinsics::sqrtf64(self) } + } + } +} + /// A type that can be randomly generated using an `Rng`. #[doc(hidden)] pub trait Rand : Sized { diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 6a8026a807e..9c4320ff633 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -16,7 +16,6 @@ #![allow(missing_docs)] use core::num; -#[cfg(not(target_env = "msvc"))] use intrinsics; use libc::c_int; use num::{FpCategory, ParseFloatError}; @@ -40,11 +39,11 @@ mod cmath { pub fn fmaxf(a: c_float, b: c_float) -> c_float; pub fn fminf(a: c_float, b: c_float) -> c_float; pub fn fmodf(a: c_float, b: c_float) -> c_float; - pub fn nextafterf(x: c_float, y: c_float) -> c_float; + pub fn ilogbf(n: c_float) -> c_int; pub fn logbf(n: c_float) -> c_float; pub fn log1pf(n: c_float) -> c_float; - pub fn ilogbf(n: c_float) -> c_int; pub fn modff(n: c_float, iptr: &mut c_float) -> c_float; + pub fn nextafterf(x: c_float, y: c_float) -> c_float; pub fn tgammaf(n: c_float) -> c_float; #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")] @@ -268,7 +267,27 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn floor(self) -> f32 { num::Float::floor(self) } + pub fn floor(self) -> f32 { + return floorf(self); + + // On MSVC LLVM will lower many math intrinsics to a call to the + // corresponding function. On MSVC, however, many of these functions + // aren't actually available as symbols to call, but rather they are all + // `static inline` functions in header files. This means that from a C + // perspective it's "compatible", but not so much from an ABI + // perspective (which we're worried about). + // + // The inline header functions always just cast to a f64 and do their + // operation, so we do that here as well, but only for MSVC targets. + // + // Note that there are many MSVC-specific float operations which + // redirect to this comment, so `floorf` is just one case of a missing + // function on MSVC, but there are many others elsewhere. + #[cfg(target_env = "msvc")] + fn floorf(f: f32) -> f32 { (f as f64).floor() as f32 } + #[cfg(not(target_env = "msvc"))] + fn floorf(f: f32) -> f32 { unsafe { intrinsics::floorf32(f) } } + } /// Returns the smallest integer greater than or equal to a number. /// @@ -281,7 +300,15 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn ceil(self) -> f32 { num::Float::ceil(self) } + pub fn ceil(self) -> f32 { + return ceilf(self); + + // see notes above in `floor` + #[cfg(target_env = "msvc")] + fn ceilf(f: f32) -> f32 { (f as f64).ceil() as f32 } + #[cfg(not(target_env = "msvc"))] + fn ceilf(f: f32) -> f32 { unsafe { intrinsics::ceilf32(f) } } + } /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. @@ -295,7 +322,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn round(self) -> f32 { num::Float::round(self) } + pub fn round(self) -> f32 { + unsafe { intrinsics::roundf32(self) } + } /// Returns the integer part of a number. /// @@ -308,7 +337,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn trunc(self) -> f32 { num::Float::trunc(self) } + pub fn trunc(self) -> f32 { + unsafe { intrinsics::truncf32(self) } + } /// Returns the fractional part of a number. /// @@ -325,7 +356,7 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn fract(self) -> f32 { num::Float::fract(self) } + pub fn fract(self) -> f32 { self - self.trunc() } /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. @@ -424,7 +455,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) } + pub fn mul_add(self, a: f32, b: f32) -> f32 { + unsafe { intrinsics::fmaf32(self, a, b) } + } /// Takes the reciprocal (inverse) of a number, `1/x`. /// @@ -468,7 +501,15 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) } + pub fn powf(self, n: f32) -> f32 { + return powf(self, n); + + // see notes above in `floor` + #[cfg(target_env = "msvc")] + fn powf(f: f32, n: f32) -> f32 { (f as f64).powf(n as f64) as f32 } + #[cfg(not(target_env = "msvc"))] + fn powf(f: f32, n: f32) -> f32 { unsafe { intrinsics::powf32(f, n) } } + } /// Takes the square root of a number. /// @@ -487,7 +528,13 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn sqrt(self) -> f32 { num::Float::sqrt(self) } + pub fn sqrt(self) -> f32 { + if self < 0.0 { + NAN + } else { + unsafe { intrinsics::sqrtf32(self) } + } + } /// Returns `e^(self)`, (the exponential function). /// @@ -505,7 +552,15 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn exp(self) -> f32 { num::Float::exp(self) } + pub fn exp(self) -> f32 { + return expf(self); + + // see notes above in `floor` + #[cfg(target_env = "msvc")] + fn expf(f: f32) -> f32 { (f as f64).exp() as f32 } + #[cfg(not(target_env = "msvc"))] + fn expf(f: f32) -> f32 { unsafe { intrinsics::expf32(f) } } + } /// Returns `2^(self)`. /// @@ -521,7 +576,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn exp2(self) -> f32 { num::Float::exp2(self) } + pub fn exp2(self) -> f32 { + unsafe { intrinsics::exp2f32(self) } + } /// Returns the natural logarithm of the number. /// @@ -539,7 +596,15 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn ln(self) -> f32 { num::Float::ln(self) } + pub fn ln(self) -> f32 { + return logf(self); + + // see notes above in `floor` + #[cfg(target_env = "msvc")] + fn logf(f: f32) -> f32 { (f as f64).ln() as f32 } + #[cfg(not(target_env = "msvc"))] + fn logf(f: f32) -> f32 { unsafe { intrinsics::logf32(f) } } + } /// Returns the logarithm of the number with respect to an arbitrary base. /// @@ -560,7 +625,7 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log(self, base: f32) -> f32 { num::Float::log(self, base) } + pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number. /// @@ -576,7 +641,9 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log2(self) -> f32 { num::Float::log2(self) } + pub fn log2(self) -> f32 { + unsafe { intrinsics::log2f32(self) } + } /// Returns the base 10 logarithm of the number. /// @@ -592,7 +659,15 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log10(self) -> f32 { num::Float::log10(self) } + pub fn log10(self) -> f32 { + return log10f(self); + + // see notes above in `floor` + #[cfg(target_env = "msvc")] + fn log10f(f: f32) -> f32 { (f as f64).log10() as f32 } + #[cfg(not(target_env = "msvc"))] + fn log10f(f: f32) -> f32 { unsafe { intrinsics::log10f32(f) } } + } /// Converts radians to degrees. /// diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index e757ff90fdd..e9483139056 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -45,12 +45,12 @@ mod cmath { pub fn fmax(a: c_double, b: c_double) -> c_double; pub fn fmin(a: c_double, b: c_double) -> c_double; pub fn fmod(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 ilogb(n: c_double) -> c_int; 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 nextafter(x: c_double, y: c_double) -> c_double; 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; @@ -220,7 +220,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn floor(self) -> f64 { num::Float::floor(self) } + pub fn floor(self) -> f64 { + unsafe { intrinsics::floorf64(self) } + } /// Returns the smallest integer greater than or equal to a number. /// @@ -233,7 +235,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn ceil(self) -> f64 { num::Float::ceil(self) } + pub fn ceil(self) -> f64 { + unsafe { intrinsics::ceilf64(self) } + } /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. @@ -247,7 +251,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn round(self) -> f64 { num::Float::round(self) } + pub fn round(self) -> f64 { + unsafe { intrinsics::roundf64(self) } + } /// Returns the integer part of a number. /// @@ -260,7 +266,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn trunc(self) -> f64 { num::Float::trunc(self) } + pub fn trunc(self) -> f64 { + unsafe { intrinsics::truncf64(self) } + } /// Returns the fractional part of a number. /// @@ -275,7 +283,7 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn fract(self) -> f64 { num::Float::fract(self) } + pub fn fract(self) -> f64 { self - self.trunc() } /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. @@ -384,7 +392,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) } + pub fn mul_add(self, a: f64, b: f64) -> f64 { + unsafe { intrinsics::fmaf64(self, a, b) } + } /// Takes the reciprocal (inverse) of a number, `1/x`. /// @@ -422,7 +432,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) } + pub fn powf(self, n: f64) -> f64 { + unsafe { intrinsics::powf64(self, n) } + } /// Takes the square root of a number. /// @@ -439,7 +451,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn sqrt(self) -> f64 { num::Float::sqrt(self) } + pub fn sqrt(self) -> f64 { + unsafe { intrinsics::sqrtf64(self) } + } /// Returns `e^(self)`, (the exponential function). /// @@ -455,7 +469,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn exp(self) -> f64 { num::Float::exp(self) } + pub fn exp(self) -> f64 { + unsafe { intrinsics::expf64(self) } + } /// Returns `2^(self)`. /// @@ -469,7 +485,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn exp2(self) -> f64 { num::Float::exp2(self) } + pub fn exp2(self) -> f64 { + unsafe { intrinsics::exp2f64(self) } + } /// Returns the natural logarithm of the number. /// @@ -485,7 +503,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn ln(self) -> f64 { num::Float::ln(self) } + pub fn ln(self) -> f64 { + unsafe { intrinsics::logf64(self) } + } /// Returns the logarithm of the number with respect to an arbitrary base. /// @@ -504,7 +524,7 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log(self, base: f64) -> f64 { num::Float::log(self, base) } + pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number. /// @@ -518,7 +538,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log2(self) -> f64 { num::Float::log2(self) } + pub fn log2(self) -> f64 { + unsafe { intrinsics::log2f64(self) } + } /// Returns the base 10 logarithm of the number. /// @@ -532,7 +554,9 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn log10(self) -> f64 { num::Float::log10(self) } + pub fn log10(self) -> f64 { + unsafe { intrinsics::log10f64(self) } + } /// Converts radians to degrees. ///