qfall_math/integer_mod_q/z_q/
get.rs

1// Copyright © 2023 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//! Get elements of [`Zq`] like its [`Z`] value and [`Modulus`].
10
11use crate::{
12    integer::Z,
13    integer_mod_q::{Modulus, Zq},
14};
15
16impl Zq {
17    /// Returns the [`Z`] value of the [`Zq`] element.
18    ///
19    /// The representation in the range `[0, modulus)` is returned.
20    /// Use [`Zq::get_representative_least_absolute_residue`] if they should be
21    /// in the range `[-modulus/2, modulus/2]`.
22    ///
23    /// # Examples
24    /// ```
25    /// use qfall_math::integer_mod_q::Zq;
26    /// use qfall_math::integer::Z;
27    /// let zq_value = Zq::from((4, 7));
28    ///
29    /// let z_value = zq_value.get_representative_least_nonnegative_residue();
30    ///
31    /// assert_eq!(Z::from(4), z_value);
32    /// ```
33    pub fn get_representative_least_nonnegative_residue(&self) -> Z {
34        self.value.clone()
35    }
36
37    /// Returns the [`Z`] value of the [`Zq`] element with the representatives close to `0`.
38    ///
39    /// The output value is in the range of `[-modulus/2, modulus/2]`.
40    /// For even moduli, the positive representative is chosen for the element `modulus / 2`.
41    /// Use [`Zq::get_representative_least_nonnegative_residue`] if they should be
42    /// in the range `[0, modulus)`.
43    ///
44    /// # Examples
45    /// ```
46    /// use qfall_math::integer_mod_q::Zq;
47    /// use qfall_math::integer::Z;
48    /// let zq_value = Zq::from((5, 7));
49    ///
50    /// let z_value = zq_value.get_representative_least_absolute_residue();
51    ///
52    /// assert_eq!(Z::from(2), z_value);
53    /// ```
54    pub fn get_representative_least_absolute_residue(&self) -> Z {
55        let mod_z = Z::from(&self.modulus);
56        if self.value < mod_z.div_ceil(2) {
57            self.value.clone()
58        } else {
59            Z::from(self.modulus.clone()) - self.value.clone()
60        }
61    }
62
63    /// Returns the [`Modulus`] of the [`Zq`] element.
64    ///
65    /// # Examples
66    /// ```
67    /// use qfall_math::integer_mod_q::{Zq, Modulus};
68    /// use std::str::FromStr;
69    /// let value = Zq::from((4, 7));
70    /// let cmp = Modulus::from(7);
71    ///
72    /// let modulus = value.get_mod();
73    ///
74    /// assert_eq!(cmp, modulus);
75    /// ```
76    pub fn get_mod(&self) -> Modulus {
77        self.modulus.clone()
78    }
79}
80
81#[cfg(test)]
82mod test_get_representative_least_nonnegative_residue {
83    use super::{Z, Zq};
84
85    /// Check whether `get_representative_least_nonnegative_residue` outputs the correct value for small values
86    #[test]
87    fn get_small() {
88        let value_0 = Zq::from((2, 20));
89        let value_1 = Zq::from((-2, 20));
90
91        let res_0 = value_0.get_representative_least_nonnegative_residue();
92        let res_1 = value_1.get_representative_least_nonnegative_residue();
93
94        assert_eq!(res_0, Z::from(2));
95        assert_eq!(res_1, Z::from(18));
96    }
97
98    /// Check whether `get_representative_least_nonnegative_residue` outputs the correct value for large values
99    #[test]
100    fn get_large() {
101        let value_0 = Zq::from((i64::MAX, u64::MAX));
102        let value_1 = Zq::from((i64::MIN, u64::MAX));
103
104        let res_0 = value_0.get_representative_least_nonnegative_residue();
105        let res_1 = value_1.get_representative_least_nonnegative_residue();
106
107        assert_eq!(res_0, Z::from(i64::MAX));
108        assert_eq!(res_1, Z::from(i64::MAX));
109    }
110}
111
112#[cfg(test)]
113mod test_get_representative_least_absolute_residue {
114    use super::{Z, Zq};
115
116    /// Check whether `get_representative_least_absolute_residue` outputs the correct value for small values
117    #[test]
118    fn get_small() {
119        let value_0 = Zq::from((2, 20));
120        let value_1 = Zq::from((-2, 20));
121
122        let res_0 = value_0.get_representative_least_absolute_residue();
123        let res_1 = value_1.get_representative_least_absolute_residue();
124
125        assert_eq!(res_0, Z::from(2));
126        assert_eq!(res_1, Z::from(2));
127    }
128
129    /// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
130    #[test]
131    fn get_large() {
132        let value_0 = Zq::from((i64::MAX, u64::MAX));
133        let value_1 = Zq::from((u64::MAX - 1, u64::MAX));
134
135        let res_0 = value_0.get_representative_least_absolute_residue();
136        let res_1 = value_1.get_representative_least_absolute_residue();
137
138        assert_eq!(res_0, Z::from(i64::MAX));
139        assert_eq!(res_1, Z::from(1));
140    }
141
142    /// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
143    #[test]
144    fn get_special() {
145        let value_0 = Zq::from((10, 20));
146        let value_1 = Zq::from((0, 20));
147
148        let res_0 = value_0.get_representative_least_absolute_residue();
149        let res_1 = value_1.get_representative_least_absolute_residue();
150
151        assert_eq!(res_0, Z::from(10));
152        assert_eq!(res_1, Z::from(0));
153    }
154}
155
156#[cfg(test)]
157mod test_get_mod {
158    use super::{Modulus, Zq};
159
160    /// Check whether `get_mod` outputs the correct modulus for small moduli
161    #[test]
162    fn get_small() {
163        let value = Zq::from((2, 20));
164
165        let modulus = value.get_mod();
166
167        assert_eq!(modulus, Modulus::from(20));
168    }
169
170    /// Check whether `get_mod` outputs the correct modulus for large moduli
171    #[test]
172    fn get_large() {
173        let value = Zq::from((2, u64::MAX));
174
175        let modulus = value.get_mod();
176
177        assert_eq!(modulus, Modulus::from(u64::MAX));
178    }
179}