qfall_math/integer_mod_q/z_q/get.rs
1// Copyright 2023 Jan 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 `(-⌈modulus/2⌉, ⌊modulus/2⌋]`,
40 /// i.e. `[-(modulus-1)/2, (modulus-1)/2]` for odd moduli and `(-modulus/2, modulus/2]` for even moduli.
41 /// Hence, the positive representative is chosen for the element `modulus/2` of even moduli.
42 /// Use [`Zq::get_representative_least_nonnegative_residue`] if they should be
43 /// in the range `[0, modulus)`.
44 ///
45 /// # Examples
46 /// ```
47 /// use qfall_math::integer_mod_q::Zq;
48 /// use qfall_math::integer::Z;
49 /// let zq_value = Zq::from((5, 7));
50 ///
51 /// let z_value = zq_value.get_representative_least_absolute_residue();
52 ///
53 /// assert_eq!(Z::from(-2), z_value);
54 /// ```
55 pub fn get_representative_least_absolute_residue(&self) -> Z {
56 let mod_z = Z::from(&self.modulus);
57 let mod_half = mod_z.div_floor(2);
58 if self.value > mod_half {
59 &self.value - mod_z
60 } else {
61 self.value.clone()
62 }
63 }
64
65 /// Returns the [`Modulus`] of the [`Zq`] element.
66 ///
67 /// # Examples
68 /// ```
69 /// use qfall_math::integer_mod_q::{Zq, Modulus};
70 /// use std::str::FromStr;
71 /// let value = Zq::from((4, 7));
72 /// let cmp = Modulus::from(7);
73 ///
74 /// let modulus = value.get_mod();
75 ///
76 /// assert_eq!(cmp, modulus);
77 /// ```
78 pub fn get_mod(&self) -> Modulus {
79 self.modulus.clone()
80 }
81}
82
83#[cfg(test)]
84mod test_get_representative_least_nonnegative_residue {
85 use super::{Z, Zq};
86
87 /// Check whether `get_representative_least_nonnegative_residue` outputs the correct value for small values
88 #[test]
89 fn get_small() {
90 let value_0 = Zq::from((2, 20));
91 let value_1 = Zq::from((-2, 20));
92
93 let res_0 = value_0.get_representative_least_nonnegative_residue();
94 let res_1 = value_1.get_representative_least_nonnegative_residue();
95
96 assert_eq!(res_0, Z::from(2));
97 assert_eq!(res_1, Z::from(18));
98 }
99
100 /// Check whether `get_representative_least_nonnegative_residue` outputs the correct value for large values
101 #[test]
102 fn get_large() {
103 let value_0 = Zq::from((i64::MAX, u64::MAX));
104 let value_1 = Zq::from((i64::MIN, u64::MAX));
105
106 let res_0 = value_0.get_representative_least_nonnegative_residue();
107 let res_1 = value_1.get_representative_least_nonnegative_residue();
108
109 assert_eq!(res_0, Z::from(i64::MAX));
110 assert_eq!(res_1, Z::from(i64::MAX));
111 }
112}
113
114#[cfg(test)]
115mod test_get_representative_least_absolute_residue {
116 use super::{Z, Zq};
117
118 /// Check whether `get_representative_least_absolute_residue` outputs the correct value for small values
119 #[test]
120 fn get_small() {
121 let value_0 = Zq::from((2, 20));
122 let value_1 = Zq::from((-2, 20));
123
124 let res_0 = value_0.get_representative_least_absolute_residue();
125 let res_1 = value_1.get_representative_least_absolute_residue();
126
127 assert_eq!(res_0, Z::from(2));
128 assert_eq!(res_1, Z::from(-2));
129 }
130
131 /// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
132 #[test]
133 fn get_large() {
134 let value_0 = Zq::from((i64::MAX, u64::MAX));
135 let value_1 = Zq::from((u64::MAX - 1, u64::MAX));
136
137 let res_0 = value_0.get_representative_least_absolute_residue();
138 let res_1 = value_1.get_representative_least_absolute_residue();
139
140 assert_eq!(res_0, Z::from(i64::MAX));
141 assert_eq!(res_1, Z::from(-1));
142 }
143
144 /// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
145 #[test]
146 fn get_special() {
147 let value_0 = Zq::from((10, 20));
148 let value_1 = Zq::from((0, 20));
149 let value_2 = Zq::from((11, 21));
150
151 let res_0 = value_0.get_representative_least_absolute_residue();
152 let res_1 = value_1.get_representative_least_absolute_residue();
153 let res_2 = value_2.get_representative_least_absolute_residue();
154
155 assert_eq!(res_0, Z::from(10));
156 assert_eq!(res_1, Z::from(0));
157 assert_eq!(res_2, Z::from(-10));
158 }
159
160 /// Checks whether an element of the upper half is mapped to its negative representative,
161 /// i.e. `256 mod 257` to `-1`.
162 #[test]
163 fn upper_half_negative() {
164 let value = Zq::from((256, 257));
165
166 let res = value.get_representative_least_absolute_residue();
167
168 assert_eq!(Z::MINUS_ONE, res);
169 }
170
171 /// Checks whether every element is mapped into `(-⌈modulus/2⌉, ⌊modulus/2⌋]`
172 /// according to `mod±` as defined in FIPS 204 for an odd and an even modulus.
173 #[test]
174 fn full_range() {
175 for modulus in [256, 257] {
176 for value in 0..modulus {
177 let expected = if value > modulus / 2 {
178 value - modulus
179 } else {
180 value
181 };
182
183 let res = Zq::from((value, modulus)).get_representative_least_absolute_residue();
184
185 assert_eq!(Z::from(expected), res);
186 }
187 }
188 }
189}
190
191#[cfg(test)]
192mod test_get_mod {
193 use super::{Modulus, Zq};
194
195 /// Check whether `get_mod` outputs the correct modulus for small moduli
196 #[test]
197 fn get_small() {
198 let value = Zq::from((2, 20));
199
200 let modulus = value.get_mod();
201
202 assert_eq!(modulus, Modulus::from(20));
203 }
204
205 /// Check whether `get_mod` outputs the correct modulus for large moduli
206 #[test]
207 fn get_large() {
208 let value = Zq::from((2, u64::MAX));
209
210 let modulus = value.get_mod();
211
212 assert_eq!(modulus, Modulus::from(u64::MAX));
213 }
214}