Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit c2bf953

Browse files
committed
Add roundeven{,f,f16,f128}
C23 specifies a new set of `roundeven` functions that round to the nearest integral, with ties to even. It does not raise any floating point exceptions. This behavior is similar to two other functions: 1. `rint`, which rounds to the nearest integer respecting rounding mode and possibly raising exceptions. 2. `nearbyint`, which is identical to `rint` except it may not raise exceptions. Technically `rint`, `nearbyint`, and `roundeven` all behave the same in Rust because we assume default floating point environment. The backends are allowed to lower to `roundeven`, however, so we should provide it in case the fallback is needed. Add the `roundeven` family here and convert `rint` to a function that takes a rounding mode. This currently has no effect.
1 parent 913256d commit c2bf953

20 files changed

+363
-101
lines changed

crates/libm-macros/src/shared.rs

+94-10
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,60 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
99
FloatTy::F16,
1010
Signature { args: &[Ty::F16], returns: &[Ty::F16] },
1111
None,
12-
&["ceilf16", "fabsf16", "floorf16", "rintf16", "roundf16", "sqrtf16", "truncf16"],
12+
&[
13+
"ceilf16",
14+
"fabsf16",
15+
"floorf16",
16+
"rintf16",
17+
"roundevenf16",
18+
"roundf16",
19+
"sqrtf16",
20+
"truncf16",
21+
],
1322
),
1423
(
1524
// `fn(f32) -> f32`
1625
FloatTy::F32,
1726
Signature { args: &[Ty::F32], returns: &[Ty::F32] },
1827
None,
1928
&[
20-
"acosf", "acoshf", "asinf", "asinhf", "atanf", "atanhf", "cbrtf", "ceilf", "cosf",
21-
"coshf", "erfcf", "erff", "exp10f", "exp2f", "expf", "expm1f", "fabsf", "floorf",
22-
"j0f", "j1f", "lgammaf", "log10f", "log1pf", "log2f", "logf", "rintf", "roundf",
23-
"sinf", "sinhf", "sqrtf", "tanf", "tanhf", "tgammaf", "truncf", "y0f", "y1f",
29+
"acosf",
30+
"acoshf",
31+
"asinf",
32+
"asinhf",
33+
"atanf",
34+
"atanhf",
35+
"cbrtf",
36+
"ceilf",
37+
"cosf",
38+
"coshf",
39+
"erfcf",
40+
"erff",
41+
"exp10f",
42+
"exp2f",
43+
"expf",
44+
"expm1f",
45+
"fabsf",
46+
"floorf",
47+
"j0f",
48+
"j1f",
49+
"lgammaf",
50+
"log10f",
51+
"log1pf",
52+
"log2f",
53+
"logf",
54+
"rintf",
55+
"roundevenf",
56+
"roundf",
57+
"sinf",
58+
"sinhf",
59+
"sqrtf",
60+
"tanf",
61+
"tanhf",
62+
"tgammaf",
63+
"truncf",
64+
"y0f",
65+
"y1f",
2466
],
2567
),
2668
(
@@ -29,18 +71,60 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
2971
Signature { args: &[Ty::F64], returns: &[Ty::F64] },
3072
None,
3173
&[
32-
"acos", "acosh", "asin", "asinh", "atan", "atanh", "cbrt", "ceil", "cos", "cosh",
33-
"erf", "erfc", "exp", "exp10", "exp2", "expm1", "fabs", "floor", "j0", "j1", "lgamma",
34-
"log", "log10", "log1p", "log2", "rint", "round", "sin", "sinh", "sqrt", "tan", "tanh",
35-
"tgamma", "trunc", "y0", "y1",
74+
"acos",
75+
"acosh",
76+
"asin",
77+
"asinh",
78+
"atan",
79+
"atanh",
80+
"cbrt",
81+
"ceil",
82+
"cos",
83+
"cosh",
84+
"erf",
85+
"erfc",
86+
"exp",
87+
"exp10",
88+
"exp2",
89+
"expm1",
90+
"fabs",
91+
"floor",
92+
"j0",
93+
"j1",
94+
"lgamma",
95+
"log",
96+
"log10",
97+
"log1p",
98+
"log2",
99+
"rint",
100+
"round",
101+
"roundeven",
102+
"sin",
103+
"sinh",
104+
"sqrt",
105+
"tan",
106+
"tanh",
107+
"tgamma",
108+
"trunc",
109+
"y0",
110+
"y1",
36111
],
37112
),
38113
(
39114
// `fn(f128) -> f128`
40115
FloatTy::F128,
41116
Signature { args: &[Ty::F128], returns: &[Ty::F128] },
42117
None,
43-
&["ceilf128", "fabsf128", "floorf128", "rintf128", "roundf128", "sqrtf128", "truncf128"],
118+
&[
119+
"ceilf128",
120+
"fabsf128",
121+
"floorf128",
122+
"rintf128",
123+
"roundevenf128",
124+
"roundf128",
125+
"sqrtf128",
126+
"truncf128",
127+
],
44128
),
45129
(
46130
// `(f16, f16) -> f16`

crates/libm-test/benches/icount.rs

+4
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ main!(
274274
icount_bench_rintf16_group,
275275
icount_bench_rintf_group,
276276
icount_bench_round_group,
277+
icount_bench_roundeven_group,
278+
icount_bench_roundevenf128_group,
279+
icount_bench_roundevenf16_group,
280+
icount_bench_roundevenf_group,
277281
icount_bench_roundf128_group,
278282
icount_bench_roundf16_group,
279283
icount_bench_roundf_group,

crates/libm-test/benches/random.rs

+4
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ libm_macros::for_each_function! {
154154
| ldexpf16
155155
| rintf128
156156
| rintf16
157+
| roundeven
158+
| roundevenf
159+
| roundevenf128
160+
| roundevenf16
157161
| roundf128
158162
| roundf16
159163
| scalbnf128

crates/libm-test/src/domain.rs

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ pub fn get_domain<F: Float, I: Int>(
246246
BaseName::Remquo => &EitherPrim::UNBOUNDED2[..],
247247
BaseName::Rint => &EitherPrim::UNBOUNDED1[..],
248248
BaseName::Round => &EitherPrim::UNBOUNDED1[..],
249+
BaseName::Roundeven => &EitherPrim::UNBOUNDED1[..],
249250
BaseName::Scalbn => &EitherPrim::UNBOUNDED_F_I[..],
250251
BaseName::Sin => &EitherPrim::TRIG[..],
251252
BaseName::Sincos => &EitherPrim::TRIG[..],

crates/libm-test/src/gen/case_list.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//!
77
//! This is useful for adding regression tests or expected failures.
88
9+
use libm::hf64;
910
#[cfg(f128_enabled)]
1011
use libm::hf128;
1112

@@ -574,7 +575,15 @@ fn remquof_cases() -> Vec<TestCase<op::remquof::Routine>> {
574575
}
575576

576577
fn rint_cases() -> Vec<TestCase<op::rint::Routine>> {
577-
vec![]
578+
let mut v = vec![];
579+
TestCase::append_pairs(
580+
&mut v,
581+
&[
582+
// Failure on i586
583+
((hf64!("-0x1.e3f13ff995ffcp+38"),), Some(hf64!("-0x1.e3f13ff994000p+38"))),
584+
],
585+
);
586+
v
578587
}
579588

580589
fn rintf_cases() -> Vec<TestCase<op::rintf::Routine>> {
@@ -591,6 +600,11 @@ fn rintf16_cases() -> Vec<TestCase<op::rintf16::Routine>> {
591600
vec![]
592601
}
593602

603+
#[cfg(f16_enabled)]
604+
fn roundf16_cases() -> Vec<TestCase<op::roundf16::Routine>> {
605+
vec![]
606+
}
607+
594608
fn round_cases() -> Vec<TestCase<op::round::Routine>> {
595609
vec![]
596610
}
@@ -605,7 +619,28 @@ fn roundf128_cases() -> Vec<TestCase<op::roundf128::Routine>> {
605619
}
606620

607621
#[cfg(f16_enabled)]
608-
fn roundf16_cases() -> Vec<TestCase<op::roundf16::Routine>> {
622+
fn roundevenf16_cases() -> Vec<TestCase<op::roundevenf16::Routine>> {
623+
vec![]
624+
}
625+
626+
fn roundeven_cases() -> Vec<TestCase<op::roundeven::Routine>> {
627+
let mut v = vec![];
628+
TestCase::append_pairs(
629+
&mut v,
630+
&[
631+
// Failure on i586
632+
((hf64!("-0x1.e3f13ff995ffcp+38"),), Some(hf64!("-0x1.e3f13ff994000p+38"))),
633+
],
634+
);
635+
v
636+
}
637+
638+
fn roundevenf_cases() -> Vec<TestCase<op::roundevenf::Routine>> {
639+
vec![]
640+
}
641+
642+
#[cfg(f128_enabled)]
643+
fn roundevenf128_cases() -> Vec<TestCase<op::roundevenf128::Routine>> {
609644
vec![]
610645
}
611646

crates/libm-test/src/mpfloat.rs

+8
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ libm_macros::for_each_function! {
184184
rintf128,
185185
rintf16,
186186
round,
187+
roundeven,
188+
roundevenf,
189+
roundevenf128,
190+
roundevenf16,
187191
roundf,
188192
roundf128,
189193
roundf16,
@@ -253,6 +257,8 @@ impl_no_round! {
253257
rint => round_even_mut; // FIXME: respect rounding mode
254258
rintf => round_even_mut; // FIXME: respect rounding mode
255259
round => round_mut;
260+
roundeven => round_even_mut;
261+
roundevenf => round_even_mut;
256262
roundf => round_mut;
257263
trunc => trunc_mut;
258264
truncf => trunc_mut;
@@ -265,6 +271,7 @@ impl_no_round! {
265271
floorf16 => floor_mut;
266272
rintf16 => round_even_mut; // FIXME: respect rounding mode
267273
roundf16 => round_mut;
274+
roundevenf16 => round_even_mut;
268275
truncf16 => trunc_mut;
269276
}
270277

@@ -275,6 +282,7 @@ impl_no_round! {
275282
floorf128 => floor_mut;
276283
rintf128 => round_even_mut; // FIXME: respect rounding mode
277284
roundf128 => round_mut;
285+
roundevenf128 => round_even_mut;
278286
truncf128 => trunc_mut;
279287
}
280288

crates/libm-test/src/precision.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub fn default_ulp(ctx: &CheckCtx) -> u32 {
4040
| Bn::Remquo
4141
| Bn::Rint
4242
| Bn::Round
43+
| Bn::Roundeven
4344
| Bn::Scalbn
4445
| Bn::Sqrt
4546
| Bn::Trunc => 0,
@@ -282,7 +283,7 @@ impl MaybeOverride<(f64,)> for SpecialCase {
282283
}
283284

284285
if cfg!(x86_no_sse)
285-
&& ctx.base_name == BaseName::Rint
286+
&& (ctx.base_name == BaseName::Rint || ctx.base_name == BaseName::Roundeven)
286287
&& (expected - actual).abs() <= F::ONE
287288
&& (expected - actual).abs() > F::ZERO
288289
{

crates/libm-test/tests/compare_built_musl.rs

+4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ libm_macros::for_each_function! {
126126
ldexpf16,
127127
rintf128,
128128
rintf16,
129+
roundeven,
130+
roundevenf,
131+
roundevenf128,
132+
roundevenf16,
129133
roundf128,
130134
roundf16,
131135
scalbnf128,

crates/util/src/main.rs

+4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
123123
| ldexpf16
124124
| rintf128
125125
| rintf16
126+
| roundeven
127+
| roundevenf
128+
| roundevenf128
129+
| roundevenf16
126130
| roundf128
127131
| roundf16
128132
| scalbnf128

etc/function-definitions.json

+27-7
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,6 @@
791791
"sources": [
792792
"src/math/arch/aarch64.rs",
793793
"src/math/arch/wasm32.rs",
794-
"src/math/generic/rint.rs",
795794
"src/math/rint.rs"
796795
],
797796
"type": "f64"
@@ -800,22 +799,19 @@
800799
"sources": [
801800
"src/math/arch/aarch64.rs",
802801
"src/math/arch/wasm32.rs",
803-
"src/math/generic/rint.rs",
804-
"src/math/rintf.rs"
802+
"src/math/rint.rs"
805803
],
806804
"type": "f32"
807805
},
808806
"rintf128": {
809807
"sources": [
810-
"src/math/generic/rint.rs",
811-
"src/math/rintf128.rs"
808+
"src/math/rint.rs"
812809
],
813810
"type": "f128"
814811
},
815812
"rintf16": {
816813
"sources": [
817-
"src/math/generic/rint.rs",
818-
"src/math/rintf16.rs"
814+
"src/math/rint.rs"
819815
],
820816
"type": "f16"
821817
},
@@ -826,6 +822,30 @@
826822
],
827823
"type": "f64"
828824
},
825+
"roundeven": {
826+
"sources": [
827+
"src/math/roundeven.rs"
828+
],
829+
"type": "f64"
830+
},
831+
"roundevenf": {
832+
"sources": [
833+
"src/math/roundeven.rs"
834+
],
835+
"type": "f32"
836+
},
837+
"roundevenf128": {
838+
"sources": [
839+
"src/math/roundeven.rs"
840+
],
841+
"type": "f128"
842+
},
843+
"roundevenf16": {
844+
"sources": [
845+
"src/math/roundeven.rs"
846+
],
847+
"type": "f16"
848+
},
829849
"roundf": {
830850
"sources": [
831851
"src/math/generic/round.rs",

etc/function-list.txt

+4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ rintf
125125
rintf128
126126
rintf16
127127
round
128+
roundeven
129+
roundevenf
130+
roundevenf128
131+
roundevenf16
128132
roundf
129133
roundf128
130134
roundf16

0 commit comments

Comments
 (0)