rust/crates/core_simd/src/math.rs

152 lines
5.9 KiB
Rust
Raw Normal View History

2021-08-07 14:28:27 -05:00
use crate::{LaneCount, Simd, SupportedLaneCount};
2021-03-28 20:44:16 -05:00
macro_rules! impl_uint_arith {
2021-08-07 14:28:27 -05:00
($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
2021-03-28 20:44:16 -05:00
/// Lanewise saturating add.
///
/// # Examples
/// ```
/// # #![feature(portable_simd)]
2021-03-28 20:44:16 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
/// let x = Simd::from_array([2, 1, 0, MAX]);
/// let max = Simd::splat(MAX);
2021-03-28 20:44:16 -05:00
/// let unsat = x + max;
/// let sat = x.saturating_add(max);
/// assert_eq!(x - 1, unsat);
/// assert_eq!(sat, max);
/// ```
#[inline]
pub fn saturating_add(self, second: Self) -> Self {
unsafe { crate::intrinsics::simd_saturating_add(self, second) }
}
/// Lanewise saturating subtract.
///
/// # Examples
/// ```
/// # #![feature(portable_simd)]
2021-03-28 20:44:16 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
/// let x = Simd::from_array([2, 1, 0, MAX]);
/// let max = Simd::splat(MAX);
2021-03-28 20:44:16 -05:00
/// let unsat = x - max;
/// let sat = x.saturating_sub(max);
/// assert_eq!(unsat, x + 1);
2021-08-07 14:28:27 -05:00
/// assert_eq!(sat, Simd::splat(0));
2021-03-28 20:44:16 -05:00
#[inline]
pub fn saturating_sub(self, second: Self) -> Self {
unsafe { crate::intrinsics::simd_saturating_sub(self, second) }
}
})+
}
}
macro_rules! impl_int_arith {
2021-08-07 14:28:27 -05:00
($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
2021-03-28 20:44:16 -05:00
/// Lanewise saturating add.
///
/// # Examples
/// ```
/// # #![feature(portable_simd)]
2021-03-28 20:44:16 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let x = Simd::from_array([MIN, 0, 1, MAX]);
/// let max = Simd::splat(MAX);
2021-03-28 20:44:16 -05:00
/// let unsat = x + max;
/// let sat = x.saturating_add(max);
2021-08-07 14:28:27 -05:00
/// assert_eq!(unsat, Simd::from_array([-1, MAX, MIN, -2]));
/// assert_eq!(sat, Simd::from_array([-1, MAX, MAX, MAX]));
2021-03-28 20:44:16 -05:00
/// ```
#[inline]
pub fn saturating_add(self, second: Self) -> Self {
unsafe { crate::intrinsics::simd_saturating_add(self, second) }
}
/// Lanewise saturating subtract.
///
/// # Examples
/// ```
/// # #![feature(portable_simd)]
2021-03-28 20:44:16 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let x = Simd::from_array([MIN, -2, -1, MAX]);
/// let max = Simd::splat(MAX);
2021-03-28 20:44:16 -05:00
/// let unsat = x - max;
/// let sat = x.saturating_sub(max);
2021-08-07 14:28:27 -05:00
/// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0]));
/// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0]));
2021-03-28 20:44:16 -05:00
#[inline]
pub fn saturating_sub(self, second: Self) -> Self {
unsafe { crate::intrinsics::simd_saturating_sub(self, second) }
}
2021-04-02 10:28:48 -05:00
2021-04-13 22:19:53 -05:00
/// Lanewise absolute value, implemented in Rust.
/// Every lane becomes its absolute value.
///
/// # Examples
/// ```
/// # #![feature(portable_simd)]
2021-04-13 22:19:53 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let xs = Simd::from_array([MIN, MIN +1, -5, 0]);
/// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0]));
2021-04-13 22:19:53 -05:00
/// ```
#[inline]
pub fn abs(self) -> Self {
2021-08-07 14:28:27 -05:00
const SHR: $ty = <$ty>::BITS as $ty - 1;
2021-04-13 23:15:20 -05:00
let m = self >> SHR;
(self^m) - m
2021-04-13 22:19:53 -05:00
}
2021-04-02 10:28:48 -05:00
/// Lanewise saturating absolute value, implemented in Rust.
2021-04-02 11:11:24 -05:00
/// As abs(), except the MIN value becomes MAX instead of itself.
2021-04-02 10:28:48 -05:00
///
/// # Examples
2021-04-11 10:42:29 -05:00
/// ```
/// # #![feature(portable_simd)]
2021-04-02 10:28:48 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let xs = Simd::from_array([MIN, -2, 0, 3]);
2021-04-13 22:19:53 -05:00
/// let unsat = xs.abs();
/// let sat = xs.saturating_abs();
2021-08-07 14:28:27 -05:00
/// assert_eq!(unsat, Simd::from_array([MIN, 2, 0, 3]));
/// assert_eq!(sat, Simd::from_array([MAX, 2, 0, 3]));
2021-04-02 10:28:48 -05:00
/// ```
#[inline]
pub fn saturating_abs(self) -> Self {
// arith shift for -1 or 0 mask based on sign bit, giving 2s complement
2021-08-07 14:28:27 -05:00
const SHR: $ty = <$ty>::BITS as $ty - 1;
2021-04-02 10:28:48 -05:00
let m = self >> SHR;
(self^m).saturating_sub(m)
}
/// Lanewise saturating negation, implemented in Rust.
2021-04-02 11:11:24 -05:00
/// As neg(), except the MIN value becomes MAX instead of itself.
2021-04-02 10:28:48 -05:00
///
/// # Examples
2021-04-11 10:42:29 -05:00
/// ```
/// # #![feature(portable_simd)]
2021-04-02 10:28:48 -05:00
/// # use core_simd::*;
2021-08-07 14:28:27 -05:00
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let x = Simd::from_array([MIN, -2, 3, MAX]);
2021-04-02 10:28:48 -05:00
/// let unsat = -x;
/// let sat = x.saturating_neg();
2021-08-07 14:28:27 -05:00
/// assert_eq!(unsat, Simd::from_array([MIN, 2, -3, MIN + 1]));
/// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1]));
2021-04-02 10:28:48 -05:00
/// ```
#[inline]
pub fn saturating_neg(self) -> Self {
Self::splat(0).saturating_sub(self)
}
2021-03-28 20:44:16 -05:00
})+
}
}
2021-08-07 14:28:27 -05:00
impl_uint_arith! { u8, u16, u32, u64, usize }
impl_int_arith! { i8, i16, i32, i64, isize }