Skip to main content

fixed_bigint/fixeduint/
abs_diff_impl.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Absolute difference implementation for FixedUInt.
16
17use super::{const_ct_select, FixedUInt, MachineWord};
18use crate::const_numtraits::{ConstAbsDiff, ConstOverflowingSub, ConstWrappingSub, ConstZero};
19use crate::machineword::ConstMachineWord;
20use crate::personality::{Personality, PersonalityTag};
21
22c0nst::c0nst! {
23    impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> c0nst ConstAbsDiff for FixedUInt<T, N, P> {
24        fn abs_diff(self, other: Self) -> Self {
25            match P::TAG {
26                PersonalityTag::Nct => {
27                    if self >= other {
28                        self - other
29                    } else {
30                        other - self
31                    }
32                }
33                PersonalityTag::Ct => {
34                    let (diff, borrow) =
35                        <Self as ConstOverflowingSub>::overflowing_sub(&self, &other);
36                    let neg_diff =
37                        <Self as ConstWrappingSub>::wrapping_sub(&<Self as ConstZero>::zero(), &diff);
38                    const_ct_select(diff, neg_diff, borrow as u8)
39                }
40            }
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn test_abs_diff() {
51        type U16 = FixedUInt<u8, 2>;
52
53        assert_eq!(
54            ConstAbsDiff::abs_diff(U16::from(10u8), U16::from(3u8)),
55            U16::from(7u8)
56        );
57        assert_eq!(
58            ConstAbsDiff::abs_diff(U16::from(3u8), U16::from(10u8)),
59            U16::from(7u8)
60        );
61        assert_eq!(
62            ConstAbsDiff::abs_diff(U16::from(5u8), U16::from(5u8)),
63            U16::from(0u8)
64        );
65        assert_eq!(
66            ConstAbsDiff::abs_diff(U16::from(0u8), U16::from(100u8)),
67            U16::from(100u8)
68        );
69        assert_eq!(
70            ConstAbsDiff::abs_diff(U16::from(255u8), U16::from(0u8)),
71            U16::from(255u8)
72        );
73    }
74
75    c0nst::c0nst! {
76        pub c0nst fn const_abs_diff<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
77            a: FixedUInt<T, N, P>,
78            b: FixedUInt<T, N, P>,
79        ) -> FixedUInt<T, N, P> {
80            ConstAbsDiff::abs_diff(a, b)
81        }
82    }
83
84    #[test]
85    fn test_const_abs_diff() {
86        type U16 = FixedUInt<u8, 2>;
87
88        assert_eq!(
89            const_abs_diff(U16::from(10u8), U16::from(3u8)),
90            U16::from(7u8)
91        );
92
93        #[cfg(feature = "nightly")]
94        {
95            const A: U16 = FixedUInt::from_array([10, 0]);
96            const B: U16 = FixedUInt::from_array([3, 0]);
97            const DIFF: U16 = const_abs_diff(A, B);
98            assert_eq!(DIFF, FixedUInt::from_array([7, 0]));
99        }
100    }
101}