qfall_math/integer/z/arithmetic/
add.rs1use super::super::Z;
12use crate::{
13 integer::PolyOverZ,
14 integer_mod_q::Zq,
15 macros::arithmetics::{
16 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
17 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
18 arithmetic_trait_mixed_borrowed_owned,
19 },
20 rational::Q,
21};
22use flint3_sys::{
23 fmpq_add_fmpz, fmpz, fmpz_mod_add_fmpz, {fmpz_add, fmpz_add_si, fmpz_add_ui},
24};
25use std::ops::{Add, AddAssign};
26
27impl AddAssign<&Z> for Z {
28 fn add_assign(&mut self, other: &Self) {
50 unsafe { fmpz_add(&mut self.value, &self.value, &other.value) };
51 }
52}
53impl AddAssign<i64> for Z {
54 fn add_assign(&mut self, other: i64) {
56 unsafe { fmpz_add_si(&mut self.value, &self.value, other) };
57 }
58}
59impl AddAssign<u64> for Z {
60 fn add_assign(&mut self, other: u64) {
62 unsafe { fmpz_add_ui(&mut self.value, &self.value, other) };
63 }
64}
65
66arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Z, Z);
67arithmetic_assign_between_types!(AddAssign, add_assign, Z, i64, i32 i16 i8);
68arithmetic_assign_between_types!(AddAssign, add_assign, Z, u64, u32 u16 u8);
69
70impl Add for &Z {
71 type Output = Z;
72 fn add(self, other: Self) -> Self::Output {
93 let mut out = Z::default();
94 unsafe {
95 fmpz_add(&mut out.value, &self.value, &other.value);
96 }
97 out
98 }
99}
100
101arithmetic_trait_borrowed_to_owned!(Add, add, Z, Z, Z);
102arithmetic_trait_mixed_borrowed_owned!(Add, add, Z, Z, Z);
103arithmetic_between_types!(Add, add, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
104
105impl Add<&Q> for &Z {
106 type Output = Q;
107
108 fn add(self, other: &Q) -> Self::Output {
131 let mut out = Q::default();
132 unsafe {
133 fmpq_add_fmpz(&mut out.value, &other.value, &self.value);
134 }
135 out
136 }
137}
138
139arithmetic_trait_borrowed_to_owned!(Add, add, Z, Q, Q);
140arithmetic_trait_mixed_borrowed_owned!(Add, add, Z, Q, Q);
141arithmetic_between_types!(Add, add, Z, Q, f32 f64);
142
143impl Add<&Zq> for &Z {
144 type Output = Zq;
145 fn add(self, other: &Zq) -> Self::Output {
168 let mut out: fmpz = 0;
169 unsafe {
170 fmpz_mod_add_fmpz(
171 &mut out,
172 &other.value.value,
173 &self.value,
174 other.modulus.get_fmpz_mod_ctx_struct(),
175 );
176 }
177 Zq {
178 modulus: other.modulus.clone(),
179 value: Z { value: out },
180 }
181 }
182}
183
184arithmetic_trait_borrowed_to_owned!(Add, add, Z, Zq, Zq);
185arithmetic_trait_mixed_borrowed_owned!(Add, add, Z, Zq, Zq);
186
187impl Add<&PolyOverZ> for &Z {
188 type Output = PolyOverZ;
189 fn add(self, other: &PolyOverZ) -> Self::Output {
212 if other.is_zero() {
215 PolyOverZ::from(self)
216 } else {
217 let out = other.clone();
218 unsafe {
219 fmpz_add(out.poly.coeffs, &self.value, out.poly.coeffs);
220 }
221 out
222 }
223 }
224}
225
226arithmetic_trait_borrowed_to_owned!(Add, add, Z, PolyOverZ, PolyOverZ);
227arithmetic_trait_mixed_borrowed_owned!(Add, add, Z, PolyOverZ, PolyOverZ);
228
229#[cfg(test)]
230mod test_add_assign {
231 use crate::integer::Z;
232
233 #[test]
235 fn correct_small() {
236 let mut a: Z = Z::MINUS_ONE;
237 let b = Z::MINUS_ONE;
238 let c = Z::ONE;
239
240 a += &b;
241 assert_eq!(-2, a);
242 a += &c;
243 assert_eq!(-1, a);
244 a += &c;
245 assert_eq!(0, a);
246 a += &c;
247 assert_eq!(1, a);
248 a += &c;
249 assert_eq!(2, a);
250 a += 2 * b;
251 assert_eq!(0, a);
252 }
253
254 #[test]
256 fn correct_large() {
257 let mut a: Z = Z::from(i64::MAX);
258 let b = Z::from(i64::MIN);
259 let c = Z::from(u64::MAX);
260
261 a += b;
262 assert_eq!(-1, a);
263 a += c;
264 assert_eq!(u64::MAX - 1, a);
265 }
266
267 #[test]
269 fn availability() {
270 let mut a: Z = Z::from(42);
271 let b: Z = Z::from(1);
272
273 a += &b;
274 a += b;
275 a += 1_u8;
276 a += 1_u16;
277 a += 1_u32;
278 a += 1_u64;
279 a += 1_i8;
280 a += 1_i16;
281 a += 1_i32;
282 a += 1_i64;
283 }
284}
285
286#[cfg(test)]
287mod test_add_between_types {
288 use crate::integer::Z;
289
290 #[test]
292 #[allow(clippy::op_ref)]
293 fn add() {
294 let a: Z = Z::from(42);
295 let b: u64 = 1;
296 let c: u32 = 1;
297 let d: u16 = 1;
298 let e: u8 = 1;
299 let f: i64 = 1;
300 let g: i32 = 1;
301 let h: i16 = 1;
302 let i: i8 = 1;
303
304 let _: Z = &a + &b;
305 let _: Z = &a + &c;
306 let _: Z = &a + &d;
307 let _: Z = &a + &e;
308 let _: Z = &a + &f;
309 let _: Z = &a + &g;
310 let _: Z = &a + &h;
311 let _: Z = &a + &i;
312
313 let _: Z = &b + &a;
314 let _: Z = &c + &a;
315 let _: Z = &d + &a;
316 let _: Z = &e + &a;
317 let _: Z = &f + &a;
318 let _: Z = &g + &a;
319 let _: Z = &h + &a;
320 let _: Z = &i + &a;
321
322 let _: Z = &a + b;
323 let _: Z = &a + c;
324 let _: Z = &a + d;
325 let _: Z = &a + e;
326 let _: Z = &a + f;
327 let _: Z = &a + g;
328 let _: Z = &a + h;
329 let _: Z = &a + i;
330
331 let _: Z = &b + Z::from(42);
332 let _: Z = &c + Z::from(42);
333 let _: Z = &d + Z::from(42);
334 let _: Z = &e + Z::from(42);
335 let _: Z = &f + Z::from(42);
336 let _: Z = &g + Z::from(42);
337 let _: Z = &h + Z::from(42);
338 let _: Z = &i + Z::from(42);
339
340 let _: Z = Z::from(42) + &b;
341 let _: Z = Z::from(42) + &c;
342 let _: Z = Z::from(42) + &d;
343 let _: Z = Z::from(42) + &e;
344 let _: Z = Z::from(42) + &f;
345 let _: Z = Z::from(42) + &g;
346 let _: Z = Z::from(42) + &h;
347 let _: Z = Z::from(42) + &i;
348
349 let _: Z = b + &a;
350 let _: Z = c + &a;
351 let _: Z = d + &a;
352 let _: Z = e + &a;
353 let _: Z = f + &a;
354 let _: Z = g + &a;
355 let _: Z = h + &a;
356 let _: Z = i + &a;
357
358 let _: Z = Z::from(42) + b;
359 let _: Z = Z::from(42) + c;
360 let _: Z = Z::from(42) + d;
361 let _: Z = Z::from(42) + e;
362 let _: Z = Z::from(42) + f;
363 let _: Z = Z::from(42) + g;
364 let _: Z = Z::from(42) + h;
365 let _: Z = Z::from(42) + i;
366
367 let _: Z = b + Z::from(42);
368 let _: Z = c + Z::from(42);
369 let _: Z = d + Z::from(42);
370 let _: Z = e + Z::from(42);
371 let _: Z = f + Z::from(42);
372 let _: Z = g + Z::from(42);
373 let _: Z = h + Z::from(42);
374 let _: Z = i + Z::from(42);
375 }
376}
377
378#[cfg(test)]
379mod test_add_between_z_and_q {
380 use super::Z;
381 use crate::rational::Q;
382
383 #[test]
385 fn availability() {
386 let a: Z = Z::from(42);
387 let b: Q = Q::from((5, 7));
388
389 let _: Q = &a + &b;
390 let _: Q = &a + b.clone();
391 let _: Q = a.clone() + &b;
392 let _: Q = a.clone() + b;
393 let _: Q = &a + 0.5_f32;
394 let _: Q = &a + 0.5_f64;
395 let _: Q = a.clone() + 0.5_f32;
396 let _: Q = a.clone() + 0.5_f64;
397 let _: Q = 0.5_f32 + &a;
398 let _: Q = 0.5_f64 + &a;
399 let _: Q = 0.5_f32 + a.clone();
400 let _: Q = 0.5_f64 + a.clone();
401 }
402
403 #[test]
405 fn add() {
406 let a: Z = Z::from(4);
407 let b: Q = Q::from((5, 7));
408 let c: Q = a + b;
409 assert_eq!(c, Q::from((33, 7)));
410 }
411
412 #[test]
414 fn add_borrow() {
415 let a: Z = Z::from(4);
416 let b: Q = Q::from((5, 7));
417 let c: Q = &a + &b;
418 assert_eq!(c, Q::from((33, 7)));
419 }
420
421 #[test]
423 fn add_first_borrowed() {
424 let a: Z = Z::from(4);
425 let b: Q = Q::from((5, 7));
426 let c: Q = &a + b;
427 assert_eq!(c, Q::from((33, 7)));
428 }
429
430 #[test]
432 fn add_second_borrowed() {
433 let a: Z = Z::from(4);
434 let b: Q = Q::from((5, 7));
435 let c: Q = a + &b;
436 assert_eq!(c, Q::from((33, 7)));
437 }
438
439 #[test]
441 fn add_large_numbers() {
442 let a: Z = Z::from(u64::MAX);
443 let b: Q = Q::from((1, u64::MAX));
444 let c: Q = Q::from((u64::MAX, 2));
445
446 let d: Q = &a + b;
447 let e: Q = a + c;
448
449 assert_eq!(d, Q::from((1, u64::MAX)) + Q::from(u64::MAX));
450 assert_eq!(e, Q::from(u64::MAX) + Q::from((u64::MAX, 2)));
451 }
452}
453
454#[cfg(test)]
455mod test_add {
456 use super::Z;
457
458 #[test]
460 fn add() {
461 let a: Z = Z::from(42);
462 let b: Z = Z::from(24);
463 let c: Z = a + b;
464 assert_eq!(c, Z::from(66));
465 }
466
467 #[test]
469 fn add_borrow() {
470 let a: Z = Z::from(42);
471 let b: Z = Z::from(24);
472 let c: Z = &a + &b;
473 assert_eq!(c, Z::from(66));
474 }
475
476 #[test]
478 fn add_first_borrowed() {
479 let a: Z = Z::from(42);
480 let b: Z = Z::from(24);
481 let c: Z = &a + b;
482 assert_eq!(c, Z::from(66));
483 }
484
485 #[test]
487 fn add_second_borrowed() {
488 let a: Z = Z::from(42);
489 let b: Z = Z::from(24);
490 let c: Z = a + &b;
491 assert_eq!(c, Z::from(66));
492 }
493
494 #[test]
496 fn add_large_numbers() {
497 let a: Z = Z::from(u64::MAX);
498 let b: Z = Z::from(-221319874);
499 let c: Z = Z::from(i64::MIN);
500
501 let d: Z = &a + b;
502 let e: Z = a + c;
503
504 assert_eq!(d, Z::from(u64::MAX - 221319874));
505 assert_eq!(e, Z::from(i64::MAX));
506 }
507}
508
509#[cfg(test)]
510mod test_add_between_z_and_zq {
511 use super::Z;
512 use crate::integer_mod_q::Zq;
513
514 #[test]
516 fn add() {
517 let a: Z = Z::from(9);
518 let b: Zq = Zq::from((4, 11));
519 let c: Zq = a + b;
520 assert_eq!(c, Zq::from((2, 11)));
521 }
522
523 #[test]
525 fn add_borrow() {
526 let a: Z = Z::from(9);
527 let b: Zq = Zq::from((4, 11));
528 let c: Zq = &a + &b;
529 assert_eq!(c, Zq::from((2, 11)));
530 }
531
532 #[test]
534 fn add_first_borrowed() {
535 let a: Z = Z::from(9);
536 let b: Zq = Zq::from((4, 11));
537 let c: Zq = &a + b;
538 assert_eq!(c, Zq::from((2, 11)));
539 }
540
541 #[test]
543 fn add_second_borrowed() {
544 let a: Z = Z::from(9);
545 let b: Zq = Zq::from((4, 11));
546 let c: Zq = a + &b;
547 assert_eq!(c, Zq::from((2, 11)));
548 }
549
550 #[test]
552 fn add_large_numbers() {
553 let a: Z = Z::from(u64::MAX);
554 let b: Zq = Zq::from((i64::MAX, u64::MAX - 58));
555 let c: Zq = Zq::from((i64::MAX - 1, i64::MAX));
556
557 let d: Zq = &a + b;
558 let e: Zq = a + c;
559
560 assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 + 58, u64::MAX - 58)));
561 assert_eq!(e, Zq::from((0, i64::MAX)));
562 }
563}
564
565#[cfg(test)]
566mod test_add_between_z_and_poly_over_z {
567 use super::Z;
568 use crate::integer::PolyOverZ;
569 use std::str::FromStr;
570
571 #[test]
573 fn add() {
574 let a: Z = Z::from(9);
575 let b: PolyOverZ = PolyOverZ::from_str("4 1 1 2 3").unwrap();
576 let c: PolyOverZ = a + b;
577 assert_eq!(c, PolyOverZ::from_str("4 10 1 2 3").unwrap());
578 }
579
580 #[test]
582 fn add_borrow() {
583 let a: Z = Z::from(9);
584 let b: PolyOverZ = PolyOverZ::from_str("4 1 1 2 3").unwrap();
585 let c: PolyOverZ = &a + &b;
586 assert_eq!(c, PolyOverZ::from_str("4 10 1 2 3").unwrap());
587 }
588
589 #[test]
591 fn add_first_borrowed() {
592 let a: Z = Z::from(9);
593 let b: PolyOverZ = PolyOverZ::from_str("4 1 1 2 3").unwrap();
594 let c: PolyOverZ = &a + b;
595 assert_eq!(c, PolyOverZ::from_str("4 10 1 2 3").unwrap());
596 }
597
598 #[test]
600 fn add_second_borrowed() {
601 let a: Z = Z::from(9);
602 let b: PolyOverZ = PolyOverZ::from_str("4 1 1 2 3").unwrap();
603 let c: PolyOverZ = a + &b;
604 assert_eq!(c, PolyOverZ::from_str("4 10 1 2 3").unwrap());
605 }
606
607 #[test]
609 fn add_large_numbers() {
610 let a: Z = Z::from(i64::MAX);
611 let b: PolyOverZ =
612 PolyOverZ::from_str(&format!("3 {} {} {}", i64::MAX, u64::MAX, i32::MAX)).unwrap();
613 let c: PolyOverZ = a + b;
614 assert_eq!(
615 c,
616 PolyOverZ::from_str(&format!("3 {} {} {}", u64::MAX - 1, u64::MAX, i32::MAX)).unwrap()
617 );
618 }
619
620 #[test]
622 fn add_zero() {
623 let a: Z = Z::from(15);
624 let b: PolyOverZ = PolyOverZ::default();
625 let c: PolyOverZ = a + b;
626 assert_eq!(c, PolyOverZ::from_str("1 15").unwrap());
627
628 let d: Z = Z::ZERO;
629 let e: PolyOverZ = PolyOverZ::from_str("1 15").unwrap();
630 let f: PolyOverZ = d + e;
631 assert_eq!(f, PolyOverZ::from_str("1 15").unwrap());
632 }
633}