1 | use crate::simd::{ |
2 | intrinsics, |
3 | ptr::{SimdConstPtr, SimdMutPtr}, |
4 | LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, |
5 | }; |
6 | |
7 | /// Parallel `PartialEq`. |
8 | pub trait SimdPartialEq { |
9 | /// The mask type returned by each comparison. |
10 | type Mask; |
11 | |
12 | /// Test if each element is equal to the corresponding element in `other`. |
13 | #[must_use = "method returns a new mask and does not mutate the original value" ] |
14 | fn simd_eq(self, other: Self) -> Self::Mask; |
15 | |
16 | /// Test if each element is equal to the corresponding element in `other`. |
17 | #[must_use = "method returns a new mask and does not mutate the original value" ] |
18 | fn simd_ne(self, other: Self) -> Self::Mask; |
19 | } |
20 | |
21 | macro_rules! impl_number { |
22 | { $($number:ty),* } => { |
23 | $( |
24 | impl<const N: usize> SimdPartialEq for Simd<$number, N> |
25 | where |
26 | LaneCount<N>: SupportedLaneCount, |
27 | { |
28 | type Mask = Mask<<$number as SimdElement>::Mask, N>; |
29 | |
30 | #[inline] |
31 | fn simd_eq(self, other: Self) -> Self::Mask { |
32 | // Safety: `self` is a vector, and the result of the comparison |
33 | // is always a valid mask. |
34 | unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) } |
35 | } |
36 | |
37 | #[inline] |
38 | fn simd_ne(self, other: Self) -> Self::Mask { |
39 | // Safety: `self` is a vector, and the result of the comparison |
40 | // is always a valid mask. |
41 | unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) } |
42 | } |
43 | } |
44 | )* |
45 | } |
46 | } |
47 | |
48 | impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } |
49 | |
50 | macro_rules! impl_mask { |
51 | { $($integer:ty),* } => { |
52 | $( |
53 | impl<const N: usize> SimdPartialEq for Mask<$integer, N> |
54 | where |
55 | LaneCount<N>: SupportedLaneCount, |
56 | { |
57 | type Mask = Self; |
58 | |
59 | #[inline] |
60 | fn simd_eq(self, other: Self) -> Self::Mask { |
61 | // Safety: `self` is a vector, and the result of the comparison |
62 | // is always a valid mask. |
63 | unsafe { Self::from_int_unchecked(intrinsics::simd_eq(self.to_int(), other.to_int())) } |
64 | } |
65 | |
66 | #[inline] |
67 | fn simd_ne(self, other: Self) -> Self::Mask { |
68 | // Safety: `self` is a vector, and the result of the comparison |
69 | // is always a valid mask. |
70 | unsafe { Self::from_int_unchecked(intrinsics::simd_ne(self.to_int(), other.to_int())) } |
71 | } |
72 | } |
73 | )* |
74 | } |
75 | } |
76 | |
77 | impl_mask! { i8, i16, i32, i64, isize } |
78 | |
79 | impl<T, const N: usize> SimdPartialEq for Simd<*const T, N> |
80 | where |
81 | LaneCount<N>: SupportedLaneCount, |
82 | { |
83 | type Mask = Mask<isize, N>; |
84 | |
85 | #[inline ] |
86 | fn simd_eq(self, other: Self) -> Self::Mask { |
87 | self.addr().simd_eq(other.addr()) |
88 | } |
89 | |
90 | #[inline ] |
91 | fn simd_ne(self, other: Self) -> Self::Mask { |
92 | self.addr().simd_ne(other.addr()) |
93 | } |
94 | } |
95 | |
96 | impl<T, const N: usize> SimdPartialEq for Simd<*mut T, N> |
97 | where |
98 | LaneCount<N>: SupportedLaneCount, |
99 | { |
100 | type Mask = Mask<isize, N>; |
101 | |
102 | #[inline ] |
103 | fn simd_eq(self, other: Self) -> Self::Mask { |
104 | self.addr().simd_eq(other.addr()) |
105 | } |
106 | |
107 | #[inline ] |
108 | fn simd_ne(self, other: Self) -> Self::Mask { |
109 | self.addr().simd_ne(other.addr()) |
110 | } |
111 | } |
112 | |