1use super::super::Zq;
12use crate::{
13 error::MathError,
14 integer::Z,
15 macros::arithmetics::{
16 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
17 arithmetic_between_types_zq, arithmetic_trait_borrowed_to_owned,
18 arithmetic_trait_mixed_borrowed_owned,
19 },
20 traits::CompareBase,
21};
22use flint_sys::{
23 fmpz::fmpz,
24 fmpz_mod::{fmpz_mod_mul, fmpz_mod_mul_fmpz, fmpz_mod_mul_si, fmpz_mod_mul_ui},
25};
26use std::ops::{Mul, MulAssign};
27
28impl MulAssign<&Zq> for Zq {
29 fn mul_assign(&mut self, other: &Self) {
56 if !self.compare_base(other) {
57 panic!("{}", self.call_compare_base_error(other).unwrap());
58 }
59
60 unsafe {
61 fmpz_mod_mul(
62 &mut self.value.value,
63 &self.value.value,
64 &other.value.value,
65 self.modulus.get_fmpz_mod_ctx_struct(),
66 )
67 };
68 }
69}
70impl MulAssign<i64> for Zq {
71 fn mul_assign(&mut self, other: i64) {
73 unsafe {
74 fmpz_mod_mul_si(
75 &mut self.value.value,
76 &self.value.value,
77 other,
78 self.modulus.get_fmpz_mod_ctx_struct(),
79 )
80 };
81 }
82}
83impl MulAssign<u64> for Zq {
84 fn mul_assign(&mut self, other: u64) {
86 unsafe {
87 fmpz_mod_mul_ui(
88 &mut self.value.value,
89 &self.value.value,
90 other,
91 self.modulus.get_fmpz_mod_ctx_struct(),
92 )
93 };
94 }
95}
96impl MulAssign<&Z> for Zq {
97 fn mul_assign(&mut self, other: &Z) {
99 unsafe {
100 fmpz_mod_mul_fmpz(
101 &mut self.value.value,
102 &self.value.value,
103 &other.value,
104 self.modulus.get_fmpz_mod_ctx_struct(),
105 )
106 };
107 }
108}
109
110arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Zq, Zq);
111arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Zq, Z);
112arithmetic_assign_between_types!(MulAssign, mul_assign, Zq, i64, i32 i16 i8);
113arithmetic_assign_between_types!(MulAssign, mul_assign, Zq, u64, u32 u16 u8);
114
115impl Mul for &Zq {
116 type Output = Zq;
117 fn mul(self, other: Self) -> Self::Output {
141 self.mul_safe(other).unwrap()
142 }
143}
144
145impl Zq {
146 pub fn mul_safe(&self, other: &Self) -> Result<Zq, MathError> {
168 if !self.compare_base(other) {
169 return Err(self.call_compare_base_error(other).unwrap());
170 }
171 let mut out_z = Z::ZERO;
172 unsafe {
173 fmpz_mod_mul(
174 &mut out_z.value,
175 &self.value.value,
176 &other.value.value,
177 self.modulus.get_fmpz_mod_ctx_struct(),
178 )
179 };
180
181 Ok(Self {
182 value: out_z,
183 modulus: self.modulus.clone(),
184 })
185 }
186}
187
188arithmetic_trait_borrowed_to_owned!(Mul, mul, Zq, Zq, Zq);
189arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Zq, Zq, Zq);
190
191impl Mul<&Z> for &Zq {
192 type Output = Zq;
193
194 fn mul(self, other: &Z) -> Self::Output {
217 let mut out = fmpz(0);
218 unsafe {
219 fmpz_mod_mul_fmpz(
220 &mut out,
221 &self.value.value,
222 &other.value,
223 self.modulus.get_fmpz_mod_ctx_struct(),
224 );
225 }
226 Zq {
227 modulus: self.modulus.clone(),
228 value: Z { value: out },
229 }
230 }
231}
232
233arithmetic_trait_borrowed_to_owned!(Mul, mul, Zq, Z, Zq);
234arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Zq, Z, Zq);
235arithmetic_between_types_zq!(Mul, mul, Zq, i64 i32 i16 i8 u64 u32 u16 u8);
236
237#[cfg(test)]
238mod test_mul_assign {
239 use crate::{integer::Z, integer_mod_q::Zq};
240
241 #[test]
243 fn correct_small() {
244 let mut a: Zq = Zq::from((-1, 7));
245 let b = Zq::from((-1, 7));
246 let c = Zq::from((0, 7));
247
248 a *= &b;
249 assert_eq!(Zq::from((1, 7)), a);
250 a *= &b;
251 assert_eq!(Zq::from((6, 7)), a);
252 a *= &c;
253 assert_eq!(Zq::from((0, 7)), a);
254 }
255
256 #[test]
258 fn correct_large() {
259 let mut a = Zq::from((i64::MAX, u64::MAX));
260 let b = Zq::from((-1, u64::MAX));
261
262 a *= &b;
263 assert_eq!(Zq::from((9223372036854775808u64, u64::MAX)), a);
264 a *= b;
265 assert_eq!(Zq::from((i64::MAX, u64::MAX)), a);
266 }
267
268 #[test]
270 fn availability() {
271 let mut a = Zq::from((3, 7));
272 let b = Zq::from((1, 7));
273 let c = Z::from(1);
274
275 a *= &b;
276 a *= b;
277 a *= &c;
278 a *= c;
279 a *= 1_u8;
280 a *= 1_u16;
281 a *= 1_u32;
282 a *= 1_u64;
283 a *= 1_i8;
284 a *= 1_i16;
285 a *= 1_i32;
286 a *= 1_i64;
287 }
288
289 #[test]
291 #[should_panic]
292 fn mismatching_moduli() {
293 let mut a = Zq::from((3, 7));
294 let b = Zq::from((1, 8));
295
296 a *= b;
297 }
298}
299
300#[cfg(test)]
301mod test_mul {
302 use super::Zq;
303
304 #[test]
306 fn mul() {
307 let a: Zq = Zq::from((11, 17));
308 let b: Zq = Zq::from((12, 17));
309 let c: Zq = a * b;
310 assert_eq!(c, Zq::from((13, 17)));
311 }
312
313 #[test]
315 fn mul_borrow() {
316 let a: Zq = Zq::from((10, 11));
317 let b: Zq = Zq::from((1, 11));
318 let c: Zq = &a * &b;
319 assert_eq!(c, Zq::from((10, 11)));
320 }
321
322 #[test]
324 fn mul_first_borrowed() {
325 let a: Zq = Zq::from((2, 11));
326 let b: Zq = Zq::from((5, 11));
327 let c: Zq = &a * b;
328 assert_eq!(c, Zq::from((10, 11)));
329 }
330
331 #[test]
333 fn mul_second_borrowed() {
334 let a: Zq = Zq::from((12, 11));
335 let b: Zq = Zq::from((10, 11));
336 let c: Zq = a * &b;
337 assert_eq!(c, Zq::from((-1, 11)));
338 }
339
340 #[test]
342 fn mul_large_numbers() {
343 let a: Zq = Zq::from((u32::MAX, u32::MAX - 58));
344 let b: Zq = Zq::from((i32::MAX, u32::MAX - 58));
345 let c: Zq = a * b;
346 assert_eq!(
347 c,
348 Zq::from((u64::from((u32::MAX - 1) / 2) * 58, u32::MAX - 58))
349 );
350 }
351
352 #[test]
354 #[should_panic]
355 fn mul_mismatching_modulus() {
356 let a: Zq = Zq::from((4, 11));
357 let b: Zq = Zq::from((1, 3));
358 let _c: Zq = a * b;
359 }
360
361 #[test]
363 fn mul_safe_is_err() {
364 let a: Zq = Zq::from((4, 11));
365 let b: Zq = Zq::from((1, 3));
366 assert!(&a.mul_safe(&b).is_err());
367 }
368}
369
370#[cfg(test)]
371mod test_mul_between_zq_and_z {
372 use super::Z;
373 use crate::integer_mod_q::Zq;
374
375 #[test]
377 fn mul() {
378 let a: Zq = Zq::from((4, 11));
379 let b: Z = Z::from(9);
380 let c: Zq = a * b;
381 assert_eq!(c, Zq::from((3, 11)));
382 }
383
384 #[test]
386 fn mul_borrow() {
387 let a: Zq = Zq::from((4, 11));
388 let b: Z = Z::from(9);
389 let c: Zq = &a * &b;
390 assert_eq!(c, Zq::from((3, 11)));
391 }
392
393 #[test]
395 fn mul_first_borrowed() {
396 let a: Zq = Zq::from((4, 11));
397 let b: Z = Z::from(9);
398 let c: Zq = &a * b;
399 assert_eq!(c, Zq::from((3, 11)));
400 }
401
402 #[test]
404 fn mul_second_borrowed() {
405 let a: Zq = Zq::from((4, 11));
406 let b: Z = Z::from(9);
407 let c: Zq = a * &b;
408 assert_eq!(c, Zq::from((3, 11)));
409 }
410
411 #[test]
413 fn mul_large_numbers() {
414 let a: Zq = Zq::from((i64::MAX, u64::MAX - 58));
415 let b: Zq = Zq::from((i64::MAX - 1, i64::MAX));
416 let c: Z = Z::from(u64::MAX);
417
418 let d: Zq = a * &c;
419 let e: Zq = b * c;
420
421 assert_eq!(
422 d,
423 Zq::from(((u64::MAX - 1) / 2, u64::MAX - 58)) * Zq::from((u64::MAX, u64::MAX - 58))
424 );
425 assert_eq!(e, Zq::from((-1, i64::MAX)) * Zq::from((u64::MAX, i64::MAX)));
426 }
427}
428
429#[cfg(test)]
430mod test_mul_between_types {
431 use crate::integer_mod_q::Zq;
432
433 #[test]
435 #[allow(clippy::op_ref)]
436 fn mul() {
437 let a: Zq = Zq::from((4, 11));
438 let b: u64 = 1;
439 let c: u32 = 1;
440 let d: u16 = 1;
441 let e: u8 = 1;
442 let f: i64 = 1;
443 let g: i32 = 1;
444 let h: i16 = 1;
445 let i: i8 = 1;
446
447 let _: Zq = &a * &b;
448 let _: Zq = &a * &c;
449 let _: Zq = &a * &d;
450 let _: Zq = &a * &e;
451 let _: Zq = &a * &f;
452 let _: Zq = &a * &g;
453 let _: Zq = &a * &h;
454 let _: Zq = &a * &i;
455
456 let _: Zq = &b * &a;
457 let _: Zq = &c * &a;
458 let _: Zq = &d * &a;
459 let _: Zq = &e * &a;
460 let _: Zq = &f * &a;
461 let _: Zq = &g * &a;
462 let _: Zq = &h * &a;
463 let _: Zq = &i * &a;
464
465 let _: Zq = &a * b;
466 let _: Zq = &a * c;
467 let _: Zq = &a * d;
468 let _: Zq = &a * e;
469 let _: Zq = &a * f;
470 let _: Zq = &a * g;
471 let _: Zq = &a * h;
472 let _: Zq = &a * i;
473
474 let _: Zq = &b * Zq::from((4, 11));
475 let _: Zq = &c * Zq::from((4, 11));
476 let _: Zq = &d * Zq::from((4, 11));
477 let _: Zq = &e * Zq::from((4, 11));
478 let _: Zq = &f * Zq::from((4, 11));
479 let _: Zq = &g * Zq::from((4, 11));
480 let _: Zq = &h * Zq::from((4, 11));
481 let _: Zq = &i * Zq::from((4, 11));
482
483 let _: Zq = Zq::from((4, 11)) * &b;
484 let _: Zq = Zq::from((4, 11)) * &c;
485 let _: Zq = Zq::from((4, 11)) * &d;
486 let _: Zq = Zq::from((4, 11)) * &e;
487 let _: Zq = Zq::from((4, 11)) * &f;
488 let _: Zq = Zq::from((4, 11)) * &g;
489 let _: Zq = Zq::from((4, 11)) * &h;
490 let _: Zq = Zq::from((4, 11)) * &i;
491
492 let _: Zq = b * &a;
493 let _: Zq = c * &a;
494 let _: Zq = d * &a;
495 let _: Zq = e * &a;
496 let _: Zq = f * &a;
497 let _: Zq = g * &a;
498 let _: Zq = h * &a;
499 let _: Zq = i * &a;
500
501 let _: Zq = Zq::from((4, 11)) * b;
502 let _: Zq = Zq::from((4, 11)) * c;
503 let _: Zq = Zq::from((4, 11)) * d;
504 let _: Zq = Zq::from((4, 11)) * e;
505 let _: Zq = Zq::from((4, 11)) * f;
506 let _: Zq = Zq::from((4, 11)) * g;
507 let _: Zq = Zq::from((4, 11)) * h;
508 let _: Zq = Zq::from((4, 11)) * i;
509
510 let _: Zq = b * Zq::from((4, 11));
511 let _: Zq = c * Zq::from((4, 11));
512 let _: Zq = d * Zq::from((4, 11));
513 let _: Zq = e * Zq::from((4, 11));
514 let _: Zq = f * Zq::from((4, 11));
515 let _: Zq = g * Zq::from((4, 11));
516 let _: Zq = h * Zq::from((4, 11));
517 let _: Zq = i * Zq::from((4, 11));
518 }
519}