1use core::fmt::{self, Display, Formatter};
8use core::str::FromStr;
9
10pub trait CondCode: Copy {
12 #[must_use]
17 fn inverse(self) -> Self;
18
19 #[must_use]
24 fn reverse(self) -> Self;
25}
26
27#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
33pub enum IntCC {
34 Equal,
36 NotEqual,
38 SignedLessThan,
40 SignedGreaterThanOrEqual,
42 SignedGreaterThan,
44 SignedLessThanOrEqual,
46 UnsignedLessThan,
48 UnsignedGreaterThanOrEqual,
50 UnsignedGreaterThan,
52 UnsignedLessThanOrEqual,
54 Overflow,
56 NotOverflow,
58}
59
60impl CondCode for IntCC {
61 fn inverse(self) -> Self {
62 use self::IntCC::*;
63 match self {
64 Equal => NotEqual,
65 NotEqual => Equal,
66 SignedLessThan => SignedGreaterThanOrEqual,
67 SignedGreaterThanOrEqual => SignedLessThan,
68 SignedGreaterThan => SignedLessThanOrEqual,
69 SignedLessThanOrEqual => SignedGreaterThan,
70 UnsignedLessThan => UnsignedGreaterThanOrEqual,
71 UnsignedGreaterThanOrEqual => UnsignedLessThan,
72 UnsignedGreaterThan => UnsignedLessThanOrEqual,
73 UnsignedLessThanOrEqual => UnsignedGreaterThan,
74 Overflow => NotOverflow,
75 NotOverflow => Overflow,
76 }
77 }
78
79 fn reverse(self) -> Self {
80 use self::IntCC::*;
81 match self {
82 Equal => Equal,
83 NotEqual => NotEqual,
84 SignedGreaterThan => SignedLessThan,
85 SignedGreaterThanOrEqual => SignedLessThanOrEqual,
86 SignedLessThan => SignedGreaterThan,
87 SignedLessThanOrEqual => SignedGreaterThanOrEqual,
88 UnsignedGreaterThan => UnsignedLessThan,
89 UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual,
90 UnsignedLessThan => UnsignedGreaterThan,
91 UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual,
92 Overflow => Overflow,
93 NotOverflow => NotOverflow,
94 }
95 }
96}
97
98impl IntCC {
99 pub fn without_equal(self) -> Self {
102 use self::IntCC::*;
103 match self {
104 SignedGreaterThan | SignedGreaterThanOrEqual => SignedGreaterThan,
105 SignedLessThan | SignedLessThanOrEqual => SignedLessThan,
106 UnsignedGreaterThan | UnsignedGreaterThanOrEqual => UnsignedGreaterThan,
107 UnsignedLessThan | UnsignedLessThanOrEqual => UnsignedLessThan,
108 _ => self,
109 }
110 }
111
112 pub fn unsigned(self) -> Self {
115 use self::IntCC::*;
116 match self {
117 SignedGreaterThan | UnsignedGreaterThan => UnsignedGreaterThan,
118 SignedGreaterThanOrEqual | UnsignedGreaterThanOrEqual => UnsignedGreaterThanOrEqual,
119 SignedLessThan | UnsignedLessThan => UnsignedLessThan,
120 SignedLessThanOrEqual | UnsignedLessThanOrEqual => UnsignedLessThanOrEqual,
121 _ => self,
122 }
123 }
124
125 pub fn to_static_str(self) -> &'static str {
127 use self::IntCC::*;
128 match self {
129 Equal => "eq",
130 NotEqual => "ne",
131 SignedGreaterThan => "sgt",
132 SignedGreaterThanOrEqual => "sge",
133 SignedLessThan => "slt",
134 SignedLessThanOrEqual => "sle",
135 UnsignedGreaterThan => "ugt",
136 UnsignedGreaterThanOrEqual => "uge",
137 UnsignedLessThan => "ult",
138 UnsignedLessThanOrEqual => "ule",
139 Overflow => "of",
140 NotOverflow => "nof",
141 }
142 }
143}
144
145impl Display for IntCC {
146 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
147 f.write_str(self.to_static_str())
148 }
149}
150
151impl FromStr for IntCC {
152 type Err = ();
153
154 fn from_str(s: &str) -> Result<Self, Self::Err> {
155 use self::IntCC::*;
156 match s {
157 "eq" => Ok(Equal),
158 "ne" => Ok(NotEqual),
159 "sge" => Ok(SignedGreaterThanOrEqual),
160 "sgt" => Ok(SignedGreaterThan),
161 "sle" => Ok(SignedLessThanOrEqual),
162 "slt" => Ok(SignedLessThan),
163 "uge" => Ok(UnsignedGreaterThanOrEqual),
164 "ugt" => Ok(UnsignedGreaterThan),
165 "ule" => Ok(UnsignedLessThanOrEqual),
166 "ult" => Ok(UnsignedLessThan),
167 "of" => Ok(Overflow),
168 "nof" => Ok(NotOverflow),
169 _ => Err(()),
170 }
171 }
172}
173
174#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
190pub enum FloatCC {
191 Ordered,
193 Unordered,
195
196 Equal,
198 NotEqual,
201 OrderedNotEqual,
203 UnorderedOrEqual,
205
206 LessThan,
208 LessThanOrEqual,
210 GreaterThan,
212 GreaterThanOrEqual,
214
215 UnorderedOrLessThan,
217 UnorderedOrLessThanOrEqual,
219 UnorderedOrGreaterThan,
221 UnorderedOrGreaterThanOrEqual,
223}
224
225impl CondCode for FloatCC {
226 fn inverse(self) -> Self {
227 use self::FloatCC::*;
228 match self {
229 Ordered => Unordered,
230 Unordered => Ordered,
231 Equal => NotEqual,
232 NotEqual => Equal,
233 OrderedNotEqual => UnorderedOrEqual,
234 UnorderedOrEqual => OrderedNotEqual,
235 LessThan => UnorderedOrGreaterThanOrEqual,
236 LessThanOrEqual => UnorderedOrGreaterThan,
237 GreaterThan => UnorderedOrLessThanOrEqual,
238 GreaterThanOrEqual => UnorderedOrLessThan,
239 UnorderedOrLessThan => GreaterThanOrEqual,
240 UnorderedOrLessThanOrEqual => GreaterThan,
241 UnorderedOrGreaterThan => LessThanOrEqual,
242 UnorderedOrGreaterThanOrEqual => LessThan,
243 }
244 }
245 fn reverse(self) -> Self {
246 use self::FloatCC::*;
247 match self {
248 Ordered => Ordered,
249 Unordered => Unordered,
250 Equal => Equal,
251 NotEqual => NotEqual,
252 OrderedNotEqual => OrderedNotEqual,
253 UnorderedOrEqual => UnorderedOrEqual,
254 LessThan => GreaterThan,
255 LessThanOrEqual => GreaterThanOrEqual,
256 GreaterThan => LessThan,
257 GreaterThanOrEqual => LessThanOrEqual,
258 UnorderedOrLessThan => UnorderedOrGreaterThan,
259 UnorderedOrLessThanOrEqual => UnorderedOrGreaterThanOrEqual,
260 UnorderedOrGreaterThan => UnorderedOrLessThan,
261 UnorderedOrGreaterThanOrEqual => UnorderedOrLessThanOrEqual,
262 }
263 }
264}
265
266impl Display for FloatCC {
267 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
268 use self::FloatCC::*;
269 f.write_str(match *self {
270 Ordered => "ord",
271 Unordered => "uno",
272 Equal => "eq",
273 NotEqual => "ne",
274 OrderedNotEqual => "one",
275 UnorderedOrEqual => "ueq",
276 LessThan => "lt",
277 LessThanOrEqual => "le",
278 GreaterThan => "gt",
279 GreaterThanOrEqual => "ge",
280 UnorderedOrLessThan => "ult",
281 UnorderedOrLessThanOrEqual => "ule",
282 UnorderedOrGreaterThan => "ugt",
283 UnorderedOrGreaterThanOrEqual => "uge",
284 })
285 }
286}
287
288impl FromStr for FloatCC {
289 type Err = ();
290
291 fn from_str(s: &str) -> Result<Self, Self::Err> {
292 use self::FloatCC::*;
293 match s {
294 "ord" => Ok(Ordered),
295 "uno" => Ok(Unordered),
296 "eq" => Ok(Equal),
297 "ne" => Ok(NotEqual),
298 "one" => Ok(OrderedNotEqual),
299 "ueq" => Ok(UnorderedOrEqual),
300 "lt" => Ok(LessThan),
301 "le" => Ok(LessThanOrEqual),
302 "gt" => Ok(GreaterThan),
303 "ge" => Ok(GreaterThanOrEqual),
304 "ult" => Ok(UnorderedOrLessThan),
305 "ule" => Ok(UnorderedOrLessThanOrEqual),
306 "ugt" => Ok(UnorderedOrGreaterThan),
307 "uge" => Ok(UnorderedOrGreaterThanOrEqual),
308 _ => Err(()),
309 }
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316 use std::string::ToString;
317
318 static INT_ALL: [IntCC; 12] = [
319 IntCC::Equal,
320 IntCC::NotEqual,
321 IntCC::SignedLessThan,
322 IntCC::SignedGreaterThanOrEqual,
323 IntCC::SignedGreaterThan,
324 IntCC::SignedLessThanOrEqual,
325 IntCC::UnsignedLessThan,
326 IntCC::UnsignedGreaterThanOrEqual,
327 IntCC::UnsignedGreaterThan,
328 IntCC::UnsignedLessThanOrEqual,
329 IntCC::Overflow,
330 IntCC::NotOverflow,
331 ];
332
333 #[test]
334 fn int_inverse() {
335 for r in &INT_ALL {
336 let cc = *r;
337 let inv = cc.inverse();
338 assert!(cc != inv);
339 assert_eq!(inv.inverse(), cc);
340 }
341 }
342
343 #[test]
344 fn int_reverse() {
345 for r in &INT_ALL {
346 let cc = *r;
347 let rev = cc.reverse();
348 assert_eq!(rev.reverse(), cc);
349 }
350 }
351
352 #[test]
353 fn int_display() {
354 for r in &INT_ALL {
355 let cc = *r;
356 assert_eq!(cc.to_string().parse(), Ok(cc));
357 }
358 assert_eq!("bogus".parse::<IntCC>(), Err(()));
359 }
360
361 static FLOAT_ALL: [FloatCC; 14] = [
362 FloatCC::Ordered,
363 FloatCC::Unordered,
364 FloatCC::Equal,
365 FloatCC::NotEqual,
366 FloatCC::OrderedNotEqual,
367 FloatCC::UnorderedOrEqual,
368 FloatCC::LessThan,
369 FloatCC::LessThanOrEqual,
370 FloatCC::GreaterThan,
371 FloatCC::GreaterThanOrEqual,
372 FloatCC::UnorderedOrLessThan,
373 FloatCC::UnorderedOrLessThanOrEqual,
374 FloatCC::UnorderedOrGreaterThan,
375 FloatCC::UnorderedOrGreaterThanOrEqual,
376 ];
377
378 #[test]
379 fn float_inverse() {
380 for r in &FLOAT_ALL {
381 let cc = *r;
382 let inv = cc.inverse();
383 assert!(cc != inv);
384 assert_eq!(inv.inverse(), cc);
385 }
386 }
387
388 #[test]
389 fn float_reverse() {
390 for r in &FLOAT_ALL {
391 let cc = *r;
392 let rev = cc.reverse();
393 assert_eq!(rev.reverse(), cc);
394 }
395 }
396
397 #[test]
398 fn float_display() {
399 for r in &FLOAT_ALL {
400 let cc = *r;
401 assert_eq!(cc.to_string().parse(), Ok(cc));
402 }
403 assert_eq!("bogus".parse::<FloatCC>(), Err(()));
404 }
405}