Skip to content

Commit 21c19b5

Browse files
committed
Add ceilf16 and ceilf128
Use the generic algorithms to provide implementations for these routines.
1 parent 1a60db7 commit 21c19b5

File tree

12 files changed

+154
-9
lines changed

12 files changed

+154
-9
lines changed

crates/libm-macros/src/shared.rs

+2-2
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-
&["fabsf16", "truncf16"],
12+
&["ceilf16", "fabsf16", "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-
&["fabsf128", "truncf128"],
43+
&["ceilf128", "fabsf128", "truncf128"],
4444
),
4545
(
4646
// `(f16, f16) -> f16`

crates/libm-test/benches/random.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,14 @@ libm_macros::for_each_function! {
117117
exp10 | exp10f | exp2 | exp2f => (true, Some(musl_math_sys::MACRO_FN_NAME)),
118118

119119
// Musl does not provide `f16` and `f128` functions
120-
copysignf16 | copysignf128 | fabsf16 | fabsf128 | truncf16 | truncf128 => (false, None),
120+
ceilf128
121+
| ceilf16
122+
| copysignf128
123+
| copysignf16
124+
| fabsf128
125+
| fabsf16
126+
| truncf128
127+
| truncf16 => (false, None),
121128

122129
// By default we never skip (false) and always have a musl function available
123130
_ => (false, Some(musl_math_sys::MACRO_FN_NAME))

crates/libm-test/src/domain.rs

+10
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ impl HasDomain<f128> for crate::op::fabsf128::Routine {
200200
const DOMAIN: Domain<f128> = Domain::<f128>::UNBOUNDED;
201201
}
202202

203+
#[cfg(f16_enabled)]
204+
impl HasDomain<f16> for crate::op::ceilf16::Routine {
205+
const DOMAIN: Domain<f16> = Domain::<f16>::UNBOUNDED;
206+
}
207+
208+
#[cfg(f128_enabled)]
209+
impl HasDomain<f128> for crate::op::ceilf128::Routine {
210+
const DOMAIN: Domain<f128> = Domain::<f128>::UNBOUNDED;
211+
}
212+
203213
#[cfg(f16_enabled)]
204214
impl HasDomain<f16> for crate::op::truncf16::Routine {
205215
const DOMAIN: Domain<f16> = Domain::<f16>::UNBOUNDED;

crates/libm-test/src/mpfloat.rs

+4
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ libm_macros::for_each_function! {
137137
// Most of these need a manual implementation
138138
ceil,
139139
ceilf,
140+
ceilf128,
141+
ceilf16,
140142
copysign,
141143
copysignf,
142144
copysignf128,
@@ -237,12 +239,14 @@ impl_no_round! {
237239
#[cfg(f16_enabled)]
238240
impl_no_round! {
239241
fabsf16 => abs_mut;
242+
ceilf16 => ceil_mut;
240243
truncf16 => trunc_mut;
241244
}
242245

243246
#[cfg(f128_enabled)]
244247
impl_no_round! {
245248
fabsf128 => abs_mut;
249+
ceilf128 => ceil_mut;
246250
truncf128 => trunc_mut;
247251
}
248252

crates/libm-test/tests/compare_built_musl.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,16 @@ where
4848
libm_macros::for_each_function! {
4949
callback: musl_rand_tests,
5050
// Musl does not support `f16` and `f128` on all platforms.
51-
skip: [copysignf16, copysignf128, fabsf16, fabsf128, truncf16, truncf128],
51+
skip: [
52+
ceilf128,
53+
ceilf16,
54+
copysignf128,
55+
copysignf16,
56+
fabsf128,
57+
fabsf16,
58+
truncf128,
59+
truncf16,
60+
],
5261
attributes: [
5362
#[cfg_attr(x86_no_sse, ignore)] // FIXME(correctness): wrong result on i586
5463
[exp10, exp10f, exp2, exp2f, rint]
@@ -144,9 +153,11 @@ libm_macros::for_each_function! {
144153
ynf,
145154

146155
// Not provided by musl
147-
fabsf16,
156+
ceilf128,
157+
ceilf16,
148158
fabsf128,
149-
truncf16,
159+
fabsf16,
150160
truncf128,
161+
truncf16,
151162
],
152163
}

crates/util/src/main.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,14 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
8484
emit_types: [CFn, RustFn, RustArgs],
8585
extra: (basis, op, inputs),
8686
fn_extra: match MACRO_FN_NAME {
87-
copysignf16 | copysignf128 | fabsf16 | fabsf128 | truncf16 | truncf128 => None,
87+
ceilf128
88+
| ceilf16
89+
| copysignf128
90+
| copysignf16
91+
| fabsf128
92+
| fabsf16
93+
| truncf128
94+
| truncf16 => None,
8895
_ => Some(musl_math_sys::MACRO_FN_NAME)
8996
}
9097
}

etc/function-definitions.json

+18-2
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,33 @@
109109
"src/libm_helper.rs",
110110
"src/math/arch/i586.rs",
111111
"src/math/arch/wasm32.rs",
112-
"src/math/ceil.rs"
112+
"src/math/ceil.rs",
113+
"src/math/generic/ceil.rs"
113114
],
114115
"type": "f64"
115116
},
116117
"ceilf": {
117118
"sources": [
118119
"src/math/arch/wasm32.rs",
119-
"src/math/ceilf.rs"
120+
"src/math/ceilf.rs",
121+
"src/math/generic/ceil.rs"
120122
],
121123
"type": "f32"
122124
},
125+
"ceilf128": {
126+
"sources": [
127+
"src/math/ceilf128.rs",
128+
"src/math/generic/ceil.rs"
129+
],
130+
"type": "f128"
131+
},
132+
"ceilf16": {
133+
"sources": [
134+
"src/math/ceilf16.rs",
135+
"src/math/generic/ceil.rs"
136+
],
137+
"type": "f16"
138+
},
123139
"copysign": {
124140
"sources": [
125141
"src/libm_helper.rs",

etc/function-list.txt

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ cbrt
1717
cbrtf
1818
ceil
1919
ceilf
20+
ceilf128
21+
ceilf16
2022
copysign
2123
copysignf
2224
copysignf128

src/math/ceilf128.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// Ceil (f128)
2+
///
3+
/// Finds the nearest integer greater than or equal to `x`.
4+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
5+
pub fn ceilf128(x: f128) -> f128 {
6+
super::generic::ceil(x)
7+
}

src/math/ceilf16.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// Ceil (f16)
2+
///
3+
/// Finds the nearest integer greater than or equal to `x`.
4+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
5+
pub fn ceilf16(x: f16) -> f16 {
6+
super::generic::ceil(x)
7+
}

src/math/generic/ceil.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* SPDX-License-Identifier: MIT
2+
* origin: musl src/math/ceil.c */
3+
4+
use super::super::{CastInto, Float};
5+
6+
pub fn ceil<F: Float>(x: F) -> F {
7+
let toint = F::ONE / F::EPSILON;
8+
9+
// NB: using `exp` here and comparing to values adjusted by `EXP_BIAS` has better
10+
// perf than using `exp_unbiased` here.
11+
let e = x.exp();
12+
let y: F;
13+
14+
// If the represented value has no fractional part, no truncation is needed.
15+
if e >= (F::SIG_BITS + F::EXP_BIAS).cast() || x == F::ZERO {
16+
return x;
17+
}
18+
19+
let neg = x.is_sign_negative();
20+
21+
// y = int(x) - x, where int(x) is an integer neighbor of x.
22+
// The `x - t + t - x` method is a way to expose non-round-to-even modes.
23+
y = if neg { x - toint + toint - x } else { x + toint - toint - x };
24+
25+
// Exp < 0; special case because of non-nearest rounding modes
26+
if e < F::EXP_BIAS.cast() {
27+
// Raise `FE_INEXACT`
28+
force_eval!(y);
29+
return if neg { F::NEG_ZERO } else { F::ONE };
30+
}
31+
32+
if y < F::ZERO { x + y + F::ONE } else { x + y }
33+
}
34+
35+
#[cfg(test)]
36+
mod tests {
37+
use super::*;
38+
39+
#[test]
40+
fn sanity_check_f64() {
41+
assert_eq!(ceil(1.1f64), 2.0);
42+
assert_eq!(ceil(2.9f64), 3.0);
43+
}
44+
45+
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/ceil
46+
#[test]
47+
fn spec_tests_f64() {
48+
// Not Asserted: that the current rounding mode has no effect.
49+
assert!(ceil(f64::NAN).is_nan());
50+
for f in [0.0, -0.0, f64::INFINITY, f64::NEG_INFINITY].iter().copied() {
51+
assert_eq!(ceil(f), f);
52+
}
53+
}
54+
55+
#[test]
56+
fn sanity_check_f32() {
57+
assert_eq!(ceil(1.1f32), 2.0);
58+
assert_eq!(ceil(2.9f32), 3.0);
59+
}
60+
61+
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/ceil
62+
#[test]
63+
fn spec_tests_f32() {
64+
// Not Asserted: that the current rounding mode has no effect.
65+
assert!(ceil(f32::NAN).is_nan());
66+
for f in [0.0, -0.0, f32::INFINITY, f32::NEG_INFINITY].iter().copied() {
67+
assert_eq!(ceil(f), f);
68+
}
69+
}
70+
}

src/math/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,12 @@ pub use self::truncf::truncf;
341341

342342
cfg_if! {
343343
if #[cfg(f16_enabled)] {
344+
mod ceilf16;
344345
mod copysignf16;
345346
mod fabsf16;
346347
mod truncf16;
347348

349+
pub use self::ceilf16::ceilf16;
348350
pub use self::copysignf16::copysignf16;
349351
pub use self::fabsf16::fabsf16;
350352
pub use self::truncf16::truncf16;
@@ -353,10 +355,12 @@ cfg_if! {
353355

354356
cfg_if! {
355357
if #[cfg(f128_enabled)] {
358+
mod ceilf128;
356359
mod copysignf128;
357360
mod fabsf128;
358361
mod truncf128;
359362

363+
pub use self::ceilf128::ceilf128;
360364
pub use self::copysignf128::copysignf128;
361365
pub use self::fabsf128::fabsf128;
362366
pub use self::truncf128::truncf128;

0 commit comments

Comments
 (0)