about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/num/f32.rs140
-rw-r--r--src/libcore/num/f64.rs92
-rw-r--r--src/libcore/num/flt2dec/decoder.rs5
-rw-r--r--src/libcore/num/flt2dec/mod.rs1
-rw-r--r--src/libcore/num/flt2dec/strategy/dragon.rs1
-rw-r--r--src/libcore/num/flt2dec/strategy/grisu.rs2
-rw-r--r--src/libcore/num/mod.rs38
-rw-r--r--src/libcore/ops.rs4
-rw-r--r--src/libcoretest/num/flt2dec/mod.rs18
-rw-r--r--src/librand/distributions/exponential.rs2
-rw-r--r--src/librand/distributions/gamma.rs2
-rw-r--r--src/librand/distributions/normal.rs2
-rw-r--r--src/librand/lib.rs40
-rw-r--r--src/libstd/num/f32.rs109
-rw-r--r--src/libstd/num/f64.rs56
15 files changed, 194 insertions, 318 deletions
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 6ce037f17ae..1b7cbb050d1 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -216,63 +216,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]
@@ -308,14 +251,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 }
@@ -325,81 +260,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 b9dbc046799..a057e5fe51a 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -216,39 +216,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]
@@ -284,74 +251,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 91e1d6e4e51..700523e49a2 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -132,7 +132,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 086437445de..23432a2044c 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1297,18 +1297,6 @@ pub trait Float: Sized {
     /// 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;
@@ -1325,10 +1313,6 @@ pub trait Float: Sized {
     /// `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;
 
@@ -1336,28 +1320,6 @@ pub trait Float: Sized {
     ///
     /// 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 6d522ad1fab..7c386c6c33e 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<F, T>(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<F, T>(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 a72bc389286..c3dace51311 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -30,6 +30,7 @@
             reason = "use `rand` from crates.io",
             issue = "27703")]
 #![feature(core_float)]
+#![feature(core_intrinsics)]
 #![feature(core_slice_ext)]
 #![feature(no_std)]
 #![feature(num_bits_bytes)]
@@ -43,6 +44,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};
@@ -60,6 +63,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 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.
     ///