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

Commit 71606c6

Browse files
authored
Merge pull request #465 from tgross35/generic-round
Add `roundf16` and `roundf128`
2 parents be9ba62 + 2d2c45d commit 71606c6

File tree

15 files changed

+132
-57
lines changed

15 files changed

+132
-57
lines changed

libm/crates/libm-macros/src/shared.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ 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", "sqrtf16", "truncf16"],
12+
&["ceilf16", "fabsf16", "floorf16", "rintf16", "roundf16", "sqrtf16", "truncf16"],
1313
),
1414
(
1515
// `fn(f32) -> f32`
@@ -40,7 +40,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
4040
FloatTy::F128,
4141
Signature { args: &[Ty::F128], returns: &[Ty::F128] },
4242
None,
43-
&["ceilf128", "fabsf128", "floorf128", "rintf128", "sqrtf128", "truncf128"],
43+
&["ceilf128", "fabsf128", "floorf128", "rintf128", "roundf128", "sqrtf128", "truncf128"],
4444
),
4545
(
4646
// `(f16, f16) -> f16`

libm/crates/libm-test/benches/random.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ libm_macros::for_each_function! {
129129
| floorf16
130130
| rintf128
131131
| rintf16
132+
| roundf128
133+
| roundf16
132134
| sqrtf128
133135
| sqrtf16
134136
| truncf128

libm/crates/libm-test/src/mpfloat.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ libm_macros::for_each_function! {
175175
rintf16,
176176
round,
177177
roundf,
178+
roundf128,
179+
roundf16,
178180
scalbn,
179181
scalbnf,
180182
sincos,sincosf,
@@ -247,6 +249,7 @@ impl_no_round! {
247249
fabsf16 => abs_mut;
248250
floorf16 => floor_mut;
249251
rintf16 => round_even_mut; // FIXME: respect rounding mode
252+
roundf16 => round_mut;
250253
truncf16 => trunc_mut;
251254
}
252255

@@ -256,6 +259,7 @@ impl_no_round! {
256259
fabsf128 => abs_mut;
257260
floorf128 => floor_mut;
258261
rintf128 => round_even_mut; // FIXME: respect rounding mode
262+
roundf128 => round_mut;
259263
truncf128 => trunc_mut;
260264
}
261265

libm/crates/libm-test/src/precision.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ use crate::{BaseName, CheckBasis, CheckCtx, Float, Identifier, Int, TestResult};
1313
pub struct SpecialCase;
1414

1515
/// ULP allowed to differ from the results returned by a test basis.
16-
///
17-
/// Note that these results were obtained using 400M rounds of random inputs, which
18-
/// is not a value used by default.
1916
pub fn default_ulp(ctx: &CheckCtx) -> u32 {
2017
// ULP compared to the infinite (MPFR) result.
2118
let mut ulp = match ctx.base_name {

libm/crates/libm-test/tests/compare_built_musl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ libm_macros::for_each_function! {
9191
floorf16,
9292
rintf128,
9393
rintf16,
94+
roundf128,
95+
roundf16,
9496
sqrtf128,
9597
sqrtf16,
9698
truncf128,

libm/crates/util/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
9898
| floorf16
9999
| rintf128
100100
| rintf16
101+
| roundf128
102+
| roundf16
101103
| sqrtf128
102104
| sqrtf16
103105
| truncf128

libm/etc/function-definitions.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,16 +685,32 @@
685685
"round": {
686686
"sources": [
687687
"src/libm_helper.rs",
688+
"src/math/generic/round.rs",
688689
"src/math/round.rs"
689690
],
690691
"type": "f64"
691692
},
692693
"roundf": {
693694
"sources": [
695+
"src/math/generic/round.rs",
694696
"src/math/roundf.rs"
695697
],
696698
"type": "f32"
697699
},
700+
"roundf128": {
701+
"sources": [
702+
"src/math/generic/round.rs",
703+
"src/math/roundf128.rs"
704+
],
705+
"type": "f128"
706+
},
707+
"roundf16": {
708+
"sources": [
709+
"src/math/generic/round.rs",
710+
"src/math/roundf16.rs"
711+
],
712+
"type": "f16"
713+
},
698714
"scalbn": {
699715
"sources": [
700716
"src/libm_helper.rs",

libm/etc/function-list.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ rintf128
101101
rintf16
102102
round
103103
roundf
104+
roundf128
105+
roundf16
104106
scalbn
105107
scalbnf
106108
sin

libm/src/math/generic/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod fabs;
44
mod fdim;
55
mod floor;
66
mod rint;
7+
mod round;
78
mod scalbn;
89
mod sqrt;
910
mod trunc;
@@ -14,6 +15,7 @@ pub use fabs::fabs;
1415
pub use fdim::fdim;
1516
pub use floor::floor;
1617
pub use rint::rint;
18+
pub use round::round;
1719
pub use scalbn::scalbn;
1820
pub use sqrt::sqrt;
1921
pub use trunc::trunc;

libm/src/math/generic/round.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use super::super::{Float, MinInt};
2+
use super::{copysign, trunc};
3+
4+
pub fn round<F: Float>(x: F) -> F {
5+
let f0p5 = F::from_parts(false, F::EXP_BIAS - 1, F::Int::ZERO); // 0.5
6+
let f0p25 = F::from_parts(false, F::EXP_BIAS - 2, F::Int::ZERO); // 0.25
7+
8+
trunc(x + copysign(f0p5 - f0p25 * F::EPSILON, x))
9+
}
10+
11+
#[cfg(test)]
12+
mod tests {
13+
use super::*;
14+
15+
#[test]
16+
#[cfg(f16_enabled)]
17+
fn zeroes_f16() {
18+
assert_biteq!(round(0.0_f16), 0.0_f16);
19+
assert_biteq!(round(-0.0_f16), -0.0_f16);
20+
}
21+
22+
#[test]
23+
#[cfg(f16_enabled)]
24+
fn sanity_check_f16() {
25+
assert_eq!(round(-1.0_f16), -1.0);
26+
assert_eq!(round(2.8_f16), 3.0);
27+
assert_eq!(round(-0.5_f16), -1.0);
28+
assert_eq!(round(0.5_f16), 1.0);
29+
assert_eq!(round(-1.5_f16), -2.0);
30+
assert_eq!(round(1.5_f16), 2.0);
31+
}
32+
33+
#[test]
34+
fn zeroes_f32() {
35+
assert_biteq!(round(0.0_f32), 0.0_f32);
36+
assert_biteq!(round(-0.0_f32), -0.0_f32);
37+
}
38+
39+
#[test]
40+
fn sanity_check_f32() {
41+
assert_eq!(round(-1.0_f32), -1.0);
42+
assert_eq!(round(2.8_f32), 3.0);
43+
assert_eq!(round(-0.5_f32), -1.0);
44+
assert_eq!(round(0.5_f32), 1.0);
45+
assert_eq!(round(-1.5_f32), -2.0);
46+
assert_eq!(round(1.5_f32), 2.0);
47+
}
48+
49+
#[test]
50+
fn zeroes_f64() {
51+
assert_biteq!(round(0.0_f64), 0.0_f64);
52+
assert_biteq!(round(-0.0_f64), -0.0_f64);
53+
}
54+
55+
#[test]
56+
fn sanity_check_f64() {
57+
assert_eq!(round(-1.0_f64), -1.0);
58+
assert_eq!(round(2.8_f64), 3.0);
59+
assert_eq!(round(-0.5_f64), -1.0);
60+
assert_eq!(round(0.5_f64), 1.0);
61+
assert_eq!(round(-1.5_f64), -2.0);
62+
assert_eq!(round(1.5_f64), 2.0);
63+
}
64+
65+
#[test]
66+
#[cfg(f128_enabled)]
67+
fn zeroes_f128() {
68+
assert_biteq!(round(0.0_f128), 0.0_f128);
69+
assert_biteq!(round(-0.0_f128), -0.0_f128);
70+
}
71+
72+
#[test]
73+
#[cfg(f128_enabled)]
74+
fn sanity_check_f128() {
75+
assert_eq!(round(-1.0_f128), -1.0);
76+
assert_eq!(round(2.8_f128), 3.0);
77+
assert_eq!(round(-0.5_f128), -1.0);
78+
assert_eq!(round(0.5_f128), 1.0);
79+
assert_eq!(round(-1.5_f128), -2.0);
80+
assert_eq!(round(1.5_f128), 2.0);
81+
}
82+
}

libm/src/math/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ cfg_if! {
347347
mod fdimf16;
348348
mod floorf16;
349349
mod rintf16;
350+
mod roundf16;
350351
mod sqrtf16;
351352
mod truncf16;
352353

@@ -356,6 +357,7 @@ cfg_if! {
356357
pub use self::fdimf16::fdimf16;
357358
pub use self::floorf16::floorf16;
358359
pub use self::rintf16::rintf16;
360+
pub use self::roundf16::roundf16;
359361
pub use self::sqrtf16::sqrtf16;
360362
pub use self::truncf16::truncf16;
361363
}
@@ -369,6 +371,7 @@ cfg_if! {
369371
mod fdimf128;
370372
mod floorf128;
371373
mod rintf128;
374+
mod roundf128;
372375
mod sqrtf128;
373376
mod truncf128;
374377

@@ -378,6 +381,7 @@ cfg_if! {
378381
pub use self::fdimf128::fdimf128;
379382
pub use self::floorf128::floorf128;
380383
pub use self::rintf128::rintf128;
384+
pub use self::roundf128::roundf128;
381385
pub use self::sqrtf128::sqrtf128;
382386
pub use self::truncf128::truncf128;
383387
}

libm/src/math/round.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,5 @@
1-
use core::f64;
2-
3-
use super::{copysign, trunc};
4-
1+
/// Round `x` to the nearest integer, breaking ties away from zero.
52
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
63
pub fn round(x: f64) -> f64 {
7-
trunc(x + copysign(0.5 - 0.25 * f64::EPSILON, x))
8-
}
9-
10-
#[cfg(test)]
11-
mod tests {
12-
use super::round;
13-
14-
#[test]
15-
fn negative_zero() {
16-
assert_eq!(round(-0.0_f64).to_bits(), (-0.0_f64).to_bits());
17-
}
18-
19-
#[test]
20-
fn sanity_check() {
21-
assert_eq!(round(-1.0), -1.0);
22-
assert_eq!(round(2.8), 3.0);
23-
assert_eq!(round(-0.5), -1.0);
24-
assert_eq!(round(0.5), 1.0);
25-
assert_eq!(round(-1.5), -2.0);
26-
assert_eq!(round(1.5), 2.0);
27-
}
4+
super::generic::round(x)
285
}

libm/src/math/roundf.rs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,5 @@
1-
use core::f32;
2-
3-
use super::{copysignf, truncf};
4-
1+
/// Round `x` to the nearest integer, breaking ties away from zero.
52
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
63
pub fn roundf(x: f32) -> f32 {
7-
truncf(x + copysignf(0.5 - 0.25 * f32::EPSILON, x))
8-
}
9-
10-
// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
11-
#[cfg(not(target_arch = "powerpc64"))]
12-
#[cfg(test)]
13-
mod tests {
14-
use super::roundf;
15-
16-
#[test]
17-
fn negative_zero() {
18-
assert_eq!(roundf(-0.0_f32).to_bits(), (-0.0_f32).to_bits());
19-
}
20-
21-
#[test]
22-
fn sanity_check() {
23-
assert_eq!(roundf(-1.0), -1.0);
24-
assert_eq!(roundf(2.8), 3.0);
25-
assert_eq!(roundf(-0.5), -1.0);
26-
assert_eq!(roundf(0.5), 1.0);
27-
assert_eq!(roundf(-1.5), -2.0);
28-
assert_eq!(roundf(1.5), 2.0);
29-
}
4+
super::generic::round(x)
305
}

libm/src/math/roundf128.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// Round `x` to the nearest integer, breaking ties away from zero.
2+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
3+
pub fn roundf128(x: f128) -> f128 {
4+
super::generic::round(x)
5+
}

libm/src/math/roundf16.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// Round `x` to the nearest integer, breaking ties away from zero.
2+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
3+
pub fn roundf16(x: f16) -> f16 {
4+
super::generic::round(x)
5+
}

0 commit comments

Comments
 (0)