#![allow(missing_docs)]
use core::num;
-#[cfg(not(target_env = "msvc"))]
use intrinsics;
use libc::c_int;
use num::{FpCategory, ParseFloatError};
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")]
/// Parses a float as with a given radix
#[unstable(feature = "float_from_str_radix", reason = "recently moved API",
issue = "27736")]
+ #[deprecated(since = "1.4.0",
+ reason = "unclear how useful or correct this is")]
pub fn from_str_radix(s: &str, radix: u32) -> Result<f32, ParseFloatError> {
num::Float::from_str_radix(s, radix)
}
/// ```
#[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.
///
/// ```
#[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`.
/// ```
#[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.
///
/// ```
#[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.
///
/// ```
#[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`.
/// ```
#[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`.
///
/// ```
#[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.
///
/// ```
#[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).
///
/// ```
#[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)`.
///
/// ```
#[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.
///
/// ```
#[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.
///
/// ```
#[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.
///
/// ```
#[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.
///
/// ```
#[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.
///