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