1use crate::simd::{
2Mask, Select, Simd,
3cmp::SimdPartialEq,
4 ptr::{SimdConstPtr, SimdMutPtr},
5};
67/// Parallel `PartialOrd`.
8pub trait SimdPartialOrd: SimdPartialEq {
9/// Test if each element is less than the corresponding element in `other`.
10#[must_use = "method returns a new mask and does not mutate the original value"]
11fn simd_lt(self, other: Self) -> Self::Mask;
1213/// Test if each element is less than or equal to the corresponding element in `other`.
14#[must_use = "method returns a new mask and does not mutate the original value"]
15fn simd_le(self, other: Self) -> Self::Mask;
1617/// Test if each element is greater than the corresponding element in `other`.
18#[must_use = "method returns a new mask and does not mutate the original value"]
19fn simd_gt(self, other: Self) -> Self::Mask;
2021/// Test if each element is greater than or equal to the corresponding element in `other`.
22#[must_use = "method returns a new mask and does not mutate the original value"]
23fn simd_ge(self, other: Self) -> Self::Mask;
24}
2526/// Parallel `Ord`.
27pub trait SimdOrd: SimdPartialOrd {
28/// Returns the element-wise maximum with `other`.
29#[must_use = "method returns a new vector and does not mutate the original value"]
30fn simd_max(self, other: Self) -> Self;
3132/// Returns the element-wise minimum with `other`.
33#[must_use = "method returns a new vector and does not mutate the original value"]
34fn simd_min(self, other: Self) -> Self;
3536/// Restrict each element to a certain interval.
37 ///
38 /// For each element, returns `max` if `self` is greater than `max`, and `min` if `self` is
39 /// less than `min`. Otherwise returns `self`.
40 ///
41 /// # Panics
42 ///
43 /// Panics if `min > max` on any element.
44#[must_use = "method returns a new vector and does not mutate the original value"]
45fn simd_clamp(self, min: Self, max: Self) -> Self;
46}
4748macro_rules!impl_integer {
49 { $($integer:ty),* } => {
50 $(
51impl<const N: usize> SimdPartialOrd for Simd<$integer, N>
52 {
53#[inline]
54fn simd_lt(self, other: Self) -> Self::Mask {
55// Safety: `self` is a vector, and the result of the comparison
56 // is always a valid mask.
57unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) }
58 }
5960#[inline]
61fn simd_le(self, other: Self) -> Self::Mask {
62// Safety: `self` is a vector, and the result of the comparison
63 // is always a valid mask.
64unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) }
65 }
6667#[inline]
68fn simd_gt(self, other: Self) -> Self::Mask {
69// Safety: `self` is a vector, and the result of the comparison
70 // is always a valid mask.
71unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) }
72 }
7374#[inline]
75fn simd_ge(self, other: Self) -> Self::Mask {
76// Safety: `self` is a vector, and the result of the comparison
77 // is always a valid mask.
78unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) }
79 }
80 }
8182impl<const N: usize> SimdOrd for Simd<$integer, N>
83 {
84#[inline]
85fn simd_max(self, other: Self) -> Self {
86self.simd_lt(other).select(other, self)
87 }
8889#[inline]
90fn simd_min(self, other: Self) -> Self {
91self.simd_gt(other).select(other, self)
92 }
9394#[inline]
95 #[track_caller]
96fn simd_clamp(self, min: Self, max: Self) -> Self {
97assert!(
98 min.simd_le(max).all(),
99"each element in `min` must be less than or equal to the corresponding element in `max`",
100 );
101self.simd_max(min).simd_min(max)
102 }
103 }
104 )*
105 }
106}
107108impl<const N : usize> SimdPartialOrd for Simd<isize, N> {
#[inline]
fn simd_lt(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self,
other))
}
}
#[inline]
fn simd_le(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self,
other))
}
}
#[inline]
fn simd_gt(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self,
other))
}
}
#[inline]
fn simd_ge(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self,
other))
}
}
}
impl<const N : usize> SimdOrd for Simd<isize, N> {
#[inline]
fn simd_max(self, other: Self) -> Self {
self.simd_lt(other).select(other, self)
}
#[inline]
fn simd_min(self, other: Self) -> Self {
self.simd_gt(other).select(other, self)
}
#[inline]
#[track_caller]
fn simd_clamp(self, min: Self, max: Self) -> Self {
if !min.simd_le(max).all() {
{
crate::panicking::panic_fmt(format_args!("each element in `min` must be less than or equal to the corresponding element in `max`"));
}
};
self.simd_max(min).simd_min(max)
}
}impl_integer! { u8, u16, u32, u64, usize, i8, i16, i32, i64, isize }109110macro_rules!impl_float {
111 { $($float:ty),* } => {
112 $(
113impl<const N: usize> SimdPartialOrd for Simd<$float, N>
114 {
115#[inline]
116fn simd_lt(self, other: Self) -> Self::Mask {
117// Safety: `self` is a vector, and the result of the comparison
118 // is always a valid mask.
119unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) }
120 }
121122#[inline]
123fn simd_le(self, other: Self) -> Self::Mask {
124// Safety: `self` is a vector, and the result of the comparison
125 // is always a valid mask.
126unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) }
127 }
128129#[inline]
130fn simd_gt(self, other: Self) -> Self::Mask {
131// Safety: `self` is a vector, and the result of the comparison
132 // is always a valid mask.
133unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) }
134 }
135136#[inline]
137fn simd_ge(self, other: Self) -> Self::Mask {
138// Safety: `self` is a vector, and the result of the comparison
139 // is always a valid mask.
140unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) }
141 }
142 }
143 )*
144 }
145}
146147impl<const N : usize> SimdPartialOrd for Simd<f64, N> {
#[inline]
fn simd_lt(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self,
other))
}
}
#[inline]
fn simd_le(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self,
other))
}
}
#[inline]
fn simd_gt(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self,
other))
}
}
#[inline]
fn simd_ge(self, other: Self) -> Self::Mask {
unsafe {
Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self,
other))
}
}
}impl_float! { f16, f32, f64 }148149macro_rules!impl_mask {
150 { $($integer:ty),* } => {
151 $(
152impl<const N: usize> SimdPartialOrd for Mask<$integer, N>
153 {
154#[inline]
155fn simd_lt(self, other: Self) -> Self::Mask {
156// Safety: `self` is a vector, and the result of the comparison
157 // is always a valid mask.
158unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(), other.to_simd())) }
159 }
160161#[inline]
162fn simd_le(self, other: Self) -> Self::Mask {
163// Safety: `self` is a vector, and the result of the comparison
164 // is always a valid mask.
165unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_le(self.to_simd(), other.to_simd())) }
166 }
167168#[inline]
169fn simd_gt(self, other: Self) -> Self::Mask {
170// Safety: `self` is a vector, and the result of the comparison
171 // is always a valid mask.
172unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(), other.to_simd())) }
173 }
174175#[inline]
176fn simd_ge(self, other: Self) -> Self::Mask {
177// Safety: `self` is a vector, and the result of the comparison
178 // is always a valid mask.
179unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(), other.to_simd())) }
180 }
181 }
182183impl<const N: usize> SimdOrd for Mask<$integer, N>
184 {
185#[inline]
186fn simd_max(self, other: Self) -> Self {
187self.simd_gt(other).select(other, self)
188 }
189190#[inline]
191fn simd_min(self, other: Self) -> Self {
192self.simd_lt(other).select(other, self)
193 }
194195#[inline]
196 #[track_caller]
197fn simd_clamp(self, min: Self, max: Self) -> Self {
198assert!(
199 min.simd_le(max).all(),
200"each element in `min` must be less than or equal to the corresponding element in `max`",
201 );
202self.simd_max(min).simd_min(max)
203 }
204 }
205 )*
206 }
207}
208209impl<const N : usize> SimdPartialOrd for Mask<isize, N> {
#[inline]
fn simd_lt(self, other: Self) -> Self::Mask {
unsafe {
Self::from_simd_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(),
other.to_simd()))
}
}
#[inline]
fn simd_le(self, other: Self) -> Self::Mask {
unsafe {
Self::from_simd_unchecked(core::intrinsics::simd::simd_le(self.to_simd(),
other.to_simd()))
}
}
#[inline]
fn simd_gt(self, other: Self) -> Self::Mask {
unsafe {
Self::from_simd_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(),
other.to_simd()))
}
}
#[inline]
fn simd_ge(self, other: Self) -> Self::Mask {
unsafe {
Self::from_simd_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(),
other.to_simd()))
}
}
}
impl<const N : usize> SimdOrd for Mask<isize, N> {
#[inline]
fn simd_max(self, other: Self) -> Self {
self.simd_gt(other).select(other, self)
}
#[inline]
fn simd_min(self, other: Self) -> Self {
self.simd_lt(other).select(other, self)
}
#[inline]
#[track_caller]
fn simd_clamp(self, min: Self, max: Self) -> Self {
if !min.simd_le(max).all() {
{
crate::panicking::panic_fmt(format_args!("each element in `min` must be less than or equal to the corresponding element in `max`"));
}
};
self.simd_max(min).simd_min(max)
}
}impl_mask! { i8, i16, i32, i64, isize }210211impl<T, const N: usize> SimdPartialOrdfor Simd<*const T, N> {
212#[inline]
213fn simd_lt(self, other: Self) -> Self::Mask {
214self.addr().simd_lt(other.addr())
215 }
216217#[inline]
218fn simd_le(self, other: Self) -> Self::Mask {
219self.addr().simd_le(other.addr())
220 }
221222#[inline]
223fn simd_gt(self, other: Self) -> Self::Mask {
224self.addr().simd_gt(other.addr())
225 }
226227#[inline]
228fn simd_ge(self, other: Self) -> Self::Mask {
229self.addr().simd_ge(other.addr())
230 }
231}
232233impl<T, const N: usize> SimdOrdfor Simd<*const T, N> {
234#[inline]
235fn simd_max(self, other: Self) -> Self {
236self.simd_lt(other).select(other, self)
237 }
238239#[inline]
240fn simd_min(self, other: Self) -> Self {
241self.simd_gt(other).select(other, self)
242 }
243244#[inline]
245 #[track_caller]
246fn simd_clamp(self, min: Self, max: Self) -> Self {
247if !min.simd_le(max).all() {
{
crate::panicking::panic_fmt(format_args!("each element in `min` must be less than or equal to the corresponding element in `max`"));
}
};assert!(
248 min.simd_le(max).all(),
249"each element in `min` must be less than or equal to the corresponding element in `max`",
250 );
251self.simd_max(min).simd_min(max)
252 }
253}
254255impl<T, const N: usize> SimdPartialOrdfor Simd<*mut T, N> {
256#[inline]
257fn simd_lt(self, other: Self) -> Self::Mask {
258self.addr().simd_lt(other.addr())
259 }
260261#[inline]
262fn simd_le(self, other: Self) -> Self::Mask {
263self.addr().simd_le(other.addr())
264 }
265266#[inline]
267fn simd_gt(self, other: Self) -> Self::Mask {
268self.addr().simd_gt(other.addr())
269 }
270271#[inline]
272fn simd_ge(self, other: Self) -> Self::Mask {
273self.addr().simd_ge(other.addr())
274 }
275}
276277impl<T, const N: usize> SimdOrdfor Simd<*mut T, N> {
278#[inline]
279fn simd_max(self, other: Self) -> Self {
280self.simd_lt(other).select(other, self)
281 }
282283#[inline]
284fn simd_min(self, other: Self) -> Self {
285self.simd_gt(other).select(other, self)
286 }
287288#[inline]
289 #[track_caller]
290fn simd_clamp(self, min: Self, max: Self) -> Self {
291if !min.simd_le(max).all() {
{
crate::panicking::panic_fmt(format_args!("each element in `min` must be less than or equal to the corresponding element in `max`"));
}
};assert!(
292 min.simd_le(max).all(),
293"each element in `min` must be less than or equal to the corresponding element in `max`",
294 );
295self.simd_max(min).simd_min(max)
296 }
297}