Skip to content

Commit be681fe

Browse files
Add round_ties_even to f32 and f64
1 parent e1c9121 commit be681fe

File tree

12 files changed

+127
-0
lines changed

12 files changed

+127
-0
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ fn codegen_float_intrinsic_call<'tcx>(
297297
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64),
298298
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32),
299299
sym::roundf64 => ("round", 1, fx.tcx.types.f64),
300+
sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32),
301+
sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64),
300302
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32),
301303
sym::sinf64 => ("sin", 1, fx.tcx.types.f64),
302304
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32),

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
6868
sym::nearbyintf64 => "nearbyint",
6969
sym::roundf32 => "roundf",
7070
sym::roundf64 => "round",
71+
sym::roundevenf32 => "roundevenf",
72+
sym::roundevenf64 => "roundeven",
7173
sym::abort => "abort",
7274
_ => return None,
7375
};

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,13 @@ impl<'ll> CodegenCx<'ll, '_> {
745745

746746
ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
747747
ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
748+
748749
ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
749750
ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
750751

752+
ifn!("llvm.roundeven.f32", fn(t_f32) -> t_f32);
753+
ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);
754+
751755
ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
752756
ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
753757
ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ fn get_simple_intrinsic<'ll>(
7272
sym::roundf32 => "llvm.round.f32",
7373
sym::roundf64 => "llvm.round.f64",
7474
sym::ptr_mask => "llvm.ptrmask",
75+
sym::roundevenf32 => "llvm.roundeven.f32",
76+
sym::roundevenf64 => "llvm.roundeven.f64",
7577
_ => return None,
7678
};
7779
Some(cx.get_intrinsic(llvm_name))

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
300300
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
301301
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
302302
sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
303+
sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32),
304+
sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),
303305

304306
sym::volatile_load | sym::unaligned_volatile_load => {
305307
(1, vec![tcx.mk_imm_ptr(param(0))], param(0))

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,8 @@ symbols! {
11791179
rlib,
11801180
rotate_left,
11811181
rotate_right,
1182+
roundevenf32,
1183+
roundevenf64,
11821184
roundf32,
11831185
roundf64,
11841186
rt,

library/core/src/intrinsics.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,22 @@ extern "rust-intrinsic" {
16131613
/// [`f64::round`](../../std/primitive.f64.html#method.round)
16141614
pub fn roundf64(x: f64) -> f64;
16151615

1616+
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
1617+
/// with an even least significant digit.
1618+
///
1619+
/// The stabilized version of this intrinsic is
1620+
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
1621+
#[cfg(not(bootstrap))]
1622+
pub fn roundevenf32(x: f32) -> f32;
1623+
1624+
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
1625+
/// with an even least significant digit.
1626+
///
1627+
/// The stabilized version of this intrinsic is
1628+
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
1629+
#[cfg(not(bootstrap))]
1630+
pub fn roundevenf64(x: f64) -> f64;
1631+
16161632
/// Float addition that allows optimizations based on algebraic rules.
16171633
/// May assume inputs are finite.
16181634
///

library/std/src/f32.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,14 @@ impl f32 {
7878
/// let f = 3.3_f32;
7979
/// let g = -3.3_f32;
8080
/// let h = -3.7_f32;
81+
/// let i = 3.5_f32;
82+
/// let j = 4.5_f32;
8183
///
8284
/// assert_eq!(f.round(), 3.0);
8385
/// assert_eq!(g.round(), -3.0);
8486
/// assert_eq!(h.round(), -4.0);
87+
/// assert_eq!(i.round(), 4.0);
88+
/// assert_eq!(j.round(), 5.0);
8589
/// ```
8690
#[rustc_allow_incoherent_impl]
8791
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -91,6 +95,33 @@ impl f32 {
9195
unsafe { intrinsics::roundf32(self) }
9296
}
9397

98+
/// Returns the nearest integer to a number. Rounds half-way cases to the number
99+
/// with an even least significant digit.
100+
///
101+
/// # Examples
102+
///
103+
/// ```
104+
/// #![feature(round_ties_even)]
105+
///
106+
/// let f = 3.3_f32;
107+
/// let g = -3.3_f32;
108+
/// let h = 3.5_f32;
109+
/// let i = 4.5_f32;
110+
///
111+
/// assert_eq!(f.round_ties_even(), 3.0);
112+
/// assert_eq!(g.round_ties_even(), -3.0);
113+
/// assert_eq!(h.round_ties_even(), 4.0);
114+
/// assert_eq!(i.round_ties_even(), 4.0);
115+
/// ```
116+
#[cfg(not(bootstrap))]
117+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
118+
#[must_use = "method returns a new number and does not mutate the original value"]
119+
#[unstable(feature = "round_ties_even", issue = "none")]
120+
#[inline]
121+
pub fn round_ties_even(self) -> f32 {
122+
unsafe { intrinsics::roundevenf32(self) }
123+
}
124+
94125
/// Returns the integer part of `self`.
95126
/// This means that non-integer numbers are always truncated towards zero.
96127
///

library/std/src/f32/tests.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ fn test_ceil() {
209209

210210
#[test]
211211
fn test_round() {
212+
assert_approx_eq!(2.5f32.round(), 3.0f32);
212213
assert_approx_eq!(1.0f32.round(), 1.0f32);
213214
assert_approx_eq!(1.3f32.round(), 1.0f32);
214215
assert_approx_eq!(1.5f32.round(), 2.0f32);
@@ -221,6 +222,22 @@ fn test_round() {
221222
assert_approx_eq!((-1.7f32).round(), -2.0f32);
222223
}
223224

225+
#[cfg(not(bootstrap))]
226+
#[test]
227+
fn test_round_ties_even() {
228+
assert_approx_eq!(2.5f32.round_ties_even(), 2.0f32);
229+
assert_approx_eq!(1.0f32.round_ties_even(), 1.0f32);
230+
assert_approx_eq!(1.3f32.round_ties_even(), 1.0f32);
231+
assert_approx_eq!(1.5f32.round_ties_even(), 2.0f32);
232+
assert_approx_eq!(1.7f32.round_ties_even(), 2.0f32);
233+
assert_approx_eq!(0.0f32.round_ties_even(), 0.0f32);
234+
assert_approx_eq!((-0.0f32).round_ties_even(), -0.0f32);
235+
assert_approx_eq!((-1.0f32).round_ties_even(), -1.0f32);
236+
assert_approx_eq!((-1.3f32).round_ties_even(), -1.0f32);
237+
assert_approx_eq!((-1.5f32).round_ties_even(), -2.0f32);
238+
assert_approx_eq!((-1.7f32).round_ties_even(), -2.0f32);
239+
}
240+
224241
#[test]
225242
fn test_trunc() {
226243
assert_approx_eq!(1.0f32.trunc(), 1.0f32);

library/std/src/f64.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,14 @@ impl f64 {
7878
/// let f = 3.3_f64;
7979
/// let g = -3.3_f64;
8080
/// let h = -3.7_f64;
81+
/// let i = 3.5_f64;
82+
/// let j = 4.5_f64;
8183
///
8284
/// assert_eq!(f.round(), 3.0);
8385
/// assert_eq!(g.round(), -3.0);
8486
/// assert_eq!(h.round(), -4.0);
87+
/// assert_eq!(i.round(), 4.0);
88+
/// assert_eq!(j.round(), 5.0);
8589
/// ```
8690
#[rustc_allow_incoherent_impl]
8791
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -91,6 +95,33 @@ impl f64 {
9195
unsafe { intrinsics::roundf64(self) }
9296
}
9397

98+
/// Returns the nearest integer to a number. Rounds half-way cases to the number
99+
/// with an even least significant digit.
100+
///
101+
/// # Examples
102+
///
103+
/// ```
104+
/// #![feature(round_ties_even)]
105+
///
106+
/// let f = 3.3_f64;
107+
/// let g = -3.3_f64;
108+
/// let h = 3.5_f64;
109+
/// let i = 4.5_f64;
110+
///
111+
/// assert_eq!(f.round_ties_even(), 3.0);
112+
/// assert_eq!(g.round_ties_even(), -3.0);
113+
/// assert_eq!(h.round_ties_even(), 4.0);
114+
/// assert_eq!(i.round_ties_even(), 4.0);
115+
/// ```
116+
#[cfg(not(bootstrap))]
117+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
118+
#[must_use = "method returns a new number and does not mutate the original value"]
119+
#[unstable(feature = "round_ties_even", issue = "none")]
120+
#[inline]
121+
pub fn round_ties_even(self) -> f64 {
122+
unsafe { intrinsics::roundevenf64(self) }
123+
}
124+
94125
/// Returns the integer part of `self`.
95126
/// This means that non-integer numbers are always truncated towards zero.
96127
///

library/std/src/f64/tests.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ fn test_ceil() {
199199

200200
#[test]
201201
fn test_round() {
202+
assert_approx_eq!(2.5f64.round(), 3.0f64);
202203
assert_approx_eq!(1.0f64.round(), 1.0f64);
203204
assert_approx_eq!(1.3f64.round(), 1.0f64);
204205
assert_approx_eq!(1.5f64.round(), 2.0f64);
@@ -211,6 +212,22 @@ fn test_round() {
211212
assert_approx_eq!((-1.7f64).round(), -2.0f64);
212213
}
213214

215+
#[cfg(not(bootstrap))]
216+
#[test]
217+
fn test_round_ties_even() {
218+
assert_approx_eq!(2.5f64.round_ties_even(), 2.0f64);
219+
assert_approx_eq!(1.0f64.round_ties_even(), 1.0f64);
220+
assert_approx_eq!(1.3f64.round_ties_even(), 1.0f64);
221+
assert_approx_eq!(1.5f64.round_ties_even(), 2.0f64);
222+
assert_approx_eq!(1.7f64.round_ties_even(), 2.0f64);
223+
assert_approx_eq!(0.0f64.round_ties_even(), 0.0f64);
224+
assert_approx_eq!((-0.0f64).round_ties_even(), -0.0f64);
225+
assert_approx_eq!((-1.0f64).round_ties_even(), -1.0f64);
226+
assert_approx_eq!((-1.3f64).round_ties_even(), -1.0f64);
227+
assert_approx_eq!((-1.5f64).round_ties_even(), -2.0f64);
228+
assert_approx_eq!((-1.7f64).round_ties_even(), -2.0f64);
229+
}
230+
214231
#[test]
215232
fn test_trunc() {
216233
assert_approx_eq!(1.0f64.trunc(), 1.0f64);

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@
307307
#![feature(provide_any)]
308308
#![feature(ptr_as_uninit)]
309309
#![feature(raw_os_nonzero)]
310+
#![cfg_attr(not(bootstrap), feature(round_ties_even))]
310311
#![feature(slice_internals)]
311312
#![feature(slice_ptr_get)]
312313
#![feature(std_internals)]

0 commit comments

Comments
 (0)