1 //! Implements `PartialOrd` for vector types.
2 //!
3 //! This implements a lexicographical order.
4 
5 macro_rules! impl_cmp_partial_ord {
6     ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
7         impl $id {
8             /// Returns a wrapper that implements `PartialOrd`.
9             #[inline]
10             pub fn partial_lex_ord(&self) -> LexicographicallyOrdered<$id> {
11                 LexicographicallyOrdered(*self)
12             }
13         }
14 
15         impl crate::cmp::PartialOrd<LexicographicallyOrdered<$id>>
16             for LexicographicallyOrdered<$id>
17         {
18             #[inline]
19             fn partial_cmp(
20                 &self, other: &Self,
21             ) -> Option<crate::cmp::Ordering> {
22                 if PartialEq::eq(self, other) {
23                     Some(crate::cmp::Ordering::Equal)
24                 } else if PartialOrd::lt(self, other) {
25                     Some(crate::cmp::Ordering::Less)
26                 } else if PartialOrd::gt(self, other) {
27                     Some(crate::cmp::Ordering::Greater)
28                 } else {
29                     None
30                 }
31             }
32             #[inline]
33             fn lt(&self, other: &Self) -> bool {
34                 let m_lt = self.0.lt(other.0);
35                 let m_eq = self.0.eq(other.0);
36                 for i in 0..$id::lanes() {
37                     if m_eq.extract(i) {
38                         continue;
39                     }
40                     return m_lt.extract(i);
41                 }
42                 false
43             }
44             #[inline]
45             fn le(&self, other: &Self) -> bool {
46                 self.lt(other) | PartialEq::eq(self, other)
47             }
48             #[inline]
49             fn ge(&self, other: &Self) -> bool {
50                 self.gt(other) | PartialEq::eq(self, other)
51             }
52             #[inline]
53             fn gt(&self, other: &Self) -> bool {
54                 let m_gt = self.0.gt(other.0);
55                 let m_eq = self.0.eq(other.0);
56                 for i in 0..$id::lanes() {
57                     if m_eq.extract(i) {
58                         continue;
59                     }
60                     return m_gt.extract(i);
61                 }
62                 false
63             }
64         }
65     };
66 }
67 
68 macro_rules! test_cmp_partial_ord_int {
69     ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
70         test_if!{
71             $test_tt:
72             paste::item! {
73                 pub mod [<$id _cmp_PartialOrd>] {
74                     use super::*;
75                     #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
76                     fn partial_lex_ord() {
77                         use crate::testing::utils::{test_cmp};
78                         // constant values
79                         let a = $id::splat(0);
80                         let b = $id::splat(1);
81 
82                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
83                                  Some(crate::cmp::Ordering::Less));
84                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
85                                  Some(crate::cmp::Ordering::Greater));
86                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
87                                  Some(crate::cmp::Ordering::Equal));
88                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
89                                  Some(crate::cmp::Ordering::Equal));
90 
91                         // variable values: a = [0, 1, 2, 3]; b = [3, 2, 1, 0]
92                         let mut a = $id::splat(0);
93                         let mut b = $id::splat(0);
94                         for i in 0..$id::lanes() {
95                             a = a.replace(i, i as $elem_ty);
96                             b = b.replace(i, ($id::lanes() - i) as $elem_ty);
97                         }
98                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
99                                  Some(crate::cmp::Ordering::Less));
100                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
101                                  Some(crate::cmp::Ordering::Greater));
102                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
103                                  Some(crate::cmp::Ordering::Equal));
104                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
105                                  Some(crate::cmp::Ordering::Equal));
106 
107                         // variable values: a = [0, 1, 2, 3]; b = [0, 1, 2, 4]
108                         let mut b = a;
109                         b = b.replace(
110                             $id::lanes() - 1,
111                             a.extract($id::lanes() - 1) + 1 as $elem_ty
112                         );
113                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
114                                  Some(crate::cmp::Ordering::Less));
115                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
116                                  Some(crate::cmp::Ordering::Greater));
117                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
118                                  Some(crate::cmp::Ordering::Equal));
119                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
120                                  Some(crate::cmp::Ordering::Equal));
121 
122                         if $id::lanes() > 2 {
123                             // variable values a = [0, 1, 0, 0]; b = [0, 1, 2, 3]
124                             let b = a;
125                             let mut a = $id::splat(0);
126                             a = a.replace(1, 1 as $elem_ty);
127                             test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
128                                      Some(crate::cmp::Ordering::Less));
129                             test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
130                                      Some(crate::cmp::Ordering::Greater));
131                             test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
132                                      Some(crate::cmp::Ordering::Equal));
133                             test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
134                                      Some(crate::cmp::Ordering::Equal));
135 
136                             // variable values: a = [0, 1, 2, 3]; b = [0, 1, 3, 2]
137                             let mut b = a;
138                             b = b.replace(
139                                 2, a.extract($id::lanes() - 1) + 1 as $elem_ty
140                             );
141                             test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
142                                      Some(crate::cmp::Ordering::Less));
143                             test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
144                                      Some(crate::cmp::Ordering::Greater));
145                             test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
146                                      Some(crate::cmp::Ordering::Equal));
147                             test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
148                                      Some(crate::cmp::Ordering::Equal));
149                         }
150                     }
151                 }
152             }
153         }
154     };
155 }
156 
157 macro_rules! test_cmp_partial_ord_mask {
158     ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
159         test_if!{
160             $test_tt:
161             paste::item! {
162                 pub mod [<$id _cmp_PartialOrd>] {
163                     use super::*;
164                     #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
165                     fn partial_lex_ord() {
166                         use crate::testing::utils::{test_cmp};
167                         use crate::cmp::Ordering;
168 
169                         // constant values
170                         let a = $id::splat(false);
171                         let b = $id::splat(true);
172 
173                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
174                                  Some(Ordering::Less));
175                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
176                                  Some(Ordering::Greater));
177                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
178                                  Some(Ordering::Equal));
179                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
180                                  Some(Ordering::Equal));
181 
182                         // variable values:
183                         // a = [false, false, false, false];
184                         // b = [false, false, false, true]
185                         let a = $id::splat(false);
186                         let mut b = $id::splat(false);
187                         b = b.replace($id::lanes() - 1, true);
188                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
189                                  Some(Ordering::Less));
190                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
191                                  Some(Ordering::Greater));
192                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
193                                  Some(Ordering::Equal));
194                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
195                                  Some(Ordering::Equal));
196 
197                         // variable values:
198                         // a = [true, true, true, false];
199                         // b = [true, true, true, true]
200                         let mut a = $id::splat(true);
201                         let b = $id::splat(true);
202                         a = a.replace($id::lanes() - 1, false);
203                         test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
204                                  Some(Ordering::Less));
205                         test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
206                                  Some(Ordering::Greater));
207                         test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
208                                  Some(Ordering::Equal));
209                         test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
210                                  Some(Ordering::Equal));
211 
212                         if $id::lanes() > 2 {
213                             // variable values
214                             // a = [false, true, false, false];
215                             // b = [false, true, true, true]
216                             let mut a = $id::splat(false);
217                             let mut b = $id::splat(true);
218                             a = a.replace(1, true);
219                             b = b.replace(0, false);
220                             test_cmp(a.partial_lex_ord(), b.partial_lex_ord(),
221                                      Some(Ordering::Less));
222                             test_cmp(b.partial_lex_ord(), a.partial_lex_ord(),
223                                      Some(Ordering::Greater));
224                             test_cmp(a.partial_lex_ord(), a.partial_lex_ord(),
225                                      Some(Ordering::Equal));
226                             test_cmp(b.partial_lex_ord(), b.partial_lex_ord(),
227                                      Some(Ordering::Equal));
228                         }
229                     }
230                 }
231             }
232         }
233     };
234 }
235