Combine the source files for more generic implementations

Splitting into different source files by float size doesn't have any
benefit when the only content is a small function that forwards to the
generic implementation. Combine the source files for all width versions
of:

* ceil
* copysign
* fabs
* fdim
* floor
* fmaximum
* fmaximum_num
* fminimum
* fminimum_num
* ldexp
* scalbn
* sqrt
* truc

fmod is excluded to avoid conflicts with an open PR.

As part of this change move unit tests out of the generic module,
instead testing the type-specific functions (e.g. `ceilf16` rather than
`ceil::<f16>()`). This ensures that unit tests are validating whatever
we expose, such as arch-specific implementations via
`select_implementation!`, which would otherwise be skipped. (They are
still covered by integration tests).
This commit is contained in:
Trevor Gross 2025-04-18 00:22:21 +00:00 committed by Trevor Gross
parent 579627ddd5
commit a15c8c9a3d
54 changed files with 820 additions and 805 deletions

View file

@ -108,21 +108,21 @@
"ceilf": {
"sources": [
"src/math/arch/wasm32.rs",
"src/math/ceilf.rs",
"src/math/ceil.rs",
"src/math/generic/ceil.rs"
],
"type": "f32"
},
"ceilf128": {
"sources": [
"src/math/ceilf128.rs",
"src/math/ceil.rs",
"src/math/generic/ceil.rs"
],
"type": "f128"
},
"ceilf16": {
"sources": [
"src/math/ceilf16.rs",
"src/math/ceil.rs",
"src/math/generic/ceil.rs"
],
"type": "f16"
@ -136,21 +136,21 @@
},
"copysignf": {
"sources": [
"src/math/copysignf.rs",
"src/math/copysign.rs",
"src/math/generic/copysign.rs"
],
"type": "f32"
},
"copysignf128": {
"sources": [
"src/math/copysignf128.rs",
"src/math/copysign.rs",
"src/math/generic/copysign.rs"
],
"type": "f128"
},
"copysignf16": {
"sources": [
"src/math/copysignf16.rs",
"src/math/copysign.rs",
"src/math/generic/copysign.rs"
],
"type": "f16"
@ -262,21 +262,21 @@
"fabsf": {
"sources": [
"src/math/arch/wasm32.rs",
"src/math/fabsf.rs",
"src/math/fabs.rs",
"src/math/generic/fabs.rs"
],
"type": "f32"
},
"fabsf128": {
"sources": [
"src/math/fabsf128.rs",
"src/math/fabs.rs",
"src/math/generic/fabs.rs"
],
"type": "f128"
},
"fabsf16": {
"sources": [
"src/math/fabsf16.rs",
"src/math/fabs.rs",
"src/math/generic/fabs.rs"
],
"type": "f16"
@ -290,21 +290,21 @@
},
"fdimf": {
"sources": [
"src/math/fdimf.rs",
"src/math/fdim.rs",
"src/math/generic/fdim.rs"
],
"type": "f32"
},
"fdimf128": {
"sources": [
"src/math/fdimf128.rs",
"src/math/fdim.rs",
"src/math/generic/fdim.rs"
],
"type": "f128"
},
"fdimf16": {
"sources": [
"src/math/fdimf16.rs",
"src/math/fdim.rs",
"src/math/generic/fdim.rs"
],
"type": "f16"
@ -321,21 +321,21 @@
"floorf": {
"sources": [
"src/math/arch/wasm32.rs",
"src/math/floorf.rs",
"src/math/floor.rs",
"src/math/generic/floor.rs"
],
"type": "f32"
},
"floorf128": {
"sources": [
"src/math/floorf128.rs",
"src/math/floor.rs",
"src/math/generic/floor.rs"
],
"type": "f128"
},
"floorf16": {
"sources": [
"src/math/floorf16.rs",
"src/math/floor.rs",
"src/math/generic/floor.rs"
],
"type": "f16"
@ -636,19 +636,19 @@
},
"ldexpf": {
"sources": [
"src/math/ldexpf.rs"
"src/math/ldexp.rs"
],
"type": "f32"
},
"ldexpf128": {
"sources": [
"src/math/ldexpf128.rs"
"src/math/ldexp.rs"
],
"type": "f128"
},
"ldexpf16": {
"sources": [
"src/math/ldexpf16.rs"
"src/math/ldexp.rs"
],
"type": "f16"
},
@ -847,21 +847,21 @@
"roundf": {
"sources": [
"src/math/generic/round.rs",
"src/math/roundf.rs"
"src/math/round.rs"
],
"type": "f32"
},
"roundf128": {
"sources": [
"src/math/generic/round.rs",
"src/math/roundf128.rs"
"src/math/round.rs"
],
"type": "f128"
},
"roundf16": {
"sources": [
"src/math/generic/round.rs",
"src/math/roundf16.rs"
"src/math/round.rs"
],
"type": "f16"
},
@ -875,21 +875,21 @@
"scalbnf": {
"sources": [
"src/math/generic/scalbn.rs",
"src/math/scalbnf.rs"
"src/math/scalbn.rs"
],
"type": "f32"
},
"scalbnf128": {
"sources": [
"src/math/generic/scalbn.rs",
"src/math/scalbnf128.rs"
"src/math/scalbn.rs"
],
"type": "f128"
},
"scalbnf16": {
"sources": [
"src/math/generic/scalbn.rs",
"src/math/scalbnf16.rs"
"src/math/scalbn.rs"
],
"type": "f16"
},
@ -945,14 +945,14 @@
"src/math/arch/i686.rs",
"src/math/arch/wasm32.rs",
"src/math/generic/sqrt.rs",
"src/math/sqrtf.rs"
"src/math/sqrt.rs"
],
"type": "f32"
},
"sqrtf128": {
"sources": [
"src/math/generic/sqrt.rs",
"src/math/sqrtf128.rs"
"src/math/sqrt.rs"
],
"type": "f128"
},
@ -960,7 +960,7 @@
"sources": [
"src/math/arch/aarch64.rs",
"src/math/generic/sqrt.rs",
"src/math/sqrtf16.rs"
"src/math/sqrt.rs"
],
"type": "f16"
},
@ -1012,21 +1012,21 @@
"sources": [
"src/math/arch/wasm32.rs",
"src/math/generic/trunc.rs",
"src/math/truncf.rs"
"src/math/trunc.rs"
],
"type": "f32"
},
"truncf128": {
"sources": [
"src/math/generic/trunc.rs",
"src/math/truncf128.rs"
"src/math/trunc.rs"
],
"type": "f128"
},
"truncf16": {
"sources": [
"src/math/generic/trunc.rs",
"src/math/truncf16.rs"
"src/math/trunc.rs"
],
"type": "f16"
},

View file

@ -13,7 +13,7 @@
* ====================================================
*/
use super::sqrtf::sqrtf;
use super::sqrt::sqrtf;
const PIO2_HI: f32 = 1.5707962513e+00; /* 0x3fc90fda */
const PIO2_LO: f32 = 7.5497894159e-08; /* 0x33a22168 */

View file

@ -13,8 +13,8 @@
* ====================================================
*/
use super::fabsf::fabsf;
use super::sqrt::sqrt;
use super::support::Float;
const PIO2: f64 = 1.570796326794896558e+00;
@ -61,7 +61,7 @@ pub fn asinf(mut x: f32) -> f32 {
}
/* 1 > |x| >= 0.5 */
let z = (1. - fabsf(x)) * 0.5;
let z = (1. - Float::abs(x)) * 0.5;
let s = sqrt(z as f64);
x = (PIO2 - 2. * (s + s * (r(z) as f64))) as f32;
if (hx >> 31) != 0 { -x } else { x }

View file

@ -1,3 +1,26 @@
/// Ceil (f16)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ceilf16(x: f16) -> f16 {
super::generic::ceil(x)
}
/// Ceil (f32)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ceilf(x: f32) -> f32 {
select_implementation! {
name: ceilf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::ceil(x)
}
/// Ceil (f64)
///
/// Finds the nearest integer greater than or equal to `x`.
@ -12,3 +35,12 @@ pub fn ceil(x: f64) -> f64 {
super::generic::ceil(x)
}
/// Ceil (f128)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ceilf128(x: f128) -> f128 {
super::generic::ceil(x)
}

View file

@ -1,13 +0,0 @@
/// Ceil (f32)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ceilf(x: f32) -> f32 {
select_implementation! {
name: ceilf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::ceil(x)
}

View file

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

View file

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

View file

@ -1,3 +1,22 @@
/// 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(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn copysignf16(x: f16, y: f16) -> f16 {
super::generic::copysign(x, y)
}
/// Sign of Y, magnitude of X (f32)
///
/// 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 copysignf(x: f32, y: f32) -> f32 {
super::generic::copysign(x, y)
}
/// Sign of Y, magnitude of X (f64)
///
/// Constructs a number with the magnitude (absolute value) of its
@ -6,3 +25,64 @@
pub fn copysign(x: f64, y: f64) -> f64 {
super::generic::copysign(x, y)
}
/// 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(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn copysignf128(x: f128, y: f128) -> f128 {
super::generic::copysign(x, y)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Float;
fn spec_test<F: Float>(f: impl Fn(F, F) -> F) {
assert_biteq!(f(F::ZERO, F::ZERO), F::ZERO);
assert_biteq!(f(F::NEG_ZERO, F::ZERO), F::ZERO);
assert_biteq!(f(F::ZERO, F::NEG_ZERO), F::NEG_ZERO);
assert_biteq!(f(F::NEG_ZERO, F::NEG_ZERO), F::NEG_ZERO);
assert_biteq!(f(F::ONE, F::ONE), F::ONE);
assert_biteq!(f(F::NEG_ONE, F::ONE), F::ONE);
assert_biteq!(f(F::ONE, F::NEG_ONE), F::NEG_ONE);
assert_biteq!(f(F::NEG_ONE, F::NEG_ONE), F::NEG_ONE);
assert_biteq!(f(F::INFINITY, F::INFINITY), F::INFINITY);
assert_biteq!(f(F::NEG_INFINITY, F::INFINITY), F::INFINITY);
assert_biteq!(f(F::INFINITY, F::NEG_INFINITY), F::NEG_INFINITY);
assert_biteq!(f(F::NEG_INFINITY, F::NEG_INFINITY), F::NEG_INFINITY);
// Not required but we expect it
assert_biteq!(f(F::NAN, F::NAN), F::NAN);
assert_biteq!(f(F::NEG_NAN, F::NAN), F::NAN);
assert_biteq!(f(F::NAN, F::NEG_NAN), F::NEG_NAN);
assert_biteq!(f(F::NEG_NAN, F::NEG_NAN), F::NEG_NAN);
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>(copysignf16);
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>(copysignf);
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>(copysign);
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>(copysignf128);
}
}

View file

@ -1,8 +0,0 @@
/// Sign of Y, magnitude of X (f32)
///
/// 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 copysignf(x: f32, y: f32) -> f32 {
super::generic::copysign(x, y)
}

View file

@ -1,8 +0,0 @@
/// 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

@ -1,8 +0,0 @@
/// 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,3 +1,28 @@
/// Absolute value (magnitude) (f16)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fabsf16(x: f16) -> f16 {
super::generic::fabs(x)
}
/// 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)]
pub fn fabsf(x: f32) -> f32 {
select_implementation! {
name: fabsf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::fabs(x)
}
/// Absolute value (magnitude) (f64)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
@ -13,25 +38,79 @@ pub fn fabs(x: f64) -> f64 {
super::generic::fabs(x)
}
/// Absolute value (magnitude) (f128)
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fabsf128(x: f128) -> f128 {
super::generic::fabs(x)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Float;
#[test]
fn sanity_check() {
assert_eq!(fabs(-1.0), 1.0);
assert_eq!(fabs(2.8), 2.8);
/// Based on https://en.cppreference.com/w/cpp/numeric/math/fabs
fn spec_test<F: Float>(f: impl Fn(F) -> F) {
assert_biteq!(f(F::ZERO), F::ZERO);
assert_biteq!(f(F::NEG_ZERO), F::ZERO);
assert_biteq!(f(F::INFINITY), F::INFINITY);
assert_biteq!(f(F::NEG_INFINITY), F::INFINITY);
assert!(f(F::NAN).is_nan());
// Not spec rewquired but we expect it
assert!(f(F::NAN).is_sign_positive());
assert!(f(F::from_bits(F::NAN.to_bits() | F::SIGN_MASK)).is_sign_positive());
}
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn spec_tests() {
assert!(fabs(f64::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(fabs(f), 0.0);
}
for f in [f64::INFINITY, f64::NEG_INFINITY].iter().copied() {
assert_eq!(fabs(f), f64::INFINITY);
}
#[cfg(f16_enabled)]
fn sanity_check_f16() {
assert_eq!(fabsf16(-1.0f16), 1.0);
assert_eq!(fabsf16(2.8f16), 2.8);
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>(fabsf16);
}
#[test]
fn sanity_check_f32() {
assert_eq!(fabsf(-1.0f32), 1.0);
assert_eq!(fabsf(2.8f32), 2.8);
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>(fabsf);
}
#[test]
fn sanity_check_f64() {
assert_eq!(fabs(-1.0f64), 1.0);
assert_eq!(fabs(2.8f64), 2.8);
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>(fabs);
}
#[test]
#[cfg(f128_enabled)]
fn sanity_check_f128() {
assert_eq!(fabsf128(-1.0f128), 1.0);
assert_eq!(fabsf128(2.8f128), 2.8);
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>(fabsf128);
}
}

View file

@ -1,39 +0,0 @@
/// 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)]
pub fn fabsf(x: f32) -> f32 {
select_implementation! {
name: fabsf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::fabs(x)
}
// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
#[cfg(not(target_arch = "powerpc64"))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanity_check() {
assert_eq!(fabsf(-1.0), 1.0);
assert_eq!(fabsf(2.8), 2.8);
}
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn spec_tests() {
assert!(fabsf(f32::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(fabsf(f), 0.0);
}
for f in [f32::INFINITY, f32::NEG_INFINITY].iter().copied() {
assert_eq!(fabsf(f), f32::INFINITY);
}
}
}

View file

@ -1,31 +0,0 @@
/// 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 {
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

@ -1,31 +0,0 @@
/// 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 {
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

@ -1,3 +1,30 @@
/// Positive difference (f16)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf16(x: f16, y: f16) -> f16 {
super::generic::fdim(x, y)
}
/// Positive difference (f32)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf(x: f32, y: f32) -> f32 {
super::generic::fdim(x, y)
}
/// Positive difference (f64)
///
/// Determines the positive difference between arguments, returning:
@ -10,3 +37,17 @@
pub fn fdim(x: f64, y: f64) -> f64 {
super::generic::fdim(x, y)
}
/// Positive difference (f128)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf128(x: f128, y: f128) -> f128 {
super::generic::fdim(x, y)
}

View file

@ -1,12 +0,0 @@
/// Positive difference (f32)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf(x: f32, y: f32) -> f32 {
super::generic::fdim(x, y)
}

View file

@ -1,12 +0,0 @@
/// Positive difference (f128)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf128(x: f128, y: f128) -> f128 {
super::generic::fdim(x, y)
}

View file

@ -1,12 +0,0 @@
/// Positive difference (f16)
///
/// Determines the positive difference between arguments, returning:
/// * x - y if x > y, or
/// * +0 if x <= y, or
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fdimf16(x: f16, y: f16) -> f16 {
super::generic::fdim(x, y)
}

View file

@ -1,3 +1,12 @@
/// Floor (f16)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf16(x: f16) -> f16 {
return super::generic::floor(x);
}
/// Floor (f64)
///
/// Finds the nearest integer less than or equal to `x`.
@ -12,3 +21,26 @@ pub fn floor(x: f64) -> f64 {
return super::generic::floor(x);
}
/// Floor (f32)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf(x: f32) -> f32 {
select_implementation! {
name: floorf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
return super::generic::floor(x);
}
/// Floor (f128)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf128(x: f128) -> f128 {
return super::generic::floor(x);
}

View file

@ -1,13 +0,0 @@
/// Floor (f32)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf(x: f32) -> f32 {
select_implementation! {
name: floorf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
return super::generic::floor(x);
}

View file

@ -1,7 +0,0 @@
/// Floor (f128)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf128(x: f128) -> f128 {
return super::generic::floor(x);
}

View file

@ -1,7 +0,0 @@
/// Floor (f16)
///
/// Finds the nearest integer less than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn floorf16(x: f16) -> f16 {
return super::generic::floor(x);
}

View file

@ -73,3 +73,95 @@ pub fn fmax(x: f64, y: f64) -> f64 {
pub fn fmaxf128(x: f128, y: f128) -> f128 {
super::generic::fmax(x, y)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::{Float, Hexf};
fn fmin_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fmin({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fmin_spec_tests_f16() {
fmin_spec_test::<f16>(fminf16);
}
#[test]
fn fmin_spec_tests_f32() {
fmin_spec_test::<f32>(fminf);
}
#[test]
fn fmin_spec_tests_f64() {
fmin_spec_test::<f64>(fmin);
}
#[test]
#[cfg(f128_enabled)]
fn fmin_spec_tests_f128() {
fmin_spec_test::<f128>(fminf128);
}
fn fmax_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fmax({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fmax_spec_tests_f16() {
fmax_spec_test::<f16>(fmaxf16);
}
#[test]
fn fmax_spec_tests_f32() {
fmax_spec_test::<f32>(fmaxf);
}
#[test]
fn fmax_spec_tests_f64() {
fmax_spec_test::<f64>(fmax);
}
#[test]
#[cfg(f128_enabled)]
fn fmax_spec_tests_f128() {
fmax_spec_test::<f128>(fmaxf128);
}
}

View file

@ -65,3 +65,99 @@ pub fn fmaximum(x: f64, y: f64) -> f64 {
pub fn fmaximumf128(x: f128, y: f128) -> f128 {
super::generic::fmaximum(x, y)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::{Float, Hexf};
fn fminimum_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::NAN),
(F::ZERO, F::NAN, F::NAN),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
(F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fminimum({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fminimum_spec_tests_f16() {
fminimum_spec_test::<f16>(fminimumf16);
}
#[test]
fn fminimum_spec_tests_f32() {
fminimum_spec_test::<f32>(fminimumf);
}
#[test]
fn fminimum_spec_tests_f64() {
fminimum_spec_test::<f64>(fminimum);
}
#[test]
#[cfg(f128_enabled)]
fn fminimum_spec_tests_f128() {
fminimum_spec_test::<f128>(fminimumf128);
}
fn fmaximum_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::NAN),
(F::ZERO, F::NAN, F::NAN),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::ZERO),
(F::NEG_ZERO, F::ZERO, F::ZERO),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fmaximum({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fmaximum_spec_tests_f16() {
fmaximum_spec_test::<f16>(fmaximumf16);
}
#[test]
fn fmaximum_spec_tests_f32() {
fmaximum_spec_test::<f32>(fmaximumf);
}
#[test]
fn fmaximum_spec_tests_f64() {
fmaximum_spec_test::<f64>(fmaximum);
}
#[test]
#[cfg(f128_enabled)]
fn fmaximum_spec_tests_f128() {
fmaximum_spec_test::<f128>(fmaximumf128);
}
}

View file

@ -65,3 +65,99 @@ pub fn fmaximum_num(x: f64, y: f64) -> f64 {
pub fn fmaximum_numf128(x: f128, y: f128) -> f128 {
super::generic::fmaximum_num(x, y)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::{Float, Hexf};
fn fminimum_num_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
(F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fminimum_num({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fminimum_num_spec_tests_f16() {
fminimum_num_spec_test::<f16>(fminimum_numf16);
}
#[test]
fn fminimum_num_spec_tests_f32() {
fminimum_num_spec_test::<f32>(fminimum_numf);
}
#[test]
fn fminimum_num_spec_tests_f64() {
fminimum_num_spec_test::<f64>(fminimum_num);
}
#[test]
#[cfg(f128_enabled)]
fn fminimum_num_spec_tests_f128() {
fminimum_num_spec_test::<f128>(fminimum_numf128);
}
fn fmaximum_num_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::ZERO),
(F::NEG_ZERO, F::ZERO, F::ZERO),
];
for (x, y, res) in cases {
let val = f(x, y);
assert_biteq!(val, res, "fmaximum_num({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn fmaximum_num_spec_tests_f16() {
fmaximum_num_spec_test::<f16>(fmaximum_numf16);
}
#[test]
fn fmaximum_num_spec_tests_f32() {
fmaximum_num_spec_test::<f32>(fmaximum_numf);
}
#[test]
fn fmaximum_num_spec_tests_f64() {
fmaximum_num_spec_test::<f64>(fmaximum_num);
}
#[test]
#[cfg(f128_enabled)]
fn fmaximum_num_spec_tests_f128() {
fmaximum_num_spec_test::<f128>(fmaximum_numf128);
}
}

View file

@ -22,52 +22,3 @@ pub fn fmax<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
];
for (x, y, res) in cases {
let val = fmax(x, y);
assert_biteq!(val, res, "fmax({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -25,54 +25,3 @@ pub fn fmaximum<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::NAN),
(F::ZERO, F::NAN, F::NAN),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::ZERO),
(F::NEG_ZERO, F::ZERO, F::ZERO),
];
for (x, y, res) in cases {
let val = fmaximum(x, y);
assert_biteq!(val, res, "fmaximum({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -24,54 +24,3 @@ pub fn fmaximum_num<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ONE),
(F::ONE, F::ZERO, F::ONE),
(F::ZERO, F::NEG_ONE, F::ZERO),
(F::NEG_ONE, F::ZERO, F::ZERO),
(F::INFINITY, F::ZERO, F::INFINITY),
(F::NEG_INFINITY, F::ZERO, F::ZERO),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::ZERO),
(F::NEG_ZERO, F::ZERO, F::ZERO),
];
for (x, y, res) in cases {
let val = fmaximum_num(x, y);
assert_biteq!(val, res, "fmaximum_num({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -21,52 +21,3 @@ pub fn fmin<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
];
for (x, y, res) in cases {
let val = fmin(x, y);
assert_biteq!(val, res, "fmin({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -25,54 +25,3 @@ pub fn fminimum<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::NAN),
(F::ZERO, F::NAN, F::NAN),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
(F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
];
for (x, y, res) in cases {
let val = fminimum(x, y);
assert_biteq!(val, res, "fminimum({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -24,54 +24,3 @@ pub fn fminimum_num<F: Float>(x: F, y: F) -> F {
// Canonicalize
res * F::ONE
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::Hexf;
fn spec_test<F: Float>() {
let cases = [
(F::ZERO, F::ZERO, F::ZERO),
(F::ONE, F::ONE, F::ONE),
(F::ZERO, F::ONE, F::ZERO),
(F::ONE, F::ZERO, F::ZERO),
(F::ZERO, F::NEG_ONE, F::NEG_ONE),
(F::NEG_ONE, F::ZERO, F::NEG_ONE),
(F::INFINITY, F::ZERO, F::ZERO),
(F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
(F::NAN, F::ZERO, F::ZERO),
(F::ZERO, F::NAN, F::ZERO),
(F::NAN, F::NAN, F::NAN),
(F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
(F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
];
for (x, y, res) in cases {
let val = fminimum_num(x, y);
assert_biteq!(val, res, "fminimum_num({}, {})", Hexf(x), Hexf(y));
}
}
#[test]
#[cfg(f16_enabled)]
fn spec_tests_f16() {
spec_test::<f16>();
}
#[test]
fn spec_tests_f32() {
spec_test::<f32>();
}
#[test]
fn spec_tests_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_tests_f128() {
spec_test::<f128>();
}
}

View file

@ -118,68 +118,3 @@ where
let scale = F::from_parts(false, (F::EXP_BIAS as i32 + n) as u32, zero);
x * scale
}
#[cfg(test)]
mod tests {
use super::*;
// Tests against N3220
fn spec_test<F: Float>()
where
u32: CastInto<F::Int>,
F::Int: CastFrom<i32>,
F::Int: CastFrom<u32>,
{
// `scalbn(±0, n)` returns `±0`.
assert_biteq!(scalbn(F::NEG_ZERO, 10), F::NEG_ZERO);
assert_biteq!(scalbn(F::NEG_ZERO, 0), F::NEG_ZERO);
assert_biteq!(scalbn(F::NEG_ZERO, -10), F::NEG_ZERO);
assert_biteq!(scalbn(F::ZERO, 10), F::ZERO);
assert_biteq!(scalbn(F::ZERO, 0), F::ZERO);
assert_biteq!(scalbn(F::ZERO, -10), F::ZERO);
// `scalbn(x, 0)` returns `x`.
assert_biteq!(scalbn(F::MIN, 0), F::MIN);
assert_biteq!(scalbn(F::MAX, 0), F::MAX);
assert_biteq!(scalbn(F::INFINITY, 0), F::INFINITY);
assert_biteq!(scalbn(F::NEG_INFINITY, 0), F::NEG_INFINITY);
assert_biteq!(scalbn(F::ZERO, 0), F::ZERO);
assert_biteq!(scalbn(F::NEG_ZERO, 0), F::NEG_ZERO);
// `scalbn(±∞, n)` returns `±∞`.
assert_biteq!(scalbn(F::INFINITY, 10), F::INFINITY);
assert_biteq!(scalbn(F::INFINITY, -10), F::INFINITY);
assert_biteq!(scalbn(F::NEG_INFINITY, 10), F::NEG_INFINITY);
assert_biteq!(scalbn(F::NEG_INFINITY, -10), F::NEG_INFINITY);
// NaN should remain NaNs.
assert!(scalbn(F::NAN, 10).is_nan());
assert!(scalbn(F::NAN, 0).is_nan());
assert!(scalbn(F::NAN, -10).is_nan());
assert!(scalbn(-F::NAN, 10).is_nan());
assert!(scalbn(-F::NAN, 0).is_nan());
assert!(scalbn(-F::NAN, -10).is_nan());
}
#[test]
#[cfg(f16_enabled)]
fn spec_test_f16() {
spec_test::<f16>();
}
#[test]
fn spec_test_f32() {
spec_test::<f32>();
}
#[test]
fn spec_test_f64() {
spec_test::<f64>();
}
#[test]
#[cfg(f128_enabled)]
fn spec_test_f128() {
spec_test::<f128>();
}
}

View file

@ -1,4 +1,21 @@
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf16(x: f16, n: i32) -> f16 {
super::scalbnf16(x, n)
}
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf(x: f32, n: i32) -> f32 {
super::scalbnf(x, n)
}
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexp(x: f64, n: i32) -> f64 {
super::scalbn(x, n)
}
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf128(x: f128, n: i32) -> f128 {
super::scalbnf128(x, n)
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf(x: f32, n: i32) -> f32 {
super::scalbnf(x, n)
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf128(x: f128, n: i32) -> f128 {
super::scalbnf128(x, n)
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn ldexpf16(x: f16, n: i32) -> f16 {
super::scalbnf16(x, n)
}

View file

@ -140,9 +140,7 @@ mod atanhf;
mod cbrt;
mod cbrtf;
mod ceil;
mod ceilf;
mod copysign;
mod copysignf;
mod cos;
mod cosf;
mod cosh;
@ -158,11 +156,8 @@ mod expf;
mod expm1;
mod expm1f;
mod fabs;
mod fabsf;
mod fdim;
mod fdimf;
mod floor;
mod floorf;
mod fma;
mod fma_wide;
mod fmin_fmax;
@ -183,7 +178,6 @@ mod j1f;
mod jn;
mod jnf;
mod ldexp;
mod ldexpf;
mod lgamma;
mod lgamma_r;
mod lgammaf;
@ -209,9 +203,7 @@ mod remquof;
mod rint;
mod round;
mod roundeven;
mod roundf;
mod scalbn;
mod scalbnf;
mod sin;
mod sincos;
mod sincosf;
@ -219,7 +211,6 @@ mod sinf;
mod sinh;
mod sinhf;
mod sqrt;
mod sqrtf;
mod tan;
mod tanf;
mod tanh;
@ -227,7 +218,6 @@ mod tanhf;
mod tgamma;
mod tgammaf;
mod trunc;
mod truncf;
// Use separated imports instead of {}-grouped imports for easier merging.
pub use self::acos::acos;
@ -246,10 +236,8 @@ pub use self::atanh::atanh;
pub use self::atanhf::atanhf;
pub use self::cbrt::cbrt;
pub use self::cbrtf::cbrtf;
pub use self::ceil::ceil;
pub use self::ceilf::ceilf;
pub use self::copysign::copysign;
pub use self::copysignf::copysignf;
pub use self::ceil::{ceil, ceilf};
pub use self::copysign::{copysign, copysignf};
pub use self::cos::cos;
pub use self::cosf::cosf;
pub use self::cosh::cosh;
@ -264,12 +252,9 @@ pub use self::exp10f::exp10f;
pub use self::expf::expf;
pub use self::expm1::expm1;
pub use self::expm1f::expm1f;
pub use self::fabs::fabs;
pub use self::fabsf::fabsf;
pub use self::fdim::fdim;
pub use self::fdimf::fdimf;
pub use self::floor::floor;
pub use self::floorf::floorf;
pub use self::fabs::{fabs, fabsf};
pub use self::fdim::{fdim, fdimf};
pub use self::floor::{floor, floorf};
pub use self::fma::fma;
pub use self::fma_wide::fmaf;
pub use self::fmin_fmax::{fmax, fmaxf, fmin, fminf};
@ -289,8 +274,7 @@ pub use self::j1::{j1, y1};
pub use self::j1f::{j1f, y1f};
pub use self::jn::{jn, yn};
pub use self::jnf::{jnf, ynf};
pub use self::ldexp::ldexp;
pub use self::ldexpf::ldexpf;
pub use self::ldexp::{ldexp, ldexpf};
pub use self::lgamma::lgamma;
pub use self::lgamma_r::lgamma_r;
pub use self::lgammaf::lgammaf;
@ -314,61 +298,47 @@ pub use self::remainderf::remainderf;
pub use self::remquo::remquo;
pub use self::remquof::remquof;
pub use self::rint::{rint, rintf};
pub use self::round::round;
pub use self::round::{round, roundf};
pub use self::roundeven::{roundeven, roundevenf};
pub use self::roundf::roundf;
pub use self::scalbn::scalbn;
pub use self::scalbnf::scalbnf;
pub use self::scalbn::{scalbn, scalbnf};
pub use self::sin::sin;
pub use self::sincos::sincos;
pub use self::sincosf::sincosf;
pub use self::sinf::sinf;
pub use self::sinh::sinh;
pub use self::sinhf::sinhf;
pub use self::sqrt::sqrt;
pub use self::sqrtf::sqrtf;
pub use self::sqrt::{sqrt, sqrtf};
pub use self::tan::tan;
pub use self::tanf::tanf;
pub use self::tanh::tanh;
pub use self::tanhf::tanhf;
pub use self::tgamma::tgamma;
pub use self::tgammaf::tgammaf;
pub use self::trunc::trunc;
pub use self::truncf::truncf;
pub use self::trunc::{trunc, truncf};
cfg_if! {
if #[cfg(f16_enabled)] {
// verify-sorted-start
mod ceilf16;
mod copysignf16;
mod fabsf16;
mod fdimf16;
mod floorf16;
mod fmodf16;
mod ldexpf16;
mod roundf16;
mod scalbnf16;
mod sqrtf16;
mod truncf16;
// verify-sorted-end
// verify-sorted-start
pub use self::ceilf16::ceilf16;
pub use self::copysignf16::copysignf16;
pub use self::fabsf16::fabsf16;
pub use self::fdimf16::fdimf16;
pub use self::floorf16::floorf16;
pub use self::ceil::ceilf16;
pub use self::copysign::copysignf16;
pub use self::fabs::fabsf16;
pub use self::fdim::fdimf16;
pub use self::floor::floorf16;
pub use self::fmin_fmax::{fmaxf16, fminf16};
pub use self::fminimum_fmaximum::{fmaximumf16, fminimumf16};
pub use self::fminimum_fmaximum_num::{fmaximum_numf16, fminimum_numf16};
pub use self::fmodf16::fmodf16;
pub use self::ldexpf16::ldexpf16;
pub use self::ldexp::ldexpf16;
pub use self::rint::rintf16;
pub use self::round::roundf16;
pub use self::roundeven::roundevenf16;
pub use self::roundf16::roundf16;
pub use self::scalbnf16::scalbnf16;
pub use self::sqrtf16::sqrtf16;
pub use self::truncf16::truncf16;
pub use self::scalbn::scalbnf16;
pub use self::sqrt::sqrtf16;
pub use self::trunc::truncf16;
// verify-sorted-end
#[allow(unused_imports)]
@ -379,37 +349,27 @@ cfg_if! {
cfg_if! {
if #[cfg(f128_enabled)] {
// verify-sorted-start
mod ceilf128;
mod copysignf128;
mod fabsf128;
mod fdimf128;
mod floorf128;
mod fmodf128;
mod ldexpf128;
mod roundf128;
mod scalbnf128;
mod sqrtf128;
mod truncf128;
// verify-sorted-end
// verify-sorted-start
pub use self::ceilf128::ceilf128;
pub use self::copysignf128::copysignf128;
pub use self::fabsf128::fabsf128;
pub use self::fdimf128::fdimf128;
pub use self::floorf128::floorf128;
pub use self::ceil::ceilf128;
pub use self::copysign::copysignf128;
pub use self::fabs::fabsf128;
pub use self::fdim::fdimf128;
pub use self::floor::floorf128;
pub use self::fma::fmaf128;
pub use self::fmin_fmax::{fmaxf128, fminf128};
pub use self::fminimum_fmaximum::{fmaximumf128, fminimumf128};
pub use self::fminimum_fmaximum_num::{fmaximum_numf128, fminimum_numf128};
pub use self::fmodf128::fmodf128;
pub use self::ldexpf128::ldexpf128;
pub use self::ldexp::ldexpf128;
pub use self::rint::rintf128;
pub use self::round::roundf128;
pub use self::roundeven::roundevenf128;
pub use self::roundf128::roundf128;
pub use self::scalbnf128::scalbnf128;
pub use self::sqrtf128::sqrtf128;
pub use self::truncf128::truncf128;
pub use self::scalbn::scalbnf128;
pub use self::sqrt::sqrtf128;
pub use self::trunc::truncf128;
// verify-sorted-end
}
}

View file

@ -1,5 +1,25 @@
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf16(x: f16) -> f16 {
super::generic::round(x)
}
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf(x: f32) -> f32 {
super::generic::round(x)
}
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn round(x: f64) -> f64 {
super::generic::round(x)
}
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf128(x: f128) -> f128 {
super::generic::round(x)
}

View file

@ -1,5 +0,0 @@
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf(x: f32) -> f32 {
super::generic::round(x)
}

View file

@ -1,5 +0,0 @@
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf128(x: f128) -> f128 {
super::generic::round(x)
}

View file

@ -1,5 +0,0 @@
/// Round `x` to the nearest integer, breaking ties away from zero.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn roundf16(x: f16) -> f16 {
super::generic::round(x)
}

View file

@ -1,4 +1,87 @@
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf16(x: f16, n: i32) -> f16 {
super::generic::scalbn(x, n)
}
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf(x: f32, n: i32) -> f32 {
super::generic::scalbn(x, n)
}
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbn(x: f64, n: i32) -> f64 {
super::generic::scalbn(x, n)
}
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf128(x: f128, n: i32) -> f128 {
super::generic::scalbn(x, n)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::{CastFrom, CastInto, Float};
// Tests against N3220
fn spec_test<F: Float>(f: impl Fn(F, i32) -> F)
where
u32: CastInto<F::Int>,
F::Int: CastFrom<i32>,
F::Int: CastFrom<u32>,
{
// `scalbn(±0, n)` returns `±0`.
assert_biteq!(f(F::NEG_ZERO, 10), F::NEG_ZERO);
assert_biteq!(f(F::NEG_ZERO, 0), F::NEG_ZERO);
assert_biteq!(f(F::NEG_ZERO, -10), F::NEG_ZERO);
assert_biteq!(f(F::ZERO, 10), F::ZERO);
assert_biteq!(f(F::ZERO, 0), F::ZERO);
assert_biteq!(f(F::ZERO, -10), F::ZERO);
// `scalbn(x, 0)` returns `x`.
assert_biteq!(f(F::MIN, 0), F::MIN);
assert_biteq!(f(F::MAX, 0), F::MAX);
assert_biteq!(f(F::INFINITY, 0), F::INFINITY);
assert_biteq!(f(F::NEG_INFINITY, 0), F::NEG_INFINITY);
assert_biteq!(f(F::ZERO, 0), F::ZERO);
assert_biteq!(f(F::NEG_ZERO, 0), F::NEG_ZERO);
// `scalbn(±∞, n)` returns `±∞`.
assert_biteq!(f(F::INFINITY, 10), F::INFINITY);
assert_biteq!(f(F::INFINITY, -10), F::INFINITY);
assert_biteq!(f(F::NEG_INFINITY, 10), F::NEG_INFINITY);
assert_biteq!(f(F::NEG_INFINITY, -10), F::NEG_INFINITY);
// NaN should remain NaNs.
assert!(f(F::NAN, 10).is_nan());
assert!(f(F::NAN, 0).is_nan());
assert!(f(F::NAN, -10).is_nan());
assert!(f(-F::NAN, 10).is_nan());
assert!(f(-F::NAN, 0).is_nan());
assert!(f(-F::NAN, -10).is_nan());
}
#[test]
#[cfg(f16_enabled)]
fn spec_test_f16() {
spec_test::<f16>(scalbnf16);
}
#[test]
fn spec_test_f32() {
spec_test::<f32>(scalbnf);
}
#[test]
fn spec_test_f64() {
spec_test::<f64>(scalbn);
}
#[test]
#[cfg(f128_enabled)]
fn spec_test_f128() {
spec_test::<f128>(scalbnf128);
}
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf(x: f32, n: i32) -> f32 {
super::generic::scalbn(x, n)
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf128(x: f128, n: i32) -> f128 {
super::generic::scalbn(x, n)
}

View file

@ -1,4 +0,0 @@
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn scalbnf16(x: f16, n: i32) -> f16 {
super::generic::scalbn(x, n)
}

View file

@ -1,3 +1,32 @@
/// The square root of `x` (f16).
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf16(x: f16) -> f16 {
select_implementation! {
name: sqrtf16,
use_arch: all(target_arch = "aarch64", target_feature = "fp16"),
args: x,
}
return super::generic::sqrt(x);
}
/// The square root of `x` (f32).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf(x: f32) -> f32 {
select_implementation! {
name: sqrtf,
use_arch: any(
all(target_arch = "aarch64", target_feature = "neon"),
all(target_arch = "wasm32", intrinsics_enabled),
target_feature = "sse2"
),
args: x,
}
super::generic::sqrt(x)
}
/// The square root of `x` (f64).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrt(x: f64) -> f64 {
@ -13,3 +42,10 @@ pub fn sqrt(x: f64) -> f64 {
super::generic::sqrt(x)
}
/// The square root of `x` (f128).
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf128(x: f128) -> f128 {
return super::generic::sqrt(x);
}

View file

@ -1,15 +0,0 @@
/// The square root of `x` (f32).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf(x: f32) -> f32 {
select_implementation! {
name: sqrtf,
use_arch: any(
all(target_arch = "aarch64", target_feature = "neon"),
all(target_arch = "wasm32", intrinsics_enabled),
target_feature = "sse2"
),
args: x,
}
super::generic::sqrt(x)
}

View file

@ -1,5 +0,0 @@
/// The square root of `x` (f128).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf128(x: f128) -> f128 {
return super::generic::sqrt(x);
}

View file

@ -1,11 +0,0 @@
/// The square root of `x` (f16).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn sqrtf16(x: f16) -> f16 {
select_implementation! {
name: sqrtf16,
use_arch: all(target_arch = "aarch64", target_feature = "fp16"),
args: x,
}
return super::generic::sqrt(x);
}

View file

@ -1,3 +1,26 @@
/// Rounds the number toward 0 to the closest integral value (f16).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf16(x: f16) -> f16 {
super::generic::trunc(x)
}
/// Rounds the number toward 0 to the closest integral value (f32).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf(x: f32) -> f32 {
select_implementation! {
name: truncf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::trunc(x)
}
/// Rounds the number toward 0 to the closest integral value (f64).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
@ -11,3 +34,20 @@ pub fn trunc(x: f64) -> f64 {
super::generic::trunc(x)
}
/// Rounds the number toward 0 to the closest integral value (f128).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf128(x: f128) -> f128 {
super::generic::trunc(x)
}
#[cfg(test)]
mod tests {
#[test]
fn sanity_check() {
assert_eq!(super::truncf(1.1), 1.0);
}
}

View file

@ -1,23 +0,0 @@
/// Rounds the number toward 0 to the closest integral value (f32).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf(x: f32) -> f32 {
select_implementation! {
name: truncf,
use_arch: all(target_arch = "wasm32", intrinsics_enabled),
args: x,
}
super::generic::trunc(x)
}
// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
#[cfg(not(target_arch = "powerpc64"))]
#[cfg(test)]
mod tests {
#[test]
fn sanity_check() {
assert_eq!(super::truncf(1.1), 1.0);
}
}

View file

@ -1,7 +0,0 @@
/// Rounds the number toward 0 to the closest integral value (f128).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf128(x: f128) -> f128 {
super::generic::trunc(x)
}

View file

@ -1,7 +0,0 @@
/// Rounds the number toward 0 to the closest integral value (f16).
///
/// This effectively removes the decimal part of the number, leaving the integral part.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn truncf16(x: f16) -> f16 {
super::generic::trunc(x)
}