about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLokathor <zefria@gmail.com>2020-10-07 22:15:30 -0600
committerGitHub <noreply@github.com>2020-10-07 22:15:30 -0600
commit0a46ca43e2833cb44adfc3c95c34d7edf7c15a4e (patch)
treecf21a89c7322f06c3a31806014efa3a074ff8d97
parenta1c327a034425b1cc44f47a825ab2dcbfdd24b22 (diff)
parentffd562f2181f5969d56c4a6c9399be27058c8a74 (diff)
downloadrust-0a46ca43e2833cb44adfc3c95c34d7edf7c15a4e.tar.gz
rust-0a46ca43e2833cb44adfc3c95c34d7edf7c15a4e.zip
Merge pull request #31 from thomcc/negxor
Use xor to implement Neg::neg for floats
-rw-r--r--crates/core_simd/src/ops.rs17
-rw-r--r--crates/core_simd/tests/ops_impl/float_macros.rs9
2 files changed, 24 insertions, 2 deletions
diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs
index 5af10a4e188..5a186649821 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 1c969a2e8af..7df30ec39f6 100644
--- a/crates/core_simd/tests/ops_impl/float_macros.rs
+++ b/crates/core_simd/tests/ops_impl/float_macros.rs
@@ -291,6 +291,15 @@ macro_rules! float_tests {
 
             #[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() {
                 let v = -from_slice(&A);
                 let expected = apply_unary_lanewise(v, <$scalar>::abs);