diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index 5af10a4e1886..5a186649821b 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -212,7 +212,20 @@ macro_rules! impl_op { impl core::ops::Neg for $type { type Output = Self; fn neg(self) -> Self::Output { - <$type>::splat(-<$scalar>::default()) - self + <$type>::splat(0) - self + } + } + } + }; + + { impl Neg for $type:ty, $scalar:ty, @float } => { + impl_ref_ops! { + impl core::ops::Neg for $type { + type Output = Self; + fn neg(self) -> Self::Output { + // FIXME: Replace this with fneg intrinsic once available. + // https://github.com/rust-lang/stdsimd/issues/32 + Self::from_bits(<$type>::splat(-0.0).to_bits() ^ self.to_bits()) } } } @@ -310,7 +323,7 @@ macro_rules! impl_float_ops { impl_op! { impl Mul for $vector, $scalar } impl_op! { impl Div for $vector, $scalar } impl_op! { impl Rem for $vector, $scalar } - impl_op! { impl Neg for $vector, $scalar } + impl_op! { impl Neg for $vector, $scalar, @float } impl_op! { impl Index for $vector, $scalar } )* )* diff --git a/crates/core_simd/tests/ops_impl/float_macros.rs b/crates/core_simd/tests/ops_impl/float_macros.rs index 1c969a2e8af3..7df30ec39f6c 100644 --- a/crates/core_simd/tests/ops_impl/float_macros.rs +++ b/crates/core_simd/tests/ops_impl/float_macros.rs @@ -289,6 +289,15 @@ macro_rules! float_tests { assert_biteq!(-v, expected); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn neg_odd_floats() { + for v in slice_chunks(&C) { + let expected = apply_unary_lanewise(v, core::ops::Neg::neg); + assert_biteq!(-v, expected); + } + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn abs_negative() {