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 flint_sys::{
23 fmpz::fmpz,
24 fmpz_mod::{fmpz_mod_add, fmpz_mod_add_fmpz, fmpz_mod_add_si, fmpz_mod_add_ui},
25};
26use std::ops::{Add, AddAssign};
27
28impl AddAssign<&Zq> for Zq {
29 fn add_assign(&mut self, other: &Self) {
56 if !self.compare_base(other) {
57 panic!("{}", self.call_compare_base_error(other).unwrap());
58 }
59
60 unsafe {
61 fmpz_mod_add(
62 &mut self.value.value,
63 &self.value.value,
64 &other.value.value,
65 self.modulus.get_fmpz_mod_ctx_struct(),
66 )
67 };
68 }
69}
70impl AddAssign<i64> for Zq {
71 fn add_assign(&mut self, other: i64) {
73 unsafe {
74 fmpz_mod_add_si(
75 &mut self.value.value,
76 &self.value.value,
77 other,
78 self.modulus.get_fmpz_mod_ctx_struct(),
79 )
80 };
81 }
82}
83impl AddAssign<u64> for Zq {
84 fn add_assign(&mut self, other: u64) {
86 unsafe {
87 fmpz_mod_add_ui(
88 &mut self.value.value,
89 &self.value.value,
90 other,
91 self.modulus.get_fmpz_mod_ctx_struct(),
92 )
93 };
94 }
95}
96impl AddAssign<&Z> for Zq {
97 fn add_assign(&mut self, other: &Z) {
99 unsafe {
100 fmpz_mod_add_fmpz(
101 &mut self.value.value,
102 &self.value.value,
103 &other.value,
104 self.modulus.get_fmpz_mod_ctx_struct(),
105 )
106 };
107 }
108}
109
110arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Zq, Zq);
111arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Zq, Z);
112arithmetic_assign_between_types!(AddAssign, add_assign, Zq, i64, i32 i16 i8);
113arithmetic_assign_between_types!(AddAssign, add_assign, Zq, u64, u32 u16 u8);
114
115impl Add for &Zq {
116 type Output = Zq;
117 fn add(self, other: Self) -> Self::Output {
141 self.add_safe(other).unwrap()
142 }
143}
144
145impl Zq {
146 pub fn add_safe(&self, other: &Self) -> Result<Zq, MathError> {
168 if !self.compare_base(other) {
169 return Err(self.call_compare_base_error(other).unwrap());
170 }
171 let mut out_z = Z::ZERO;
172 unsafe {
173 fmpz_mod_add(
174 &mut out_z.value,
175 &self.value.value,
176 &other.value.value,
177 self.modulus.get_fmpz_mod_ctx_struct(),
178 );
179 }
180
181 Ok(Self {
182 value: out_z,
183 modulus: self.modulus.clone(),
184 })
185 }
186}
187
188arithmetic_trait_borrowed_to_owned!(Add, add, Zq, Zq, Zq);
189arithmetic_trait_mixed_borrowed_owned!(Add, add, Zq, Zq, Zq);
190arithmetic_between_types_zq!(Add, add, Zq, i64 i32 i16 i8 u64 u32 u16 u8);
191
192impl Add<&Z> for &Zq {
193 type Output = Zq;
194
195 fn add(self, other: &Z) -> Self::Output {
218 let mut out = fmpz(0);
219 unsafe {
220 fmpz_mod_add_fmpz(
221 &mut out,
222 &self.value.value,
223 &other.value,
224 self.modulus.get_fmpz_mod_ctx_struct(),
225 );
226 }
227 Zq {
228 modulus: self.modulus.clone(),
229 value: Z { value: out },
230 }
231 }
232}
233
234arithmetic_trait_borrowed_to_owned!(Add, add, Zq, Z, Zq);
235arithmetic_trait_mixed_borrowed_owned!(Add, add, Zq, Z, Zq);
236
237#[cfg(test)]
238mod test_add_assign {
239 use crate::{integer::Z, integer_mod_q::Zq};
240
241 #[test]
243 fn correct_small() {
244 let mut a: Zq = Zq::from((-1, 7));
245 let b = Zq::from((-1, 7));
246 let c = Zq::from((1, 7));
247
248 a += &b;
249 assert_eq!(Zq::from((5, 7)), a);
250 a += &c;
251 assert_eq!(Zq::from((6, 7)), a);
252 a += &c;
253 assert_eq!(Zq::from((0, 7)), a);
254 a += &c;
255 assert_eq!(Zq::from((1, 7)), a);
256 a += &c;
257 assert_eq!(Zq::from((2, 7)), a);
258 a += 2 * b;
259 assert_eq!(Zq::from((0, 7)), a);
260 }
261
262 #[test]
264 fn correct_large() {
265 let mut a = Zq::from((i64::MAX, u64::MAX));
266 let b = Zq::from((i64::MIN + 2, u64::MAX));
267 let c = Zq::from((u64::MAX - 1, u64::MAX));
268
269 a += b;
270 assert_eq!(Zq::from((1, u64::MAX)), a);
271 a += c;
272 assert_eq!(Zq::from((0, u64::MAX)), a);
273 }
274
275 #[test]
277 fn availability() {
278 let mut a = Zq::from((3, 7));
279 let b = Zq::from((1, 7));
280 let c = Z::from(1);
281
282 a += &b;
283 a += b;
284 a += &c;
285 a += c;
286 a += 1_u8;
287 a += 1_u16;
288 a += 1_u32;
289 a += 1_u64;
290 a += 1_i8;
291 a += 1_i16;
292 a += 1_i32;
293 a += 1_i64;
294 }
295
296 #[test]
298 #[should_panic]
299 fn mismatching_moduli() {
300 let mut a = Zq::from((3, 7));
301 let b = Zq::from((1, 8));
302
303 a += b;
304 }
305}
306
307#[cfg(test)]
308mod test_add {
309 use super::Zq;
310
311 #[test]
313 fn add() {
314 let a: Zq = Zq::from((11, 17));
315 let b: Zq = Zq::from((12, 17));
316 let c: Zq = a + b;
317 assert_eq!(c, Zq::from((6, 17)));
318 }
319
320 #[test]
322 fn add_borrow() {
323 let a: Zq = Zq::from((10, 11));
324 let b: Zq = Zq::from((1, 11));
325 let c: Zq = &a + &b;
326 assert_eq!(c, Zq::from((0, 11)));
327 }
328
329 #[test]
331 fn add_first_borrowed() {
332 let a: Zq = Zq::from((2, 11));
333 let b: Zq = Zq::from((5, 11));
334 let c: Zq = &a + b;
335 assert_eq!(c, Zq::from((7, 11)));
336 }
337
338 #[test]
340 fn add_second_borrowed() {
341 let a: Zq = Zq::from((12, 11));
342 let b: Zq = Zq::from((10, 11));
343 let c: Zq = a + &b;
344 assert_eq!(c, Zq::from((0, 11)));
345 }
346
347 #[test]
349 fn add_large_numbers() {
350 let a: Zq = Zq::from((u32::MAX, u32::MAX - 58));
351 let b: Zq = Zq::from((i32::MAX, u32::MAX - 58));
352 let c: Zq = a + b;
353 assert_eq!(c, Zq::from(((u32::MAX - 1) / 2 + 58, u32::MAX - 58)));
354 }
355
356 #[test]
358 #[should_panic]
359 fn add_mismatching_modulus() {
360 let a: Zq = Zq::from((4, 11));
361 let b: Zq = Zq::from((1, 3));
362 let _c: Zq = a + b;
363 }
364
365 #[test]
367 fn add_safe_is_err() {
368 let a: Zq = Zq::from((4, 11));
369 let b: Zq = Zq::from((1, 3));
370 assert!(&a.add_safe(&b).is_err());
371 }
372}
373
374#[cfg(test)]
375mod test_add_between_zq_and_z {
376 use super::Z;
377 use crate::integer_mod_q::Zq;
378
379 #[test]
381 fn add() {
382 let a: Zq = Zq::from((4, 11));
383 let b: Z = Z::from(9);
384 let c: Zq = a + b;
385 assert_eq!(c, Zq::from((2, 11)));
386 }
387
388 #[test]
390 fn add_borrow() {
391 let a: Zq = Zq::from((4, 11));
392 let b: Z = Z::from(9);
393 let c: Zq = &a + &b;
394 assert_eq!(c, Zq::from((2, 11)));
395 }
396
397 #[test]
399 fn add_first_borrowed() {
400 let a: Zq = Zq::from((4, 11));
401 let b: Z = Z::from(9);
402 let c: Zq = &a + b;
403 assert_eq!(c, Zq::from((2, 11)));
404 }
405
406 #[test]
408 fn add_second_borrowed() {
409 let a: Zq = Zq::from((4, 11));
410 let b: Z = Z::from(9);
411 let c: Zq = a + &b;
412 assert_eq!(c, Zq::from((2, 11)));
413 }
414
415 #[test]
417 fn add_large_numbers() {
418 let a: Zq = Zq::from((i64::MAX, u64::MAX - 58));
419 let b: Zq = Zq::from((i64::MAX - 1, i64::MAX));
420 let c: Z = Z::from(u64::MAX);
421
422 let d: Zq = a + &c;
423 let e: Zq = b + c;
424
425 assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 + 58, u64::MAX - 58)));
426 assert_eq!(e, Zq::from((0, i64::MAX)));
427 }
428}
429
430#[cfg(test)]
431mod test_add_between_types {
432 use crate::integer_mod_q::Zq;
433
434 #[test]
436 #[allow(clippy::op_ref)]
437 fn add() {
438 let a: Zq = Zq::from((4, 11));
439 let b: u64 = 1;
440 let c: u32 = 1;
441 let d: u16 = 1;
442 let e: u8 = 1;
443 let f: i64 = 1;
444 let g: i32 = 1;
445 let h: i16 = 1;
446 let i: i8 = 1;
447
448 let _: Zq = &a + &b;
449 let _: Zq = &a + &c;
450 let _: Zq = &a + &d;
451 let _: Zq = &a + &e;
452 let _: Zq = &a + &f;
453 let _: Zq = &a + &g;
454 let _: Zq = &a + &h;
455 let _: Zq = &a + &i;
456
457 let _: Zq = &b + &a;
458 let _: Zq = &c + &a;
459 let _: Zq = &d + &a;
460 let _: Zq = &e + &a;
461 let _: Zq = &f + &a;
462 let _: Zq = &g + &a;
463 let _: Zq = &h + &a;
464 let _: Zq = &i + &a;
465
466 let _: Zq = &a + b;
467 let _: Zq = &a + c;
468 let _: Zq = &a + d;
469 let _: Zq = &a + e;
470 let _: Zq = &a + f;
471 let _: Zq = &a + g;
472 let _: Zq = &a + h;
473 let _: Zq = &a + i;
474
475 let _: Zq = &b + Zq::from((4, 11));
476 let _: Zq = &c + Zq::from((4, 11));
477 let _: Zq = &d + Zq::from((4, 11));
478 let _: Zq = &e + Zq::from((4, 11));
479 let _: Zq = &f + Zq::from((4, 11));
480 let _: Zq = &g + Zq::from((4, 11));
481 let _: Zq = &h + Zq::from((4, 11));
482 let _: Zq = &i + Zq::from((4, 11));
483
484 let _: Zq = Zq::from((4, 11)) + &b;
485 let _: Zq = Zq::from((4, 11)) + &c;
486 let _: Zq = Zq::from((4, 11)) + &d;
487 let _: Zq = Zq::from((4, 11)) + &e;
488 let _: Zq = Zq::from((4, 11)) + &f;
489 let _: Zq = Zq::from((4, 11)) + &g;
490 let _: Zq = Zq::from((4, 11)) + &h;
491 let _: Zq = Zq::from((4, 11)) + &i;
492
493 let _: Zq = b + &a;
494 let _: Zq = c + &a;
495 let _: Zq = d + &a;
496 let _: Zq = e + &a;
497 let _: Zq = f + &a;
498 let _: Zq = g + &a;
499 let _: Zq = h + &a;
500 let _: Zq = i + &a;
501
502 let _: Zq = Zq::from((4, 11)) + b;
503 let _: Zq = Zq::from((4, 11)) + c;
504 let _: Zq = Zq::from((4, 11)) + d;
505 let _: Zq = Zq::from((4, 11)) + e;
506 let _: Zq = Zq::from((4, 11)) + f;
507 let _: Zq = Zq::from((4, 11)) + g;
508 let _: Zq = Zq::from((4, 11)) + h;
509 let _: Zq = Zq::from((4, 11)) + i;
510
511 let _: Zq = b + Zq::from((4, 11));
512 let _: Zq = c + Zq::from((4, 11));
513 let _: Zq = d + Zq::from((4, 11));
514 let _: Zq = e + Zq::from((4, 11));
515 let _: Zq = f + Zq::from((4, 11));
516 let _: Zq = g + Zq::from((4, 11));
517 let _: Zq = h + Zq::from((4, 11));
518 let _: Zq = i + Zq::from((4, 11));
519 }
520}