qfall_math/integer_mod_q/polynomial_ring_zq/arithmetic/
mul_scalar.rs1use super::super::PolynomialRingZq;
12use crate::error::MathError;
13use crate::integer::Z;
14use crate::integer_mod_q::Zq;
15use crate::macros::arithmetics::{
16 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
17 arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
18};
19use crate::macros::for_others::implement_for_others;
20use crate::traits::CompareBase;
21use std::ops::{Mul, MulAssign};
22
23impl Mul<&Z> for &PolynomialRingZq {
24 type Output = PolynomialRingZq;
25 fn mul(self, scalar: &Z) -> Self::Output {
46 let mut out = PolynomialRingZq::from(&self.modulus);
47
48 out.poly = &self.poly * scalar;
49
50 out.reduce();
51 out
52 }
53}
54
55arithmetic_trait_reverse!(Mul, mul, Z, PolynomialRingZq, PolynomialRingZq);
56
57arithmetic_trait_borrowed_to_owned!(Mul, mul, PolynomialRingZq, Z, PolynomialRingZq);
58arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, PolynomialRingZq, PolynomialRingZq);
59arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolynomialRingZq, Z, PolynomialRingZq);
60arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, PolynomialRingZq, PolynomialRingZq);
61
62implement_for_others!(Z, PolynomialRingZq, PolynomialRingZq, Mul Scalar for i8 i16 i32 i64 u8 u16 u32 u64);
63
64impl Mul<&Zq> for &PolynomialRingZq {
65 type Output = PolynomialRingZq;
66 fn mul(self, scalar: &Zq) -> PolynomialRingZq {
89 self.mul_scalar_zq_safe(scalar).unwrap()
90 }
91}
92
93arithmetic_trait_reverse!(Mul, mul, Zq, PolynomialRingZq, PolynomialRingZq);
94
95arithmetic_trait_borrowed_to_owned!(Mul, mul, PolynomialRingZq, Zq, PolynomialRingZq);
96arithmetic_trait_borrowed_to_owned!(Mul, mul, Zq, PolynomialRingZq, PolynomialRingZq);
97arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolynomialRingZq, Zq, PolynomialRingZq);
98arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Zq, PolynomialRingZq, PolynomialRingZq);
99
100impl MulAssign<&Zq> for PolynomialRingZq {
101 fn mul_assign(&mut self, rhs: &Zq) {
132 if !self.compare_base(rhs) {
133 panic!("{}", self.call_compare_base_error(rhs).unwrap())
134 }
135 self.mul_assign(&rhs.value);
136 }
137}
138
139arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolynomialRingZq, Zq);
140
141impl PolynomialRingZq {
142 pub fn mul_scalar_zq_safe(&self, scalar: &Zq) -> Result<Self, MathError> {
165 if !self.compare_base(scalar) {
166 return Err(self.call_compare_base_error(scalar).unwrap());
167 }
168
169 let mut out = PolynomialRingZq::from(&self.modulus);
170
171 out.poly = &self.poly * &scalar.value;
172
173 out.reduce();
174 Ok(out)
175 }
176}
177
178#[cfg(test)]
179mod test_mul_z {
180 use super::PolynomialRingZq;
181 use crate::integer::Z;
182 use std::str::FromStr;
183
184 #[test]
186 fn borrowed_correctness() {
187 let poly_1 = PolynomialRingZq::from_str(&format!(
188 "3 1 2 {} / 4 1 2 3 4 mod {}",
189 i64::MAX,
190 u64::MAX
191 ))
192 .unwrap();
193 let poly_2 = poly_1.clone();
194 let poly_3 = PolynomialRingZq::from_str(&format!(
195 "3 2 4 {} / 4 1 2 3 4 mod {}",
196 (i64::MAX as u64) * 2,
197 u64::MAX
198 ))
199 .unwrap();
200 let integer = Z::from(2);
201
202 let poly_1 = &poly_1 * &integer;
203 let poly_2 = &integer * &poly_2;
204
205 assert_eq!(poly_3, poly_1);
206 assert_eq!(poly_3, poly_2);
207 }
208
209 #[test]
211 fn availability() {
212 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap();
213 let z = Z::from(2);
214
215 _ = poly.clone() * z.clone();
216 _ = poly.clone() * 2i8;
217 _ = poly.clone() * 2u8;
218 _ = poly.clone() * 2i16;
219 _ = poly.clone() * 2u16;
220 _ = poly.clone() * 2i32;
221 _ = poly.clone() * 2u32;
222 _ = poly.clone() * 2i64;
223 _ = poly.clone() * 2u64;
224
225 _ = z.clone() * poly.clone();
226 _ = 2i8 * poly.clone();
227 _ = 2u64 * poly.clone();
228
229 _ = &poly * &z;
230 _ = &z * &poly;
231 _ = &poly * z.clone();
232 _ = z.clone() * &poly;
233 _ = poly.clone() * &z;
234 _ = &z * poly.clone();
235 _ = &poly * 2i8;
236 _ = 2i8 * &poly;
237 }
238}
239
240#[cfg(test)]
241mod test_mul_zq {
242 use super::PolynomialRingZq;
243 use crate::integer_mod_q::Zq;
244 use std::str::FromStr;
245
246 #[test]
248 fn borrowed_correctness() {
249 let poly_1 = PolynomialRingZq::from_str(&format!(
250 "3 1 2 {} / 4 1 2 3 4 mod {}",
251 i64::MAX,
252 u64::MAX
253 ))
254 .unwrap();
255 let poly_2 = poly_1.clone();
256 let poly_3 = PolynomialRingZq::from_str(&format!(
257 "3 2 4 {} / 4 1 2 3 4 mod {}",
258 (i64::MAX as u64) * 2,
259 u64::MAX
260 ))
261 .unwrap();
262 let integer = Zq::from((2, u64::MAX));
263
264 let poly_1 = &poly_1 * &integer;
265 let poly_2 = &integer * &poly_2;
266
267 assert_eq!(poly_3, poly_1);
268 assert_eq!(poly_3, poly_2);
269 }
270
271 #[test]
273 fn availability() {
274 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap();
275 let z = Zq::from((2, 17));
276
277 _ = poly.clone() * z.clone();
278 _ = z.clone() * poly.clone();
279 _ = &poly * &z;
280 _ = &z * &poly;
281 _ = &poly * z.clone();
282 _ = z.clone() * &poly;
283 _ = &z * poly.clone();
284 _ = poly.clone() * &z;
285 }
286
287 #[test]
289 #[should_panic]
290 fn different_moduli_panic() {
291 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap();
292 let z = Zq::from((2, 16));
293
294 _ = &poly * &z;
295 }
296
297 #[test]
299 fn different_moduli_error() {
300 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap();
301 let z = Zq::from((2, 16));
302
303 assert!(poly.mul_scalar_zq_safe(&z).is_err());
304 }
305}
306
307#[cfg(test)]
308mod test_mul_assign {
309 use crate::{
310 integer::{PolyOverZ, Z},
311 integer_mod_q::{ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq, Zq},
312 };
313 use std::str::FromStr;
314
315 #[test]
317 fn consistency() {
318 let modulus =
319 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
320 let poly_z = PolyOverZ::from_str("2 3 1").unwrap();
321 let mut polynomial_ring_zq = PolynomialRingZq::from((&poly_z, &modulus));
322
323 let cmp = &polynomial_ring_zq * i64::MAX;
324 polynomial_ring_zq *= i64::MAX;
325
326 assert_eq!(cmp, polynomial_ring_zq)
327 }
328
329 #[test]
331 fn availability() {
332 let modulus =
333 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
334 let poly_z = PolyOverZ::from_str("2 3 1").unwrap();
335 let mut polynomial_ring_zq = PolynomialRingZq::from((&poly_z, &modulus));
336
337 let z = Z::from(2);
338 let zq = Zq::from((2, u64::MAX));
339
340 polynomial_ring_zq *= &z;
341 polynomial_ring_zq *= z;
342 polynomial_ring_zq *= &zq;
343 polynomial_ring_zq *= zq;
344 polynomial_ring_zq *= 1_u8;
345 polynomial_ring_zq *= 1_u16;
346 polynomial_ring_zq *= 1_u32;
347 polynomial_ring_zq *= 1_u64;
348 polynomial_ring_zq *= 1_i8;
349 polynomial_ring_zq *= 1_i16;
350 polynomial_ring_zq *= 1_i32;
351 polynomial_ring_zq *= 1_i64;
352 }
353
354 #[test]
356 #[should_panic]
357 fn mismatching_modulus_zq() {
358 let modulus =
359 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
360 let poly_z = PolyOverZ::from_str("2 3 1").unwrap();
361 let mut polynomial_ring_zq = PolynomialRingZq::from((&poly_z, &modulus));
362
363 let zq = Zq::from((2, u64::MAX - 1));
364
365 polynomial_ring_zq *= &zq;
366 }
367
368 #[test]
370 #[should_panic]
371 fn mismatching_modulus_poly_zq() {
372 let modulus =
373 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
374 let poly_z = PolyOverZ::from_str("2 3 1").unwrap();
375 let mut polynomial_ring_zq = PolynomialRingZq::from((&poly_z, &modulus));
376
377 let poly_z = PolyOverZ::from_str("2 3 1").unwrap();
378 let poly_zq = PolyOverZq::from((&poly_z, u64::MAX - 1));
379
380 polynomial_ring_zq *= &poly_zq;
381 }
382}