diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/num/f32.rs | 109 | ||||
| -rw-r--r-- | src/libstd/num/f64.rs | 56 |
2 files changed, 132 insertions, 33 deletions
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index bcbd1a80e8b..62f6cfcb36f 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")] @@ -270,7 +269,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. /// @@ -283,7 +302,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`. @@ -297,7 +324,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. /// @@ -310,7 +339,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. /// @@ -327,7 +358,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`. @@ -426,7 +457,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`. /// @@ -470,7 +503,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. /// @@ -489,7 +530,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). /// @@ -507,7 +554,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)`. /// @@ -523,7 +578,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. /// @@ -541,7 +598,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. /// @@ -562,7 +627,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. /// @@ -578,7 +643,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. /// @@ -594,7 +661,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 ea48c46b611..14c540e819e 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; @@ -222,7 +222,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. /// @@ -235,7 +237,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`. @@ -249,7 +253,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. /// @@ -262,7 +268,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. /// @@ -277,7 +285,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`. @@ -386,7 +394,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`. /// @@ -424,7 +434,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. /// @@ -441,7 +453,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). /// @@ -457,7 +471,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)`. /// @@ -471,7 +487,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. /// @@ -487,7 +505,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. /// @@ -506,7 +526,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. /// @@ -520,7 +540,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. /// @@ -534,7 +556,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. /// |
