fixed_bigint/heapless/
abs_diff.rs1use super::HeaplessBigInt;
9use super::cmp::ct_select;
10use crate::MachineWord;
11use const_num_traits::{AbsDiff, Ct, Nct, OverflowingSub, WrappingSub, Zero};
12
13impl<T, const CAP: usize> AbsDiff for HeaplessBigInt<T, CAP, Nct>
14where
15 T: MachineWord,
16{
17 type Output = Self;
18 fn abs_diff(self, other: Self) -> Self {
19 if self >= other {
20 self - other
21 } else {
22 other - self
23 }
24 }
25}
26
27impl<T, const CAP: usize> AbsDiff for HeaplessBigInt<T, CAP, Ct>
28where
29 T: MachineWord + subtle::ConditionallySelectable,
30{
31 type Output = Self;
32 fn abs_diff(self, other: Self) -> Self {
33 let (diff, borrow) = OverflowingSub::overflowing_sub(self, other);
36 let neg_diff = WrappingSub::wrapping_sub(Self::zero(), diff);
37 ct_select(&diff, &neg_diff, borrow)
38 }
39}
40
41impl<T, const CAP: usize> AbsDiff for &HeaplessBigInt<T, CAP, Nct>
43where
44 T: MachineWord,
45{
46 type Output = HeaplessBigInt<T, CAP, Nct>;
47 fn abs_diff(self, other: Self) -> Self::Output {
48 <HeaplessBigInt<T, CAP, Nct> as AbsDiff>::abs_diff(*self, *other)
49 }
50}
51
52impl<T, const CAP: usize> AbsDiff for &HeaplessBigInt<T, CAP, Ct>
53where
54 T: MachineWord + subtle::ConditionallySelectable,
55{
56 type Output = HeaplessBigInt<T, CAP, Ct>;
57 fn abs_diff(self, other: Self) -> Self::Output {
58 <HeaplessBigInt<T, CAP, Ct> as AbsDiff>::abs_diff(*self, *other)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::HeaplessBigInt;
65 use const_num_traits::{AbsDiff, Ct, Nct};
66
67 type HN = HeaplessBigInt<u8, 4, Nct>;
68 type HC = HeaplessBigInt<u8, 4, Ct>;
69
70 #[test]
71 fn ct_abs_diff_matches_nct_and_value() {
72 for (a, b) in [(10u32, 3), (3, 10), (0, 0), (u32::MAX, 1), (1, u32::MAX)] {
73 let expected = a.abs_diff(b);
74 assert_eq!(
75 AbsDiff::abs_diff(HC::from(a), HC::from(b)),
76 HC::from(expected),
77 "ct abs_diff({a}, {b})"
78 );
79 assert_eq!(
80 AbsDiff::abs_diff(HN::from(a), HN::from(b)),
81 HN::from(expected)
82 );
83 }
84 }
85
86 #[test]
87 fn byref_matches_value() {
88 let (an, bn) = (HN::from(10u8), HN::from(3u8));
89 assert_eq!(AbsDiff::abs_diff(&an, &bn), AbsDiff::abs_diff(an, bn));
90 let (ac, bc) = (HC::from(3u8), HC::from(10u8));
91 assert_eq!(AbsDiff::abs_diff(&ac, &bc), AbsDiff::abs_diff(ac, bc));
92 }
93}