/// 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;
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::*;
{
$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 {
}
/// 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 {
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);
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(
)
}
- 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! (
--- /dev/null
+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 }