Add fabsf16, fabsf128, copysignf16, and copysignf128

Use the generic implementations to provide these simple methods.
This commit is contained in:
Trevor Gross 2025-01-02 21:11:50 +00:00
parent aabb7d9dcc
commit 42c7ace5ba
8 changed files with 133 additions and 3 deletions

View file

@ -30,7 +30,7 @@ macro_rules! libm_helper {
}
};
({$($func:tt);*}) => {
({$($func:tt;)*}) => {
$(
libm_helper! { $func }
)*
@ -103,7 +103,7 @@ libm_helper! {
(fn trunc(x: f32) -> (f32); => truncf);
(fn y0(x: f32) -> (f32); => y0f);
(fn y1(x: f32) -> (f32); => y1f);
(fn yn(n: i32, x: f32) -> (f32); => ynf)
(fn yn(n: i32, x: f32) -> (f32); => ynf);
}
}
@ -166,6 +166,24 @@ libm_helper! {
(fn trunc(x: f64) -> (f64); => trunc);
(fn y0(x: f64) -> (f64); => y0);
(fn y1(x: f64) -> (f64); => y1);
(fn yn(n: i32, x: f64) -> (f64); => yn)
(fn yn(n: i32, x: f64) -> (f64); => yn);
}
}
#[cfg(f16_enabled)]
libm_helper! {
f16,
funcs: {
(fn copysign(x: f16, y: f16) -> (f16); => copysignf16);
(fn fabs(x: f16) -> (f16); => fabsf16);
}
}
#[cfg(f128_enabled)]
libm_helper! {
f128,
funcs: {
(fn copysign(x: f128, y: f128) -> (f128); => copysignf128);
(fn fabs(x: f128) -> (f128); => fabsf128);
}
}

View file

@ -0,0 +1,8 @@
/// Sign of Y, magnitude of X (f128)
///
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn copysignf128(x: f128, y: f128) -> f128 {
super::generic::copysign(x, y)
}

View file

@ -0,0 +1,8 @@
/// Sign of Y, magnitude of X (f16)
///
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn copysignf16(x: f16, y: f16) -> f16 {
super::generic::copysign(x, y)
}

View file

@ -1,4 +1,5 @@
/// Absolute value (magnitude) (f64)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]

View file

@ -1,4 +1,5 @@
/// Absolute value (magnitude) (f32)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]

View file

@ -0,0 +1,37 @@
/// Absolute value (magnitude) (f128)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fabsf128(x: f128) -> f128 {
select_implementation! {
name: fabsf,
use_intrinsic: target_arch = "wasm32",
args: x,
}
super::generic::fabs(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanity_check() {
assert_eq!(fabsf128(-1.0), 1.0);
assert_eq!(fabsf128(2.8), 2.8);
}
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn spec_tests() {
assert!(fabsf128(f128::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(fabsf128(f), 0.0);
}
for f in [f128::INFINITY, f128::NEG_INFINITY].iter().copied() {
assert_eq!(fabsf128(f), f128::INFINITY);
}
}
}

View file

@ -0,0 +1,37 @@
/// Absolute value (magnitude) (f16)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fabsf16(x: f16) -> f16 {
select_implementation! {
name: fabsf,
use_intrinsic: target_arch = "wasm32",
args: x,
}
super::generic::fabs(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanity_check() {
assert_eq!(fabsf16(-1.0), 1.0);
assert_eq!(fabsf16(2.8), 2.8);
}
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn spec_tests() {
assert!(fabsf16(f16::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(fabsf16(f), 0.0);
}
for f in [f16::INFINITY, f16::NEG_INFINITY].iter().copied() {
assert_eq!(fabsf16(f), f16::INFINITY);
}
}
}

View file

@ -339,6 +339,26 @@ pub use self::tgammaf::tgammaf;
pub use self::trunc::trunc;
pub use self::truncf::truncf;
cfg_if! {
if #[cfg(f16_enabled)] {
mod copysignf16;
mod fabsf16;
pub use self::copysignf16::copysignf16;
pub use self::fabsf16::fabsf16;
}
}
cfg_if! {
if #[cfg(f128_enabled)] {
mod copysignf128;
mod fabsf128;
pub use self::copysignf128::copysignf128;
pub use self::fabsf128::fabsf128;
}
}
#[inline]
fn get_high_word(x: f64) -> u32 {
(x.to_bits() >> 32) as u32