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

Commit 308daa3

Browse files
committed
Add nexttoward and signbit
1 parent b849b08 commit 308daa3

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed

crates/libm/src/math/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ mod modf;
149149
mod modff;
150150
mod nextafter;
151151
mod nextafterf;
152+
mod nexttoward;
153+
mod nexttowardf;
152154
mod pow;
153155
mod powf;
154156
mod remainder;
@@ -159,6 +161,8 @@ mod round;
159161
mod roundf;
160162
mod scalbn;
161163
mod scalbnf;
164+
mod signbit;
165+
mod signbitf;
162166
mod sin;
163167
mod sincos;
164168
mod sincosf;
@@ -263,6 +267,8 @@ pub use self::modf::modf;
263267
pub use self::modff::modff;
264268
pub use self::nextafter::nextafter;
265269
pub use self::nextafterf::nextafterf;
270+
pub use self::nexttoward::nexttoward;
271+
pub use self::nexttowardf::nexttowardf;
266272
pub use self::pow::pow;
267273
pub use self::powf::powf;
268274
pub use self::remainder::remainder;

crates/libm/src/math/nexttoward.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use super::signbit::signbit;
2+
3+
#[inline]
4+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
5+
pub extern "C" fn nexttoward(x: f64, y: /*long double*/ f64) -> f64 {
6+
let mut ux_i = x.to_bits();
7+
if x.is_nan() || y.is_nan() {
8+
return x + y;
9+
}
10+
11+
if x == y {
12+
return y;
13+
}
14+
if x == 0.0 {
15+
ux_i = 1;
16+
if signbit(y) != 0 {
17+
ux_i |= 1_u64 << 63;
18+
}
19+
} else if x < y {
20+
if signbit(x) != 0 {
21+
ux_i -= 1;
22+
} else {
23+
ux_i += 1;
24+
}
25+
} else {
26+
if signbit(x) != 0 {
27+
ux_i += 1;
28+
} else {
29+
ux_i -= 1;
30+
}
31+
}
32+
let e = ux_i >> 52 & 0x7ff;
33+
// raise overflow if ux.f is infinite and x is finite
34+
if e == 0x7ff {
35+
force_eval!(x + x);
36+
}
37+
// raise underflow if ux.f is subnormal or zero
38+
let ux_f = f64::from_bits(ux_i);
39+
if e == 0 {
40+
force_eval!(x * x + ux_f * ux_f);
41+
}
42+
ux_f
43+
}

crates/libm/src/math/nexttowardf.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use super::signbit::signbit;
2+
use super::signbitf::signbitf;
3+
4+
#[inline]
5+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
6+
pub extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
7+
let mut ux_i = x.to_bits();
8+
if x.is_nan() || y.is_nan() {
9+
return (x as f64 + y) as f32;
10+
}
11+
12+
if x == y as f32 {
13+
return y as f32;
14+
}
15+
if x == 0.0 {
16+
ux_i = 1;
17+
if signbit(y) != 0 {
18+
ux_i |= 0x8000_0000_u32;
19+
}
20+
} else if x < (y as f32) {
21+
if signbitf(x) != 0 {
22+
ux_i -= 1;
23+
} else {
24+
ux_i += 1;
25+
}
26+
} else {
27+
if signbitf(x) != 0 {
28+
ux_i += 1;
29+
} else {
30+
ux_i -= 1;
31+
}
32+
}
33+
let e = ux_i.wrapping_shr(0x7f80_0000_u32);
34+
// raise overflow if ux.f is infinite and x is finite
35+
if e == 0x7f80_0000_u32 {
36+
force_eval!(x + x);
37+
}
38+
// raise underflow if ux.f is subnormal or zero
39+
let ux_f = f32::from_bits(ux_i);
40+
if e == 0 {
41+
force_eval!(x * x + ux_f * ux_f);
42+
}
43+
ux_f
44+
}

crates/libm/src/math/signbit.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[inline]
2+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
3+
pub(crate) extern "C" fn signbit(x: f64) -> i32 {
4+
(x.to_bits() >> 63) as i32
5+
}

crates/libm/src/math/signbitf.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[inline]
2+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
3+
pub(crate) extern "C" fn signbitf(x: f32) -> i32 {
4+
(x.to_bits() >> 31) as i32
5+
}

0 commit comments

Comments
 (0)