Skip to content

Commit

Permalink
Rollup merge of rust-lang#130568 - eduardosm:const-float-methods, r=R…
Browse files Browse the repository at this point in the history
…alfJung,tgross35

Make some float methods unstable `const fn`

Some float methods are now `const fn` under the `const_float_methods` feature gate.

I also made some unstable methods `const fn`, keeping their constness under their respective feature gate.

In order to support `min`, `max`, `abs` and `copysign`, the implementation of some intrinsics had to be moved from Miri to rustc_const_eval (cc `@RalfJung).`

Tracking issue: rust-lang#130843

```rust
impl <float> {
    // #[feature(const_float_methods)]
    pub const fn recip(self) -> Self;
    pub const fn to_degrees(self) -> Self;
    pub const fn to_radians(self) -> Self;
    pub const fn max(self, other: Self) -> Self;
    pub const fn min(self, other: Self) -> Self;
    pub const fn clamp(self, min: Self, max: Self) -> Self;
    pub const fn abs(self) -> Self;
    pub const fn signum(self) -> Self;
    pub const fn copysign(self, sign: Self) -> Self;

    // #[feature(float_minimum_maximum)]
    pub const fn maximum(self, other: Self) -> Self;
    pub const fn minimum(self, other: Self) -> Self;

    // Only f16/f128 (f32/f64 already const)
    pub const fn is_sign_positive(self) -> bool;
    pub const fn is_sign_negative(self) -> bool;
    pub const fn next_up(self) -> Self;
    pub const fn next_down(self) -> Self;
}
```

r? libs-api

try-job: dist-s390x-linux
  • Loading branch information
compiler-errors authored Oct 15, 2024
2 parents 435ce04 + 1897d05 commit 9d9ea42
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 204 deletions.
387 changes: 239 additions & 148 deletions core/src/intrinsics.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
#![feature(const_char_encode_utf16)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
#![feature(const_float_methods)]
#![feature(const_fmt_arguments_new)]
#![feature(const_hash)]
#![feature(const_heap)]
Expand Down
42 changes: 29 additions & 13 deletions core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ impl f128 {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
pub fn is_sign_positive(self) -> bool {
pub const fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}

Expand All @@ -497,7 +497,7 @@ impl f128 {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
pub fn is_sign_negative(self) -> bool {
pub const fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
// SAFETY: This is just transmuting to get the sign bit, it's fine.
Expand Down Expand Up @@ -538,7 +538,7 @@ impl f128 {
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
Expand Down Expand Up @@ -592,7 +592,7 @@ impl f128 {
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
Expand Down Expand Up @@ -627,8 +627,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
pub const fn recip(self) -> Self {
1.0 / self
}

Expand All @@ -647,8 +648,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
pub const fn to_degrees(self) -> Self {
// Use a literal for better precision.
const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
self * PIS_IN_180
Expand All @@ -670,8 +672,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f128 {
pub const fn to_radians(self) -> f128 {
// Use a literal for better precision.
const RADS_PER_DEG: f128 =
0.0174532925199432957692369076848861271344287188854172545609719_f128;
Expand All @@ -698,8 +701,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn max(self, other: f128) -> f128 {
pub const fn max(self, other: f128) -> f128 {
intrinsics::maxnumf128(self, other)
}

Expand All @@ -723,8 +727,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn min(self, other: f128) -> f128 {
pub const fn min(self, other: f128) -> f128 {
intrinsics::minnumf128(self, other)
}

Expand Down Expand Up @@ -757,7 +762,7 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn maximum(self, other: f128) -> f128 {
pub const fn maximum(self, other: f128) -> f128 {
if self > other {
self
} else if other > self {
Expand Down Expand Up @@ -798,7 +803,7 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn minimum(self, other: f128) -> f128 {
pub const fn minimum(self, other: f128) -> f128 {
if self < other {
self
} else if other < self {
Expand Down Expand Up @@ -1269,9 +1274,20 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn clamp(mut self, min: f128, max: f128) -> f128 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
#[inline] // inline to avoid LLVM crash
const fn assert_at_const(min: f128, max: f128) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f128, max: f128) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}
Expand Down
42 changes: 29 additions & 13 deletions core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ impl f16 {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
pub fn is_sign_positive(self) -> bool {
pub const fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}

Expand Down Expand Up @@ -488,7 +488,7 @@ impl f16 {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
pub fn is_sign_negative(self) -> bool {
pub const fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
// SAFETY: This is just transmuting to get the sign bit, it's fine.
Expand Down Expand Up @@ -529,7 +529,7 @@ impl f16 {
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
Expand Down Expand Up @@ -583,7 +583,7 @@ impl f16 {
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
Expand Down Expand Up @@ -618,8 +618,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
pub const fn recip(self) -> Self {
1.0 / self
}

Expand All @@ -638,8 +639,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
pub const fn to_degrees(self) -> Self {
// Use a literal for better precision.
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
self * PIS_IN_180
Expand All @@ -661,8 +663,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f16 {
pub const fn to_radians(self) -> f16 {
// Use a literal for better precision.
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
self * RADS_PER_DEG
Expand All @@ -687,8 +690,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn max(self, other: f16) -> f16 {
pub const fn max(self, other: f16) -> f16 {
intrinsics::maxnumf16(self, other)
}

Expand All @@ -711,8 +715,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn min(self, other: f16) -> f16 {
pub const fn min(self, other: f16) -> f16 {
intrinsics::minnumf16(self, other)
}

Expand Down Expand Up @@ -744,7 +749,7 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn maximum(self, other: f16) -> f16 {
pub const fn maximum(self, other: f16) -> f16 {
if self > other {
self
} else if other > self {
Expand Down Expand Up @@ -784,7 +789,7 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn minimum(self, other: f16) -> f16 {
pub const fn minimum(self, other: f16) -> f16 {
if self < other {
self
} else if other < self {
Expand Down Expand Up @@ -1244,9 +1249,20 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn clamp(mut self, min: f16, max: f16) -> f16 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
#[inline] // inline to avoid LLVM crash
const fn assert_at_const(min: f16, max: f16) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f16, max: f16) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}
Expand Down
33 changes: 24 additions & 9 deletions core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the operation, without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn recip(self) -> f32 {
pub const fn recip(self) -> f32 {
1.0 / self
}

Expand All @@ -845,8 +846,9 @@ impl f32 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_degrees(self) -> f32 {
pub const fn to_degrees(self) -> f32 {
// Use a constant for better precision.
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
self * PIS_IN_180
Expand All @@ -864,8 +866,9 @@ impl f32 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_radians(self) -> f32 {
pub const fn to_radians(self) -> f32 {
const RADS_PER_DEG: f32 = consts::PI / 180.0;
self * RADS_PER_DEG
}
Expand All @@ -885,8 +888,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn max(self, other: f32) -> f32 {
pub const fn max(self, other: f32) -> f32 {
intrinsics::maxnumf32(self, other)
}

Expand All @@ -905,8 +909,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn min(self, other: f32) -> f32 {
pub const fn min(self, other: f32) -> f32 {
intrinsics::minnumf32(self, other)
}

Expand All @@ -933,7 +938,7 @@ impl f32 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn maximum(self, other: f32) -> f32 {
pub const fn maximum(self, other: f32) -> f32 {
if self > other {
self
} else if other > self {
Expand Down Expand Up @@ -968,7 +973,7 @@ impl f32 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn minimum(self, other: f32) -> f32 {
pub const fn minimum(self, other: f32) -> f32 {
if self < other {
self
} else if other < self {
Expand Down Expand Up @@ -1401,9 +1406,19 @@ impl f32 {
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "clamp", since = "1.50.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn clamp(mut self, min: f32, max: f32) -> f32 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
const fn assert_at_const(min: f32, max: f32) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f32, max: f32) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}
Expand Down
Loading

0 comments on commit 9d9ea42

Please sign in to comment.