1 use crate::simd::intrinsics::{simd_saturating_add, simd_saturating_sub};
2 use crate::simd::{LaneCount, Simd, SupportedLaneCount};
4 macro_rules! impl_uint_arith {
6 $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
8 /// Lanewise saturating add.
12 /// # #![feature(portable_simd)]
13 /// # #[cfg(feature = "std")] use core_simd::Simd;
14 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
15 #[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
16 /// let x = Simd::from_array([2, 1, 0, MAX]);
17 /// let max = Simd::splat(MAX);
18 /// let unsat = x + max;
19 /// let sat = x.saturating_add(max);
20 /// assert_eq!(x - 1, unsat);
21 /// assert_eq!(sat, max);
24 pub fn saturating_add(self, second: Self) -> Self {
25 unsafe { simd_saturating_add(self, second) }
28 /// Lanewise saturating subtract.
32 /// # #![feature(portable_simd)]
33 /// # #[cfg(feature = "std")] use core_simd::Simd;
34 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
35 #[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
36 /// let x = Simd::from_array([2, 1, 0, MAX]);
37 /// let max = Simd::splat(MAX);
38 /// let unsat = x - max;
39 /// let sat = x.saturating_sub(max);
40 /// assert_eq!(unsat, x + 1);
41 /// assert_eq!(sat, Simd::splat(0));
43 pub fn saturating_sub(self, second: Self) -> Self {
44 unsafe { simd_saturating_sub(self, second) }
50 macro_rules! impl_int_arith {
52 $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
54 /// Lanewise saturating add.
58 /// # #![feature(portable_simd)]
59 /// # #[cfg(feature = "std")] use core_simd::Simd;
60 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
61 #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
62 /// let x = Simd::from_array([MIN, 0, 1, MAX]);
63 /// let max = Simd::splat(MAX);
64 /// let unsat = x + max;
65 /// let sat = x.saturating_add(max);
66 /// assert_eq!(unsat, Simd::from_array([-1, MAX, MIN, -2]));
67 /// assert_eq!(sat, Simd::from_array([-1, MAX, MAX, MAX]));
70 pub fn saturating_add(self, second: Self) -> Self {
71 unsafe { simd_saturating_add(self, second) }
74 /// Lanewise saturating subtract.
78 /// # #![feature(portable_simd)]
79 /// # #[cfg(feature = "std")] use core_simd::Simd;
80 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
81 #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
82 /// let x = Simd::from_array([MIN, -2, -1, MAX]);
83 /// let max = Simd::splat(MAX);
84 /// let unsat = x - max;
85 /// let sat = x.saturating_sub(max);
86 /// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0]));
87 /// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0]));
89 pub fn saturating_sub(self, second: Self) -> Self {
90 unsafe { simd_saturating_sub(self, second) }
93 /// Lanewise absolute value, implemented in Rust.
94 /// Every lane becomes its absolute value.
98 /// # #![feature(portable_simd)]
99 /// # #[cfg(feature = "std")] use core_simd::Simd;
100 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
101 #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
102 /// let xs = Simd::from_array([MIN, MIN +1, -5, 0]);
103 /// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0]));
106 pub fn abs(self) -> Self {
107 const SHR: $ty = <$ty>::BITS as $ty - 1;
112 /// Lanewise saturating absolute value, implemented in Rust.
113 /// As abs(), except the MIN value becomes MAX instead of itself.
117 /// # #![feature(portable_simd)]
118 /// # #[cfg(feature = "std")] use core_simd::Simd;
119 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
120 #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
121 /// let xs = Simd::from_array([MIN, -2, 0, 3]);
122 /// let unsat = xs.abs();
123 /// let sat = xs.saturating_abs();
124 /// assert_eq!(unsat, Simd::from_array([MIN, 2, 0, 3]));
125 /// assert_eq!(sat, Simd::from_array([MAX, 2, 0, 3]));
128 pub fn saturating_abs(self) -> Self {
129 // arith shift for -1 or 0 mask based on sign bit, giving 2s complement
130 const SHR: $ty = <$ty>::BITS as $ty - 1;
132 (self^m).saturating_sub(m)
135 /// Lanewise saturating negation, implemented in Rust.
136 /// As neg(), except the MIN value becomes MAX instead of itself.
140 /// # #![feature(portable_simd)]
141 /// # #[cfg(feature = "std")] use core_simd::Simd;
142 /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
143 #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
144 /// let x = Simd::from_array([MIN, -2, 3, MAX]);
146 /// let sat = x.saturating_neg();
147 /// assert_eq!(unsat, Simd::from_array([MIN, 2, -3, MIN + 1]));
148 /// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1]));
151 pub fn saturating_neg(self) -> Self {
152 Self::splat(0).saturating_sub(self)
158 impl_uint_arith! { u8, u16, u32, u64, usize }
159 impl_int_arith! { i8, i16, i32, i64, isize }