提交 19778492 编写于 作者: B bors

Auto merge of #50933 - SimonSapin:anchorage, r=alexcrichton

Remove the unstable Float trait

Following up to #49896 and #50629. Fixes #32110.
......@@ -33,7 +33,7 @@
use fmt::{Debug, LowerExp};
use num::diy_float::Fp;
use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
use num::Float;
use num::FpCategory;
use num::dec2flt::num::{self, Big};
use num::dec2flt::table;
......@@ -54,24 +54,29 @@ pub fn new(sig: u64, k: i16) -> Self {
/// See the parent module's doc comment for why this is necessary.
///
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
pub trait RawFloat
: Float
+ Copy
: Copy
+ Debug
+ LowerExp
+ Mul<Output=Self>
+ Div<Output=Self>
+ Neg<Output=Self>
where
Self: Float<Bits = <Self as RawFloat>::RawBits>
{
const INFINITY: Self;
const NAN: Self;
const ZERO: Self;
/// Same as `Float::Bits` with extra traits.
type RawBits: Add<Output = Self::RawBits> + From<u8> + TryFrom<u64>;
/// Type used by `to_bits` and `from_bits`.
type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
/// Raw transmutation to integer.
fn to_bits(self) -> Self::Bits;
/// Raw transmutation from integer.
fn from_bits(v: Self::Bits) -> Self;
/// Returns the category that this number falls into.
fn classify(self) -> FpCategory;
/// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8);
......@@ -153,7 +158,7 @@ pub trait RawFloat
}
impl RawFloat for f32 {
type RawBits = u32;
type Bits = u32;
const SIG_BITS: u8 = 24;
const EXP_BITS: u8 = 8;
......@@ -192,11 +197,15 @@ fn from_int(x: u64) -> f32 {
fn short_fast_pow10(e: usize) -> Self {
table::F32_SHORT_POWERS[e]
}
fn classify(self) -> FpCategory { self.classify() }
fn to_bits(self) -> Self::Bits { self.to_bits() }
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
}
impl RawFloat for f64 {
type RawBits = u64;
type Bits = u64;
const SIG_BITS: u8 = 53;
const EXP_BITS: u8 = 11;
......@@ -235,6 +244,10 @@ fn from_int(x: u64) -> f64 {
fn short_fast_pow10(e: usize) -> Self {
table::F64_SHORT_POWERS[e]
}
fn classify(self) -> FpCategory { self.classify() }
fn to_bits(self) -> Self::Bits { self.to_bits() }
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
}
/// Convert an Fp to the closest machine float type.
......
......@@ -18,9 +18,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use mem;
use num::Float;
use num::FpCategory;
use num::FpCategory as Fp;
/// The radix or base of the internal representation of `f32`.
#[stable(feature = "rust1", since = "1.0.0")]
......@@ -149,136 +147,9 @@ pub mod consts {
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}
#[unstable(feature = "core_float",
reason = "stable interface is via `impl f{32,64}` in later crates",
issue = "32110")]
impl Float for f32 {
type Bits = u32;
/// Returns `true` if the number is NaN.
#[inline]
fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if the number is infinite.
#[inline]
fn is_infinite(self) -> bool {
self == INFINITY || self == NEG_INFINITY
}
/// Returns `true` if the number is neither infinite or NaN.
#[inline]
fn is_finite(self) -> bool {
!(self.is_nan() || self.is_infinite())
}
/// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
#[inline]
fn is_normal(self) -> bool {
self.classify() == Fp::Normal
}
/// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific
/// predicate instead.
fn classify(self) -> Fp {
const EXP_MASK: u32 = 0x7f800000;
const MAN_MASK: u32 = 0x007fffff;
let bits = self.to_bits();
match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => Fp::Zero,
(_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan,
_ => Fp::Normal,
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
#[inline]
fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
#[inline]
fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
self.to_bits() & 0x8000_0000 != 0
}
/// Returns the reciprocal (multiplicative inverse) of the number.
#[inline]
fn recip(self) -> f32 {
1.0 / self
}
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f32 {
// Use a constant for better precision.
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
self * PIS_IN_180
}
/// Converts to radians, assuming the number is in degrees.
#[inline]
fn to_radians(self) -> f32 {
let value: f32 = consts::PI;
self * (value / 180.0f32)
}
/// Returns the maximum of the two numbers.
#[inline]
fn max(self, other: f32) -> f32 {
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if self.is_nan() || self < other { other } else { self }) * 1.0
}
/// Returns the minimum of the two numbers.
#[inline]
fn min(self, other: f32) -> f32 {
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if other.is_nan() || self < other { self } else { other }) * 1.0
}
/// Raw transmutation to `u32`.
#[inline]
fn to_bits(self) -> u32 {
unsafe { mem::transmute(self) }
}
/// Raw transmutation from `u32`.
#[inline]
fn from_bits(v: u32) -> Self {
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
}
// FIXME: remove (inline) this macro and the Float trait
// when updating to a bootstrap compiler that has the new lang items.
#[unstable(feature = "core_float", issue = "32110")]
macro_rules! f32_core_methods { () => {
#[lang = "f32"]
#[cfg(not(test))]
impl f32 {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
......@@ -292,7 +163,9 @@ fn from_bits(v: u32) -> Self {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { Float::is_nan(self) }
pub fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
......@@ -313,7 +186,9 @@ pub fn is_nan(self) -> bool { Float::is_nan(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
pub fn is_infinite(self) -> bool {
self == INFINITY || self == NEG_INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
///
......@@ -333,7 +208,9 @@ pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { Float::is_finite(self) }
pub fn is_finite(self) -> bool {
!(self.is_nan() || self.is_infinite())
}
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
......@@ -358,7 +235,9 @@ pub fn is_finite(self) -> bool { Float::is_finite(self) }
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_normal(self) -> bool { Float::is_normal(self) }
pub fn is_normal(self) -> bool {
self.classify() == FpCategory::Normal
}
/// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific
......@@ -375,8 +254,19 @@ pub fn is_normal(self) -> bool { Float::is_normal(self) }
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { Float::classify(self) }
pub fn classify(self) -> FpCategory {
const EXP_MASK: u32 = 0x7f800000;
const MAN_MASK: u32 = 0x007fffff;
let bits = self.to_bits();
match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => FpCategory::Zero,
(_, 0) => FpCategory::Subnormal,
(0, EXP_MASK) => FpCategory::Infinite,
(_, EXP_MASK) => FpCategory::Nan,
_ => FpCategory::Normal,
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
......@@ -390,7 +280,9 @@ pub fn classify(self) -> FpCategory { Float::classify(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
pub fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
......@@ -404,7 +296,11 @@ pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
pub fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
self.to_bits() & 0x8000_0000 != 0
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
......@@ -418,7 +314,9 @@ pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f32 { Float::recip(self) }
pub fn recip(self) -> f32 {
1.0 / self
}
/// Converts radians to degrees.
///
......@@ -433,7 +331,11 @@ pub fn recip(self) -> f32 { Float::recip(self) }
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
pub fn to_degrees(self) -> f32 {
// Use a constant for better precision.
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
self * PIS_IN_180
}
/// Converts degrees to radians.
///
......@@ -448,7 +350,10 @@ pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_radians(self) -> f32 { Float::to_radians(self) }
pub fn to_radians(self) -> f32 {
let value: f32 = consts::PI;
self * (value / 180.0f32)
}
/// Returns the maximum of the two numbers.
///
......@@ -463,7 +368,15 @@ pub fn to_radians(self) -> f32 { Float::to_radians(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f32) -> f32 {
Float::max(self, other)
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if self.is_nan() || self < other { other } else { self }) * 1.0
}
/// Returns the minimum of the two numbers.
......@@ -479,7 +392,15 @@ pub fn max(self, other: f32) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f32) -> f32 {
Float::min(self, other)
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if other.is_nan() || self < other { self } else { other }) * 1.0
}
/// Raw transmutation to `u32`.
......@@ -502,7 +423,7 @@ pub fn min(self, other: f32) -> f32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u32 {
Float::to_bits(self)
unsafe { mem::transmute(self) }
}
/// Raw transmutation from `u32`.
......@@ -546,12 +467,7 @@ pub fn to_bits(self) -> u32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u32) -> Self {
Float::from_bits(v)
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
}}
#[lang = "f32"]
#[cfg(not(test))]
impl f32 {
f32_core_methods!();
}
......@@ -18,9 +18,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use mem;
use num::Float;
use num::FpCategory;
use num::FpCategory as Fp;
/// The radix or base of the internal representation of `f64`.
#[stable(feature = "rust1", since = "1.0.0")]
......@@ -149,135 +147,9 @@ pub mod consts {
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
}
#[unstable(feature = "core_float",
reason = "stable interface is via `impl f{32,64}` in later crates",
issue = "32110")]
impl Float for f64 {
type Bits = u64;
/// Returns `true` if the number is NaN.
#[inline]
fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if the number is infinite.
#[inline]
fn is_infinite(self) -> bool {
self == INFINITY || self == NEG_INFINITY
}
/// Returns `true` if the number is neither infinite or NaN.
#[inline]
fn is_finite(self) -> bool {
!(self.is_nan() || self.is_infinite())
}
/// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
#[inline]
fn is_normal(self) -> bool {
self.classify() == Fp::Normal
}
/// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific
/// predicate instead.
fn classify(self) -> Fp {
const EXP_MASK: u64 = 0x7ff0000000000000;
const MAN_MASK: u64 = 0x000fffffffffffff;
let bits = self.to_bits();
match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => Fp::Zero,
(_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan,
_ => Fp::Normal,
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
#[inline]
fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
#[inline]
fn is_sign_negative(self) -> bool {
self.to_bits() & 0x8000_0000_0000_0000 != 0
}
/// Returns the reciprocal (multiplicative inverse) of the number.
#[inline]
fn recip(self) -> f64 {
1.0 / self
}
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f64 {
// The division here is correctly rounded with respect to the true
// value of 180/π. (This differs from f32, where a constant must be
// used to ensure a correctly rounded result.)
self * (180.0f64 / consts::PI)
}
/// Converts to radians, assuming the number is in degrees.
#[inline]
fn to_radians(self) -> f64 {
let value: f64 = consts::PI;
self * (value / 180.0)
}
/// Returns the maximum of the two numbers.
#[inline]
fn max(self, other: f64) -> f64 {
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if self.is_nan() || self < other { other } else { self }) * 1.0
}
/// Returns the minimum of the two numbers.
#[inline]
fn min(self, other: f64) -> f64 {
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if other.is_nan() || self < other { self } else { other }) * 1.0
}
/// Raw transmutation to `u64`.
#[inline]
fn to_bits(self) -> u64 {
unsafe { mem::transmute(self) }
}
/// Raw transmutation from `u64`.
#[inline]
fn from_bits(v: u64) -> Self {
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
}
// FIXME: remove (inline) this macro and the Float trait
// when updating to a bootstrap compiler that has the new lang items.
#[unstable(feature = "core_float", issue = "32110")]
macro_rules! f64_core_methods { () => {
#[lang = "f64"]
#[cfg(not(test))]
impl f64 {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
......@@ -291,7 +163,9 @@ fn from_bits(v: u64) -> Self {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { Float::is_nan(self) }
pub fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
......@@ -312,7 +186,9 @@ pub fn is_nan(self) -> bool { Float::is_nan(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
pub fn is_infinite(self) -> bool {
self == INFINITY || self == NEG_INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
///
......@@ -332,7 +208,9 @@ pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { Float::is_finite(self) }
pub fn is_finite(self) -> bool {
!(self.is_nan() || self.is_infinite())
}
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
......@@ -357,7 +235,9 @@ pub fn is_finite(self) -> bool { Float::is_finite(self) }
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_normal(self) -> bool { Float::is_normal(self) }
pub fn is_normal(self) -> bool {
self.classify() == FpCategory::Normal
}
/// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific
......@@ -374,8 +254,19 @@ pub fn is_normal(self) -> bool { Float::is_normal(self) }
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { Float::classify(self) }
pub fn classify(self) -> FpCategory {
const EXP_MASK: u64 = 0x7ff0000000000000;
const MAN_MASK: u64 = 0x000fffffffffffff;
let bits = self.to_bits();
match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => FpCategory::Zero,
(_, 0) => FpCategory::Subnormal,
(0, EXP_MASK) => FpCategory::Infinite,
(_, EXP_MASK) => FpCategory::Nan,
_ => FpCategory::Normal,
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
......@@ -389,13 +280,17 @@ pub fn classify(self) -> FpCategory { Float::classify(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
pub fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
#[inline]
#[doc(hidden)]
pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
pub fn is_positive(self) -> bool {
self.is_sign_positive()
}
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
......@@ -409,13 +304,17 @@ pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
pub fn is_sign_negative(self) -> bool {
self.to_bits() & 0x8000_0000_0000_0000 != 0
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
#[inline]
#[doc(hidden)]
pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
pub fn is_negative(self) -> bool {
self.is_sign_negative()
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
......@@ -427,7 +326,9 @@ pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f64 { Float::recip(self) }
pub fn recip(self) -> f64 {
1.0 / self
}
/// Converts radians to degrees.
///
......@@ -442,7 +343,12 @@ pub fn recip(self) -> f64 { Float::recip(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
pub fn to_degrees(self) -> f64 {
// The division here is correctly rounded with respect to the true
// value of 180/π. (This differs from f32, where a constant must be
// used to ensure a correctly rounded result.)
self * (180.0f64 / consts::PI)
}
/// Converts degrees to radians.
///
......@@ -457,7 +363,10 @@ pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_radians(self) -> f64 { Float::to_radians(self) }
pub fn to_radians(self) -> f64 {
let value: f64 = consts::PI;
self * (value / 180.0)
}
/// Returns the maximum of the two numbers.
///
......@@ -472,7 +381,15 @@ pub fn to_radians(self) -> f64 { Float::to_radians(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f64) -> f64 {
Float::max(self, other)
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if self.is_nan() || self < other { other } else { self }) * 1.0
}
/// Returns the minimum of the two numbers.
......@@ -488,7 +405,15 @@ pub fn max(self, other: f64) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f64) -> f64 {
Float::min(self, other)
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if other.is_nan() || self < other { self } else { other }) * 1.0
}
/// Raw transmutation to `u64`.
......@@ -511,7 +436,7 @@ pub fn min(self, other: f64) -> f64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u64 {
Float::to_bits(self)
unsafe { mem::transmute(self) }
}
/// Raw transmutation from `u64`.
......@@ -555,12 +480,7 @@ pub fn to_bits(self) -> u64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u64) -> Self {
Float::from_bits(v)
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
}}
#[lang = "f64"]
#[cfg(not(test))]
impl f64 {
f64_core_methods!();
}
......@@ -4080,61 +4080,6 @@ pub enum FpCategory {
Normal,
}
// Technically private and only exposed for coretests:
#[doc(hidden)]
#[unstable(feature = "float_internals",
reason = "internal routines only exposed for testing",
issue = "0")]
pub trait Float: Sized {
/// Type used by `to_bits` and `from_bits`.
type Bits;
/// Returns `true` if this value is NaN and false otherwise.
fn is_nan(self) -> bool;
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
fn is_infinite(self) -> bool;
/// Returns `true` if this number is neither infinite nor NaN.
fn is_finite(self) -> bool;
/// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
fn is_normal(self) -> bool;
/// Returns the category that this number falls into.
fn classify(self) -> FpCategory;
/// Returns `true` if `self` is positive, including `+0.0` and
/// `Float::infinity()`.
fn is_sign_positive(self) -> bool;
/// Returns `true` if `self` is negative, including `-0.0` and
/// `Float::neg_infinity()`.
fn is_sign_negative(self) -> bool;
/// Take the reciprocal (inverse) of a number, `1/x`.
fn recip(self) -> Self;
/// Convert radians to degrees.
fn to_degrees(self) -> Self;
/// Convert degrees to radians.
fn to_radians(self) -> Self;
/// Returns the maximum of the two numbers.
fn max(self, other: Self) -> Self;
/// Returns the minimum of the two numbers.
fn min(self, other: Self) -> Self;
/// Raw transmutation to integer.
fn to_bits(self) -> Self::Bits;
/// Raw transmutation from integer.
fn from_bits(v: Self::Bits) -> Self;
}
macro_rules! from_str_radix_int_impl {
($($t:ty)*) => {$(
#[stable(feature = "rust1", since = "1.0.0")]
......
......@@ -508,51 +508,50 @@ fn $fn_name() {
macro_rules! test_float {
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname {
use core::num::Float;
// FIXME(nagisa): these tests should test for sign of -0.0
#[test]
fn min() {
assert_eq!(0.0.min(0.0), 0.0);
assert_eq!((-0.0).min(-0.0), -0.0);
assert_eq!(9.0.min(9.0), 9.0);
assert_eq!((-9.0).min(0.0), -9.0);
assert_eq!(0.0.min(9.0), 0.0);
assert_eq!((-0.0).min(-9.0), -9.0);
assert_eq!($inf.min(9.0), 9.0);
assert_eq!(9.0.min($inf), 9.0);
assert_eq!($inf.min(-9.0), -9.0);
assert_eq!((-9.0).min($inf), -9.0);
assert_eq!($neginf.min(9.0), $neginf);
assert_eq!(9.0.min($neginf), $neginf);
assert_eq!($neginf.min(-9.0), $neginf);
assert_eq!((-9.0).min($neginf), $neginf);
assert_eq!($nan.min(9.0), 9.0);
assert_eq!($nan.min(-9.0), -9.0);
assert_eq!(9.0.min($nan), 9.0);
assert_eq!((-9.0).min($nan), -9.0);
assert!($nan.min($nan).is_nan());
assert_eq!((0.0 as $fty).min(0.0), 0.0);
assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
assert_eq!((9.0 as $fty).min(9.0), 9.0);
assert_eq!((-9.0 as $fty).min(0.0), -9.0);
assert_eq!((0.0 as $fty).min(9.0), 0.0);
assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
assert_eq!(($inf as $fty).min(9.0), 9.0);
assert_eq!((9.0 as $fty).min($inf), 9.0);
assert_eq!(($inf as $fty).min(-9.0), -9.0);
assert_eq!((-9.0 as $fty).min($inf), -9.0);
assert_eq!(($neginf as $fty).min(9.0), $neginf);
assert_eq!((9.0 as $fty).min($neginf), $neginf);
assert_eq!(($neginf as $fty).min(-9.0), $neginf);
assert_eq!((-9.0 as $fty).min($neginf), $neginf);
assert_eq!(($nan as $fty).min(9.0), 9.0);
assert_eq!(($nan as $fty).min(-9.0), -9.0);
assert_eq!((9.0 as $fty).min($nan), 9.0);
assert_eq!((-9.0 as $fty).min($nan), -9.0);
assert!(($nan as $fty).min($nan).is_nan());
}
#[test]
fn max() {
assert_eq!(0.0.max(0.0), 0.0);
assert_eq!((-0.0).max(-0.0), -0.0);
assert_eq!(9.0.max(9.0), 9.0);
assert_eq!((-9.0).max(0.0), 0.0);
assert_eq!(0.0.max(9.0), 9.0);
assert_eq!((-0.0).max(-9.0), -0.0);
assert_eq!($inf.max(9.0), $inf);
assert_eq!(9.0.max($inf), $inf);
assert_eq!($inf.max(-9.0), $inf);
assert_eq!((-9.0).max($inf), $inf);
assert_eq!($neginf.max(9.0), 9.0);
assert_eq!(9.0.max($neginf), 9.0);
assert_eq!($neginf.max(-9.0), -9.0);
assert_eq!((-9.0).max($neginf), -9.0);
assert_eq!($nan.max(9.0), 9.0);
assert_eq!($nan.max(-9.0), -9.0);
assert_eq!(9.0.max($nan), 9.0);
assert_eq!((-9.0).max($nan), -9.0);
assert!($nan.max($nan).is_nan());
assert_eq!((0.0 as $fty).max(0.0), 0.0);
assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
assert_eq!((9.0 as $fty).max(9.0), 9.0);
assert_eq!((-9.0 as $fty).max(0.0), 0.0);
assert_eq!((0.0 as $fty).max(9.0), 9.0);
assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
assert_eq!(($inf as $fty).max(9.0), $inf);
assert_eq!((9.0 as $fty).max($inf), $inf);
assert_eq!(($inf as $fty).max(-9.0), $inf);
assert_eq!((-9.0 as $fty).max($inf), $inf);
assert_eq!(($neginf as $fty).max(9.0), 9.0);
assert_eq!((9.0 as $fty).max($neginf), 9.0);
assert_eq!(($neginf as $fty).max(-9.0), -9.0);
assert_eq!((-9.0 as $fty).max($neginf), -9.0);
assert_eq!(($nan as $fty).max(9.0), 9.0);
assert_eq!(($nan as $fty).max(-9.0), -9.0);
assert_eq!((9.0 as $fty).max($nan), 9.0);
assert_eq!((-9.0 as $fty).max($nan), -9.0);
assert!(($nan as $fty).max($nan).is_nan());
}
} }
}
......
......@@ -4552,23 +4552,25 @@ fn start(_: isize, _: *const *const u8) -> isize where (): Copy {
The error happens on numeric literals:
```compile_fail,E0689
2.0.recip();
2.0.neg();
```
and on numeric bindings without an identified concrete type:
```compile_fail,E0689
let x = 2.0;
x.recip(); // same error as above
x.neg(); // same error as above
```
Because of this, you must give the numeric literal or binding a type:
```
let _ = 2.0_f32.recip();
use std::ops::Neg;
let _ = 2.0_f32.neg();
let x: f32 = 2.0;
let _ = x.recip();
let _ = (2.0 as f32).recip();
let _ = x.neg();
let _ = (2.0 as f32).neg();
```
"##,
......
......@@ -48,13 +48,13 @@
macro_rules! real_method_stmt {
() => {
2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
}
}
macro_rules! real_method_expr {
() => {
2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
}
}
......
......@@ -25,17 +25,17 @@ LL | (1).0 //~ ERROR doesn't have fields
LL | fake_anon_field_stmt!();
| ------------------------ in this macro invocation
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
--> $DIR/macro-backtrace-invalid-internals.rs:51:15
|
LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
| ^^^^^
LL | 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
| ^^^
...
LL | real_method_stmt!();
| -------------------- in this macro invocation
help: you must specify a concrete type for this numeric value, like `f32`
|
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
LL | 2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
| ^^^^^^^
error[E0599]: no method named `fake` found for type `{integer}` in the current scope
......@@ -65,17 +65,17 @@ LL | (1).0 //~ ERROR doesn't have fields
LL | let _ = fake_anon_field_expr!();
| ----------------------- in this macro invocation
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
--> $DIR/macro-backtrace-invalid-internals.rs:57:15
|
LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
| ^^^^^
LL | 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
| ^^^
...
LL | let _ = real_method_expr!();
| ------------------- in this macro invocation
help: you must specify a concrete type for this numeric value, like `f32`
|
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
LL | 2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
| ^^^^^^^
error: aborting due to 8 previous errors
......
......@@ -9,10 +9,10 @@
// except according to those terms.
fn main() {
let x = 2.0.recip();
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
let x = 2.0.neg();
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
let y = 2.0;
let x = y.recip();
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
let x = y.neg();
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
println!("{:?}", x);
}
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
--> $DIR/method-on-ambiguous-numeric-type.rs:12:17
|
LL | let x = 2.0.recip();
| ^^^^^
LL | let x = 2.0.neg();
| ^^^
help: you must specify a concrete type for this numeric value, like `f32`
|
LL | let x = 2.0_f32.recip();
LL | let x = 2.0_f32.neg();
| ^^^^^^^
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
--> $DIR/method-on-ambiguous-numeric-type.rs:15:15
|
LL | let x = y.recip();
| ^^^^^
LL | let x = y.neg();
| ^^^
help: you must specify a type for this binding, like `f32`
|
LL | let y: f32 = 2.0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册