Skip to content

Commit 15f1544

Browse files
committed
feat: make float rounding methods const
1 parent 02d6f96 commit 15f1544

File tree

12 files changed

+244
-124
lines changed

12 files changed

+244
-124
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,37 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
518518
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
519519
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
520520

521+
sym::floorf16 => self.float_floor_intrinsic::<Half>(args, dest)?,
522+
sym::floorf32 => self.float_floor_intrinsic::<Single>(args, dest)?,
523+
sym::floorf64 => self.float_floor_intrinsic::<Double>(args, dest)?,
524+
sym::floorf128 => self.float_floor_intrinsic::<Quad>(args, dest)?,
525+
526+
sym::ceilf16 => self.float_ceil_intrinsic::<Half>(args, dest)?,
527+
sym::ceilf32 => self.float_ceil_intrinsic::<Single>(args, dest)?,
528+
sym::ceilf64 => self.float_ceil_intrinsic::<Double>(args, dest)?,
529+
sym::ceilf128 => self.float_ceil_intrinsic::<Quad>(args, dest)?,
530+
531+
sym::truncf16 => self.float_trunc_intrinsic::<Half>(args, dest)?,
532+
sym::truncf32 => self.float_trunc_intrinsic::<Single>(args, dest)?,
533+
sym::truncf64 => self.float_trunc_intrinsic::<Double>(args, dest)?,
534+
sym::truncf128 => self.float_trunc_intrinsic::<Quad>(args, dest)?,
535+
536+
sym::roundf16 => self.float_round_intrinsic::<Half>(args, dest)?,
537+
sym::roundf32 => self.float_round_intrinsic::<Single>(args, dest)?,
538+
sym::roundf64 => self.float_round_intrinsic::<Double>(args, dest)?,
539+
sym::roundf128 => self.float_round_intrinsic::<Quad>(args, dest)?,
540+
541+
sym::round_ties_even_f16 => self.float_round_ties_even_intrinsic::<Half>(args, dest)?,
542+
sym::round_ties_even_f32 => {
543+
self.float_round_ties_even_intrinsic::<Single>(args, dest)?
544+
}
545+
sym::round_ties_even_f64 => {
546+
self.float_round_ties_even_intrinsic::<Double>(args, dest)?
547+
}
548+
sym::round_ties_even_f128 => {
549+
self.float_round_ties_even_intrinsic::<Quad>(args, dest)?
550+
}
551+
521552
// Unsupported intrinsic: skip the return_to_block below.
522553
_ => return interp_ok(false),
523554
}
@@ -900,4 +931,74 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
900931
self.write_scalar(x.abs(), dest)?;
901932
interp_ok(())
902933
}
934+
935+
fn float_floor_intrinsic<F>(
936+
&mut self,
937+
args: &[OpTy<'tcx, M::Provenance>],
938+
dest: &MPlaceTy<'tcx, M::Provenance>,
939+
) -> InterpResult<'tcx, ()>
940+
where
941+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
942+
{
943+
let x: F = self.read_scalar(&args[0])?.to_float()?;
944+
let res = x.round_to_integral(rustc_apfloat::Round::TowardNegative).value;
945+
self.write_scalar(res, dest)?;
946+
interp_ok(())
947+
}
948+
949+
fn float_ceil_intrinsic<F>(
950+
&mut self,
951+
args: &[OpTy<'tcx, M::Provenance>],
952+
dest: &MPlaceTy<'tcx, M::Provenance>,
953+
) -> InterpResult<'tcx, ()>
954+
where
955+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
956+
{
957+
let x: F = self.read_scalar(&args[0])?.to_float()?;
958+
let res = x.round_to_integral(rustc_apfloat::Round::TowardPositive).value;
959+
self.write_scalar(res, dest)?;
960+
interp_ok(())
961+
}
962+
963+
fn float_trunc_intrinsic<F>(
964+
&mut self,
965+
args: &[OpTy<'tcx, M::Provenance>],
966+
dest: &MPlaceTy<'tcx, M::Provenance>,
967+
) -> InterpResult<'tcx, ()>
968+
where
969+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
970+
{
971+
let x: F = self.read_scalar(&args[0])?.to_float()?;
972+
let res = x.round_to_integral(rustc_apfloat::Round::TowardZero).value;
973+
self.write_scalar(res, dest)?;
974+
interp_ok(())
975+
}
976+
977+
fn float_round_intrinsic<F>(
978+
&mut self,
979+
args: &[OpTy<'tcx, M::Provenance>],
980+
dest: &MPlaceTy<'tcx, M::Provenance>,
981+
) -> InterpResult<'tcx, ()>
982+
where
983+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
984+
{
985+
let x: F = self.read_scalar(&args[0])?.to_float()?;
986+
let res = x.round_to_integral(rustc_apfloat::Round::NearestTiesToAway).value;
987+
self.write_scalar(res, dest)?;
988+
interp_ok(())
989+
}
990+
991+
fn float_round_ties_even_intrinsic<F>(
992+
&mut self,
993+
args: &[OpTy<'tcx, M::Provenance>],
994+
dest: &MPlaceTy<'tcx, M::Provenance>,
995+
) -> InterpResult<'tcx, ()>
996+
where
997+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
998+
{
999+
let x: F = self.read_scalar(&args[0])?.to_float()?;
1000+
let res = x.round_to_integral(rustc_apfloat::Round::NearestTiesToEven).value;
1001+
self.write_scalar(res, dest)?;
1002+
interp_ok(())
1003+
}
9031004
}

library/core/src/intrinsics/mod.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,86 +2186,86 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
21862186
/// [`f16::floor`](../../std/primitive.f16.html#method.floor)
21872187
#[rustc_intrinsic]
21882188
#[rustc_nounwind]
2189-
pub unsafe fn floorf16(x: f16) -> f16;
2189+
pub const unsafe fn floorf16(x: f16) -> f16;
21902190
/// Returns the largest integer less than or equal to an `f32`.
21912191
///
21922192
/// The stabilized version of this intrinsic is
21932193
/// [`f32::floor`](../../std/primitive.f32.html#method.floor)
21942194
#[rustc_intrinsic]
21952195
#[rustc_nounwind]
2196-
pub unsafe fn floorf32(x: f32) -> f32;
2196+
pub const unsafe fn floorf32(x: f32) -> f32;
21972197
/// Returns the largest integer less than or equal to an `f64`.
21982198
///
21992199
/// The stabilized version of this intrinsic is
22002200
/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
22012201
#[rustc_intrinsic]
22022202
#[rustc_nounwind]
2203-
pub unsafe fn floorf64(x: f64) -> f64;
2203+
pub const unsafe fn floorf64(x: f64) -> f64;
22042204
/// Returns the largest integer less than or equal to an `f128`.
22052205
///
22062206
/// The stabilized version of this intrinsic is
22072207
/// [`f128::floor`](../../std/primitive.f128.html#method.floor)
22082208
#[rustc_intrinsic]
22092209
#[rustc_nounwind]
2210-
pub unsafe fn floorf128(x: f128) -> f128;
2210+
pub const unsafe fn floorf128(x: f128) -> f128;
22112211

22122212
/// Returns the smallest integer greater than or equal to an `f16`.
22132213
///
22142214
/// The stabilized version of this intrinsic is
22152215
/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
22162216
#[rustc_intrinsic]
22172217
#[rustc_nounwind]
2218-
pub unsafe fn ceilf16(x: f16) -> f16;
2218+
pub const unsafe fn ceilf16(x: f16) -> f16;
22192219
/// Returns the smallest integer greater than or equal to an `f32`.
22202220
///
22212221
/// The stabilized version of this intrinsic is
22222222
/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
22232223
#[rustc_intrinsic]
22242224
#[rustc_nounwind]
2225-
pub unsafe fn ceilf32(x: f32) -> f32;
2225+
pub const unsafe fn ceilf32(x: f32) -> f32;
22262226
/// Returns the smallest integer greater than or equal to an `f64`.
22272227
///
22282228
/// The stabilized version of this intrinsic is
22292229
/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
22302230
#[rustc_intrinsic]
22312231
#[rustc_nounwind]
2232-
pub unsafe fn ceilf64(x: f64) -> f64;
2232+
pub const unsafe fn ceilf64(x: f64) -> f64;
22332233
/// Returns the smallest integer greater than or equal to an `f128`.
22342234
///
22352235
/// The stabilized version of this intrinsic is
22362236
/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
22372237
#[rustc_intrinsic]
22382238
#[rustc_nounwind]
2239-
pub unsafe fn ceilf128(x: f128) -> f128;
2239+
pub const unsafe fn ceilf128(x: f128) -> f128;
22402240

22412241
/// Returns the integer part of an `f16`.
22422242
///
22432243
/// The stabilized version of this intrinsic is
22442244
/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
22452245
#[rustc_intrinsic]
22462246
#[rustc_nounwind]
2247-
pub unsafe fn truncf16(x: f16) -> f16;
2247+
pub const unsafe fn truncf16(x: f16) -> f16;
22482248
/// Returns the integer part of an `f32`.
22492249
///
22502250
/// The stabilized version of this intrinsic is
22512251
/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
22522252
#[rustc_intrinsic]
22532253
#[rustc_nounwind]
2254-
pub unsafe fn truncf32(x: f32) -> f32;
2254+
pub const unsafe fn truncf32(x: f32) -> f32;
22552255
/// Returns the integer part of an `f64`.
22562256
///
22572257
/// The stabilized version of this intrinsic is
22582258
/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
22592259
#[rustc_intrinsic]
22602260
#[rustc_nounwind]
2261-
pub unsafe fn truncf64(x: f64) -> f64;
2261+
pub const unsafe fn truncf64(x: f64) -> f64;
22622262
/// Returns the integer part of an `f128`.
22632263
///
22642264
/// The stabilized version of this intrinsic is
22652265
/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
22662266
#[rustc_intrinsic]
22672267
#[rustc_nounwind]
2268-
pub unsafe fn truncf128(x: f128) -> f128;
2268+
pub const unsafe fn truncf128(x: f128) -> f128;
22692269

22702270
/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even
22712271
/// least significant digit.
@@ -2274,7 +2274,7 @@ pub unsafe fn truncf128(x: f128) -> f128;
22742274
/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
22752275
#[rustc_intrinsic]
22762276
#[rustc_nounwind]
2277-
pub fn round_ties_even_f16(x: f16) -> f16;
2277+
pub const fn round_ties_even_f16(x: f16) -> f16;
22782278

22792279
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even
22802280
/// least significant digit.
@@ -2283,10 +2283,11 @@ pub fn round_ties_even_f16(x: f16) -> f16;
22832283
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
22842284
#[rustc_intrinsic]
22852285
#[rustc_nounwind]
2286-
pub fn round_ties_even_f32(x: f32) -> f32;
2286+
pub const fn round_ties_even_f32(x: f32) -> f32;
22872287

22882288
/// Provided for compatibility with stdarch. DO NOT USE.
22892289
#[inline(always)]
2290+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
22902291
pub unsafe fn rintf32(x: f32) -> f32 {
22912292
round_ties_even_f32(x)
22922293
}
@@ -2298,11 +2299,12 @@ pub unsafe fn rintf32(x: f32) -> f32 {
22982299
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
22992300
#[rustc_intrinsic]
23002301
#[rustc_nounwind]
2301-
pub fn round_ties_even_f64(x: f64) -> f64;
2302+
pub const fn round_ties_even_f64(x: f64) -> f64;
23022303

23032304
/// Provided for compatibility with stdarch. DO NOT USE.
23042305
#[inline(always)]
2305-
pub unsafe fn rintf64(x: f64) -> f64 {
2306+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
2307+
pub const unsafe fn rintf64(x: f64) -> f64 {
23062308
round_ties_even_f64(x)
23072309
}
23082310

@@ -2313,36 +2315,36 @@ pub unsafe fn rintf64(x: f64) -> f64 {
23132315
/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
23142316
#[rustc_intrinsic]
23152317
#[rustc_nounwind]
2316-
pub fn round_ties_even_f128(x: f128) -> f128;
2318+
pub const fn round_ties_even_f128(x: f128) -> f128;
23172319

23182320
/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
23192321
///
23202322
/// The stabilized version of this intrinsic is
23212323
/// [`f16::round`](../../std/primitive.f16.html#method.round)
23222324
#[rustc_intrinsic]
23232325
#[rustc_nounwind]
2324-
pub unsafe fn roundf16(x: f16) -> f16;
2326+
pub const unsafe fn roundf16(x: f16) -> f16;
23252327
/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
23262328
///
23272329
/// The stabilized version of this intrinsic is
23282330
/// [`f32::round`](../../std/primitive.f32.html#method.round)
23292331
#[rustc_intrinsic]
23302332
#[rustc_nounwind]
2331-
pub unsafe fn roundf32(x: f32) -> f32;
2333+
pub const unsafe fn roundf32(x: f32) -> f32;
23322334
/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
23332335
///
23342336
/// The stabilized version of this intrinsic is
23352337
/// [`f64::round`](../../std/primitive.f64.html#method.round)
23362338
#[rustc_intrinsic]
23372339
#[rustc_nounwind]
2338-
pub unsafe fn roundf64(x: f64) -> f64;
2340+
pub const unsafe fn roundf64(x: f64) -> f64;
23392341
/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
23402342
///
23412343
/// The stabilized version of this intrinsic is
23422344
/// [`f128::round`](../../std/primitive.f128.html#method.round)
23432345
#[rustc_intrinsic]
23442346
#[rustc_nounwind]
2345-
pub unsafe fn roundf128(x: f128) -> f128;
2347+
pub const unsafe fn roundf128(x: f128) -> f128;
23462348

23472349
/// Float addition that allows optimizations based on algebraic rules.
23482350
/// May assume inputs are finite.

library/core/src/num/f128.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,8 @@ impl f128 {
14481448
#[rustc_allow_incoherent_impl]
14491449
#[unstable(feature = "f128", issue = "116909")]
14501450
#[must_use = "method returns a new number and does not mutate the original value"]
1451-
pub fn floor(self) -> f128 {
1451+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
1452+
pub const fn floor(self) -> f128 {
14521453
// SAFETY: intrinsic with no preconditions
14531454
unsafe { intrinsics::floorf128(self) }
14541455
}
@@ -1478,7 +1479,8 @@ impl f128 {
14781479
#[rustc_allow_incoherent_impl]
14791480
#[unstable(feature = "f128", issue = "116909")]
14801481
#[must_use = "method returns a new number and does not mutate the original value"]
1481-
pub fn ceil(self) -> f128 {
1482+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
1483+
pub const fn ceil(self) -> f128 {
14821484
// SAFETY: intrinsic with no preconditions
14831485
unsafe { intrinsics::ceilf128(self) }
14841486
}
@@ -1514,7 +1516,8 @@ impl f128 {
15141516
#[rustc_allow_incoherent_impl]
15151517
#[unstable(feature = "f128", issue = "116909")]
15161518
#[must_use = "method returns a new number and does not mutate the original value"]
1517-
pub fn round(self) -> f128 {
1519+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
1520+
pub const fn round(self) -> f128 {
15181521
// SAFETY: intrinsic with no preconditions
15191522
unsafe { intrinsics::roundf128(self) }
15201523
}
@@ -1548,7 +1551,8 @@ impl f128 {
15481551
#[rustc_allow_incoherent_impl]
15491552
#[unstable(feature = "f128", issue = "116909")]
15501553
#[must_use = "method returns a new number and does not mutate the original value"]
1551-
pub fn round_ties_even(self) -> f128 {
1554+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
1555+
pub const fn round_ties_even(self) -> f128 {
15521556
intrinsics::round_ties_even_f128(self)
15531557
}
15541558

@@ -1580,7 +1584,8 @@ impl f128 {
15801584
#[rustc_allow_incoherent_impl]
15811585
#[unstable(feature = "f128", issue = "116909")]
15821586
#[must_use = "method returns a new number and does not mutate the original value"]
1583-
pub fn trunc(self) -> f128 {
1587+
#[rustc_allow_const_fn_unstable(core_intrinsics)]
1588+
pub const fn trunc(self) -> f128 {
15841589
// SAFETY: intrinsic with no preconditions
15851590
unsafe { intrinsics::truncf128(self) }
15861591
}
@@ -1611,7 +1616,7 @@ impl f128 {
16111616
#[rustc_allow_incoherent_impl]
16121617
#[unstable(feature = "f128", issue = "116909")]
16131618
#[must_use = "method returns a new number and does not mutate the original value"]
1614-
pub fn fract(self) -> f128 {
1619+
pub const fn fract(self) -> f128 {
16151620
self - self.trunc()
16161621
}
16171622

0 commit comments

Comments
 (0)