about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2021-04-02 19:41:59 -0400
committerGitHub <noreply@github.com>2021-04-02 19:41:59 -0400
commit4e6d44086cb817cc81b5528d643bab53095773cb (patch)
treed833cff6ee3b40352bb76800868d7f420b70d76b
parent6620015a779a5391808d16d3e65459bd0bdfb65b (diff)
parent331230fabff28d2c883967e2ac4ef02eaea4db5c (diff)
downloadrust-4e6d44086cb817cc81b5528d643bab53095773cb.tar.gz
rust-4e6d44086cb817cc81b5528d643bab53095773cb.zip
Merge pull request #87 from rust-lang/feat/sat-abs-neg
Add saturating abs/neg
-rw-r--r--crates/core_simd/src/math.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs
index 6fabf35e3da..eb46feb5c4b 100644
--- a/crates/core_simd/src/math.rs
+++ b/crates/core_simd/src/math.rs
@@ -78,6 +78,43 @@ macro_rules! impl_int_arith {
             pub fn saturating_sub(self, second: Self) -> Self {
                 unsafe { crate::intrinsics::simd_saturating_sub(self, second) }
             }
+
+            /// Lanewise saturating absolute value, implemented in Rust.
+            /// As abs(), except the MIN value becomes MAX instead of itself.
+            ///
+            /// # Examples
+            /// # use core_simd::*;
+            #[doc = concat!("# use core::", stringify!($n), "::{MIN, MAX};")]
+            #[doc = concat!("let x = ", stringify!($name), "::splat([MIN, -2, 0, 3]);")]
+            /// let unsat = x.abs();
+            /// let sat = x.saturating_abs();
+            #[doc = concat!("assert_eq!(unsat, ", stringify!($name), "::from_array([MIN, 2, 0, 3]);")]
+            #[doc = concat!("assert_eq!(sat, ", stringify!($name), "::from_array([MAX, 2, 0, 3]));")]
+            /// ```
+            #[inline]
+            pub fn saturating_abs(self) -> Self {
+                // arith shift for -1 or 0 mask based on sign bit, giving 2s complement
+                const SHR: $n = <$n>::BITS as $n - 1;
+                let m = self >> SHR;
+                (self^m).saturating_sub(m)
+            }
+
+            /// Lanewise saturating negation, implemented in Rust.
+            /// As neg(), except the MIN value becomes MAX instead of itself.
+            ///
+            /// # Examples
+            /// # use core_simd::*;
+            #[doc = concat!("# use core::", stringify!($n), "::{MIN, MAX};")]
+            #[doc = concat!("let x = ", stringify!($name), "::splat([MIN, -2, 3, MAX]);")]
+            /// let unsat = -x;
+            /// let sat = x.saturating_neg();
+            #[doc = concat!("assert_eq!(unsat, ", stringify!($name), "::from_array([MIN, 2, -3, MIN + 1]);")]
+            #[doc = concat!("assert_eq!(sat, ", stringify!($name), "::from_array([MAX, 2, -3, MIN + 1]));")]
+            /// ```
+            #[inline]
+            pub fn saturating_neg(self) -> Self {
+                Self::splat(0).saturating_sub(self)
+            }
         })+
     }
 }