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::{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}