1use crate::Choice;
2use core::{
3 cmp,
4 num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128},
5};
6
7pub trait CtGt {
9 #[must_use]
11 fn ct_gt(&self, other: &Self) -> Choice;
12}
13
14macro_rules! impl_unsigned_ct_gt {
16 ( $($uint:ty),+ ) => {
17 $(
18 impl CtGt for $uint {
19 #[inline]
20 fn ct_gt(&self, other: &Self) -> Choice {
21 let (_, overflow) = other.overflowing_sub(*self);
22 Choice(overflow.into())
23 }
24 }
25 )+
26 };
27}
28
29impl_unsigned_ct_gt!(u8, u16, u32, u64, u128);
30
31macro_rules! impl_ct_gt_for_nonzero_integer {
33 ( $($ty:ty),+ ) => {
34 $(
35 impl CtGt for $ty {
36 #[inline]
37 fn ct_gt(&self, other: &Self) -> Choice {
38 self.get().ct_gt(&other.get())
39 }
40 }
41 )+
42 };
43}
44
45impl_ct_gt_for_nonzero_integer!(NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128);
46
47impl CtGt for cmp::Ordering {
48 #[inline]
49 fn ct_gt(&self, other: &Self) -> Choice {
50 let a = (*self as i8) + 1;
52 let b = (*other as i8) + 1;
53 (a as u8).ct_gt(&(b as u8))
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::CtGt;
60 use core::cmp::Ordering;
61
62 #[test]
63 fn ct_gt() {
64 let a = 42u64;
65 let b = 43u64;
66 assert!(!a.ct_gt(&a).to_bool());
67 assert!(!a.ct_gt(&b).to_bool());
68 assert!(b.ct_gt(&a).to_bool());
69 }
70
71 #[test]
72 fn ordering() {
73 assert!(!Ordering::Equal.ct_gt(&Ordering::Equal).to_bool());
74 assert!(!Ordering::Less.ct_gt(&Ordering::Greater).to_bool());
75 assert!(Ordering::Greater.ct_gt(&Ordering::Less).to_bool());
76 }
77}