Give rounding intrinsics their own modules
This commit is contained in:
parent
24ebae870e
commit
b4fda6ef06
4 changed files with 81 additions and 63 deletions
|
|
@ -43,14 +43,6 @@ extern "platform-intrinsic" {
|
|||
/// neg/fneg
|
||||
pub(crate) fn simd_neg<T>(x: T) -> T;
|
||||
|
||||
// floor
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn simd_floor<T>(x: T) -> T;
|
||||
|
||||
// ceil
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn simd_ceil<T>(x: T) -> T;
|
||||
|
||||
/// fabs
|
||||
pub(crate) fn simd_fabs<T>(x: T) -> T;
|
||||
|
||||
|
|
@ -85,3 +77,17 @@ extern "platform-intrinsic" {
|
|||
pub(crate) fn simd_reduce_or<T, U>(x: T) -> U;
|
||||
pub(crate) fn simd_reduce_xor<T, U>(x: T) -> U;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod std {
|
||||
extern "platform-intrinsic" {
|
||||
// ceil
|
||||
pub(crate) fn simd_ceil<T>(x: T) -> T;
|
||||
|
||||
// floor
|
||||
pub(crate) fn simd_floor<T>(x: T) -> T;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) use crate::intrinsics::std::*;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ macro_rules! implement {
|
|||
{
|
||||
$type:ident, $int_type:ident
|
||||
} => {
|
||||
#[cfg(feature = "std")]
|
||||
impl<const LANES: usize> crate::$type<LANES>
|
||||
where
|
||||
Self: crate::LanesAtMost32,
|
||||
{
|
||||
/// Returns the largest integer less than or equal to each lane.
|
||||
#[cfg(feature = "std")]
|
||||
#[must_use = "method returns a new vector and does not mutate the original value"]
|
||||
#[inline]
|
||||
pub fn floor(self) -> Self {
|
||||
|
|
@ -15,7 +15,6 @@ macro_rules! implement {
|
|||
}
|
||||
|
||||
/// Returns the smallest integer greater than or equal to each lane.
|
||||
#[cfg(feature = "std")]
|
||||
#[must_use = "method returns a new vector and does not mutate the original value"]
|
||||
#[inline]
|
||||
pub fn ceil(self) -> Self {
|
||||
|
|
|
|||
|
|
@ -353,7 +353,6 @@ macro_rules! impl_float_tests {
|
|||
mod $scalar {
|
||||
type Vector<const LANES: usize> = core_simd::$vector<LANES>;
|
||||
type Scalar = $scalar;
|
||||
type IntScalar = $int_scalar;
|
||||
|
||||
impl_unary_op_test!(Vector<LANES>, Scalar, Neg::neg);
|
||||
impl_binary_op_test!(Vector<LANES>, Scalar, Add::add, AddAssign::add_assign);
|
||||
|
|
@ -362,25 +361,6 @@ macro_rules! impl_float_tests {
|
|||
impl_binary_op_test!(Vector<LANES>, Scalar, Div::div, DivAssign::div_assign);
|
||||
impl_binary_op_test!(Vector<LANES>, Scalar, Rem::rem, RemAssign::rem_assign);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
test_helpers::test_lanes! {
|
||||
fn ceil<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::ceil,
|
||||
&Scalar::ceil,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
|
||||
fn floor<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::floor,
|
||||
&Scalar::floor,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test_helpers::test_lanes! {
|
||||
fn is_sign_positive<const LANES: usize>() {
|
||||
test_helpers::test_unary_mask_elementwise(
|
||||
|
|
@ -446,39 +426,6 @@ macro_rules! impl_float_tests {
|
|||
)
|
||||
}
|
||||
|
||||
fn round_from_int<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::round_from_int,
|
||||
&|x| x as Scalar,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
|
||||
fn to_int_unchecked<const LANES: usize>() {
|
||||
// The maximum integer that can be represented by the equivalently sized float has
|
||||
// all of the mantissa digits set to 1, pushed up to the MSB.
|
||||
const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1);
|
||||
const MAX_REPRESENTABLE_VALUE: Scalar =
|
||||
(ALL_MANTISSA_BITS << (core::mem::size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar;
|
||||
|
||||
let mut runner = proptest::test_runner::TestRunner::default();
|
||||
runner.run(
|
||||
&test_helpers::array::UniformArrayStrategy::new(-MAX_REPRESENTABLE_VALUE..MAX_REPRESENTABLE_VALUE),
|
||||
|x| {
|
||||
let result_1 = unsafe { Vector::from_array(x).to_int_unchecked().to_array() };
|
||||
let result_2 = {
|
||||
let mut result = [0; LANES];
|
||||
for (i, o) in x.iter().zip(result.iter_mut()) {
|
||||
*o = unsafe { i.to_int_unchecked() };
|
||||
}
|
||||
result
|
||||
};
|
||||
test_helpers::prop_assert_biteq!(result_1, result_2);
|
||||
Ok(())
|
||||
},
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
fn horizontal_sum<const LANES: usize>() {
|
||||
test_helpers::test_1(&|x| {
|
||||
test_helpers::prop_assert_biteq! (
|
||||
|
|
|
|||
66
crates/core_simd/tests/round.rs
Normal file
66
crates/core_simd/tests/round.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
macro_rules! float_rounding_test {
|
||||
{ $vector:ident, $scalar:tt, $int_scalar:tt } => {
|
||||
mod $scalar {
|
||||
type Vector<const LANES: usize> = core_simd::$vector<LANES>;
|
||||
type Scalar = $scalar;
|
||||
type IntScalar = $int_scalar;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
test_helpers::test_lanes! {
|
||||
fn ceil<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::ceil,
|
||||
&Scalar::ceil,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
|
||||
fn floor<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::floor,
|
||||
&Scalar::floor,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test_helpers::test_lanes! {
|
||||
fn from_int<const LANES: usize>() {
|
||||
test_helpers::test_unary_elementwise(
|
||||
&Vector::<LANES>::round_from_int,
|
||||
&|x| x as Scalar,
|
||||
&|_| true,
|
||||
)
|
||||
}
|
||||
|
||||
fn to_int_unchecked<const LANES: usize>() {
|
||||
// The maximum integer that can be represented by the equivalently sized float has
|
||||
// all of the mantissa digits set to 1, pushed up to the MSB.
|
||||
const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1);
|
||||
const MAX_REPRESENTABLE_VALUE: Scalar =
|
||||
(ALL_MANTISSA_BITS << (core::mem::size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar;
|
||||
|
||||
let mut runner = proptest::test_runner::TestRunner::default();
|
||||
runner.run(
|
||||
&test_helpers::array::UniformArrayStrategy::new(-MAX_REPRESENTABLE_VALUE..MAX_REPRESENTABLE_VALUE),
|
||||
|x| {
|
||||
let result_1 = unsafe { Vector::from_array(x).to_int_unchecked().to_array() };
|
||||
let result_2 = {
|
||||
let mut result = [0; LANES];
|
||||
for (i, o) in x.iter().zip(result.iter_mut()) {
|
||||
*o = unsafe { i.to_int_unchecked() };
|
||||
}
|
||||
result
|
||||
};
|
||||
test_helpers::prop_assert_biteq!(result_1, result_2);
|
||||
Ok(())
|
||||
},
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float_rounding_test! { SimdF32, f32, i32 }
|
||||
float_rounding_test! { SimdF64, f64, i64 }
|
||||
Loading…
Add table
Add a link
Reference in a new issue