Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b825477

Browse files
committedMay 22, 2018
Remove the unstable Float trait
Following up to #49896 and #50629. Fixes #32110. E0689 is weird.
1 parent ba1363f commit b825477

File tree

10 files changed

+232
-437
lines changed

10 files changed

+232
-437
lines changed
 

‎src/libcore/num/dec2flt/rawfp.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use ops::{Add, Mul, Div, Neg};
3333
use fmt::{Debug, LowerExp};
3434
use num::diy_float::Fp;
3535
use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
36-
use num::Float;
36+
use num::FpCategory;
3737
use num::dec2flt::num::{self, Big};
3838
use num::dec2flt::table;
3939

@@ -54,24 +54,29 @@ impl Unpacked {
5454
/// See the parent module's doc comment for why this is necessary.
5555
///
5656
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
57-
/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
5857
pub trait RawFloat
59-
: Float
60-
+ Copy
58+
: Copy
6159
+ Debug
6260
+ LowerExp
6361
+ Mul<Output=Self>
6462
+ Div<Output=Self>
6563
+ Neg<Output=Self>
66-
where
67-
Self: Float<Bits = <Self as RawFloat>::RawBits>
6864
{
6965
const INFINITY: Self;
7066
const NAN: Self;
7167
const ZERO: Self;
7268

73-
/// Same as `Float::Bits` with extra traits.
74-
type RawBits: Add<Output = Self::RawBits> + From<u8> + TryFrom<u64>;
69+
/// Type used by `to_bits` and `from_bits`.
70+
type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
71+
72+
/// Raw transmutation to integer.
73+
fn to_bits(self) -> Self::Bits;
74+
75+
/// Raw transmutation from integer.
76+
fn from_bits(v: Self::Bits) -> Self;
77+
78+
/// Returns the category that this number falls into.
79+
fn classify(self) -> FpCategory;
7580

7681
/// Returns the mantissa, exponent and sign as integers.
7782
fn integer_decode(self) -> (u64, i16, i8);
@@ -153,7 +158,7 @@ macro_rules! other_constants {
153158
}
154159

155160
impl RawFloat for f32 {
156-
type RawBits = u32;
161+
type Bits = u32;
157162

158163
const SIG_BITS: u8 = 24;
159164
const EXP_BITS: u8 = 8;
@@ -192,11 +197,15 @@ impl RawFloat for f32 {
192197
fn short_fast_pow10(e: usize) -> Self {
193198
table::F32_SHORT_POWERS[e]
194199
}
200+
201+
fn classify(self) -> FpCategory { self.classify() }
202+
fn to_bits(self) -> Self::Bits { self.to_bits() }
203+
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
195204
}
196205

197206

198207
impl RawFloat for f64 {
199-
type RawBits = u64;
208+
type Bits = u64;
200209

201210
const SIG_BITS: u8 = 53;
202211
const EXP_BITS: u8 = 11;
@@ -235,6 +244,10 @@ impl RawFloat for f64 {
235244
fn short_fast_pow10(e: usize) -> Self {
236245
table::F64_SHORT_POWERS[e]
237246
}
247+
248+
fn classify(self) -> FpCategory { self.classify() }
249+
fn to_bits(self) -> Self::Bits { self.to_bits() }
250+
fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
238251
}
239252

240253
/// Convert an Fp to the closest machine float type.

‎src/libcore/num/f32.rs

Lines changed: 69 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818
#![stable(feature = "rust1", since = "1.0.0")]
1919

2020
use mem;
21-
use num::Float;
2221
use num::FpCategory;
23-
use num::FpCategory as Fp;
2422

2523
/// The radix or base of the internal representation of `f32`.
2624
#[stable(feature = "rust1", since = "1.0.0")]
@@ -149,136 +147,9 @@ pub mod consts {
149147
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
150148
}
151149

152-
#[unstable(feature = "core_float",
153-
reason = "stable interface is via `impl f{32,64}` in later crates",
154-
issue = "32110")]
155-
impl Float for f32 {
156-
type Bits = u32;
157-
158-
/// Returns `true` if the number is NaN.
159-
#[inline]
160-
fn is_nan(self) -> bool {
161-
self != self
162-
}
163-
164-
/// Returns `true` if the number is infinite.
165-
#[inline]
166-
fn is_infinite(self) -> bool {
167-
self == INFINITY || self == NEG_INFINITY
168-
}
169-
170-
/// Returns `true` if the number is neither infinite or NaN.
171-
#[inline]
172-
fn is_finite(self) -> bool {
173-
!(self.is_nan() || self.is_infinite())
174-
}
175-
176-
/// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
177-
#[inline]
178-
fn is_normal(self) -> bool {
179-
self.classify() == Fp::Normal
180-
}
181-
182-
/// Returns the floating point category of the number. If only one property
183-
/// is going to be tested, it is generally faster to use the specific
184-
/// predicate instead.
185-
fn classify(self) -> Fp {
186-
const EXP_MASK: u32 = 0x7f800000;
187-
const MAN_MASK: u32 = 0x007fffff;
188-
189-
let bits = self.to_bits();
190-
match (bits & MAN_MASK, bits & EXP_MASK) {
191-
(0, 0) => Fp::Zero,
192-
(_, 0) => Fp::Subnormal,
193-
(0, EXP_MASK) => Fp::Infinite,
194-
(_, EXP_MASK) => Fp::Nan,
195-
_ => Fp::Normal,
196-
}
197-
}
198-
199-
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
200-
/// positive sign bit and positive infinity.
201-
#[inline]
202-
fn is_sign_positive(self) -> bool {
203-
!self.is_sign_negative()
204-
}
205-
206-
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
207-
/// negative sign bit and negative infinity.
208-
#[inline]
209-
fn is_sign_negative(self) -> bool {
210-
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
211-
// applies to zeros and NaNs as well.
212-
self.to_bits() & 0x8000_0000 != 0
213-
}
214-
215-
/// Returns the reciprocal (multiplicative inverse) of the number.
216-
#[inline]
217-
fn recip(self) -> f32 {
218-
1.0 / self
219-
}
220-
221-
/// Converts to degrees, assuming the number is in radians.
222-
#[inline]
223-
fn to_degrees(self) -> f32 {
224-
// Use a constant for better precision.
225-
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
226-
self * PIS_IN_180
227-
}
228-
229-
/// Converts to radians, assuming the number is in degrees.
230-
#[inline]
231-
fn to_radians(self) -> f32 {
232-
let value: f32 = consts::PI;
233-
self * (value / 180.0f32)
234-
}
235-
236-
/// Returns the maximum of the two numbers.
237-
#[inline]
238-
fn max(self, other: f32) -> f32 {
239-
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
240-
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
241-
// is either x or y, canonicalized (this means results might differ among implementations).
242-
// When either x or y is a signalingNaN, then the result is according to 6.2.
243-
//
244-
// Since we do not support sNaN in Rust yet, we do not need to handle them.
245-
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
246-
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
247-
(if self.is_nan() || self < other { other } else { self }) * 1.0
248-
}
249-
250-
/// Returns the minimum of the two numbers.
251-
#[inline]
252-
fn min(self, other: f32) -> f32 {
253-
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
254-
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
255-
// is either x or y, canonicalized (this means results might differ among implementations).
256-
// When either x or y is a signalingNaN, then the result is according to 6.2.
257-
//
258-
// Since we do not support sNaN in Rust yet, we do not need to handle them.
259-
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
260-
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
261-
(if other.is_nan() || self < other { self } else { other }) * 1.0
262-
}
263-
264-
/// Raw transmutation to `u32`.
265-
#[inline]
266-
fn to_bits(self) -> u32 {
267-
unsafe { mem::transmute(self) }
268-
}
269-
270-
/// Raw transmutation from `u32`.
271-
#[inline]
272-
fn from_bits(v: u32) -> Self {
273-
// It turns out the safety issues with sNaN were overblown! Hooray!
274-
unsafe { mem::transmute(v) }
275-
}
276-
}
277-
278-
// FIXME: remove (inline) this macro and the Float trait
279-
// when updating to a bootstrap compiler that has the new lang items.
280-
#[unstable(feature = "core_float", issue = "32110")]
281-
macro_rules! f32_core_methods { () => {
150+
#[lang = "f32"]
151+
#[cfg(not(test))]
152+
impl f32 {
282153
/// Returns `true` if this value is `NaN` and false otherwise.
283154
///
284155
/// ```
@@ -292,7 +163,9 @@ macro_rules! f32_core_methods { () => {
292163
/// ```
293164
#[stable(feature = "rust1", since = "1.0.0")]
294165
#[inline]
295-
pub fn is_nan(self) -> bool { Float::is_nan(self) }
166+
pub fn is_nan(self) -> bool {
167+
self != self
168+
}
296169

297170
/// Returns `true` if this value is positive infinity or negative infinity and
298171
/// false otherwise.
@@ -313,7 +186,9 @@ macro_rules! f32_core_methods { () => {
313186
/// ```
314187
#[stable(feature = "rust1", since = "1.0.0")]
315188
#[inline]
316-
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
189+
pub fn is_infinite(self) -> bool {
190+
self == INFINITY || self == NEG_INFINITY
191+
}
317192

318193
/// Returns `true` if this number is neither infinite nor `NaN`.
319194
///
@@ -333,7 +208,9 @@ macro_rules! f32_core_methods { () => {
333208
/// ```
334209
#[stable(feature = "rust1", since = "1.0.0")]
335210
#[inline]
336-
pub fn is_finite(self) -> bool { Float::is_finite(self) }
211+
pub fn is_finite(self) -> bool {
212+
!(self.is_nan() || self.is_infinite())
213+
}
337214

338215
/// Returns `true` if the number is neither zero, infinite,
339216
/// [subnormal][subnormal], or `NaN`.
@@ -358,7 +235,9 @@ macro_rules! f32_core_methods { () => {
358235
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
359236
#[stable(feature = "rust1", since = "1.0.0")]
360237
#[inline]
361-
pub fn is_normal(self) -> bool { Float::is_normal(self) }
238+
pub fn is_normal(self) -> bool {
239+
self.classify() == FpCategory::Normal
240+
}
362241

363242
/// Returns the floating point category of the number. If only one property
364243
/// is going to be tested, it is generally faster to use the specific
@@ -375,8 +254,19 @@ macro_rules! f32_core_methods { () => {
375254
/// assert_eq!(inf.classify(), FpCategory::Infinite);
376255
/// ```
377256
#[stable(feature = "rust1", since = "1.0.0")]
378-
#[inline]
379-
pub fn classify(self) -> FpCategory { Float::classify(self) }
257+
pub fn classify(self) -> FpCategory {
258+
const EXP_MASK: u32 = 0x7f800000;
259+
const MAN_MASK: u32 = 0x007fffff;
260+
261+
let bits = self.to_bits();
262+
match (bits & MAN_MASK, bits & EXP_MASK) {
263+
(0, 0) => FpCategory::Zero,
264+
(_, 0) => FpCategory::Subnormal,
265+
(0, EXP_MASK) => FpCategory::Infinite,
266+
(_, EXP_MASK) => FpCategory::Nan,
267+
_ => FpCategory::Normal,
268+
}
269+
}
380270

381271
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
382272
/// positive sign bit and positive infinity.
@@ -390,7 +280,9 @@ macro_rules! f32_core_methods { () => {
390280
/// ```
391281
#[stable(feature = "rust1", since = "1.0.0")]
392282
#[inline]
393-
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
283+
pub fn is_sign_positive(self) -> bool {
284+
!self.is_sign_negative()
285+
}
394286

395287
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
396288
/// negative sign bit and negative infinity.
@@ -404,7 +296,11 @@ macro_rules! f32_core_methods { () => {
404296
/// ```
405297
#[stable(feature = "rust1", since = "1.0.0")]
406298
#[inline]
407-
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
299+
pub fn is_sign_negative(self) -> bool {
300+
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
301+
// applies to zeros and NaNs as well.
302+
self.to_bits() & 0x8000_0000 != 0
303+
}
408304

409305
/// Takes the reciprocal (inverse) of a number, `1/x`.
410306
///
@@ -418,7 +314,9 @@ macro_rules! f32_core_methods { () => {
418314
/// ```
419315
#[stable(feature = "rust1", since = "1.0.0")]
420316
#[inline]
421-
pub fn recip(self) -> f32 { Float::recip(self) }
317+
pub fn recip(self) -> f32 {
318+
1.0 / self
319+
}
422320

423321
/// Converts radians to degrees.
424322
///
@@ -433,7 +331,11 @@ macro_rules! f32_core_methods { () => {
433331
/// ```
434332
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
435333
#[inline]
436-
pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
334+
pub fn to_degrees(self) -> f32 {
335+
// Use a constant for better precision.
336+
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
337+
self * PIS_IN_180
338+
}
437339

438340
/// Converts degrees to radians.
439341
///
@@ -448,7 +350,10 @@ macro_rules! f32_core_methods { () => {
448350
/// ```
449351
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
450352
#[inline]
451-
pub fn to_radians(self) -> f32 { Float::to_radians(self) }
353+
pub fn to_radians(self) -> f32 {
354+
let value: f32 = consts::PI;
355+
self * (value / 180.0f32)
356+
}
452357

453358
/// Returns the maximum of the two numbers.
454359
///
@@ -463,7 +368,15 @@ macro_rules! f32_core_methods { () => {
463368
#[stable(feature = "rust1", since = "1.0.0")]
464369
#[inline]
465370
pub fn max(self, other: f32) -> f32 {
466-
Float::max(self, other)
371+
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
372+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
373+
// is either x or y, canonicalized (this means results might differ among implementations).
374+
// When either x or y is a signalingNaN, then the result is according to 6.2.
375+
//
376+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
377+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
378+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
379+
(if self.is_nan() || self < other { other } else { self }) * 1.0
467380
}
468381

469382
/// Returns the minimum of the two numbers.
@@ -479,7 +392,15 @@ macro_rules! f32_core_methods { () => {
479392
#[stable(feature = "rust1", since = "1.0.0")]
480393
#[inline]
481394
pub fn min(self, other: f32) -> f32 {
482-
Float::min(self, other)
395+
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
396+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
397+
// is either x or y, canonicalized (this means results might differ among implementations).
398+
// When either x or y is a signalingNaN, then the result is according to 6.2.
399+
//
400+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
401+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
402+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
403+
(if other.is_nan() || self < other { self } else { other }) * 1.0
483404
}
484405

485406
/// Raw transmutation to `u32`.
@@ -502,7 +423,7 @@ macro_rules! f32_core_methods { () => {
502423
#[stable(feature = "float_bits_conv", since = "1.20.0")]
503424
#[inline]
504425
pub fn to_bits(self) -> u32 {
505-
Float::to_bits(self)
426+
unsafe { mem::transmute(self) }
506427
}
507428

508429
/// Raw transmutation from `u32`.
@@ -546,12 +467,7 @@ macro_rules! f32_core_methods { () => {
546467
#[stable(feature = "float_bits_conv", since = "1.20.0")]
547468
#[inline]
548469
pub fn from_bits(v: u32) -> Self {
549-
Float::from_bits(v)
470+
// It turns out the safety issues with sNaN were overblown! Hooray!
471+
unsafe { mem::transmute(v) }
550472
}
551-
}}
552-
553-
#[lang = "f32"]
554-
#[cfg(not(test))]
555-
impl f32 {
556-
f32_core_methods!();
557473
}

‎src/libcore/num/f64.rs

Lines changed: 74 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818
#![stable(feature = "rust1", since = "1.0.0")]
1919

2020
use mem;
21-
use num::Float;
2221
use num::FpCategory;
23-
use num::FpCategory as Fp;
2422

2523
/// The radix or base of the internal representation of `f64`.
2624
#[stable(feature = "rust1", since = "1.0.0")]
@@ -149,135 +147,9 @@ pub mod consts {
149147
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
150148
}
151149

152-
#[unstable(feature = "core_float",
153-
reason = "stable interface is via `impl f{32,64}` in later crates",
154-
issue = "32110")]
155-
impl Float for f64 {
156-
type Bits = u64;
157-
158-
/// Returns `true` if the number is NaN.
159-
#[inline]
160-
fn is_nan(self) -> bool {
161-
self != self
162-
}
163-
164-
/// Returns `true` if the number is infinite.
165-
#[inline]
166-
fn is_infinite(self) -> bool {
167-
self == INFINITY || self == NEG_INFINITY
168-
}
169-
170-
/// Returns `true` if the number is neither infinite or NaN.
171-
#[inline]
172-
fn is_finite(self) -> bool {
173-
!(self.is_nan() || self.is_infinite())
174-
}
175-
176-
/// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
177-
#[inline]
178-
fn is_normal(self) -> bool {
179-
self.classify() == Fp::Normal
180-
}
181-
182-
/// Returns the floating point category of the number. If only one property
183-
/// is going to be tested, it is generally faster to use the specific
184-
/// predicate instead.
185-
fn classify(self) -> Fp {
186-
const EXP_MASK: u64 = 0x7ff0000000000000;
187-
const MAN_MASK: u64 = 0x000fffffffffffff;
188-
189-
let bits = self.to_bits();
190-
match (bits & MAN_MASK, bits & EXP_MASK) {
191-
(0, 0) => Fp::Zero,
192-
(_, 0) => Fp::Subnormal,
193-
(0, EXP_MASK) => Fp::Infinite,
194-
(_, EXP_MASK) => Fp::Nan,
195-
_ => Fp::Normal,
196-
}
197-
}
198-
199-
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
200-
/// positive sign bit and positive infinity.
201-
#[inline]
202-
fn is_sign_positive(self) -> bool {
203-
!self.is_sign_negative()
204-
}
205-
206-
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
207-
/// negative sign bit and negative infinity.
208-
#[inline]
209-
fn is_sign_negative(self) -> bool {
210-
self.to_bits() & 0x8000_0000_0000_0000 != 0
211-
}
212-
213-
/// Returns the reciprocal (multiplicative inverse) of the number.
214-
#[inline]
215-
fn recip(self) -> f64 {
216-
1.0 / self
217-
}
218-
219-
/// Converts to degrees, assuming the number is in radians.
220-
#[inline]
221-
fn to_degrees(self) -> f64 {
222-
// The division here is correctly rounded with respect to the true
223-
// value of 180/π. (This differs from f32, where a constant must be
224-
// used to ensure a correctly rounded result.)
225-
self * (180.0f64 / consts::PI)
226-
}
227-
228-
/// Converts to radians, assuming the number is in degrees.
229-
#[inline]
230-
fn to_radians(self) -> f64 {
231-
let value: f64 = consts::PI;
232-
self * (value / 180.0)
233-
}
234-
235-
/// Returns the maximum of the two numbers.
236-
#[inline]
237-
fn max(self, other: f64) -> f64 {
238-
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
239-
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
240-
// is either x or y, canonicalized (this means results might differ among implementations).
241-
// When either x or y is a signalingNaN, then the result is according to 6.2.
242-
//
243-
// Since we do not support sNaN in Rust yet, we do not need to handle them.
244-
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
245-
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
246-
(if self.is_nan() || self < other { other } else { self }) * 1.0
247-
}
248-
249-
/// Returns the minimum of the two numbers.
250-
#[inline]
251-
fn min(self, other: f64) -> f64 {
252-
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
253-
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
254-
// is either x or y, canonicalized (this means results might differ among implementations).
255-
// When either x or y is a signalingNaN, then the result is according to 6.2.
256-
//
257-
// Since we do not support sNaN in Rust yet, we do not need to handle them.
258-
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
259-
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
260-
(if other.is_nan() || self < other { self } else { other }) * 1.0
261-
}
262-
263-
/// Raw transmutation to `u64`.
264-
#[inline]
265-
fn to_bits(self) -> u64 {
266-
unsafe { mem::transmute(self) }
267-
}
268-
269-
/// Raw transmutation from `u64`.
270-
#[inline]
271-
fn from_bits(v: u64) -> Self {
272-
// It turns out the safety issues with sNaN were overblown! Hooray!
273-
unsafe { mem::transmute(v) }
274-
}
275-
}
276-
277-
// FIXME: remove (inline) this macro and the Float trait
278-
// when updating to a bootstrap compiler that has the new lang items.
279-
#[unstable(feature = "core_float", issue = "32110")]
280-
macro_rules! f64_core_methods { () => {
150+
#[lang = "f64"]
151+
#[cfg(not(test))]
152+
impl f64 {
281153
/// Returns `true` if this value is `NaN` and false otherwise.
282154
///
283155
/// ```
@@ -291,7 +163,9 @@ macro_rules! f64_core_methods { () => {
291163
/// ```
292164
#[stable(feature = "rust1", since = "1.0.0")]
293165
#[inline]
294-
pub fn is_nan(self) -> bool { Float::is_nan(self) }
166+
pub fn is_nan(self) -> bool {
167+
self != self
168+
}
295169

296170
/// Returns `true` if this value is positive infinity or negative infinity and
297171
/// false otherwise.
@@ -312,7 +186,9 @@ macro_rules! f64_core_methods { () => {
312186
/// ```
313187
#[stable(feature = "rust1", since = "1.0.0")]
314188
#[inline]
315-
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
189+
pub fn is_infinite(self) -> bool {
190+
self == INFINITY || self == NEG_INFINITY
191+
}
316192

317193
/// Returns `true` if this number is neither infinite nor `NaN`.
318194
///
@@ -332,7 +208,9 @@ macro_rules! f64_core_methods { () => {
332208
/// ```
333209
#[stable(feature = "rust1", since = "1.0.0")]
334210
#[inline]
335-
pub fn is_finite(self) -> bool { Float::is_finite(self) }
211+
pub fn is_finite(self) -> bool {
212+
!(self.is_nan() || self.is_infinite())
213+
}
336214

337215
/// Returns `true` if the number is neither zero, infinite,
338216
/// [subnormal][subnormal], or `NaN`.
@@ -357,7 +235,9 @@ macro_rules! f64_core_methods { () => {
357235
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
358236
#[stable(feature = "rust1", since = "1.0.0")]
359237
#[inline]
360-
pub fn is_normal(self) -> bool { Float::is_normal(self) }
238+
pub fn is_normal(self) -> bool {
239+
self.classify() == FpCategory::Normal
240+
}
361241

362242
/// Returns the floating point category of the number. If only one property
363243
/// is going to be tested, it is generally faster to use the specific
@@ -374,8 +254,19 @@ macro_rules! f64_core_methods { () => {
374254
/// assert_eq!(inf.classify(), FpCategory::Infinite);
375255
/// ```
376256
#[stable(feature = "rust1", since = "1.0.0")]
377-
#[inline]
378-
pub fn classify(self) -> FpCategory { Float::classify(self) }
257+
pub fn classify(self) -> FpCategory {
258+
const EXP_MASK: u64 = 0x7ff0000000000000;
259+
const MAN_MASK: u64 = 0x000fffffffffffff;
260+
261+
let bits = self.to_bits();
262+
match (bits & MAN_MASK, bits & EXP_MASK) {
263+
(0, 0) => FpCategory::Zero,
264+
(_, 0) => FpCategory::Subnormal,
265+
(0, EXP_MASK) => FpCategory::Infinite,
266+
(_, EXP_MASK) => FpCategory::Nan,
267+
_ => FpCategory::Normal,
268+
}
269+
}
379270

380271
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
381272
/// positive sign bit and positive infinity.
@@ -389,13 +280,17 @@ macro_rules! f64_core_methods { () => {
389280
/// ```
390281
#[stable(feature = "rust1", since = "1.0.0")]
391282
#[inline]
392-
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
283+
pub fn is_sign_positive(self) -> bool {
284+
!self.is_sign_negative()
285+
}
393286

394287
#[stable(feature = "rust1", since = "1.0.0")]
395288
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
396289
#[inline]
397290
#[doc(hidden)]
398-
pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
291+
pub fn is_positive(self) -> bool {
292+
self.is_sign_positive()
293+
}
399294

400295
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
401296
/// negative sign bit and negative infinity.
@@ -409,13 +304,17 @@ macro_rules! f64_core_methods { () => {
409304
/// ```
410305
#[stable(feature = "rust1", since = "1.0.0")]
411306
#[inline]
412-
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
307+
pub fn is_sign_negative(self) -> bool {
308+
self.to_bits() & 0x8000_0000_0000_0000 != 0
309+
}
413310

414311
#[stable(feature = "rust1", since = "1.0.0")]
415312
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
416313
#[inline]
417314
#[doc(hidden)]
418-
pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
315+
pub fn is_negative(self) -> bool {
316+
self.is_sign_negative()
317+
}
419318

420319
/// Takes the reciprocal (inverse) of a number, `1/x`.
421320
///
@@ -427,7 +326,9 @@ macro_rules! f64_core_methods { () => {
427326
/// ```
428327
#[stable(feature = "rust1", since = "1.0.0")]
429328
#[inline]
430-
pub fn recip(self) -> f64 { Float::recip(self) }
329+
pub fn recip(self) -> f64 {
330+
1.0 / self
331+
}
431332

432333
/// Converts radians to degrees.
433334
///
@@ -442,7 +343,12 @@ macro_rules! f64_core_methods { () => {
442343
/// ```
443344
#[stable(feature = "rust1", since = "1.0.0")]
444345
#[inline]
445-
pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
346+
pub fn to_degrees(self) -> f64 {
347+
// The division here is correctly rounded with respect to the true
348+
// value of 180/π. (This differs from f32, where a constant must be
349+
// used to ensure a correctly rounded result.)
350+
self * (180.0f64 / consts::PI)
351+
}
446352

447353
/// Converts degrees to radians.
448354
///
@@ -457,7 +363,10 @@ macro_rules! f64_core_methods { () => {
457363
/// ```
458364
#[stable(feature = "rust1", since = "1.0.0")]
459365
#[inline]
460-
pub fn to_radians(self) -> f64 { Float::to_radians(self) }
366+
pub fn to_radians(self) -> f64 {
367+
let value: f64 = consts::PI;
368+
self * (value / 180.0)
369+
}
461370

462371
/// Returns the maximum of the two numbers.
463372
///
@@ -472,7 +381,15 @@ macro_rules! f64_core_methods { () => {
472381
#[stable(feature = "rust1", since = "1.0.0")]
473382
#[inline]
474383
pub fn max(self, other: f64) -> f64 {
475-
Float::max(self, other)
384+
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
385+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
386+
// is either x or y, canonicalized (this means results might differ among implementations).
387+
// When either x or y is a signalingNaN, then the result is according to 6.2.
388+
//
389+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
390+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
391+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
392+
(if self.is_nan() || self < other { other } else { self }) * 1.0
476393
}
477394

478395
/// Returns the minimum of the two numbers.
@@ -488,7 +405,15 @@ macro_rules! f64_core_methods { () => {
488405
#[stable(feature = "rust1", since = "1.0.0")]
489406
#[inline]
490407
pub fn min(self, other: f64) -> f64 {
491-
Float::min(self, other)
408+
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
409+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
410+
// is either x or y, canonicalized (this means results might differ among implementations).
411+
// When either x or y is a signalingNaN, then the result is according to 6.2.
412+
//
413+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
414+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
415+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
416+
(if other.is_nan() || self < other { self } else { other }) * 1.0
492417
}
493418

494419
/// Raw transmutation to `u64`.
@@ -511,7 +436,7 @@ macro_rules! f64_core_methods { () => {
511436
#[stable(feature = "float_bits_conv", since = "1.20.0")]
512437
#[inline]
513438
pub fn to_bits(self) -> u64 {
514-
Float::to_bits(self)
439+
unsafe { mem::transmute(self) }
515440
}
516441

517442
/// Raw transmutation from `u64`.
@@ -555,12 +480,7 @@ macro_rules! f64_core_methods { () => {
555480
#[stable(feature = "float_bits_conv", since = "1.20.0")]
556481
#[inline]
557482
pub fn from_bits(v: u64) -> Self {
558-
Float::from_bits(v)
483+
// It turns out the safety issues with sNaN were overblown! Hooray!
484+
unsafe { mem::transmute(v) }
559485
}
560-
}}
561-
562-
#[lang = "f64"]
563-
#[cfg(not(test))]
564-
impl f64 {
565-
f64_core_methods!();
566486
}

‎src/libcore/num/mod.rs

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4080,61 +4080,6 @@ pub enum FpCategory {
40804080
Normal,
40814081
}
40824082

4083-
// Technically private and only exposed for coretests:
4084-
#[doc(hidden)]
4085-
#[unstable(feature = "float_internals",
4086-
reason = "internal routines only exposed for testing",
4087-
issue = "0")]
4088-
pub trait Float: Sized {
4089-
/// Type used by `to_bits` and `from_bits`.
4090-
type Bits;
4091-
4092-
/// Returns `true` if this value is NaN and false otherwise.
4093-
fn is_nan(self) -> bool;
4094-
4095-
/// Returns `true` if this value is positive infinity or negative infinity and
4096-
/// false otherwise.
4097-
fn is_infinite(self) -> bool;
4098-
4099-
/// Returns `true` if this number is neither infinite nor NaN.
4100-
fn is_finite(self) -> bool;
4101-
4102-
/// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
4103-
fn is_normal(self) -> bool;
4104-
4105-
/// Returns the category that this number falls into.
4106-
fn classify(self) -> FpCategory;
4107-
4108-
/// Returns `true` if `self` is positive, including `+0.0` and
4109-
/// `Float::infinity()`.
4110-
fn is_sign_positive(self) -> bool;
4111-
4112-
/// Returns `true` if `self` is negative, including `-0.0` and
4113-
/// `Float::neg_infinity()`.
4114-
fn is_sign_negative(self) -> bool;
4115-
4116-
/// Take the reciprocal (inverse) of a number, `1/x`.
4117-
fn recip(self) -> Self;
4118-
4119-
/// Convert radians to degrees.
4120-
fn to_degrees(self) -> Self;
4121-
4122-
/// Convert degrees to radians.
4123-
fn to_radians(self) -> Self;
4124-
4125-
/// Returns the maximum of the two numbers.
4126-
fn max(self, other: Self) -> Self;
4127-
4128-
/// Returns the minimum of the two numbers.
4129-
fn min(self, other: Self) -> Self;
4130-
4131-
/// Raw transmutation to integer.
4132-
fn to_bits(self) -> Self::Bits;
4133-
4134-
/// Raw transmutation from integer.
4135-
fn from_bits(v: Self::Bits) -> Self;
4136-
}
4137-
41384083
macro_rules! from_str_radix_int_impl {
41394084
($($t:ty)*) => {$(
41404085
#[stable(feature = "rust1", since = "1.0.0")]

‎src/libcore/tests/num/mod.rs

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -508,51 +508,50 @@ assume_usize_width! {
508508

509509
macro_rules! test_float {
510510
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname {
511-
use core::num::Float;
512511
// FIXME(nagisa): these tests should test for sign of -0.0
513512
#[test]
514513
fn min() {
515-
assert_eq!(0.0.min(0.0), 0.0);
516-
assert_eq!((-0.0).min(-0.0), -0.0);
517-
assert_eq!(9.0.min(9.0), 9.0);
518-
assert_eq!((-9.0).min(0.0), -9.0);
519-
assert_eq!(0.0.min(9.0), 0.0);
520-
assert_eq!((-0.0).min(-9.0), -9.0);
521-
assert_eq!($inf.min(9.0), 9.0);
522-
assert_eq!(9.0.min($inf), 9.0);
523-
assert_eq!($inf.min(-9.0), -9.0);
524-
assert_eq!((-9.0).min($inf), -9.0);
525-
assert_eq!($neginf.min(9.0), $neginf);
526-
assert_eq!(9.0.min($neginf), $neginf);
527-
assert_eq!($neginf.min(-9.0), $neginf);
528-
assert_eq!((-9.0).min($neginf), $neginf);
529-
assert_eq!($nan.min(9.0), 9.0);
530-
assert_eq!($nan.min(-9.0), -9.0);
531-
assert_eq!(9.0.min($nan), 9.0);
532-
assert_eq!((-9.0).min($nan), -9.0);
533-
assert!($nan.min($nan).is_nan());
514+
assert_eq!((0.0 as $fty).min(0.0), 0.0);
515+
assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
516+
assert_eq!((9.0 as $fty).min(9.0), 9.0);
517+
assert_eq!((-9.0 as $fty).min(0.0), -9.0);
518+
assert_eq!((0.0 as $fty).min(9.0), 0.0);
519+
assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
520+
assert_eq!(($inf as $fty).min(9.0), 9.0);
521+
assert_eq!((9.0 as $fty).min($inf), 9.0);
522+
assert_eq!(($inf as $fty).min(-9.0), -9.0);
523+
assert_eq!((-9.0 as $fty).min($inf), -9.0);
524+
assert_eq!(($neginf as $fty).min(9.0), $neginf);
525+
assert_eq!((9.0 as $fty).min($neginf), $neginf);
526+
assert_eq!(($neginf as $fty).min(-9.0), $neginf);
527+
assert_eq!((-9.0 as $fty).min($neginf), $neginf);
528+
assert_eq!(($nan as $fty).min(9.0), 9.0);
529+
assert_eq!(($nan as $fty).min(-9.0), -9.0);
530+
assert_eq!((9.0 as $fty).min($nan), 9.0);
531+
assert_eq!((-9.0 as $fty).min($nan), -9.0);
532+
assert!(($nan as $fty).min($nan).is_nan());
534533
}
535534
#[test]
536535
fn max() {
537-
assert_eq!(0.0.max(0.0), 0.0);
538-
assert_eq!((-0.0).max(-0.0), -0.0);
539-
assert_eq!(9.0.max(9.0), 9.0);
540-
assert_eq!((-9.0).max(0.0), 0.0);
541-
assert_eq!(0.0.max(9.0), 9.0);
542-
assert_eq!((-0.0).max(-9.0), -0.0);
543-
assert_eq!($inf.max(9.0), $inf);
544-
assert_eq!(9.0.max($inf), $inf);
545-
assert_eq!($inf.max(-9.0), $inf);
546-
assert_eq!((-9.0).max($inf), $inf);
547-
assert_eq!($neginf.max(9.0), 9.0);
548-
assert_eq!(9.0.max($neginf), 9.0);
549-
assert_eq!($neginf.max(-9.0), -9.0);
550-
assert_eq!((-9.0).max($neginf), -9.0);
551-
assert_eq!($nan.max(9.0), 9.0);
552-
assert_eq!($nan.max(-9.0), -9.0);
553-
assert_eq!(9.0.max($nan), 9.0);
554-
assert_eq!((-9.0).max($nan), -9.0);
555-
assert!($nan.max($nan).is_nan());
536+
assert_eq!((0.0 as $fty).max(0.0), 0.0);
537+
assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
538+
assert_eq!((9.0 as $fty).max(9.0), 9.0);
539+
assert_eq!((-9.0 as $fty).max(0.0), 0.0);
540+
assert_eq!((0.0 as $fty).max(9.0), 9.0);
541+
assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
542+
assert_eq!(($inf as $fty).max(9.0), $inf);
543+
assert_eq!((9.0 as $fty).max($inf), $inf);
544+
assert_eq!(($inf as $fty).max(-9.0), $inf);
545+
assert_eq!((-9.0 as $fty).max($inf), $inf);
546+
assert_eq!(($neginf as $fty).max(9.0), 9.0);
547+
assert_eq!((9.0 as $fty).max($neginf), 9.0);
548+
assert_eq!(($neginf as $fty).max(-9.0), -9.0);
549+
assert_eq!((-9.0 as $fty).max($neginf), -9.0);
550+
assert_eq!(($nan as $fty).max(9.0), 9.0);
551+
assert_eq!(($nan as $fty).max(-9.0), -9.0);
552+
assert_eq!((9.0 as $fty).max($nan), 9.0);
553+
assert_eq!((-9.0 as $fty).max($nan), -9.0);
554+
assert!(($nan as $fty).max($nan).is_nan());
556555
}
557556
} }
558557
}

‎src/librustc_typeck/diagnostics.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4552,23 +4552,25 @@ but the type of the numeric value or binding could not be identified.
45524552
The error happens on numeric literals:
45534553
45544554
```compile_fail,E0689
4555-
2.0.recip();
4555+
2.0.neg();
45564556
```
45574557
45584558
and on numeric bindings without an identified concrete type:
45594559
45604560
```compile_fail,E0689
45614561
let x = 2.0;
4562-
x.recip(); // same error as above
4562+
x.neg(); // same error as above
45634563
```
45644564
45654565
Because of this, you must give the numeric literal or binding a type:
45664566
45674567
```
4568-
let _ = 2.0_f32.recip();
4568+
use std::ops::Neg;
4569+
4570+
let _ = 2.0_f32.neg();
45694571
let x: f32 = 2.0;
4570-
let _ = x.recip();
4571-
let _ = (2.0 as f32).recip();
4572+
let _ = x.neg();
4573+
let _ = (2.0 as f32).neg();
45724574
```
45734575
"##,
45744576

‎src/test/ui/macros/macro-backtrace-invalid-internals.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr {
4848

4949
macro_rules! real_method_stmt {
5050
() => {
51-
2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
51+
2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
5252
}
5353
}
5454

5555
macro_rules! real_method_expr {
5656
() => {
57-
2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
57+
2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
5858
}
5959
}
6060

‎src/test/ui/macros/macro-backtrace-invalid-internals.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ LL | (1).0 //~ ERROR doesn't have fields
2525
LL | fake_anon_field_stmt!();
2626
| ------------------------ in this macro invocation
2727

28-
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
28+
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
2929
--> $DIR/macro-backtrace-invalid-internals.rs:51:15
3030
|
31-
LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
32-
| ^^^^^
31+
LL | 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
32+
| ^^^
3333
...
3434
LL | real_method_stmt!();
3535
| -------------------- in this macro invocation
3636
help: you must specify a concrete type for this numeric value, like `f32`
3737
|
38-
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
38+
LL | 2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
3939
| ^^^^^^^
4040

4141
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
6565
LL | let _ = fake_anon_field_expr!();
6666
| ----------------------- in this macro invocation
6767

68-
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
68+
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
6969
--> $DIR/macro-backtrace-invalid-internals.rs:57:15
7070
|
71-
LL | 2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
72-
| ^^^^^
71+
LL | 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
72+
| ^^^
7373
...
7474
LL | let _ = real_method_expr!();
7575
| ------------------- in this macro invocation
7676
help: you must specify a concrete type for this numeric value, like `f32`
7777
|
78-
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
78+
LL | 2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
7979
| ^^^^^^^
8080

8181
error: aborting due to 8 previous errors

‎src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let x = 2.0.recip();
13-
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
12+
let x = 2.0.neg();
13+
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
1414
let y = 2.0;
15-
let x = y.recip();
16-
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
15+
let x = y.neg();
16+
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
1717
println!("{:?}", x);
1818
}

‎src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
1+
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
22
--> $DIR/method-on-ambiguous-numeric-type.rs:12:17
33
|
4-
LL | let x = 2.0.recip();
5-
| ^^^^^
4+
LL | let x = 2.0.neg();
5+
| ^^^
66
help: you must specify a concrete type for this numeric value, like `f32`
77
|
8-
LL | let x = 2.0_f32.recip();
8+
LL | let x = 2.0_f32.neg();
99
| ^^^^^^^
1010

11-
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
11+
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
1212
--> $DIR/method-on-ambiguous-numeric-type.rs:15:15
1313
|
14-
LL | let x = y.recip();
15-
| ^^^^^
14+
LL | let x = y.neg();
15+
| ^^^
1616
help: you must specify a type for this binding, like `f32`
1717
|
1818
LL | let y: f32 = 2.0;

0 commit comments

Comments
 (0)
Please sign in to comment.