]>
Commit | Line | Data |
---|---|---|
3c0e092e XL |
1 | use crate::simd::intrinsics; |
2 | use crate::simd::{LaneCount, Mask, Simd, SimdElement, SupportedLaneCount}; | |
3 | ||
4 | impl<T, const LANES: usize> Simd<T, LANES> | |
5 | where | |
6 | T: SimdElement + PartialEq, | |
7 | LaneCount<LANES>: SupportedLaneCount, | |
8 | { | |
9 | /// Test if each lane is equal to the corresponding lane in `other`. | |
10 | #[inline] | |
a2a8927a | 11 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 12 | pub fn lanes_eq(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
13 | // Safety: `self` is a vector, and the result of the comparison |
14 | // is always a valid mask. | |
3c0e092e XL |
15 | unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) } |
16 | } | |
17 | ||
18 | /// Test if each lane is not equal to the corresponding lane in `other`. | |
19 | #[inline] | |
a2a8927a | 20 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 21 | pub fn lanes_ne(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
22 | // Safety: `self` is a vector, and the result of the comparison |
23 | // is always a valid mask. | |
3c0e092e XL |
24 | unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) } |
25 | } | |
26 | } | |
27 | ||
28 | impl<T, const LANES: usize> Simd<T, LANES> | |
29 | where | |
30 | T: SimdElement + PartialOrd, | |
31 | LaneCount<LANES>: SupportedLaneCount, | |
32 | { | |
33 | /// Test if each lane is less than the corresponding lane in `other`. | |
34 | #[inline] | |
a2a8927a | 35 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 36 | pub fn lanes_lt(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
37 | // Safety: `self` is a vector, and the result of the comparison |
38 | // is always a valid mask. | |
3c0e092e XL |
39 | unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) } |
40 | } | |
41 | ||
42 | /// Test if each lane is greater than the corresponding lane in `other`. | |
43 | #[inline] | |
a2a8927a | 44 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 45 | pub fn lanes_gt(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
46 | // Safety: `self` is a vector, and the result of the comparison |
47 | // is always a valid mask. | |
3c0e092e XL |
48 | unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) } |
49 | } | |
50 | ||
51 | /// Test if each lane is less than or equal to the corresponding lane in `other`. | |
52 | #[inline] | |
a2a8927a | 53 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 54 | pub fn lanes_le(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
55 | // Safety: `self` is a vector, and the result of the comparison |
56 | // is always a valid mask. | |
3c0e092e XL |
57 | unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) } |
58 | } | |
59 | ||
60 | /// Test if each lane is greater than or equal to the corresponding lane in `other`. | |
61 | #[inline] | |
a2a8927a | 62 | #[must_use = "method returns a new mask and does not mutate the original value"] |
3c0e092e | 63 | pub fn lanes_ge(self, other: Self) -> Mask<T::Mask, LANES> { |
5e7ed085 FG |
64 | // Safety: `self` is a vector, and the result of the comparison |
65 | // is always a valid mask. | |
3c0e092e XL |
66 | unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) } |
67 | } | |
68 | } | |
5e7ed085 FG |
69 | |
70 | macro_rules! impl_ord_methods_vector { | |
71 | { $type:ty } => { | |
72 | impl<const LANES: usize> Simd<$type, LANES> | |
73 | where | |
74 | LaneCount<LANES>: SupportedLaneCount, | |
75 | { | |
76 | /// Returns the lane-wise minimum with `other`. | |
77 | #[must_use = "method returns a new vector and does not mutate the original value"] | |
78 | #[inline] | |
79 | pub fn min(self, other: Self) -> Self { | |
80 | self.lanes_gt(other).select(other, self) | |
81 | } | |
82 | ||
83 | /// Returns the lane-wise maximum with `other`. | |
84 | #[must_use = "method returns a new vector and does not mutate the original value"] | |
85 | #[inline] | |
86 | pub fn max(self, other: Self) -> Self { | |
87 | self.lanes_lt(other).select(other, self) | |
88 | } | |
89 | ||
90 | /// Restrict each lane to a certain interval. | |
91 | /// | |
92 | /// For each lane, returns `max` if `self` is greater than `max`, and `min` if `self` is | |
93 | /// less than `min`. Otherwise returns `self`. | |
94 | /// | |
95 | /// # Panics | |
96 | /// | |
97 | /// Panics if `min > max` on any lane. | |
98 | #[must_use = "method returns a new vector and does not mutate the original value"] | |
99 | #[inline] | |
100 | pub fn clamp(self, min: Self, max: Self) -> Self { | |
101 | assert!( | |
102 | min.lanes_le(max).all(), | |
103 | "each lane in `min` must be less than or equal to the corresponding lane in `max`", | |
104 | ); | |
105 | self.max(min).min(max) | |
106 | } | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | impl_ord_methods_vector!(i8); | |
112 | impl_ord_methods_vector!(i16); | |
113 | impl_ord_methods_vector!(i32); | |
114 | impl_ord_methods_vector!(i64); | |
115 | impl_ord_methods_vector!(isize); | |
116 | impl_ord_methods_vector!(u8); | |
117 | impl_ord_methods_vector!(u16); | |
118 | impl_ord_methods_vector!(u32); | |
119 | impl_ord_methods_vector!(u64); | |
120 | impl_ord_methods_vector!(usize); |