Rollup merge of #130568 - eduardosm:const-float-methods, r=RalfJung,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: https://github.com/rust-lang/rust/issues/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
This commit is contained in:
commit
2f3f001423
18 changed files with 517 additions and 266 deletions
|
@ -334,19 +334,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
{
|
{
|
||||||
use rustc_type_ir::TyKind::*;
|
use rustc_type_ir::TyKind::*;
|
||||||
|
|
||||||
fn adjust_nan<
|
|
||||||
'tcx,
|
|
||||||
M: Machine<'tcx>,
|
|
||||||
F1: rustc_apfloat::Float + FloatConvert<F2>,
|
|
||||||
F2: rustc_apfloat::Float,
|
|
||||||
>(
|
|
||||||
ecx: &InterpCx<'tcx, M>,
|
|
||||||
f1: F1,
|
|
||||||
f2: F2,
|
|
||||||
) -> F2 {
|
|
||||||
if f2.is_nan() { M::generate_nan(ecx, &[f1]) } else { f2 }
|
|
||||||
}
|
|
||||||
|
|
||||||
match *dest_ty.kind() {
|
match *dest_ty.kind() {
|
||||||
// float -> uint
|
// float -> uint
|
||||||
Uint(t) => {
|
Uint(t) => {
|
||||||
|
@ -367,11 +354,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
}
|
}
|
||||||
// float -> float
|
// float -> float
|
||||||
Float(fty) => match fty {
|
Float(fty) => match fty {
|
||||||
FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)),
|
FloatTy::F16 => {
|
||||||
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
|
Scalar::from_f16(self.adjust_nan(f.convert(&mut false).value, &[f]))
|
||||||
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
|
}
|
||||||
|
FloatTy::F32 => {
|
||||||
|
Scalar::from_f32(self.adjust_nan(f.convert(&mut false).value, &[f]))
|
||||||
|
}
|
||||||
|
FloatTy::F64 => {
|
||||||
|
Scalar::from_f64(self.adjust_nan(f.convert(&mut false).value, &[f]))
|
||||||
|
}
|
||||||
FloatTy::F128 => {
|
FloatTy::F128 => {
|
||||||
Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value))
|
Scalar::from_f128(self.adjust_nan(f.convert(&mut false).value, &[f]))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// That's it.
|
// That's it.
|
||||||
|
|
|
@ -599,6 +599,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
|
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
|
||||||
Frame::generate_stacktrace_from_stack(self.stack())
|
Frame::generate_stacktrace_from_stack(self.stack())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn adjust_nan<F1, F2>(&self, f: F2, inputs: &[F1]) -> F2
|
||||||
|
where
|
||||||
|
F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>,
|
||||||
|
F2: rustc_apfloat::Float,
|
||||||
|
{
|
||||||
|
if f.is_nan() { M::generate_nan(self, inputs) } else { f }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
|
|
||||||
|
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
|
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
|
||||||
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
|
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
|
||||||
|
@ -438,6 +439,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
|
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sym::minnumf16 => self.float_min_intrinsic::<Half>(args, dest)?,
|
||||||
|
sym::minnumf32 => self.float_min_intrinsic::<Single>(args, dest)?,
|
||||||
|
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
|
||||||
|
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
|
||||||
|
|
||||||
|
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
|
||||||
|
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
|
||||||
|
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
|
||||||
|
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
|
||||||
|
|
||||||
|
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
|
||||||
|
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
|
||||||
|
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
|
||||||
|
sym::copysignf128 => self.float_copysign_intrinsic::<Quad>(args, dest)?,
|
||||||
|
|
||||||
|
sym::fabsf16 => self.float_abs_intrinsic::<Half>(args, dest)?,
|
||||||
|
sym::fabsf32 => self.float_abs_intrinsic::<Single>(args, dest)?,
|
||||||
|
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
|
||||||
|
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
|
||||||
|
|
||||||
// Unsupported intrinsic: skip the return_to_block below.
|
// Unsupported intrinsic: skip the return_to_block below.
|
||||||
_ => return interp_ok(false),
|
_ => return interp_ok(false),
|
||||||
}
|
}
|
||||||
|
@ -697,4 +718,63 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
let rhs_bytes = get_bytes(self, rhs)?;
|
let rhs_bytes = get_bytes(self, rhs)?;
|
||||||
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
|
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn float_min_intrinsic<F>(
|
||||||
|
&mut self,
|
||||||
|
args: &[OpTy<'tcx, M::Provenance>],
|
||||||
|
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ()>
|
||||||
|
where
|
||||||
|
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||||
|
{
|
||||||
|
let a: F = self.read_scalar(&args[0])?.to_float()?;
|
||||||
|
let b: F = self.read_scalar(&args[1])?.to_float()?;
|
||||||
|
let res = self.adjust_nan(a.min(b), &[a, b]);
|
||||||
|
self.write_scalar(res, dest)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_max_intrinsic<F>(
|
||||||
|
&mut self,
|
||||||
|
args: &[OpTy<'tcx, M::Provenance>],
|
||||||
|
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ()>
|
||||||
|
where
|
||||||
|
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||||
|
{
|
||||||
|
let a: F = self.read_scalar(&args[0])?.to_float()?;
|
||||||
|
let b: F = self.read_scalar(&args[1])?.to_float()?;
|
||||||
|
let res = self.adjust_nan(a.max(b), &[a, b]);
|
||||||
|
self.write_scalar(res, dest)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_copysign_intrinsic<F>(
|
||||||
|
&mut self,
|
||||||
|
args: &[OpTy<'tcx, M::Provenance>],
|
||||||
|
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ()>
|
||||||
|
where
|
||||||
|
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||||
|
{
|
||||||
|
let a: F = self.read_scalar(&args[0])?.to_float()?;
|
||||||
|
let b: F = self.read_scalar(&args[1])?.to_float()?;
|
||||||
|
// bitwise, no NaN adjustments
|
||||||
|
self.write_scalar(a.copy_sign(b), dest)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_abs_intrinsic<F>(
|
||||||
|
&mut self,
|
||||||
|
args: &[OpTy<'tcx, M::Provenance>],
|
||||||
|
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||||
|
) -> InterpResult<'tcx, ()>
|
||||||
|
where
|
||||||
|
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||||
|
{
|
||||||
|
let x: F = self.read_scalar(&args[0])?.to_float()?;
|
||||||
|
// bitwise, no NaN adjustments
|
||||||
|
self.write_scalar(x.abs(), dest)?;
|
||||||
|
interp_ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
use rustc_middle::mir::BinOp::*;
|
use rustc_middle::mir::BinOp::*;
|
||||||
|
|
||||||
// Performs appropriate non-deterministic adjustments of NaN results.
|
// Performs appropriate non-deterministic adjustments of NaN results.
|
||||||
let adjust_nan =
|
let adjust_nan = |f: F| -> F { self.adjust_nan(f, &[l, r]) };
|
||||||
|f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } };
|
|
||||||
|
|
||||||
match bin_op {
|
match bin_op {
|
||||||
Eq => ImmTy::from_bool(l == r, *self.tcx),
|
Eq => ImmTy::from_bool(l == r, *self.tcx),
|
||||||
|
|
|
@ -1849,154 +1849,6 @@ extern "rust-intrinsic" {
|
||||||
#[cfg(not(bootstrap))]
|
#[cfg(not(bootstrap))]
|
||||||
pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
|
pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
|
||||||
|
|
||||||
/// Returns the absolute value of an `f16`.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f16::abs`](../../std/primitive.f16.html#method.abs)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn fabsf16(x: f16) -> f16;
|
|
||||||
/// Returns the absolute value of an `f32`.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f32::abs`](../../std/primitive.f32.html#method.abs)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn fabsf32(x: f32) -> f32;
|
|
||||||
/// Returns the absolute value of an `f64`.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f64::abs`](../../std/primitive.f64.html#method.abs)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn fabsf64(x: f64) -> f64;
|
|
||||||
/// Returns the absolute value of an `f128`.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f128::abs`](../../std/primitive.f128.html#method.abs)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn fabsf128(x: f128) -> f128;
|
|
||||||
|
|
||||||
/// Returns the minimum of two `f16` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f16::min`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn minnumf16(x: f16, y: f16) -> f16;
|
|
||||||
/// Returns the minimum of two `f32` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f32::min`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn minnumf32(x: f32, y: f32) -> f32;
|
|
||||||
/// Returns the minimum of two `f64` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f64::min`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn minnumf64(x: f64, y: f64) -> f64;
|
|
||||||
/// Returns the minimum of two `f128` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f128::min`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn minnumf128(x: f128, y: f128) -> f128;
|
|
||||||
|
|
||||||
/// Returns the maximum of two `f16` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f16::max`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn maxnumf16(x: f16, y: f16) -> f16;
|
|
||||||
/// Returns the maximum of two `f32` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f32::max`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn maxnumf32(x: f32, y: f32) -> f32;
|
|
||||||
/// Returns the maximum of two `f64` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f64::max`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn maxnumf64(x: f64, y: f64) -> f64;
|
|
||||||
/// Returns the maximum of two `f128` values.
|
|
||||||
///
|
|
||||||
/// Note that, unlike most intrinsics, this is safe to call;
|
|
||||||
/// it does not require an `unsafe` block.
|
|
||||||
/// Therefore, implementations must not require the user to uphold
|
|
||||||
/// any safety invariants.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f128::max`]
|
|
||||||
#[rustc_safe_intrinsic]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn maxnumf128(x: f128, y: f128) -> f128;
|
|
||||||
|
|
||||||
/// Copies the sign from `y` to `x` for `f16` values.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn copysignf16(x: f16, y: f16) -> f16;
|
|
||||||
/// Copies the sign from `y` to `x` for `f32` values.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn copysignf32(x: f32, y: f32) -> f32;
|
|
||||||
/// Copies the sign from `y` to `x` for `f64` values.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn copysignf64(x: f64, y: f64) -> f64;
|
|
||||||
/// Copies the sign from `y` to `x` for `f128` values.
|
|
||||||
///
|
|
||||||
/// The stabilized version of this intrinsic is
|
|
||||||
/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn copysignf128(x: f128, y: f128) -> f128;
|
|
||||||
|
|
||||||
/// Returns the largest integer less than or equal to an `f16`.
|
/// Returns the largest integer less than or equal to an `f16`.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// The stabilized version of this intrinsic is
|
||||||
|
@ -3555,6 +3407,245 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum of two `f16` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f16::min`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn minnumf16(_x: f16, _y: f16) -> f16 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum of two `f32` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f32::min`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn minnumf32(_x: f32, _y: f32) -> f32 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum of two `f64` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f64::min`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn minnumf64(_x: f64, _y: f64) -> f64 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum of two `f128` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f128::min`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn minnumf128(_x: f128, _y: f128) -> f128 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum of two `f16` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f16::max`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn maxnumf16(_x: f16, _y: f16) -> f16 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum of two `f32` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f32::max`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn maxnumf32(_x: f32, _y: f32) -> f32 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum of two `f64` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f64::max`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn maxnumf64(_x: f64, _y: f64) -> f64 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum of two `f128` values.
|
||||||
|
///
|
||||||
|
/// Note that, unlike most intrinsics, this is safe to call;
|
||||||
|
/// it does not require an `unsafe` block.
|
||||||
|
/// Therefore, implementations must not require the user to uphold
|
||||||
|
/// any safety invariants.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f128::max`]
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const fn maxnumf128(_x: f128, _y: f128) -> f128 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the absolute value of an `f16`.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f16::abs`](../../std/primitive.f16.html#method.abs)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn fabsf16(_x: f16) -> f16 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the absolute value of an `f32`.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f32::abs`](../../std/primitive.f32.html#method.abs)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn fabsf32(_x: f32) -> f32 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the absolute value of an `f64`.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f64::abs`](../../std/primitive.f64.html#method.abs)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn fabsf64(_x: f64) -> f64 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the absolute value of an `f128`.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f128::abs`](../../std/primitive.f128.html#method.abs)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn fabsf128(_x: f128) -> f128 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copies the sign from `y` to `x` for `f16` values.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copies the sign from `y` to `x` for `f32` values.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
/// Copies the sign from `y` to `x` for `f64` values.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copies the sign from `y` to `x` for `f128` values.
|
||||||
|
///
|
||||||
|
/// The stabilized version of this intrinsic is
|
||||||
|
/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
|
||||||
|
#[rustc_nounwind]
|
||||||
|
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
/// Inform Miri that a given pointer definitely has a certain alignment.
|
/// Inform Miri that a given pointer definitely has a certain alignment.
|
||||||
#[cfg(miri)]
|
#[cfg(miri)]
|
||||||
pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) {
|
pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) {
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
#![feature(const_char_encode_utf16)]
|
#![feature(const_char_encode_utf16)]
|
||||||
#![feature(const_eval_select)]
|
#![feature(const_eval_select)]
|
||||||
#![feature(const_exact_div)]
|
#![feature(const_exact_div)]
|
||||||
|
#![feature(const_float_methods)]
|
||||||
#![feature(const_fmt_arguments_new)]
|
#![feature(const_fmt_arguments_new)]
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
|
|
|
@ -471,7 +471,7 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
pub fn is_sign_positive(self) -> bool {
|
pub const fn is_sign_positive(self) -> bool {
|
||||||
!self.is_sign_negative()
|
!self.is_sign_negative()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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
|
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
||||||
// applies to zeros and NaNs as well.
|
// applies to zeros and NaNs as well.
|
||||||
// SAFETY: This is just transmuting to get the sign bit, it's fine.
|
// SAFETY: This is just transmuting to get the sign bit, it's fine.
|
||||||
|
@ -538,7 +538,7 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
// #[unstable(feature = "float_next_up_down", issue = "91399")]
|
// #[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
|
// 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
|
// 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.
|
// we do our best to still produce the correct result on such targets.
|
||||||
|
@ -592,7 +592,7 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
// #[unstable(feature = "float_next_up_down", issue = "91399")]
|
// #[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
|
// 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
|
// 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.
|
// we do our best to still produce the correct result on such targets.
|
||||||
|
@ -627,8 +627,9 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[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
|
1.0 / self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,8 +648,9 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[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.
|
// Use a literal for better precision.
|
||||||
const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
|
const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
|
||||||
self * PIS_IN_180
|
self * PIS_IN_180
|
||||||
|
@ -670,8 +672,9 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[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.
|
// Use a literal for better precision.
|
||||||
const RADS_PER_DEG: f128 =
|
const RADS_PER_DEG: f128 =
|
||||||
0.0174532925199432957692369076848861271344287188854172545609719_f128;
|
0.0174532925199432957692369076848861271344287188854172545609719_f128;
|
||||||
|
@ -698,8 +701,9 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[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)
|
intrinsics::maxnumf128(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,8 +727,9 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[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)
|
intrinsics::minnumf128(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,7 +762,7 @@ impl f128 {
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[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 {
|
if self > other {
|
||||||
self
|
self
|
||||||
} else if other > self {
|
} else if other > self {
|
||||||
|
@ -798,7 +803,7 @@ impl f128 {
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[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 {
|
if self < other {
|
||||||
self
|
self
|
||||||
} else if other < self {
|
} else if other < self {
|
||||||
|
@ -1269,9 +1274,20 @@ impl f128 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn clamp(mut self, min: f128, max: f128) -> f128 {
|
pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
|
||||||
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
|
#[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 {
|
if self < min {
|
||||||
self = min;
|
self = min;
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,7 +459,7 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
pub fn is_sign_positive(self) -> bool {
|
pub const fn is_sign_positive(self) -> bool {
|
||||||
!self.is_sign_negative()
|
!self.is_sign_negative()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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
|
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
||||||
// applies to zeros and NaNs as well.
|
// applies to zeros and NaNs as well.
|
||||||
// SAFETY: This is just transmuting to get the sign bit, it's fine.
|
// SAFETY: This is just transmuting to get the sign bit, it's fine.
|
||||||
|
@ -529,7 +529,7 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
// #[unstable(feature = "float_next_up_down", issue = "91399")]
|
// #[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
|
// 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
|
// 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.
|
// we do our best to still produce the correct result on such targets.
|
||||||
|
@ -583,7 +583,7 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
// #[unstable(feature = "float_next_up_down", issue = "91399")]
|
// #[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
|
// 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
|
// 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.
|
// we do our best to still produce the correct result on such targets.
|
||||||
|
@ -618,8 +618,9 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[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
|
1.0 / self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,8 +639,9 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[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.
|
// Use a literal for better precision.
|
||||||
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
|
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
|
||||||
self * PIS_IN_180
|
self * PIS_IN_180
|
||||||
|
@ -661,8 +663,9 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[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.
|
// Use a literal for better precision.
|
||||||
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
|
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
|
||||||
self * RADS_PER_DEG
|
self * RADS_PER_DEG
|
||||||
|
@ -687,8 +690,9 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[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)
|
intrinsics::maxnumf16(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,8 +715,9 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[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)
|
intrinsics::minnumf16(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,7 +749,7 @@ impl f16 {
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[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 {
|
if self > other {
|
||||||
self
|
self
|
||||||
} else if other > self {
|
} else if other > self {
|
||||||
|
@ -784,7 +789,7 @@ impl f16 {
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[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 {
|
if self < other {
|
||||||
self
|
self
|
||||||
} else if other < self {
|
} else if other < self {
|
||||||
|
@ -1244,9 +1249,20 @@ impl f16 {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn clamp(mut self, min: f16, max: f16) -> f16 {
|
pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
|
||||||
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
|
#[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 {
|
if self < min {
|
||||||
self = min;
|
self = min;
|
||||||
}
|
}
|
||||||
|
|
|
@ -828,8 +828,9 @@ impl f32 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn recip(self) -> f32 {
|
pub const fn recip(self) -> f32 {
|
||||||
1.0 / self
|
1.0 / self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,8 +846,9 @@ impl f32 {
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_degrees(self) -> f32 {
|
pub const fn to_degrees(self) -> f32 {
|
||||||
// Use a constant for better precision.
|
// Use a constant for better precision.
|
||||||
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
|
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
|
||||||
self * PIS_IN_180
|
self * PIS_IN_180
|
||||||
|
@ -864,8 +866,9 @@ impl f32 {
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_radians(self) -> f32 {
|
pub const fn to_radians(self) -> f32 {
|
||||||
const RADS_PER_DEG: f32 = consts::PI / 180.0;
|
const RADS_PER_DEG: f32 = consts::PI / 180.0;
|
||||||
self * RADS_PER_DEG
|
self * RADS_PER_DEG
|
||||||
}
|
}
|
||||||
|
@ -885,8 +888,9 @@ impl f32 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max(self, other: f32) -> f32 {
|
pub const fn max(self, other: f32) -> f32 {
|
||||||
intrinsics::maxnumf32(self, other)
|
intrinsics::maxnumf32(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,8 +909,9 @@ impl f32 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn min(self, other: f32) -> f32 {
|
pub const fn min(self, other: f32) -> f32 {
|
||||||
intrinsics::minnumf32(self, other)
|
intrinsics::minnumf32(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,7 +938,7 @@ impl f32 {
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn maximum(self, other: f32) -> f32 {
|
pub const fn maximum(self, other: f32) -> f32 {
|
||||||
if self > other {
|
if self > other {
|
||||||
self
|
self
|
||||||
} else if other > self {
|
} else if other > self {
|
||||||
|
@ -968,7 +973,7 @@ impl f32 {
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn minimum(self, other: f32) -> f32 {
|
pub const fn minimum(self, other: f32) -> f32 {
|
||||||
if self < other {
|
if self < other {
|
||||||
self
|
self
|
||||||
} else if other < self {
|
} else if other < self {
|
||||||
|
@ -1401,9 +1406,19 @@ impl f32 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "clamp", since = "1.50.0")]
|
#[stable(feature = "clamp", since = "1.50.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clamp(mut self, min: f32, max: f32) -> f32 {
|
pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
|
||||||
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
|
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 {
|
if self < min {
|
||||||
self = min;
|
self = min;
|
||||||
}
|
}
|
||||||
|
|
|
@ -845,8 +845,9 @@ impl f64 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn recip(self) -> f64 {
|
pub const fn recip(self) -> f64 {
|
||||||
1.0 / self
|
1.0 / self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,8 +863,9 @@ impl f64 {
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_degrees(self) -> f64 {
|
pub const fn to_degrees(self) -> f64 {
|
||||||
// The division here is correctly rounded with respect to the true
|
// The division here is correctly rounded with respect to the true
|
||||||
// value of 180/π. (This differs from f32, where a constant must be
|
// value of 180/π. (This differs from f32, where a constant must be
|
||||||
// used to ensure a correctly rounded result.)
|
// used to ensure a correctly rounded result.)
|
||||||
|
@ -882,8 +884,9 @@ impl f64 {
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_radians(self) -> f64 {
|
pub const fn to_radians(self) -> f64 {
|
||||||
const RADS_PER_DEG: f64 = consts::PI / 180.0;
|
const RADS_PER_DEG: f64 = consts::PI / 180.0;
|
||||||
self * RADS_PER_DEG
|
self * RADS_PER_DEG
|
||||||
}
|
}
|
||||||
|
@ -903,8 +906,9 @@ impl f64 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max(self, other: f64) -> f64 {
|
pub const fn max(self, other: f64) -> f64 {
|
||||||
intrinsics::maxnumf64(self, other)
|
intrinsics::maxnumf64(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,8 +927,9 @@ impl f64 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn min(self, other: f64) -> f64 {
|
pub const fn min(self, other: f64) -> f64 {
|
||||||
intrinsics::minnumf64(self, other)
|
intrinsics::minnumf64(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +956,7 @@ impl f64 {
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn maximum(self, other: f64) -> f64 {
|
pub const fn maximum(self, other: f64) -> f64 {
|
||||||
if self > other {
|
if self > other {
|
||||||
self
|
self
|
||||||
} else if other > self {
|
} else if other > self {
|
||||||
|
@ -986,7 +991,7 @@ impl f64 {
|
||||||
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
#[must_use = "this returns the result of the comparison, without modifying either input"]
|
||||||
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn minimum(self, other: f64) -> f64 {
|
pub const fn minimum(self, other: f64) -> f64 {
|
||||||
if self < other {
|
if self < other {
|
||||||
self
|
self
|
||||||
} else if other < self {
|
} else if other < self {
|
||||||
|
@ -1401,9 +1406,19 @@ impl f64 {
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "clamp", since = "1.50.0")]
|
#[stable(feature = "clamp", since = "1.50.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clamp(mut self, min: f64, max: f64) -> f64 {
|
pub const fn clamp(mut self, min: f64, max: f64) -> f64 {
|
||||||
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
|
const fn assert_at_const(min: f64, max: f64) {
|
||||||
|
// 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: f64, max: f64) {
|
||||||
|
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 {
|
if self < min {
|
||||||
self = min;
|
self = min;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,8 +210,9 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn abs(self) -> Self {
|
pub const fn abs(self) -> Self {
|
||||||
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
|
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
|
||||||
// We don't do this now because LLVM has lowering bugs for f128 math.
|
// We don't do this now because LLVM has lowering bugs for f128 math.
|
||||||
Self::from_bits(self.to_bits() & !(1 << 127))
|
Self::from_bits(self.to_bits() & !(1 << 127))
|
||||||
|
@ -240,8 +241,9 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn signum(self) -> f128 {
|
pub const fn signum(self) -> f128 {
|
||||||
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
|
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,8 +280,9 @@ impl f128 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn copysign(self, sign: f128) -> f128 {
|
pub const fn copysign(self, sign: f128) -> f128 {
|
||||||
unsafe { intrinsics::copysignf128(self, sign) }
|
unsafe { intrinsics::copysignf128(self, sign) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,8 +210,9 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn abs(self) -> Self {
|
pub const fn abs(self) -> Self {
|
||||||
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
|
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
|
||||||
Self::from_bits(self.to_bits() & !(1 << 15))
|
Self::from_bits(self.to_bits() & !(1 << 15))
|
||||||
}
|
}
|
||||||
|
@ -239,8 +240,9 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn signum(self) -> f16 {
|
pub const fn signum(self) -> f16 {
|
||||||
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
|
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +279,9 @@ impl f16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub fn copysign(self, sign: f16) -> f16 {
|
pub const fn copysign(self, sign: f16) -> f16 {
|
||||||
unsafe { intrinsics::copysignf16(self, sign) }
|
unsafe { intrinsics::copysignf16(self, sign) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,9 @@ impl f32 {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn abs(self) -> f32 {
|
pub const fn abs(self) -> f32 {
|
||||||
unsafe { intrinsics::fabsf32(self) }
|
unsafe { intrinsics::fabsf32(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +219,9 @@ impl f32 {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn signum(self) -> f32 {
|
pub const fn signum(self) -> f32 {
|
||||||
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
|
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +255,8 @@ impl f32 {
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "copysign", since = "1.35.0")]
|
#[stable(feature = "copysign", since = "1.35.0")]
|
||||||
pub fn copysign(self, sign: f32) -> f32 {
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
|
pub const fn copysign(self, sign: f32) -> f32 {
|
||||||
unsafe { intrinsics::copysignf32(self, sign) }
|
unsafe { intrinsics::copysignf32(self, sign) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,9 @@ impl f64 {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn abs(self) -> f64 {
|
pub const fn abs(self) -> f64 {
|
||||||
unsafe { intrinsics::fabsf64(self) }
|
unsafe { intrinsics::fabsf64(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +219,9 @@ impl f64 {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn signum(self) -> f64 {
|
pub const fn signum(self) -> f64 {
|
||||||
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
|
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +254,9 @@ impl f64 {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "copysign", since = "1.35.0")]
|
#[stable(feature = "copysign", since = "1.35.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn copysign(self, sign: f64) -> f64 {
|
pub const fn copysign(self, sign: f64) -> f64 {
|
||||||
unsafe { intrinsics::copysignf64(self, sign) }
|
unsafe { intrinsics::copysignf64(self, sign) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,7 @@
|
||||||
#![feature(cfg_target_thread_local)]
|
#![feature(cfg_target_thread_local)]
|
||||||
#![feature(cfi_encoding)]
|
#![feature(cfi_encoding)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
|
#![feature(const_float_methods)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(deprecated_suggestion)]
|
#![feature(deprecated_suggestion)]
|
||||||
#![feature(doc_cfg)]
|
#![feature(doc_cfg)]
|
||||||
|
|
|
@ -145,20 +145,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
this.write_scalar(Scalar::from_bool(branch), dest)?;
|
this.write_scalar(Scalar::from_bool(branch), dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floating-point operations
|
|
||||||
"fabsf32" => {
|
|
||||||
let [f] = check_arg_count(args)?;
|
|
||||||
let f = this.read_scalar(f)?.to_f32()?;
|
|
||||||
// This is a "bitwise" operation, so there's no NaN non-determinism.
|
|
||||||
this.write_scalar(Scalar::from_f32(f.abs()), dest)?;
|
|
||||||
}
|
|
||||||
"fabsf64" => {
|
|
||||||
let [f] = check_arg_count(args)?;
|
|
||||||
let f = this.read_scalar(f)?.to_f64()?;
|
|
||||||
// This is a "bitwise" operation, so there's no NaN non-determinism.
|
|
||||||
this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
|
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
|
||||||
let [f] = check_arg_count(args)?;
|
let [f] = check_arg_count(args)?;
|
||||||
let f = this.read_scalar(f)?.to_f32()?;
|
let f = this.read_scalar(f)?.to_f32()?;
|
||||||
|
@ -249,31 +235,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
this.write_scalar(res, dest)?;
|
this.write_scalar(res, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"minnumf32" | "maxnumf32" | "copysignf32" => {
|
|
||||||
let [a, b] = check_arg_count(args)?;
|
|
||||||
let a = this.read_scalar(a)?.to_f32()?;
|
|
||||||
let b = this.read_scalar(b)?.to_f32()?;
|
|
||||||
let res = match intrinsic_name {
|
|
||||||
"minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
|
|
||||||
"maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
|
|
||||||
"copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
|
|
||||||
_ => bug!(),
|
|
||||||
};
|
|
||||||
this.write_scalar(Scalar::from_f32(res), dest)?;
|
|
||||||
}
|
|
||||||
"minnumf64" | "maxnumf64" | "copysignf64" => {
|
|
||||||
let [a, b] = check_arg_count(args)?;
|
|
||||||
let a = this.read_scalar(a)?.to_f64()?;
|
|
||||||
let b = this.read_scalar(b)?.to_f64()?;
|
|
||||||
let res = match intrinsic_name {
|
|
||||||
"minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
|
|
||||||
"maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
|
|
||||||
"copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
|
|
||||||
_ => bug!(),
|
|
||||||
};
|
|
||||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"fmaf32" => {
|
"fmaf32" => {
|
||||||
let [a, b, c] = check_arg_count(args)?;
|
let [a, b, c] = check_arg_count(args)?;
|
||||||
let a = this.read_scalar(a)?.to_f32()?;
|
let a = this.read_scalar(a)?.to_f32()?;
|
||||||
|
|
|
@ -115,8 +115,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
nan
|
nan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_nan<F1: Float + FloatConvert<F2>, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 {
|
|
||||||
if f.is_nan() { self.generate_nan(inputs) } else { f }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
47
tests/ui/consts/const-eval/float_methods.rs
Normal file
47
tests/ui/consts/const-eval/float_methods.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//@ run-pass
|
||||||
|
//! Tests the float intrinsics: min, max, abs, copysign
|
||||||
|
|
||||||
|
#![feature(const_float_methods)]
|
||||||
|
#![feature(f16, f128)]
|
||||||
|
|
||||||
|
const F16_MIN: f16 = 1.0_f16.min(0.5_f16);
|
||||||
|
const F16_MAX: f16 = 1.0_f16.max(0.5_f16);
|
||||||
|
const F16_ABS: f16 = (-1.0_f16).abs();
|
||||||
|
const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16);
|
||||||
|
|
||||||
|
const F32_MIN: f32 = 1.0_f32.min(0.5_f32);
|
||||||
|
const F32_MAX: f32 = 1.0_f32.max(0.5_f32);
|
||||||
|
const F32_ABS: f32 = (-1.0_f32).abs();
|
||||||
|
const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32);
|
||||||
|
|
||||||
|
const F64_MIN: f64 = 1.0_f64.min(0.5_f64);
|
||||||
|
const F64_MAX: f64 = 1.0_f64.max(0.5_f64);
|
||||||
|
const F64_ABS: f64 = (-1.0_f64).abs();
|
||||||
|
const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64);
|
||||||
|
|
||||||
|
const F128_MIN: f128 = 1.0_f128.min(0.5_f128);
|
||||||
|
const F128_MAX: f128 = 1.0_f128.max(0.5_f128);
|
||||||
|
const F128_ABS: f128 = (-1.0_f128).abs();
|
||||||
|
const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(F16_MIN, 0.5);
|
||||||
|
assert_eq!(F16_MAX, 1.0);
|
||||||
|
assert_eq!(F16_ABS, 1.0);
|
||||||
|
assert_eq!(F16_COPYSIGN, -1.0);
|
||||||
|
|
||||||
|
assert_eq!(F32_MIN, 0.5);
|
||||||
|
assert_eq!(F32_MAX, 1.0);
|
||||||
|
assert_eq!(F32_ABS, 1.0);
|
||||||
|
assert_eq!(F32_COPYSIGN, -1.0);
|
||||||
|
|
||||||
|
assert_eq!(F64_MIN, 0.5);
|
||||||
|
assert_eq!(F64_MAX, 1.0);
|
||||||
|
assert_eq!(F64_ABS, 1.0);
|
||||||
|
assert_eq!(F64_COPYSIGN, -1.0);
|
||||||
|
|
||||||
|
assert_eq!(F128_MIN, 0.5);
|
||||||
|
assert_eq!(F128_MAX, 1.0);
|
||||||
|
assert_eq!(F128_ABS, 1.0);
|
||||||
|
assert_eq!(F128_COPYSIGN, -1.0);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue