qfall_math/integer/z/arithmetic/
mul.rs1use super::super::Z;
12use crate::{
13 integer_mod_q::Zq,
14 macros::arithmetics::{
15 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
16 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
17 arithmetic_trait_mixed_borrowed_owned,
18 },
19 rational::Q,
20};
21use flint_sys::{
22 fmpq::fmpq_mul_fmpz,
23 fmpz::{fmpz, fmpz_mul, fmpz_mul_si, fmpz_mul_ui},
24 fmpz_mod::fmpz_mod_mul_fmpz,
25};
26use std::ops::{Mul, MulAssign};
27
28impl MulAssign<&Z> for Z {
29 fn mul_assign(&mut self, other: &Self) {
51 unsafe { fmpz_mul(&mut self.value, &self.value, &other.value) };
52 }
53}
54impl MulAssign<i64> for Z {
55 fn mul_assign(&mut self, other: i64) {
57 unsafe { fmpz_mul_si(&mut self.value, &self.value, other) };
58 }
59}
60impl MulAssign<u64> for Z {
61 fn mul_assign(&mut self, other: u64) {
63 unsafe { fmpz_mul_ui(&mut self.value, &self.value, other) };
64 }
65}
66
67arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Z, Z);
68arithmetic_assign_between_types!(MulAssign, mul_assign, Z, i64, i32 i16 i8);
69arithmetic_assign_between_types!(MulAssign, mul_assign, Z, u64, u32 u16 u8);
70
71impl Mul for &Z {
72 type Output = Z;
73 fn mul(self, other: Self) -> Self::Output {
94 let mut out = Z::default();
95 unsafe {
96 fmpz_mul(&mut out.value, &self.value, &other.value);
97 }
98 out
99 }
100}
101
102arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Z, Z);
103arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Z, Z);
104arithmetic_between_types!(Mul, mul, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
105
106impl Mul<&Q> for &Z {
107 type Output = Q;
108
109 fn mul(self, other: &Q) -> Self::Output {
132 let mut out = Q::default();
133 unsafe {
134 fmpq_mul_fmpz(&mut out.value, &other.value, &self.value);
135 }
136 out
137 }
138}
139
140arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Q, Q);
141arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Q, Q);
142arithmetic_between_types!(Mul, mul, Z, Q, f32 f64);
143
144impl Mul<&Zq> for &Z {
145 type Output = Zq;
146 fn mul(self, other: &Zq) -> Self::Output {
169 let mut out = fmpz(0);
170 unsafe {
171 fmpz_mod_mul_fmpz(
172 &mut out,
173 &other.value.value,
174 &self.value,
175 other.modulus.get_fmpz_mod_ctx_struct(),
176 );
177 }
178 Zq {
179 modulus: other.modulus.clone(),
180 value: Z { value: out },
181 }
182 }
183}
184
185arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Zq, Zq);
186arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Zq, Zq);
187
188#[cfg(test)]
189mod test_mul_assign {
190 use crate::integer::Z;
191
192 #[test]
194 fn correct_small() {
195 let mut a: Z = Z::MINUS_ONE;
196 let b = Z::MINUS_ONE;
197 let c = Z::ZERO;
198
199 a *= &b;
200 assert_eq!(1, a);
201 a *= &b;
202 assert_eq!(-1, a);
203 a *= &c;
204 assert_eq!(0, a);
205 a *= &c;
206 }
207
208 #[test]
210 fn correct_large() {
211 let mut a: Z = Z::from(i64::MIN);
212 let mut b = Z::from(u64::MAX);
213
214 a *= Z::MINUS_ONE;
215 assert_eq!(-1 * Z::from(i64::MIN), a);
216 b *= Z::MINUS_ONE;
217 assert_eq!(-1 * Z::from(u64::MAX), b);
218 }
219
220 #[test]
222 fn availability() {
223 let mut a: Z = Z::from(42);
224 let b: Z = Z::from(1);
225
226 a *= &b;
227 a *= b;
228 a *= 1_u8;
229 a *= 1_u16;
230 a *= 1_u32;
231 a *= 1_u64;
232 a *= 1_i8;
233 a *= 1_i16;
234 a *= 1_i32;
235 a *= 1_i64;
236 }
237}
238
239#[cfg(test)]
240mod test_mul_between_types {
241 use crate::integer::Z;
242
243 #[test]
245 #[allow(clippy::op_ref)]
246 fn mul() {
247 let a: Z = Z::from(42);
248 let b: u64 = 5;
249 let c: u32 = 5;
250 let d: u16 = 5;
251 let e: u8 = 5;
252 let f: i64 = 5;
253 let g: i32 = 5;
254 let h: i16 = 5;
255 let i: i8 = 5;
256
257 let _: Z = &a * &b;
258 let _: Z = &a * &c;
259 let _: Z = &a * &d;
260 let _: Z = &a * &e;
261 let _: Z = &a * &f;
262 let _: Z = &a * &g;
263 let _: Z = &a * &h;
264 let _: Z = &a * &i;
265
266 let _: Z = &b * &a;
267 let _: Z = &c * &a;
268 let _: Z = &d * &a;
269 let _: Z = &e * &a;
270 let _: Z = &f * &a;
271 let _: Z = &g * &a;
272 let _: Z = &h * &a;
273 let _: Z = &i * &a;
274
275 let _: Z = &a * b;
276 let _: Z = &a * c;
277 let _: Z = &a * d;
278 let _: Z = &a * e;
279 let _: Z = &a * f;
280 let _: Z = &a * g;
281 let _: Z = &a * h;
282 let _: Z = &a * i;
283
284 let _: Z = &b * Z::from(42);
285 let _: Z = &c * Z::from(42);
286 let _: Z = &d * Z::from(42);
287 let _: Z = &e * Z::from(42);
288 let _: Z = &f * Z::from(42);
289 let _: Z = &g * Z::from(42);
290 let _: Z = &h * Z::from(42);
291 let _: Z = &i * Z::from(42);
292
293 let _: Z = Z::from(42) * &b;
294 let _: Z = Z::from(42) * &c;
295 let _: Z = Z::from(42) * &d;
296 let _: Z = Z::from(42) * &e;
297 let _: Z = Z::from(42) * &f;
298 let _: Z = Z::from(42) * &g;
299 let _: Z = Z::from(42) * &h;
300 let _: Z = Z::from(42) * &i;
301
302 let _: Z = b * &a;
303 let _: Z = c * &a;
304 let _: Z = d * &a;
305 let _: Z = e * &a;
306 let _: Z = f * &a;
307 let _: Z = g * &a;
308 let _: Z = h * &a;
309 let _: Z = i * &a;
310
311 let _: Z = Z::from(42) * b;
312 let _: Z = Z::from(42) * c;
313 let _: Z = Z::from(42) * d;
314 let _: Z = Z::from(42) * e;
315 let _: Z = Z::from(42) * f;
316 let _: Z = Z::from(42) * g;
317 let _: Z = Z::from(42) * h;
318 let _: Z = Z::from(42) * i;
319
320 let _: Z = b * Z::from(42);
321 let _: Z = c * Z::from(42);
322 let _: Z = d * Z::from(42);
323 let _: Z = e * Z::from(42);
324 let _: Z = f * Z::from(42);
325 let _: Z = g * Z::from(42);
326 let _: Z = h * Z::from(42);
327 let _: Z = i * Z::from(42);
328 }
329}
330
331#[cfg(test)]
332mod test_mul {
333 use super::Z;
334
335 #[test]
337 fn mul() {
338 let a: Z = Z::from(42);
339 let b: Z = Z::from(4);
340 let c: Z = a * b;
341 assert_eq!(c, Z::from(168));
342 }
343
344 #[test]
346 fn mul_borrow() {
347 let a: Z = Z::from(42);
348 let b: Z = Z::from(4);
349 let c: Z = &a * &b;
350 assert_eq!(c, Z::from(168));
351 }
352
353 #[test]
355 fn mul_first_borrowed() {
356 let a: Z = Z::from(42);
357 let b: Z = Z::from(4);
358 let c: Z = &a * b;
359 assert_eq!(c, Z::from(168));
360 }
361
362 #[test]
364 fn mul_second_borrowed() {
365 let a: Z = Z::from(42);
366 let b: Z = Z::from(4);
367 let c: Z = a * &b;
368 assert_eq!(c, Z::from(168));
369 }
370
371 #[test]
373 fn mul_large_numbers() {
374 let a: Z = Z::from(i64::MAX);
375 let b: Z = Z::from(2);
376 let c: Z = Z::from(i32::MIN);
377 let d: Z = Z::from(i32::MAX);
378
379 let e: Z = a * b;
380 let f: Z = c * d;
381
382 assert_eq!(e, Z::from(u64::MAX - 1));
383 assert_eq!(f, Z::from(i64::from(i32::MAX) * i64::from(i32::MIN)));
384 }
385}
386
387#[cfg(test)]
388mod test_mul_between_z_and_zq {
389 use super::Z;
390 use crate::integer_mod_q::Zq;
391
392 #[test]
394 fn mul() {
395 let a: Z = Z::from(9);
396 let b: Zq = Zq::from((4, 11));
397 let c: Zq = a * b;
398 assert_eq!(c, Zq::from((3, 11)));
399 }
400
401 #[test]
403 fn mul_borrow() {
404 let a: Z = Z::from(9);
405 let b: Zq = Zq::from((4, 11));
406 let c: Zq = &a * &b;
407 assert_eq!(c, Zq::from((3, 11)));
408 }
409
410 #[test]
412 fn mul_first_borrowed() {
413 let a: Z = Z::from(9);
414 let b: Zq = Zq::from((4, 11));
415 let c: Zq = &a * b;
416 assert_eq!(c, Zq::from((3, 11)));
417 }
418
419 #[test]
421 fn mul_second_borrowed() {
422 let a: Z = Z::from(9);
423 let b: Zq = Zq::from((4, 11));
424 let c: Zq = a * &b;
425 assert_eq!(c, Zq::from((3, 11)));
426 }
427
428 #[test]
430 fn mul_large_numbers() {
431 let a: Z = Z::from(u64::MAX);
432 let b: Zq = Zq::from((i64::MAX, u64::MAX - 58));
433 let c: Zq = Zq::from((i64::MAX - 1, i64::MAX));
434
435 let d: Zq = &a * b;
436 let e: Zq = a * c;
437
438 assert_eq!(
439 d,
440 Zq::from(((u64::MAX - 1) / 2, u64::MAX - 58)) * Zq::from((u64::MAX, u64::MAX - 58))
441 );
442 assert_eq!(e, Zq::from((u64::MAX, i64::MAX)) * Zq::from((-1, i64::MAX)));
443 }
444}
445
446#[cfg(test)]
447mod test_mul_between_z_and_q {
448 use super::Z;
449 use crate::rational::Q;
450
451 #[test]
453 fn availability() {
454 let a: Z = Z::from(42);
455 let b: Q = Q::from((5, 7));
456
457 let _: Q = &a * &b;
458 let _: Q = &a * b.clone();
459 let _: Q = a.clone() * &b;
460 let _: Q = a.clone() * b;
461 let _: Q = &a * 0.5_f32;
462 let _: Q = &a * 0.5_f64;
463 let _: Q = a.clone() * 0.5_f32;
464 let _: Q = a.clone() * 0.5_f64;
465 let _: Q = 0.5_f32 * &a;
466 let _: Q = 0.5_f64 * &a;
467 let _: Q = 0.5_f32 * a.clone();
468 let _: Q = 0.5_f64 * a.clone();
469 }
470
471 #[test]
473 fn mul() {
474 let a: Z = Z::from(4);
475 let b: Q = Q::from((5, 7));
476 let c: Q = a * b;
477 assert_eq!(c, Q::from((20, 7)));
478 }
479
480 #[test]
482 fn mul_borrow() {
483 let a: Z = Z::from(4);
484 let b: Q = Q::from((5, 7));
485 let c: Q = &a * &b;
486 assert_eq!(c, Q::from((20, 7)));
487 }
488
489 #[test]
491 fn mul_first_borrowed() {
492 let a: Z = Z::from(4);
493 let b: Q = Q::from((5, 7));
494 let c: Q = &a * b;
495 assert_eq!(c, Q::from((20, 7)));
496 }
497
498 #[test]
500 fn mul_second_borrowed() {
501 let a: Z = Z::from(4);
502 let b: Q = Q::from((5, 7));
503 let c: Q = a * &b;
504 assert_eq!(c, Q::from((20, 7)));
505 }
506
507 #[test]
509 fn mul_large_numbers() {
510 let a: Z = Z::from(u64::MAX);
511 let b: Q = Q::from((1, u64::MAX));
512 let c: Q = Q::from((u64::MAX, 2));
513
514 let d: Q = &a * b;
515 let e: Q = a * c;
516
517 assert_eq!(d, Q::from((1, u64::MAX)) * Q::from(u64::MAX));
518 assert_eq!(e, Q::from(u64::MAX) * Q::from((u64::MAX, 2)));
519 }
520}