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