Skip to content

Commit

Permalink
Move intrinsics-based float methods out of libcore into libstd
Browse files Browse the repository at this point in the history
Affected methods are `abs`, `signum`, and `powi`.
CC #32110 (comment)
  • Loading branch information
SimonSapin committed Apr 21, 2018
1 parent 8a374f2 commit 18ab16b
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 104 deletions.
27 changes: 0 additions & 27 deletions src/libcore/num/f32.rs
Expand Up @@ -17,7 +17,6 @@

#![stable(feature = "rust1", since = "1.0.0")]

use intrinsics;
use mem;
use num::Float;
#[cfg(not(stage0))] use num::FpCategory;
Expand Down Expand Up @@ -189,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]
Expand All @@ -232,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 {
Expand Down
27 changes: 0 additions & 27 deletions src/libcore/num/f64.rs
Expand Up @@ -17,7 +17,6 @@

#![stable(feature = "rust1", since = "1.0.0")]

use intrinsics;
use mem;
use num::Float;
#[cfg(not(stage0))] use num::FpCategory;
Expand Down Expand Up @@ -189,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]
Expand All @@ -230,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 {
Expand Down
18 changes: 0 additions & 18 deletions src/libcore/num/mod.rs
Expand Up @@ -4125,18 +4125,6 @@ pub trait Float: Sized {
#[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 `self` is positive, including `+0.0` and
/// `Float::infinity()`.
#[stable(feature = "core", since = "1.6.0")]
Expand All @@ -4150,12 +4138,6 @@ pub trait Float: Sized {
#[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;
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_typeck/diagnostics.rs
Expand Up @@ -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();
```
"##,

Expand Down
17 changes: 14 additions & 3 deletions src/libstd/f32.rs
Expand Up @@ -19,6 +19,7 @@
#![allow(missing_docs)]

#[cfg(not(test))]
#[cfg(stage0)]
use core::num::Float;
#[cfg(not(test))]
use intrinsics;
Expand Down Expand Up @@ -163,7 +164,9 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn abs(self) -> f32 { Float::abs(self) }
pub fn abs(self) -> f32 {
unsafe { intrinsics::fabsf32(self) }
}

/// Returns a number that represents the sign of `self`.
///
Expand All @@ -183,7 +186,13 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f32 { Float::signum(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
Expand Down Expand Up @@ -272,7 +281,9 @@ impl f32 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powi(self, n: i32) -> f32 { Float::powi(self, n) }
pub fn powi(self, n: i32) -> f32 {
unsafe { intrinsics::powif32(self, n) }
}

/// Raises a number to a floating point power.
///
Expand Down
17 changes: 14 additions & 3 deletions src/libstd/f64.rs
Expand Up @@ -19,6 +19,7 @@
#![allow(missing_docs)]

#[cfg(not(test))]
#[cfg(stage0)]
use core::num::Float;
#[cfg(not(test))]
use intrinsics;
Expand Down Expand Up @@ -141,7 +142,9 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn abs(self) -> f64 { Float::abs(self) }
pub fn abs(self) -> f64 {
unsafe { intrinsics::fabsf64(self) }
}

/// Returns a number that represents the sign of `self`.
///
Expand All @@ -161,7 +164,13 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f64 { Float::signum(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
Expand Down Expand Up @@ -245,7 +254,9 @@ impl f64 {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powi(self, n: i32) -> f64 { Float::powi(self, n) }
pub fn powi(self, n: i32) -> f64 {
unsafe { intrinsics::powif64(self, n) }
}

/// Raises a number to a floating point power.
///
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/macros/macro-backtrace-invalid-internals.rs
Expand Up @@ -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}`
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/macros/macro-backtrace-invalid-internals.stderr
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
Expand Up @@ -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);
}
14 changes: 7 additions & 7 deletions src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
@@ -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;
Expand Down

0 comments on commit 18ab16b

Please sign in to comment.