fixed_bigint/fixeduint/
abs_diff_impl.rs1use super::{FixedUInt, MachineWord, const_ct_select};
18use crate::machineword::ConstMachineWord;
19use const_num_traits::{AbsDiff, ConstZero, OverflowingSub, WrappingSub};
20use const_num_traits::{Personality, PersonalityTag};
21
22c0nst::c0nst! {
23 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> AbsDiff for FixedUInt<T, N, P> {
24 type Output = Self;
25 fn abs_diff(self, other: Self) -> Self {
26 match P::TAG {
27 PersonalityTag::Nct => {
28 if self >= other {
29 self - other
30 } else {
31 other - self
32 }
33 }
34 PersonalityTag::Ct => {
35 let (diff, borrow) =
36 <Self as OverflowingSub>::overflowing_sub(self, other);
37 let neg_diff =
38 <Self as WrappingSub>::wrapping_sub(<Self as ConstZero>::ZERO, diff);
39 const_ct_select(diff, neg_diff, borrow as u8)
40 }
41 }
42 }
43 }
44
45 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> AbsDiff for &FixedUInt<T, N, P> {
46 type Output = FixedUInt<T, N, P>;
47 fn abs_diff(self, other: Self) -> FixedUInt<T, N, P> {
48 <FixedUInt<T, N, P> as AbsDiff>::abs_diff(*self, *other)
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_abs_diff() {
59 type U16 = FixedUInt<u8, 2>;
60
61 assert_eq!(
62 AbsDiff::abs_diff(U16::from(10u8), U16::from(3u8)),
63 U16::from(7u8)
64 );
65 assert_eq!(
66 AbsDiff::abs_diff(U16::from(3u8), U16::from(10u8)),
67 U16::from(7u8)
68 );
69 assert_eq!(
70 AbsDiff::abs_diff(U16::from(5u8), U16::from(5u8)),
71 U16::from(0u8)
72 );
73 assert_eq!(
74 AbsDiff::abs_diff(U16::from(0u8), U16::from(100u8)),
75 U16::from(100u8)
76 );
77 assert_eq!(
78 AbsDiff::abs_diff(U16::from(255u8), U16::from(0u8)),
79 U16::from(255u8)
80 );
81 }
82
83 c0nst::c0nst! {
84 pub c0nst fn const_abs_diff<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
85 a: FixedUInt<T, N, P>,
86 b: FixedUInt<T, N, P>,
87 ) -> FixedUInt<T, N, P> {
88 AbsDiff::abs_diff(a, b)
89 }
90 }
91
92 #[test]
93 fn test_const_abs_diff() {
94 type U16 = FixedUInt<u8, 2>;
95
96 assert_eq!(
97 const_abs_diff(U16::from(10u8), U16::from(3u8)),
98 U16::from(7u8)
99 );
100
101 #[cfg(feature = "nightly")]
102 {
103 const A: U16 = FixedUInt::from_array([10, 0]);
104 const B: U16 = FixedUInt::from_array([3, 0]);
105 const DIFF: U16 = const_abs_diff(A, B);
106 assert_eq!(DIFF, FixedUInt::from_array([7, 0]));
107 }
108 }
109}