Auto merge of - SimonSapin:inherent, r=alexcrichton

Add inherent methods in libcore for [T], [u8], str, f32, and f64

# Background

Primitive types are defined by the language, they don’t have a type definition like `pub struct Foo { … }` in any crate. So they don’t “belong” to any crate as far as `impl` coherence is concerned, and on principle no crate would be able to define inherent methods for them, without a trait. Since we want these types to have inherent methods anyway, the standard library (with cooperation from the compiler) bends this rule with code like [`#[lang = "u8"] impl u8 { /*…*/ }`](https://github.com/rust-lang/rust/blob/1.25.0/src/libcore/num/mod.rs#L2244-L2245). The `#[lang]` attribute is permanently-unstable and never intended to be used outside of the standard library.

Each lang item can only be defined once. Before this PR there is one impl-coherence-rule-bending lang item per primitive type (plus one for `[u8]`, which overlaps with `[T]`). And so one `impl` block each. These blocks for `str`, `[T]` and `[u8]` are in liballoc rather than libcore because *some* of the methods (like `<[T]>::to_vec(&self) -> Vec<T> where T: Clone`) need a global memory allocator which we don’t want to make a requirement in libcore. Similarly, `impl f32` and `impl f64` are in libstd because some of the methods are based on FFI calls to C’s `libm` and we want, as much as possible, libcore not to require “runtime support”.

In libcore, the methods of `str` and `[T]` that don’t allocate are made available through two **unstable traits** `StrExt` and `SliceExt` (so the traits can’t be *named* by programs on the Stable release channel) that have **stable methods** and are re-exported in the libcore prelude (so that programs on Stable can *call* these methods anyway). Non-allocating `[u8]` methods are not available in libcore: https://github.com/rust-lang/rust/issues/45803. Some `f32` and `f64` methods are in an unstable `core::num::Float` trait with stable methods, but that one is **not in the libcore prelude**. (So as far as Stable programs are concerns it doesn’t exist, and I don’t know what the point was to mark these methods `#[stable]`.)

https://github.com/rust-lang/rust/issues/32110 is the tracking issue for these unstable traits.

# High-level proposal

Since the standard library is already bending the rules, why not bend them *a little more*? By defining a few additional lang items, the compiler can allow the standard library to have *two* `impl` blocks (in different crates) for some primitive types.

The `StrExt` and `SliceExt` traits still exist for now so that we can bootstrap from a previous-version compiler that doesn’t have these lang items yet, but they can be removed in next release cycle. (`Float` is used internally and needs to be public for libcore unit tests, but was already `#[doc(hidden)]`.) I don’t know if https://github.com/rust-lang/rust/issues/32110 should be closed by this PR, or only when the traits are entirely removed after we make a new bootstrap compiler.

# Float methods

Among the methods of the `core::num::Float` trait, three are based on LLVM intrinsics: `abs`, `signum`, and `powi`. PR https://github.com/rust-lang/rust/pull/27823 “Remove dependencies on libm functions from libcore” moved a bunch of `core::num::Float` methods back to libstd, but left these three behind. However they aren’t specifically discussed in the PR thread. The `compiler_builtins` crate defines `__powisf2` and `__powidf2` functions that look like implementations of `powi`, but I couldn’t find a connection with the `llvm.powi.f32` and `llvm.powi.f32` intrinsics by grepping through LLVM’s code.

In discussion starting at https://github.com/rust-lang/rust/issues/32110#issuecomment-370647922 Alex says that we do not want methods in libcore that require “runtime support”, but it’s not clear whether that applies to these `abs`, `signum`, or `powi`. In doubt, I’ve **removed** them for the trait and moved them to inherent methods in libstd for now. We can move them back later (or in this PR) if we decide that’s appropriate.

# Change details

For users on the Stable release channel:

* I believe this PR does not make any breaking change
* Some methods for `[u8]`, `f32`, and `f64` are newly available to `#![no_std]` users (fixes https://github.com/rust-lang/rust/issues/45803)
* There should be no visible change for `std` users in terms of what programs compile or what their behavior is. (Only in compiler error messages, possibly.)

For Nightly users, additionally:

* The unstable `StrExt` and `SliceExt` traits are gone
* Their methods are now inherent methods of `str` and `[T]` (so only code that explicitly named the traits should be affected, not "normal" method calls)
* The `abs`, `signum` and `powi` methods of the `Float` trait are gone
* The `Float` trait’s unstable feature name changed to `float_internals` with no associated tracking issue, to reflect it being a permanently unstable implementation detail rather than a public API on a path to stabilization.
* Its remaining methods are now inherent methods of `f32` and `f64`.

-----

CC @rust-lang/libs for the API changes, @rust-lang/compiler for the new lang items
This commit is contained in:
bors 2018-04-22 00:01:29 +00:00
commit d5616e1f18
29 changed files with 3985 additions and 3891 deletions

@ -75,7 +75,7 @@
#![deny(missing_debug_implementations)]
#![cfg_attr(test, allow(deprecated))] // rand
#![cfg_attr(not(test), feature(core_float))]
#![cfg_attr(all(not(test), stage0), feature(float_internals))]
#![cfg_attr(not(test), feature(exact_size_is_empty))]
#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(test, feature(rand, test))]
@ -90,6 +90,8 @@
#![feature(collections_range)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![cfg_attr(stage0, feature(core_slice_ext))]
#![cfg_attr(stage0, feature(core_str_ext))]
#![feature(custom_attribute)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -74,6 +74,7 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen};
use core::marker::PhantomData;
use core::mem;
#[cfg(not(test))]
#[cfg(stage0)]
use core::num::Float;
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{Index, IndexMut, RangeBounds};

@ -87,3 +87,16 @@ macro_rules! forward_ref_op_assign {
}
}
#[cfg(stage0)]
macro_rules! public_in_stage0 {
( { $(#[$attr:meta])* } $($Item: tt)*) => {
$(#[$attr])* pub $($Item)*
}
}
#[cfg(not(stage0))]
macro_rules! public_in_stage0 {
( { $(#[$attr:meta])* } $($Item: tt)*) => {
$(#[$attr])* pub(crate) $($Item)*
}
}

@ -71,6 +71,7 @@
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(core_float)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
@ -93,6 +94,8 @@
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
@ -229,7 +232,7 @@ macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code)]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
mod coresimd;

@ -17,9 +17,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
use intrinsics;
use mem;
use num::Float;
#[cfg(not(stage0))] use num::FpCategory;
use num::FpCategory as Fp;
/// The radix or base of the internal representation of `f32`.
@ -188,27 +188,6 @@ impl Float for f32 {
}
}
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// number is `Float::nan()`.
#[inline]
fn abs(self) -> f32 {
unsafe { intrinsics::fabsf32(self) }
}
/// Returns a number that represents the sign of `self`.
///
/// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
/// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
/// - `Float::nan()` if the number is `Float::nan()`
#[inline]
fn signum(self) -> f32 {
if self.is_nan() {
NAN
} else {
unsafe { intrinsics::copysignf32(1.0, self) }
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
#[inline]
@ -231,11 +210,6 @@ impl Float for f32 {
1.0 / self
}
#[inline]
fn powi(self, n: i32) -> f32 {
unsafe { intrinsics::powif32(self, n) }
}
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f32 {
@ -292,3 +266,286 @@ impl Float for f32 {
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.
#[cfg_attr(stage0, macro_export)]
#[unstable(feature = "core_float", issue = "32110")]
macro_rules! f32_core_methods { () => {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
/// use std::f32;
///
/// let nan = f32::NAN;
/// let f = 7.0_f32;
///
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
/// ```
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf = f32::INFINITY;
/// let neg_inf = f32::NEG_INFINITY;
/// let nan = f32::NAN;
///
/// assert!(!f.is_infinite());
/// assert!(!nan.is_infinite());
///
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
/// ```
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf = f32::INFINITY;
/// let neg_inf = f32::NEG_INFINITY;
/// let nan = f32::NAN;
///
/// assert!(f.is_finite());
///
/// assert!(!nan.is_finite());
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
///
/// ```
/// use std::f32;
///
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
/// let max = f32::MAX;
/// let lower_than_min = 1.0e-40_f32;
/// let zero = 0.0_f32;
///
/// assert!(min.is_normal());
/// assert!(max.is_normal());
///
/// assert!(!zero.is_normal());
/// assert!(!f32::NAN.is_normal());
/// assert!(!f32::INFINITY.is_normal());
/// // Values between `0` and `min` are Subnormal.
/// assert!(!lower_than_min.is_normal());
/// ```
/// [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) }
/// 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.
///
/// ```
/// use std::num::FpCategory;
/// use std::f32;
///
/// let num = 12.4_f32;
/// let inf = f32::INFINITY;
///
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { Float::classify(self) }
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
///
/// ```
/// let f = 7.0_f32;
/// let g = -7.0_f32;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
///
/// ```
/// let f = 7.0f32;
/// let g = -7.0f32;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
/// use std::f32;
///
/// let x = 2.0_f32;
/// let abs_difference = (x.recip() - (1.0/x)).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f32 { Float::recip(self) }
/// Converts radians to degrees.
///
/// ```
/// use std::f32::{self, consts};
///
/// let angle = consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
/// Converts degrees to radians.
///
/// ```
/// use std::f32::{self, consts};
///
/// let angle = 180.0f32;
///
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_radians(self) -> f32 { Float::to_radians(self) }
/// Returns the maximum of the two numbers.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.max(y), y);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f32) -> f32 {
Float::max(self, other)
}
/// Returns the minimum of the two numbers.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.min(y), x);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f32) -> f32 {
Float::min(self, other)
}
/// Raw transmutation to `u32`.
///
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
///
/// See `from_bits` for some discussion of the portability of this operation
/// (there are almost no issues).
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
/// assert_eq!((12.5f32).to_bits(), 0x41480000);
///
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u32 {
Float::to_bits(self)
}
/// Raw transmutation from `u32`.
///
/// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
/// It turns out this is incredibly portable, for two reasons:
///
/// * Floats and Ints have the same endianness on all supported platforms.
/// * IEEE-754 very precisely specifies the bit layout of floats.
///
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
/// (notably x86 and ARM) picked the interpretation that was ultimately
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
///
/// Rather than trying to preserve signaling-ness cross-platform, this
/// implementation favours preserving the exact bits. This means that
/// any payloads encoded in NaNs will be preserved even if the result of
/// this method is sent over the network from an x86 machine to a MIPS one.
///
/// If the results of this method are only manipulated by the same
/// architecture that produced them, then there is no portability concern.
///
/// If the input isn't NaN, then there is no portability concern.
///
/// If you don't care about signalingness (very likely), then there is no
/// portability concern.
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// use std::f32;
/// let v = f32::from_bits(0x41480000);
/// let difference = (v - 12.5).abs();
/// assert!(difference <= 1e-5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u32) -> Self {
Float::from_bits(v)
}
}}
#[lang = "f32"]
#[cfg(not(test))]
#[cfg(not(stage0))]
impl f32 {
f32_core_methods!();
}

@ -17,10 +17,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
use intrinsics;
use mem;
use num::FpCategory as Fp;
use num::Float;
#[cfg(not(stage0))] 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")]
@ -188,27 +188,6 @@ impl Float for f64 {
}
}
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// number is `Float::nan()`.
#[inline]
fn abs(self) -> f64 {
unsafe { intrinsics::fabsf64(self) }
}
/// Returns a number that represents the sign of `self`.
///
/// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
/// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
/// - `Float::nan()` if the number is `Float::nan()`
#[inline]
fn signum(self) -> f64 {
if self.is_nan() {
NAN
} else {
unsafe { intrinsics::copysignf64(1.0, self) }
}
}
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
#[inline]
@ -229,11 +208,6 @@ impl Float for f64 {
1.0 / self
}
#[inline]
fn powi(self, n: i32) -> f64 {
unsafe { intrinsics::powif64(self, n) }
}
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f64 {
@ -291,3 +265,296 @@ impl Float for f64 {
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.
#[cfg_attr(stage0, macro_export)]
#[unstable(feature = "core_float", issue = "32110")]
macro_rules! f64_core_methods { () => {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
/// use std::f64;
///
/// let nan = f64::NAN;
/// let f = 7.0_f64;
///
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
/// ```
/// use std::f64;
///
/// let f = 7.0f64;
/// let inf = f64::INFINITY;
/// let neg_inf = f64::NEG_INFINITY;
/// let nan = f64::NAN;
///
/// assert!(!f.is_infinite());
/// assert!(!nan.is_infinite());
///
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
/// ```
/// use std::f64;
///
/// let f = 7.0f64;
/// let inf: f64 = f64::INFINITY;
/// let neg_inf: f64 = f64::NEG_INFINITY;
/// let nan: f64 = f64::NAN;
///
/// assert!(f.is_finite());
///
/// assert!(!nan.is_finite());
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
///
/// ```
/// use std::f64;
///
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
/// let max = f64::MAX;
/// let lower_than_min = 1.0e-308_f64;
/// let zero = 0.0f64;
///
/// assert!(min.is_normal());
/// assert!(max.is_normal());
///
/// assert!(!zero.is_normal());
/// assert!(!f64::NAN.is_normal());
/// assert!(!f64::INFINITY.is_normal());
/// // Values between `0` and `min` are Subnormal.
/// assert!(!lower_than_min.is_normal());
/// ```
/// [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) }
/// 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.
///
/// ```
/// use std::num::FpCategory;
/// use std::f64;
///
/// let num = 12.4_f64;
/// let inf = f64::INFINITY;
///
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { Float::classify(self) }
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
///
/// ```
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
#[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) }
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
///
/// ```
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
#[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) }
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
/// let x = 2.0_f64;
/// let abs_difference = (x.recip() - (1.0/x)).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f64 { Float::recip(self) }
/// Converts radians to degrees.
///
/// ```
/// use std::f64::consts;
///
/// let angle = consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
/// Converts degrees to radians.
///
/// ```
/// use std::f64::consts;
///
/// let angle = 180.0_f64;
///
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_radians(self) -> f64 { Float::to_radians(self) }
/// Returns the maximum of the two numbers.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.max(y), y);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f64) -> f64 {
Float::max(self, other)
}
/// Returns the minimum of the two numbers.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.min(y), x);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f64) -> f64 {
Float::min(self, other)
}
/// Raw transmutation to `u64`.
///
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
///
/// See `from_bits` for some discussion of the portability of this operation
/// (there are almost no issues).
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
/// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
///
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u64 {
Float::to_bits(self)
}
/// Raw transmutation from `u64`.
///
/// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
/// It turns out this is incredibly portable, for two reasons:
///
/// * Floats and Ints have the same endianness on all supported platforms.
/// * IEEE-754 very precisely specifies the bit layout of floats.
///
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
/// (notably x86 and ARM) picked the interpretation that was ultimately
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
///
/// Rather than trying to preserve signaling-ness cross-platform, this
/// implementation favours preserving the exact bits. This means that
/// any payloads encoded in NaNs will be preserved even if the result of
/// this method is sent over the network from an x86 machine to a MIPS one.
///
/// If the results of this method are only manipulated by the same
/// architecture that produced them, then there is no portability concern.
///
/// If the input isn't NaN, then there is no portability concern.
///
/// If you don't care about signalingness (very likely), then there is no
/// portability concern.
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// use std::f64;
/// let v = f64::from_bits(0x4029000000000000);
/// let difference = (v - 12.5).abs();
/// assert!(difference <= 1e-5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u64) -> Self {
Float::from_bits(v)
}
}}
#[lang = "f64"]
#[cfg(not(test))]
#[cfg(not(stage0))]
impl f64 {
f64_core_methods!();
}

@ -4098,83 +4098,58 @@ pub enum FpCategory {
Normal,
}
/// A built-in floating point number.
// Technically private and only exposed for coretests:
#[doc(hidden)]
#[unstable(feature = "core_float",
reason = "stable interface is via `impl f{32,64}` in later crates",
issue = "32110")]
#[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`.
#[stable(feature = "core_float_bits", since = "1.25.0")]
type Bits;
/// Returns `true` if this value is NaN and false otherwise.
#[stable(feature = "core", since = "1.6.0")]
fn is_nan(self) -> bool;
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
#[stable(feature = "core", since = "1.6.0")]
fn is_infinite(self) -> bool;
/// Returns `true` if this number is neither infinite nor NaN.
#[stable(feature = "core", since = "1.6.0")]
fn is_finite(self) -> bool;
/// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
#[stable(feature = "core", since = "1.6.0")]
fn is_normal(self) -> bool;
/// Returns the category that this number falls into.
#[stable(feature = "core", since = "1.6.0")]
fn classify(self) -> FpCategory;
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// number is `Float::nan()`.
#[stable(feature = "core", since = "1.6.0")]
fn abs(self) -> Self;
/// Returns a number that represents the sign of `self`.
///
/// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
/// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
/// - `Float::nan()` if the number is `Float::nan()`
#[stable(feature = "core", since = "1.6.0")]
fn signum(self) -> Self;
/// 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()`.
#[stable(feature = "core", since = "1.6.0")]
fn is_sign_positive(self) -> bool;
/// Returns `true` if `self` is negative, including `-0.0` and
/// `Float::neg_infinity()`.
#[stable(feature = "core", since = "1.6.0")]
fn is_sign_negative(self) -> bool;
/// Take the reciprocal (inverse) of a number, `1/x`.
#[stable(feature = "core", since = "1.6.0")]
fn recip(self) -> Self;
/// Raise a number to an integer power.
///
/// Using this function is generally faster than using `powf`
#[stable(feature = "core", since = "1.6.0")]
fn powi(self, n: i32) -> Self;
/// Convert radians to degrees.
#[stable(feature = "deg_rad_conversions", since="1.7.0")]
fn to_degrees(self) -> Self;
/// Convert degrees to radians.
#[stable(feature = "deg_rad_conversions", since="1.7.0")]
fn to_radians(self) -> Self;
/// Returns the maximum of the two numbers.
#[stable(feature = "core_float_min_max", since="1.20.0")]
fn max(self, other: Self) -> Self;
/// Returns the minimum of the two numbers.
#[stable(feature = "core_float_min_max", since="1.20.0")]
fn min(self, other: Self) -> Self;
/// Raw transmutation to integer.
#[stable(feature = "core_float_bits", since="1.25.0")]
fn to_bits(self) -> Self::Bits;
/// Raw transmutation from integer.
#[stable(feature = "core_float_bits", since="1.25.0")]
fn from_bits(v: Self::Bits) -> Self;
}

@ -58,7 +58,9 @@ pub use result::Result::{self, Ok, Err};
// Re-exported extension traits for primitive types
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
#[cfg(stage0)]
pub use slice::SliceExt;
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
#[cfg(stage0)]
pub use str::StrExt;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -17,6 +17,7 @@
#![feature(decode_utf8)]
#![feature(exact_size_is_empty)]
#![feature(fixed_size_array)]
#![feature(float_internals)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
#![feature(hashmap_internals)]

@ -214,6 +214,9 @@ language_item_table! {
StrImplItem, "str", str_impl;
SliceImplItem, "slice", slice_impl;
SliceU8ImplItem, "slice_u8", slice_u8_impl;
StrAllocImplItem, "str_alloc", str_alloc_impl;
SliceAllocImplItem, "slice_alloc", slice_alloc_impl;
SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl;
ConstPtrImplItem, "const_ptr", const_ptr_impl;
MutPtrImplItem, "mut_ptr", mut_ptr_impl;
I8ImplItem, "i8", i8_impl;
@ -230,6 +233,8 @@ language_item_table! {
UsizeImplItem, "usize", usize_impl;
F32ImplItem, "f32", f32_impl;
F64ImplItem, "f64", f64_impl;
F32RuntimeImplItem, "f32_runtime", f32_runtime_impl;
F64RuntimeImplItem, "f64_runtime", f64_runtime_impl;
SizedTraitLangItem, "sized", sized_trait;
UnsizeTraitLangItem, "unsize", unsize_trait;

@ -471,6 +471,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
ty::TyStr => {
let lang_def_id = lang_items.str_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.str_alloc_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TySlice(_) => {
let lang_def_id = lang_items.slice_impl();
@ -478,6 +481,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let lang_def_id = lang_items.slice_u8_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.slice_alloc_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.slice_u8_alloc_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
let lang_def_id = lang_items.const_ptr_impl();
@ -538,10 +547,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
ty::TyFloat(ast::FloatTy::F32) => {
let lang_def_id = lang_items.f32_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.f32_runtime_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyFloat(ast::FloatTy::F64) => {
let lang_def_id = lang_items.f64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.f64_runtime_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
_ => {}
}

@ -114,6 +114,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyChar => {
self.check_primitive_impl(def_id,
lang_items.char_impl(),
None,
"char",
"char",
item.span);
@ -121,6 +122,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyStr => {
self.check_primitive_impl(def_id,
lang_items.str_impl(),
lang_items.str_alloc_impl(),
"str",
"str",
item.span);
@ -128,6 +130,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
self.check_primitive_impl(def_id,
lang_items.slice_u8_impl(),
lang_items.slice_u8_alloc_impl(),
"slice_u8",
"[u8]",
item.span);
@ -135,6 +138,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TySlice(_) => {
self.check_primitive_impl(def_id,
lang_items.slice_impl(),
lang_items.slice_alloc_impl(),
"slice",
"[T]",
item.span);
@ -142,6 +146,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
self.check_primitive_impl(def_id,
lang_items.const_ptr_impl(),
None,
"const_ptr",
"*const T",
item.span);
@ -149,6 +154,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
self.check_primitive_impl(def_id,
lang_items.mut_ptr_impl(),
None,
"mut_ptr",
"*mut T",
item.span);
@ -156,6 +162,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::I8) => {
self.check_primitive_impl(def_id,
lang_items.i8_impl(),
None,
"i8",
"i8",
item.span);
@ -163,6 +170,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::I16) => {
self.check_primitive_impl(def_id,
lang_items.i16_impl(),
None,
"i16",
"i16",
item.span);
@ -170,6 +178,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::I32) => {
self.check_primitive_impl(def_id,
lang_items.i32_impl(),
None,
"i32",
"i32",
item.span);
@ -177,6 +186,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::I64) => {
self.check_primitive_impl(def_id,
lang_items.i64_impl(),
None,
"i64",
"i64",
item.span);
@ -184,6 +194,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::I128) => {
self.check_primitive_impl(def_id,
lang_items.i128_impl(),
None,
"i128",
"i128",
item.span);
@ -191,6 +202,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyInt(ast::IntTy::Isize) => {
self.check_primitive_impl(def_id,
lang_items.isize_impl(),
None,
"isize",
"isize",
item.span);
@ -198,6 +210,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::U8) => {
self.check_primitive_impl(def_id,
lang_items.u8_impl(),
None,
"u8",
"u8",
item.span);
@ -205,6 +218,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::U16) => {
self.check_primitive_impl(def_id,
lang_items.u16_impl(),
None,
"u16",
"u16",
item.span);
@ -212,6 +226,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::U32) => {
self.check_primitive_impl(def_id,
lang_items.u32_impl(),
None,
"u32",
"u32",
item.span);
@ -219,6 +234,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::U64) => {
self.check_primitive_impl(def_id,
lang_items.u64_impl(),
None,
"u64",
"u64",
item.span);
@ -226,6 +242,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::U128) => {
self.check_primitive_impl(def_id,
lang_items.u128_impl(),
None,
"u128",
"u128",
item.span);
@ -233,6 +250,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyUint(ast::UintTy::Usize) => {
self.check_primitive_impl(def_id,
lang_items.usize_impl(),
None,
"usize",
"usize",
item.span);
@ -240,6 +258,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyFloat(ast::FloatTy::F32) => {
self.check_primitive_impl(def_id,
lang_items.f32_impl(),
lang_items.f32_runtime_impl(),
"f32",
"f32",
item.span);
@ -247,6 +266,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::TyFloat(ast::FloatTy::F64) => {
self.check_primitive_impl(def_id,
lang_items.f64_impl(),
lang_items.f64_runtime_impl(),
"f64",
"f64",
item.span);
@ -305,11 +325,15 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
fn check_primitive_impl(&self,
impl_def_id: DefId,
lang_def_id: Option<DefId>,
lang_def_id2: Option<DefId>,
lang: &str,
ty: &str,
span: Span) {
match lang_def_id {
Some(lang_def_id) if lang_def_id == impl_def_id => {
match (lang_def_id, lang_def_id2) {
(Some(lang_def_id), _) if lang_def_id == impl_def_id => {
// OK
}
(_, Some(lang_def_id)) if lang_def_id == impl_def_id => {
// OK
}
_ => {

@ -4526,23 +4526,23 @@ but the type of the numeric value or binding could not be identified.
The error happens on numeric literals:
```compile_fail,E0689
2.0.powi(2);
2.0.recip();
```
and on numeric bindings without an identified concrete type:
```compile_fail,E0689
let x = 2.0;
x.powi(2); // same error as above
x.recip(); // same error as above
```
Because of this, you must give the numeric literal or binding a type:
```
let _ = 2.0_f32.powi(2);
let _ = 2.0_f32.recip();
let x: f32 = 2.0;
let _ = x.powi(2);
let _ = (2.0 as f32).powi(2);
let _ = x.recip();
let _ = (2.0 as f32).recip();
```
"##,

@ -286,10 +286,15 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
lang_items.u128_impl(),
lang_items.f32_impl(),
lang_items.f64_impl(),
lang_items.f32_runtime_impl(),
lang_items.f64_runtime_impl(),
lang_items.char_impl(),
lang_items.str_impl(),
lang_items.slice_impl(),
lang_items.slice_u8_impl(),
lang_items.str_alloc_impl(),
lang_items.slice_alloc_impl(),
lang_items.slice_u8_alloc_impl(),
lang_items.const_ptr_impl(),
lang_items.mut_ptr_impl(),
];

@ -19,10 +19,12 @@
#![allow(missing_docs)]
#[cfg(not(test))]
use core::num;
#[cfg(stage0)]
use core::num::Float;
#[cfg(not(test))]
use intrinsics;
#[cfg(not(test))]
#[cfg(stage0)]
use num::FpCategory;
#[cfg(not(test))]
use sys::cmath;
@ -39,106 +41,11 @@ pub use core::f32::{MIN, MIN_POSITIVE, MAX};
pub use core::f32::consts;
#[cfg(not(test))]
#[lang = "f32"]
#[cfg_attr(stage0, lang = "f32")]
#[cfg_attr(not(stage0), lang = "f32_runtime")]
impl f32 {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
/// use std::f32;
///
/// let nan = f32::NAN;
/// let f = 7.0_f32;
///
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
/// ```
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf = f32::INFINITY;
/// let neg_inf = f32::NEG_INFINITY;
/// let nan = f32::NAN;
///
/// assert!(!f.is_infinite());
/// assert!(!nan.is_infinite());
///
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
/// ```
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf = f32::INFINITY;
/// let neg_inf = f32::NEG_INFINITY;
/// let nan = f32::NAN;
///
/// assert!(f.is_finite());
///
/// assert!(!nan.is_finite());
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
///
/// ```
/// use std::f32;
///
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
/// let max = f32::MAX;
/// let lower_than_min = 1.0e-40_f32;
/// let zero = 0.0_f32;
///
/// assert!(min.is_normal());
/// assert!(max.is_normal());
///
/// assert!(!zero.is_normal());
/// assert!(!f32::NAN.is_normal());
/// assert!(!f32::INFINITY.is_normal());
/// // Values between `0` and `min` are Subnormal.
/// assert!(!lower_than_min.is_normal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
/// 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.
///
/// ```
/// use std::num::FpCategory;
/// use std::f32;
///
/// let num = 12.4_f32;
/// let inf = f32::INFINITY;
///
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { num::Float::classify(self) }
#[cfg(stage0)]
f32_core_methods!();
/// Returns the largest integer less than or equal to a number.
///
@ -257,7 +164,9 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn abs(self) -> f32 { num::Float::abs(self) }
pub fn abs(self) -> f32 {
unsafe { intrinsics::fabsf32(self) }
}
/// Returns a number that represents the sign of `self`.
///
@ -277,35 +186,13 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f32 { num::Float::signum(self) }
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
///
/// ```
/// let f = 7.0_f32;
/// let g = -7.0_f32;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
///
/// ```
/// let f = 7.0f32;
/// let g = -7.0f32;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
pub fn signum(self) -> f32 {
if self.is_nan() {
NAN
} else {
unsafe { intrinsics::copysignf32(1.0, self) }
}
}
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
@ -380,20 +267,6 @@ impl f32 {
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
/// use std::f32;
///
/// let x = 2.0_f32;
/// let abs_difference = (x.recip() - (1.0/x)).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f32 { num::Float::recip(self) }
/// Raises a number to an integer power.
///
/// Using this function is generally faster than using `powf`
@ -408,7 +281,9 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
pub fn powi(self, n: i32) -> f32 {
unsafe { intrinsics::powif32(self, n) }
}
/// Raises a number to a floating point power.
///
@ -584,68 +459,6 @@ impl f32 {
return unsafe { intrinsics::log10f32(self) };
}
/// Converts radians to degrees.
///
/// ```
/// use std::f32::{self, consts};
///
/// let angle = consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
/// Converts degrees to radians.
///
/// ```
/// use std::f32::{self, consts};
///
/// let angle = 180.0f32;
///
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
/// Returns the maximum of the two numbers.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.max(y), y);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f32) -> f32 {
num::Float::max(self, other)
}
/// Returns the minimum of the two numbers.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.min(y), x);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f32) -> f32 {
num::Float::min(self, other)
}
/// The positive difference of two numbers.
///
/// * If `self <= other`: `0:0`
@ -1046,73 +859,6 @@ impl f32 {
pub fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
/// Raw transmutation to `u32`.
///
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
///
/// See `from_bits` for some discussion of the portability of this operation
/// (there are almost no issues).
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
/// assert_eq!((12.5f32).to_bits(), 0x41480000);
///
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u32 {
num::Float::to_bits(self)
}
/// Raw transmutation from `u32`.
///
/// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
/// It turns out this is incredibly portable, for two reasons:
///
/// * Floats and Ints have the same endianness on all supported platforms.
/// * IEEE-754 very precisely specifies the bit layout of floats.
///
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
/// (notably x86 and ARM) picked the interpretation that was ultimately
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
///
/// Rather than trying to preserve signaling-ness cross-platform, this
/// implementation favours preserving the exact bits. This means that
/// any payloads encoded in NaNs will be preserved even if the result of
/// this method is sent over the network from an x86 machine to a MIPS one.
///
/// If the results of this method are only manipulated by the same
/// architecture that produced them, then there is no portability concern.
///
/// If the input isn't NaN, then there is no portability concern.
///
/// If you don't care about signalingness (very likely), then there is no
/// portability concern.
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// use std::f32;
/// let v = f32::from_bits(0x41480000);
/// let difference = (v - 12.5).abs();
/// assert!(difference <= 1e-5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u32) -> Self {
num::Float::from_bits(v)
}
}
#[cfg(test)]

@ -19,10 +19,12 @@
#![allow(missing_docs)]
#[cfg(not(test))]
use core::num;
#[cfg(stage0)]
use core::num::Float;
#[cfg(not(test))]
use intrinsics;
#[cfg(not(test))]
#[cfg(stage0)]
use num::FpCategory;
#[cfg(not(test))]
use sys::cmath;
@ -39,106 +41,11 @@ pub use core::f64::{MIN, MIN_POSITIVE, MAX};
pub use core::f64::consts;
#[cfg(not(test))]
#[lang = "f64"]
#[cfg_attr(stage0, lang = "f64")]
#[cfg_attr(not(stage0), lang = "f64_runtime")]
impl f64 {
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
/// use std::f64;
///
/// let nan = f64::NAN;
/// let f = 7.0_f64;
///
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
/// ```
/// use std::f64;
///
/// let f = 7.0f64;
/// let inf = f64::INFINITY;
/// let neg_inf = f64::NEG_INFINITY;
/// let nan = f64::NAN;
///
/// assert!(!f.is_infinite());
/// assert!(!nan.is_infinite());
///
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
/// ```
/// use std::f64;
///
/// let f = 7.0f64;
/// let inf: f64 = f64::INFINITY;
/// let neg_inf: f64 = f64::NEG_INFINITY;
/// let nan: f64 = f64::NAN;
///
/// assert!(f.is_finite());
///
/// assert!(!nan.is_finite());
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
///
/// ```
/// use std::f64;
///
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
/// let max = f64::MAX;
/// let lower_than_min = 1.0e-308_f64;
/// let zero = 0.0f64;
///
/// assert!(min.is_normal());
/// assert!(max.is_normal());
///
/// assert!(!zero.is_normal());
/// assert!(!f64::NAN.is_normal());
/// assert!(!f64::INFINITY.is_normal());
/// // Values between `0` and `min` are Subnormal.
/// assert!(!lower_than_min.is_normal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
/// 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.
///
/// ```
/// use std::num::FpCategory;
/// use std::f64;
///
/// let num = 12.4_f64;
/// let inf = f64::INFINITY;
///
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn classify(self) -> FpCategory { num::Float::classify(self) }
#[cfg(stage0)]
f64_core_methods!();
/// Returns the largest integer less than or equal to a number.
///
@ -235,7 +142,9 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn abs(self) -> f64 { num::Float::abs(self) }
pub fn abs(self) -> f64 {
unsafe { intrinsics::fabsf64(self) }
}
/// Returns a number that represents the sign of `self`.
///
@ -255,45 +164,13 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f64 { num::Float::signum(self) }
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
///
/// ```
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
#[inline]
pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
///
/// ```
/// let f = 7.0_f64;
/// let g = -7.0_f64;
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
#[inline]
pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
pub fn signum(self) -> f64 {
if self.is_nan() {
NAN
} else {
unsafe { intrinsics::copysignf64(1.0, self) }
}
}
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
@ -365,18 +242,6 @@ impl f64 {
}
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
/// let x = 2.0_f64;
/// let abs_difference = (x.recip() - (1.0/x)).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn recip(self) -> f64 { num::Float::recip(self) }
/// Raises a number to an integer power.
///
/// Using this function is generally faster than using `powf`
@ -389,7 +254,9 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
pub fn powi(self, n: i32) -> f64 {
unsafe { intrinsics::powif64(self, n) }
}
/// Raises a number to a floating point power.
///
@ -535,68 +402,6 @@ impl f64 {
self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
}
/// Converts radians to degrees.
///
/// ```
/// use std::f64::consts;
///
/// let angle = consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
/// Converts degrees to radians.
///
/// ```
/// use std::f64::consts;
///
/// let angle = 180.0_f64;
///
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
/// Returns the maximum of the two numbers.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.max(y), y);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f64) -> f64 {
num::Float::max(self, other)
}
/// Returns the minimum of the two numbers.
///
/// ```
/// let x = 1.0_f64;
/// let y = 2.0_f64;
///
/// assert_eq!(x.min(y), x);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f64) -> f64 {
num::Float::min(self, other)
}
/// The positive difference of two numbers.
///
/// * If `self <= other`: `0:0`
@ -1000,73 +805,6 @@ impl f64 {
}
}
}
/// Raw transmutation to `u64`.
///
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
///
/// See `from_bits` for some discussion of the portability of this operation
/// (there are almost no issues).
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
/// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
///
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u64 {
num::Float::to_bits(self)
}
/// Raw transmutation from `u64`.
///
/// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
/// It turns out this is incredibly portable, for two reasons:
///
/// * Floats and Ints have the same endianness on all supported platforms.
/// * IEEE-754 very precisely specifies the bit layout of floats.
///
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
/// (notably x86 and ARM) picked the interpretation that was ultimately
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
///
/// Rather than trying to preserve signaling-ness cross-platform, this
/// implementation favours preserving the exact bits. This means that
/// any payloads encoded in NaNs will be preserved even if the result of
/// this method is sent over the network from an x86 machine to a MIPS one.
///
/// If the results of this method are only manipulated by the same
/// architecture that produced them, then there is no portability concern.
///
/// If the input isn't NaN, then there is no portability concern.
///
/// If you don't care about signalingness (very likely), then there is no
/// portability concern.
///
/// Note that this function is distinct from `as` casting, which attempts to
/// preserve the *numeric* value, and not the bitwise value.
///
/// # Examples
///
/// ```
/// use std::f64;
/// let v = f64::from_bits(0x4029000000000000);
/// let difference = (v - 12.5).abs();
/// assert!(difference <= 1e-5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u64) -> Self {
num::Float::from_bits(v)
}
}
#[cfg(test)]

@ -252,7 +252,7 @@
#![feature(collections_range)]
#![feature(compiler_builtins_lib)]
#![feature(const_fn)]
#![feature(core_float)]
#![cfg_attr(stage0, feature(core_float))]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
@ -260,6 +260,7 @@
#![feature(fs_read_write)]
#![feature(fixed_size_array)]
#![feature(float_from_str_radix)]
#![cfg_attr(stage0, feature(float_internals))]
#![feature(fn_traits)]
#![feature(fnbox)]
#![cfg_attr(stage0, feature(generic_param_attrs))]

@ -876,21 +876,7 @@ impl Hash for Wtf8 {
}
impl Wtf8 {
pub fn is_ascii(&self) -> bool {
self.bytes.is_ascii()
}
pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
}
pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
}
pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
self.bytes.eq_ignore_ascii_case(&other.bytes)
}
pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
}
#[cfg(test)]

@ -15,7 +15,7 @@
#![no_std]
// OK
#[lang = "str"]
#[lang = "str_alloc"]
impl str {}
impl str {

@ -14,7 +14,7 @@
pub mod str {
#![doc(primitive = "str")]
#[lang = "str"]
#[lang = "str_alloc"]
impl str {
// @has search-index.js foo
pub fn foo(&self) {}

@ -8,10 +8,8 @@ LL | foo(|s| s.is_empty());
| ^^^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `is_empty`, perhaps you need to implement one of them:
= note: the following trait defines an item `is_empty`, perhaps you need to implement it:
candidate #1: `std::iter::ExactSizeIterator`
candidate #2: `core::slice::SliceExt`
candidate #3: `core::str::StrExt`
error: aborting due to previous error

@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr {
macro_rules! real_method_stmt {
() => {
2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
}
}
macro_rules! real_method_expr {
() => {
2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
2.0.recip() //~ ERROR can't call method `recip` 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 `powi` on ambiguous numeric type `{float}`
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
--> $DIR/macro-backtrace-invalid-internals.rs:51:15
|
LL | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
| ^^^^
LL | 2.0.recip() //~ ERROR can't call method `recip` 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.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` 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 `powi` on ambiguous numeric type `{float}`
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
--> $DIR/macro-backtrace-invalid-internals.rs:57:15
|
LL | 2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
| ^^^^
LL | 2.0.recip() //~ ERROR can't call method `recip` 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.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
LL | 2.0_f32.recip() //~ ERROR can't call method `recip` 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.powi(2);
//~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
let x = 2.0.recip();
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
let y = 2.0;
let x = y.powi(2);
//~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
let x = y.recip();
//~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
println!("{:?}", x);
}

@ -1,18 +1,18 @@
error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
--> $DIR/method-on-ambiguous-numeric-type.rs:12:17
|
LL | let x = 2.0.powi(2);
| ^^^^
LL | let x = 2.0.recip();
| ^^^^^
help: you must specify a concrete type for this numeric value, like `f32`
|
LL | let x = 2.0_f32.powi(2);
LL | let x = 2.0_f32.recip();
| ^^^^^^^
error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
--> $DIR/method-on-ambiguous-numeric-type.rs:15:15
|
LL | let x = y.powi(2);
| ^^^^
LL | let x = y.recip();
| ^^^^^
help: you must specify a type for this binding, like `f32`
|
LL | let y: f32 = 2.0;