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