qfall_math/integer/z/
distance.rs

1// Copyright © 2023 Marcel Luca Schmidt, Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! This module contains the implementation of the [`Distance`] trait for [`Z`].
10
11use super::Z;
12use crate::traits::Distance;
13
14impl<Integer: Into<Z>> Distance<Integer> for Z {
15    type Output = Z;
16
17    /// Computes the absolute distance between a [`Z`] instance and a value that
18    /// implements [`Into<Z>`].
19    ///
20    /// Parameters:
21    /// - `other`: specifies the [`Z`] value whose distance is calculated to `self`
22    ///
23    /// Returns the absolute difference, i.e. distance between the [`Z`] instance
24    /// and the value that implements [`Into<Z>`] as a new [`Z`] instance.
25    ///
26    /// # Examples
27    /// ```
28    /// use qfall_math::integer::Z;
29    /// use qfall_math::traits::*;
30    ///
31    /// let a = Z::from(-1);
32    ///
33    /// let distance_0 = a.distance(5);
34    /// let distance_1 = a.distance(10);
35    ///
36    /// # assert_eq!(Z::from(6), distance_0);
37    /// # assert_eq!(Z::from(11), distance_1);
38    /// ```
39    fn distance(&self, other: Integer) -> Self::Output {
40        let other = other.into();
41        let difference = other - self;
42        difference.abs()
43    }
44}
45
46#[cfg(test)]
47mod test_distance {
48    use super::{Distance, Z};
49    use crate::integer_mod_q::Modulus;
50
51    /// Checks if distance is correctly computed for small [`Z`] values
52    /// and whether distance(a, b) == distance(b, a), distance(a, a) == 0
53    #[test]
54    fn small_values() {
55        let a = Z::ONE;
56        let b = Z::from(-15);
57        let zero = Z::ZERO;
58
59        assert_eq!(Z::ONE, a.distance(&zero));
60        assert_eq!(Z::ONE, zero.distance(&a));
61        assert_eq!(Z::from(16), a.distance(&b));
62        assert_eq!(Z::from(16), b.distance(&a));
63        assert_eq!(Z::from(15), b.distance(&zero));
64        assert_eq!(Z::from(15), zero.distance(&b));
65        assert_eq!(Z::ZERO, b.distance(&b));
66    }
67
68    /// Checks if distance is correctly computed for large [`Z`] values
69    /// and whether distance(a, b) == distance(b, a), distance(a, a) == 0
70    #[test]
71    fn large_values() {
72        let a = Z::from(i64::MAX);
73        let b = Z::from(i64::MIN);
74        let zero = Z::ZERO;
75
76        assert_eq!(&a - &b, a.distance(&b));
77        assert_eq!(&a - &b, b.distance(&a));
78        assert_eq!(a, a.distance(&zero));
79        assert_eq!(a, zero.distance(&a));
80        assert_eq!(&a + Z::ONE, b.distance(&zero));
81        assert_eq!(&a + Z::ONE, zero.distance(&b));
82        assert_eq!(Z::ZERO, a.distance(&a));
83    }
84
85    /// Check whether distance is available for owned [`Z`] and other types
86    #[test]
87    fn availability() {
88        let a = Z::ZERO;
89        let modulus = Modulus::from(2);
90
91        let u_0 = a.distance(0_u8);
92        let u_1 = a.distance(15_u16);
93        let u_2 = a.distance(35_u32);
94        let u_3 = a.distance(u64::MAX);
95        let i_0 = a.distance(0_i8);
96        let i_1 = a.distance(-15_i16);
97        let i_2 = a.distance(35_i32);
98        let i_3 = a.distance(i64::MIN);
99        let dist_mod = a.distance(modulus);
100
101        assert_eq!(Z::ZERO, u_0);
102        assert_eq!(Z::from(15), u_1);
103        assert_eq!(Z::from(35), u_2);
104        assert_eq!(Z::from(u64::MAX), u_3);
105        assert_eq!(Z::ZERO, i_0);
106        assert_eq!(Z::from(15), i_1);
107        assert_eq!(Z::from(35), i_2);
108        assert_eq!(Z::from(i64::MIN).abs(), i_3);
109        assert_eq!(Z::from(2), dist_mod);
110    }
111}