Skip to content

Commit 6620015

Browse files
Merge pull request rust-lang#86 from rust-lang/feat/saturating
Introduce saturating math
2 parents 65c3ce9 + 4a6b4c0 commit 6620015

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

Diff for: crates/core_simd/src/intrinsics.rs

+6
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,10 @@ extern "platform-intrinsic" {
6262
pub(crate) fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
6363
pub(crate) fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
6464
pub(crate) fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
65+
66+
// {s,u}add.sat
67+
pub(crate) fn simd_saturating_add<T>(x: T, y: T) -> T;
68+
69+
// {s,u}sub.sat
70+
pub(crate) fn simd_saturating_sub<T>(x: T, y: T) -> T;
6571
}

Diff for: crates/core_simd/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![no_std]
22
#![allow(incomplete_features)]
33
#![feature(repr_simd, platform_intrinsics, simd_ffi, const_generics)]
4+
#![feature(extended_key_value_attributes)]
45
#![warn(missing_docs)]
56
//! Portable SIMD module.
67
@@ -16,6 +17,8 @@ mod intrinsics;
1617
mod ops;
1718
mod round;
1819

20+
mod math;
21+
1922
mod lanes_at_most_64;
2023
pub use lanes_at_most_64::LanesAtMost64;
2124

Diff for: crates/core_simd/src/math.rs

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
macro_rules! impl_uint_arith {
2+
($(($name:ident, $n:ty)),+) => {
3+
$( impl<const LANES: usize> $name<LANES> where Self: crate::LanesAtMost64 {
4+
5+
/// Lanewise saturating add.
6+
///
7+
/// # Examples
8+
/// ```
9+
/// # use core_simd::*;
10+
#[doc = concat!("# use core::", stringify!($n), "::MAX;")]
11+
#[doc = concat!("let x = ", stringify!($name), "::from_array([2, 1, 0, MAX]);")]
12+
#[doc = concat!("let max = ", stringify!($name), "::splat(MAX);")]
13+
/// let unsat = x + max;
14+
/// let sat = x.saturating_add(max);
15+
/// assert_eq!(x - 1, unsat);
16+
/// assert_eq!(sat, max);
17+
/// ```
18+
#[inline]
19+
pub fn saturating_add(self, second: Self) -> Self {
20+
unsafe { crate::intrinsics::simd_saturating_add(self, second) }
21+
}
22+
23+
/// Lanewise saturating subtract.
24+
///
25+
/// # Examples
26+
/// ```
27+
/// # use core_simd::*;
28+
#[doc = concat!("# use core::", stringify!($n), "::MAX;")]
29+
#[doc = concat!("let x = ", stringify!($name), "::from_array([2, 1, 0, MAX]);")]
30+
#[doc = concat!("let max = ", stringify!($name), "::splat(MAX);")]
31+
/// let unsat = x - max;
32+
/// let sat = x.saturating_sub(max);
33+
/// assert_eq!(unsat, x + 1);
34+
#[doc = concat!("assert_eq!(sat, ", stringify!($name), "::splat(0));")]
35+
#[inline]
36+
pub fn saturating_sub(self, second: Self) -> Self {
37+
unsafe { crate::intrinsics::simd_saturating_sub(self, second) }
38+
}
39+
})+
40+
}
41+
}
42+
43+
macro_rules! impl_int_arith {
44+
($(($name:ident, $n:ty)),+) => {
45+
$( impl<const LANES: usize> $name<LANES> where Self: crate::LanesAtMost64 {
46+
47+
/// Lanewise saturating add.
48+
///
49+
/// # Examples
50+
/// ```
51+
/// # use core_simd::*;
52+
#[doc = concat!("# use core::", stringify!($n), "::{MIN, MAX};")]
53+
#[doc = concat!("let x = ", stringify!($name), "::from_array([MIN, 0, 1, MAX]);")]
54+
#[doc = concat!("let max = ", stringify!($name), "::splat(MAX);")]
55+
/// let unsat = x + max;
56+
/// let sat = x.saturating_add(max);
57+
#[doc = concat!("assert_eq!(unsat, ", stringify!($name), "::from_array([-1, MAX, MIN, -2]));")]
58+
#[doc = concat!("assert_eq!(sat, ", stringify!($name), "::from_array([-1, MAX, MAX, MAX]));")]
59+
/// ```
60+
#[inline]
61+
pub fn saturating_add(self, second: Self) -> Self {
62+
unsafe { crate::intrinsics::simd_saturating_add(self, second) }
63+
}
64+
65+
/// Lanewise saturating subtract.
66+
///
67+
/// # Examples
68+
/// ```
69+
/// # use core_simd::*;
70+
#[doc = concat!("# use core::", stringify!($n), "::{MIN, MAX};")]
71+
#[doc = concat!("let x = ", stringify!($name), "::from_array([MIN, -2, -1, MAX]);")]
72+
#[doc = concat!("let max = ", stringify!($name), "::splat(MAX);")]
73+
/// let unsat = x - max;
74+
/// let sat = x.saturating_sub(max);
75+
#[doc = concat!("assert_eq!(unsat, ", stringify!($name), "::from_array([1, MAX, MIN, 0]));")]
76+
#[doc = concat!("assert_eq!(sat, ", stringify!($name), "::from_array([MIN, MIN, MIN, 0]));")]
77+
#[inline]
78+
pub fn saturating_sub(self, second: Self) -> Self {
79+
unsafe { crate::intrinsics::simd_saturating_sub(self, second) }
80+
}
81+
})+
82+
}
83+
}
84+
85+
use crate::vector::*;
86+
87+
impl_uint_arith! { (SimdU8, u8), (SimdU16, u16), (SimdU32, u32), (SimdU64, u64), (SimdUsize, usize) }
88+
impl_int_arith! { (SimdI8, i8), (SimdI16, i16), (SimdI32, i32), (SimdI64, i64), (SimdIsize, isize) }

0 commit comments

Comments
 (0)