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_add, fmpz_mod_add_fmpz, fmpz_mod_add_si, fmpz_mod_add_ui},
24};
25use std::ops::{Add, AddAssign};
26
27impl AddAssign<&Zq> for Zq {
28 fn add_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_add(
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 AddAssign<i64> for Zq {
70 fn add_assign(&mut self, other: i64) {
72 unsafe {
73 fmpz_mod_add_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 AddAssign<u64> for Zq {
83 fn add_assign(&mut self, other: u64) {
85 unsafe {
86 fmpz_mod_add_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 AddAssign<&Z> for Zq {
96 fn add_assign(&mut self, other: &Z) {
98 unsafe {
99 fmpz_mod_add_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!(AddAssign, add_assign, Zq, Zq);
110arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Zq, Z);
111arithmetic_assign_between_types!(AddAssign, add_assign, Zq, i64, i32 i16 i8);
112arithmetic_assign_between_types!(AddAssign, add_assign, Zq, u64, u32 u16 u8);
113
114impl Add for &Zq {
115 type Output = Zq;
116 fn add(self, other: Self) -> Self::Output {
140 self.add_safe(other).unwrap()
141 }
142}
143
144impl Zq {
145 pub fn add_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_add(
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!(Add, add, Zq, Zq, Zq);
188arithmetic_trait_mixed_borrowed_owned!(Add, add, Zq, Zq, Zq);
189arithmetic_between_types_zq!(Add, add, Zq, i64 i32 i16 i8 u64 u32 u16 u8);
190
191impl Add<&Z> for &Zq {
192 type Output = Zq;
193
194 fn add(self, other: &Z) -> Self::Output {
217 let mut out: fmpz = 0;
218 unsafe {
219 fmpz_mod_add_fmpz(
220 &mut out,
221 &self.value.value,
222 &other.value,
223 self.modulus.get_fmpz_mod_ctx_struct(),
224 );
225 }
226 Zq {
227 modulus: self.modulus.clone(),
228 value: Z { value: out },
229 }
230 }
231}
232
233arithmetic_trait_borrowed_to_owned!(Add, add, Zq, Z, Zq);
234arithmetic_trait_mixed_borrowed_owned!(Add, add, Zq, Z, Zq);
235
236#[cfg(test)]
237mod test_add_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((1, 7));
246
247 a += &b;
248 assert_eq!(Zq::from((5, 7)), a);
249 a += &c;
250 assert_eq!(Zq::from((6, 7)), a);
251 a += &c;
252 assert_eq!(Zq::from((0, 7)), a);
253 a += &c;
254 assert_eq!(Zq::from((1, 7)), a);
255 a += &c;
256 assert_eq!(Zq::from((2, 7)), a);
257 a += 2 * b;
258 assert_eq!(Zq::from((0, 7)), a);
259 }
260
261 #[test]
263 fn correct_large() {
264 let mut a = Zq::from((i64::MAX, u64::MAX));
265 let b = Zq::from((i64::MIN + 2, u64::MAX));
266 let c = Zq::from((u64::MAX - 1, u64::MAX));
267
268 a += b;
269 assert_eq!(Zq::from((1, u64::MAX)), a);
270 a += c;
271 assert_eq!(Zq::from((0, u64::MAX)), a);
272 }
273
274 #[test]
276 fn availability() {
277 let mut a = Zq::from((3, 7));
278 let b = Zq::from((1, 7));
279 let c = Z::from(1);
280
281 a += &b;
282 a += b;
283 a += &c;
284 a += c;
285 a += 1_u8;
286 a += 1_u16;
287 a += 1_u32;
288 a += 1_u64;
289 a += 1_i8;
290 a += 1_i16;
291 a += 1_i32;
292 a += 1_i64;
293 }
294
295 #[test]
297 #[should_panic]
298 fn mismatching_moduli() {
299 let mut a = Zq::from((3, 7));
300 let b = Zq::from((1, 8));
301
302 a += b;
303 }
304}
305
306#[cfg(test)]
307mod test_add {
308 use super::Zq;
309
310 #[test]
312 fn add() {
313 let a: Zq = Zq::from((11, 17));
314 let b: Zq = Zq::from((12, 17));
315 let c: Zq = a + b;
316 assert_eq!(c, Zq::from((6, 17)));
317 }
318
319 #[test]
321 fn add_borrow() {
322 let a: Zq = Zq::from((10, 11));
323 let b: Zq = Zq::from((1, 11));
324 let c: Zq = &a + &b;
325 assert_eq!(c, Zq::from((0, 11)));
326 }
327
328 #[test]
330 fn add_first_borrowed() {
331 let a: Zq = Zq::from((2, 11));
332 let b: Zq = Zq::from((5, 11));
333 let c: Zq = &a + b;
334 assert_eq!(c, Zq::from((7, 11)));
335 }
336
337 #[test]
339 fn add_second_borrowed() {
340 let a: Zq = Zq::from((12, 11));
341 let b: Zq = Zq::from((10, 11));
342 let c: Zq = a + &b;
343 assert_eq!(c, Zq::from((0, 11)));
344 }
345
346 #[test]
348 fn add_large_numbers() {
349 let a: Zq = Zq::from((u32::MAX, u32::MAX - 58));
350 let b: Zq = Zq::from((i32::MAX, u32::MAX - 58));
351 let c: Zq = a + b;
352 assert_eq!(c, Zq::from(((u32::MAX - 1) / 2 + 58, u32::MAX - 58)));
353 }
354
355 #[test]
357 #[should_panic]
358 fn add_mismatching_modulus() {
359 let a: Zq = Zq::from((4, 11));
360 let b: Zq = Zq::from((1, 3));
361 let _c: Zq = a + b;
362 }
363
364 #[test]
366 fn add_safe_is_err() {
367 let a: Zq = Zq::from((4, 11));
368 let b: Zq = Zq::from((1, 3));
369 assert!(&a.add_safe(&b).is_err());
370 }
371}
372
373#[cfg(test)]
374mod test_add_between_zq_and_z {
375 use super::Z;
376 use crate::integer_mod_q::Zq;
377
378 #[test]
380 fn add() {
381 let a: Zq = Zq::from((4, 11));
382 let b: Z = Z::from(9);
383 let c: Zq = a + b;
384 assert_eq!(c, Zq::from((2, 11)));
385 }
386
387 #[test]
389 fn add_borrow() {
390 let a: Zq = Zq::from((4, 11));
391 let b: Z = Z::from(9);
392 let c: Zq = &a + &b;
393 assert_eq!(c, Zq::from((2, 11)));
394 }
395
396 #[test]
398 fn add_first_borrowed() {
399 let a: Zq = Zq::from((4, 11));
400 let b: Z = Z::from(9);
401 let c: Zq = &a + b;
402 assert_eq!(c, Zq::from((2, 11)));
403 }
404
405 #[test]
407 fn add_second_borrowed() {
408 let a: Zq = Zq::from((4, 11));
409 let b: Z = Z::from(9);
410 let c: Zq = a + &b;
411 assert_eq!(c, Zq::from((2, 11)));
412 }
413
414 #[test]
416 fn add_large_numbers() {
417 let a: Zq = Zq::from((i64::MAX, u64::MAX - 58));
418 let b: Zq = Zq::from((i64::MAX - 1, i64::MAX));
419 let c: Z = Z::from(u64::MAX);
420
421 let d: Zq = a + &c;
422 let e: Zq = b + c;
423
424 assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 + 58, u64::MAX - 58)));
425 assert_eq!(e, Zq::from((0, i64::MAX)));
426 }
427}
428
429#[cfg(test)]
430mod test_add_between_types {
431 use crate::integer_mod_q::Zq;
432
433 #[test]
435 #[allow(clippy::op_ref)]
436 fn add() {
437 let a: Zq = Zq::from((4, 11));
438 let b: u64 = 1;
439 let c: u32 = 1;
440 let d: u16 = 1;
441 let e: u8 = 1;
442 let f: i64 = 1;
443 let g: i32 = 1;
444 let h: i16 = 1;
445 let i: i8 = 1;
446
447 let _: Zq = &a + &b;
448 let _: Zq = &a + &c;
449 let _: Zq = &a + &d;
450 let _: Zq = &a + &e;
451 let _: Zq = &a + &f;
452 let _: Zq = &a + &g;
453 let _: Zq = &a + &h;
454 let _: Zq = &a + &i;
455
456 let _: Zq = &b + &a;
457 let _: Zq = &c + &a;
458 let _: Zq = &d + &a;
459 let _: Zq = &e + &a;
460 let _: Zq = &f + &a;
461 let _: Zq = &g + &a;
462 let _: Zq = &h + &a;
463 let _: Zq = &i + &a;
464
465 let _: Zq = &a + b;
466 let _: Zq = &a + c;
467 let _: Zq = &a + d;
468 let _: Zq = &a + e;
469 let _: Zq = &a + f;
470 let _: Zq = &a + g;
471 let _: Zq = &a + h;
472 let _: Zq = &a + i;
473
474 let _: Zq = &b + Zq::from((4, 11));
475 let _: Zq = &c + Zq::from((4, 11));
476 let _: Zq = &d + Zq::from((4, 11));
477 let _: Zq = &e + Zq::from((4, 11));
478 let _: Zq = &f + Zq::from((4, 11));
479 let _: Zq = &g + Zq::from((4, 11));
480 let _: Zq = &h + Zq::from((4, 11));
481 let _: Zq = &i + Zq::from((4, 11));
482
483 let _: Zq = Zq::from((4, 11)) + &b;
484 let _: Zq = Zq::from((4, 11)) + &c;
485 let _: Zq = Zq::from((4, 11)) + &d;
486 let _: Zq = Zq::from((4, 11)) + &e;
487 let _: Zq = Zq::from((4, 11)) + &f;
488 let _: Zq = Zq::from((4, 11)) + &g;
489 let _: Zq = Zq::from((4, 11)) + &h;
490 let _: Zq = Zq::from((4, 11)) + &i;
491
492 let _: Zq = b + &a;
493 let _: Zq = c + &a;
494 let _: Zq = d + &a;
495 let _: Zq = e + &a;
496 let _: Zq = f + &a;
497 let _: Zq = g + &a;
498 let _: Zq = h + &a;
499 let _: Zq = i + &a;
500
501 let _: Zq = Zq::from((4, 11)) + b;
502 let _: Zq = Zq::from((4, 11)) + c;
503 let _: Zq = Zq::from((4, 11)) + d;
504 let _: Zq = Zq::from((4, 11)) + e;
505 let _: Zq = Zq::from((4, 11)) + f;
506 let _: Zq = Zq::from((4, 11)) + g;
507 let _: Zq = Zq::from((4, 11)) + h;
508 let _: Zq = Zq::from((4, 11)) + i;
509
510 let _: Zq = b + Zq::from((4, 11));
511 let _: Zq = c + Zq::from((4, 11));
512 let _: Zq = d + Zq::from((4, 11));
513 let _: Zq = e + Zq::from((4, 11));
514 let _: Zq = f + Zq::from((4, 11));
515 let _: Zq = g + Zq::from((4, 11));
516 let _: Zq = h + Zq::from((4, 11));
517 let _: Zq = i + Zq::from((4, 11));
518 }
519}