Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add round_ties_even to f32 and f64 #95317

Merged
merged 4 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,12 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64),
sym::truncf32 => ("truncf", 1, fx.tcx.types.f32),
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64),
sym::rintf32 => ("rintf", 1, fx.tcx.types.f32),
sym::rintf64 => ("rint", 1, fx.tcx.types.f64),
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32),
sym::roundf64 => ("round", 1, fx.tcx.types.f64),
sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32),
sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
sym::nearbyintf64 => "nearbyint",
sym::roundf32 => "roundf",
sym::roundf64 => "round",
sym::roundevenf32 => "roundevenf",
sym::roundevenf64 => "roundeven",
sym::abort => "abort",
_ => return None,
};
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,9 +745,13 @@ impl<'ll> CodegenCx<'ll, '_> {

ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);

ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
ifn!("llvm.round.f64", fn(t_f64) -> t_f64);

ifn!("llvm.roundeven.f32", fn(t_f32) -> t_f32);
ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);

ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ fn get_simple_intrinsic<'ll>(
sym::roundf32 => "llvm.round.f32",
sym::roundf64 => "llvm.round.f64",
sym::ptr_mask => "llvm.ptrmask",
sym::roundevenf32 => "llvm.roundeven.f32",
sym::roundevenf64 => "llvm.roundeven.f64",
_ => return None,
};
Some(cx.get_intrinsic(llvm_name))
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),

sym::volatile_load | sym::unaligned_volatile_load => {
(1, vec![tcx.mk_imm_ptr(param(0))], param(0))
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,8 @@ symbols! {
rlib,
rotate_left,
rotate_right,
roundevenf32,
roundevenf64,
roundf32,
roundf64,
rt,
Expand Down
19 changes: 19 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1588,9 +1588,15 @@ extern "rust-intrinsic" {

/// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception
/// if the argument is not an integer.
///
/// The stabilized version of this intrinsic is
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
pub fn rintf32(x: f32) -> f32;
/// Returns the nearest integer to an `f64`. May raise an inexact floating-point exception
/// if the argument is not an integer.
///
/// The stabilized version of this intrinsic is
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
pub fn rintf64(x: f64) -> f64;

/// Returns the nearest integer to an `f32`.
Expand All @@ -1613,6 +1619,19 @@ extern "rust-intrinsic" {
/// [`f64::round`](../../std/primitive.f64.html#method.round)
pub fn roundf64(x: f64) -> f64;

/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[cfg(not(bootstrap))]
pub fn roundevenf32(x: f32) -> f32;
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[cfg(not(bootstrap))]
pub fn roundevenf64(x: f64) -> f64;

/// Float addition that allows optimizations based on algebraic rules.
/// May assume inputs are finite.
///
Expand Down
30 changes: 30 additions & 0 deletions library/std/src/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,14 @@ impl f32 {
/// let f = 3.3_f32;
/// let g = -3.3_f32;
/// let h = -3.7_f32;
/// let i = 3.5_f32;
/// let j = 4.5_f32;
///
/// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0);
/// assert_eq!(h.round(), -4.0);
/// assert_eq!(i.round(), 4.0);
/// assert_eq!(j.round(), 5.0);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
Expand All @@ -91,6 +95,32 @@ impl f32 {
unsafe { intrinsics::roundf32(self) }
}

/// Returns the nearest integer to a number. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// # Examples
///
/// ```
/// #![feature(round_ties_even)]
///
/// let f = 3.3_f32;
/// let g = -3.3_f32;
/// let h = 3.5_f32;
/// let i = 4.5_f32;
///
/// assert_eq!(f.round_ties_even(), 3.0);
/// assert_eq!(g.round_ties_even(), -3.0);
/// assert_eq!(h.round_ties_even(), 4.0);
/// assert_eq!(i.round_ties_even(), 4.0);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "round_ties_even", issue = "96710")]
#[inline]
pub fn round_ties_even(self) -> f32 {
unsafe { intrinsics::rintf32(self) }
}

/// Returns the integer part of `self`.
/// This means that non-integer numbers are always truncated towards zero.
///
Expand Down
16 changes: 16 additions & 0 deletions library/std/src/f32/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ fn test_ceil() {

#[test]
fn test_round() {
assert_approx_eq!(2.5f32.round(), 3.0f32);
assert_approx_eq!(1.0f32.round(), 1.0f32);
assert_approx_eq!(1.3f32.round(), 1.0f32);
assert_approx_eq!(1.5f32.round(), 2.0f32);
Expand All @@ -221,6 +222,21 @@ fn test_round() {
assert_approx_eq!((-1.7f32).round(), -2.0f32);
}

#[test]
fn test_round_ties_even() {
assert_approx_eq!(2.5f32.round_ties_even(), 2.0f32);
assert_approx_eq!(1.0f32.round_ties_even(), 1.0f32);
assert_approx_eq!(1.3f32.round_ties_even(), 1.0f32);
assert_approx_eq!(1.5f32.round_ties_even(), 2.0f32);
assert_approx_eq!(1.7f32.round_ties_even(), 2.0f32);
assert_approx_eq!(0.0f32.round_ties_even(), 0.0f32);
assert_approx_eq!((-0.0f32).round_ties_even(), -0.0f32);
assert_approx_eq!((-1.0f32).round_ties_even(), -1.0f32);
assert_approx_eq!((-1.3f32).round_ties_even(), -1.0f32);
assert_approx_eq!((-1.5f32).round_ties_even(), -2.0f32);
assert_approx_eq!((-1.7f32).round_ties_even(), -2.0f32);
}

#[test]
fn test_trunc() {
assert_approx_eq!(1.0f32.trunc(), 1.0f32);
Expand Down
30 changes: 30 additions & 0 deletions library/std/src/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,14 @@ impl f64 {
/// let f = 3.3_f64;
/// let g = -3.3_f64;
/// let h = -3.7_f64;
/// let i = 3.5_f64;
/// let j = 4.5_f64;
///
/// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0);
/// assert_eq!(h.round(), -4.0);
/// assert_eq!(i.round(), 4.0);
/// assert_eq!(j.round(), 5.0);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
Expand All @@ -91,6 +95,32 @@ impl f64 {
unsafe { intrinsics::roundf64(self) }
}

/// Returns the nearest integer to a number. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// # Examples
///
/// ```
/// #![feature(round_ties_even)]
///
/// let f = 3.3_f64;
/// let g = -3.3_f64;
/// let h = 3.5_f64;
/// let i = 4.5_f64;
///
/// assert_eq!(f.round_ties_even(), 3.0);
/// assert_eq!(g.round_ties_even(), -3.0);
/// assert_eq!(h.round_ties_even(), 4.0);
/// assert_eq!(i.round_ties_even(), 4.0);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "round_ties_even", issue = "96710")]
#[inline]
pub fn round_ties_even(self) -> f64 {
unsafe { intrinsics::rintf64(self) }
}

/// Returns the integer part of `self`.
/// This means that non-integer numbers are always truncated towards zero.
///
Expand Down
16 changes: 16 additions & 0 deletions library/std/src/f64/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ fn test_ceil() {

#[test]
fn test_round() {
assert_approx_eq!(2.5f64.round(), 3.0f64);
assert_approx_eq!(1.0f64.round(), 1.0f64);
assert_approx_eq!(1.3f64.round(), 1.0f64);
assert_approx_eq!(1.5f64.round(), 2.0f64);
Expand All @@ -211,6 +212,21 @@ fn test_round() {
assert_approx_eq!((-1.7f64).round(), -2.0f64);
}

#[test]
fn test_round_ties_even() {
assert_approx_eq!(2.5f64.round_ties_even(), 2.0f64);
assert_approx_eq!(1.0f64.round_ties_even(), 1.0f64);
assert_approx_eq!(1.3f64.round_ties_even(), 1.0f64);
assert_approx_eq!(1.5f64.round_ties_even(), 2.0f64);
assert_approx_eq!(1.7f64.round_ties_even(), 2.0f64);
assert_approx_eq!(0.0f64.round_ties_even(), 0.0f64);
assert_approx_eq!((-0.0f64).round_ties_even(), -0.0f64);
assert_approx_eq!((-1.0f64).round_ties_even(), -1.0f64);
assert_approx_eq!((-1.3f64).round_ties_even(), -1.0f64);
assert_approx_eq!((-1.5f64).round_ties_even(), -2.0f64);
assert_approx_eq!((-1.7f64).round_ties_even(), -2.0f64);
}

#[test]
fn test_trunc() {
assert_approx_eq!(1.0f64.trunc(), 1.0f64);
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
#![feature(provide_any)]
#![feature(ptr_as_uninit)]
#![feature(raw_os_nonzero)]
#![feature(round_ties_even)]
#![feature(slice_internals)]
#![feature(slice_ptr_get)]
#![feature(std_internals)]
Expand Down