Auto merge of #27823 - eefriedman:float-dep-core, r=alexcrichton

There wasn't any particular reason the functions needed to be there
anyway, so just get rid of them, and adjust libstd to compensate.

With this change, libcore depends on exactly two floating-point functions:
fmod and fmodf.  They are implicitly referenced because they are used to
implement "%".

Dependencies of libcore on Linux x86-x64 with this patch:
```
0000000000000000         *UND*	0000000000000000 __powidf2
0000000000000000         *UND*	0000000000000000 __powisf2
0000000000000000         *UND*	0000000000000000 fmod
0000000000000000         *UND*	0000000000000000 fmodf
0000000000000000         *UND*	0000000000000000 memcmp
0000000000000000         *UND*	0000000000000000 memcpy
0000000000000000         *UND*	0000000000000000 memset
0000000000000000         *UND*	0000000000000000 rust_begin_unwind
0000000000000000         *UND*	0000000000000000 rust_eh_personality
```
This commit is contained in:
bors 2015-08-18 04:23:25 +00:00
commit 4c0ffc0e38
15 changed files with 194 additions and 318 deletions

View File

@ -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) }

View File

@ -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) }

View File

@ -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 }
}

View File

@ -132,7 +132,6 @@ functions.
use prelude::v1::*;
use i16;
use num::Float;
use slice::bytes;
pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded};

View File

@ -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};

View File

@ -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`.

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -10,7 +10,7 @@
//! The exponential distribution.
use core::num::Float;
use FloatMath;
use {Rng, Rand};
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};

View File

@ -13,7 +13,7 @@
use self::GammaRepr::*;
use self::ChiSquaredRepr::*;
use core::num::Float;
use FloatMath;
use {Rng, Open01};
use super::normal::StandardNormal;

View File

@ -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};

View File

@ -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 {

View File

@ -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.
///

View File

@ -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.
///