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_sub, fmpz_mod_sub_fmpz, fmpz_mod_sub_si, fmpz_mod_sub_ui},
25};
26use std::ops::{Sub, SubAssign};
27
28impl SubAssign<&Zq> for Zq {
29 fn sub_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_sub(
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 SubAssign<i64> for Zq {
71 fn sub_assign(&mut self, other: i64) {
73 unsafe {
74 fmpz_mod_sub_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 SubAssign<u64> for Zq {
84 fn sub_assign(&mut self, other: u64) {
86 unsafe {
87 fmpz_mod_sub_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 SubAssign<&Z> for Zq {
97 fn sub_assign(&mut self, other: &Z) {
99 unsafe {
100 fmpz_mod_sub_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!(SubAssign, sub_assign, Zq, Zq);
111arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, Zq, Z);
112arithmetic_assign_between_types!(SubAssign, sub_assign, Zq, i64, i32 i16 i8);
113arithmetic_assign_between_types!(SubAssign, sub_assign, Zq, u64, u32 u16 u8);
114
115impl Sub for &Zq {
116 type Output = Zq;
117 fn sub(self, other: Self) -> Self::Output {
141 self.sub_safe(other).unwrap()
142 }
143}
144
145impl Zq {
146 pub fn sub_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_sub(
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!(Sub, sub, Zq, Zq, Zq);
189arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Zq, Zq, Zq);
190arithmetic_between_types_zq!(Sub, sub, Zq, i64 i32 i16 i8 u64 u32 u16 u8);
191
192impl Sub<&Z> for &Zq {
193 type Output = Zq;
194
195 fn sub(self, other: &Z) -> Self::Output {
218 let mut out = fmpz(0);
219 unsafe {
220 fmpz_mod_sub_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!(Sub, sub, Zq, Z, Zq);
235arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Zq, Z, Zq);
236
237#[cfg(test)]
238mod test_sub_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::MAX - 1, u64::MAX));
267
268 a -= b;
269 assert_eq!(Zq::from((1, u64::MAX)), a);
270 }
271
272 #[test]
274 fn availability() {
275 let mut a = Zq::from((3, 7));
276 let b = Zq::from((1, 7));
277 let c = Z::from(1);
278
279 a -= &b;
280 a -= b;
281 a -= &c;
282 a -= c;
283 a -= 1_u8;
284 a -= 1_u16;
285 a -= 1_u32;
286 a -= 1_u64;
287 a -= 1_i8;
288 a -= 1_i16;
289 a -= 1_i32;
290 a -= 1_i64;
291 }
292
293 #[test]
295 #[should_panic]
296 fn mismatching_moduli() {
297 let mut a = Zq::from((3, 7));
298 let b = Zq::from((1, 8));
299
300 a -= b;
301 }
302}
303
304#[cfg(test)]
305mod test_sub {
306 use super::Zq;
307
308 #[test]
310 fn sub() {
311 let a: Zq = Zq::from((11, 17));
312 let b: Zq = Zq::from((12, 17));
313 let c: Zq = a - b;
314 assert_eq!(c, Zq::from((16, 17)));
315 }
316
317 #[test]
319 fn sub_borrow() {
320 let a: Zq = Zq::from((10, 11));
321 let b: Zq = Zq::from((1, 11));
322 let c: Zq = &a - &b;
323 assert_eq!(c, Zq::from((9, 11)));
324 }
325
326 #[test]
328 fn sub_first_borrowed() {
329 let a: Zq = Zq::from((2, 11));
330 let b: Zq = Zq::from((5, 11));
331 let c: Zq = &a - b;
332 assert_eq!(c, Zq::from((-3, 11)));
333 }
334
335 #[test]
337 fn sub_second_borrowed() {
338 let a: Zq = Zq::from((12, 11));
339 let b: Zq = Zq::from((10, 11));
340 let c: Zq = a - &b;
341 assert_eq!(c, Zq::from((2, 11)));
342 }
343
344 #[test]
346 fn sub_large_numbers() {
347 let a: Zq = Zq::from((u32::MAX, u32::MAX - 58));
348 let b: Zq = Zq::from((i32::MAX, u32::MAX - 58));
349 let c: Zq = a - b;
350 assert_eq!(c, Zq::from((u32::MAX - (u32::MAX - 1) / 2, u32::MAX - 58)));
351 }
352
353 #[test]
355 #[should_panic]
356 fn sub_mismatching_modulus() {
357 let a: Zq = Zq::from((4, 11));
358 let b: Zq = Zq::from((1, 3));
359 let _c: Zq = a - b;
360 }
361
362 #[test]
364 fn sub_safe_is_err() {
365 let a: Zq = Zq::from((4, 11));
366 let b: Zq = Zq::from((1, 3));
367 assert!(&a.sub_safe(&b).is_err());
368 }
369}
370
371#[cfg(test)]
372mod test_sub_between_z_and_zq {
373 use super::Z;
374 use crate::integer_mod_q::Zq;
375
376 #[test]
378 fn sub() {
379 let a: Zq = Zq::from((4, 11));
380 let b: Z = Z::from(9);
381 let c: Zq = a - b;
382 assert_eq!(c, Zq::from((6, 11)));
383 }
384
385 #[test]
387 fn sub_borrow() {
388 let a: Zq = Zq::from((4, 11));
389 let b: Z = Z::from(9);
390 let c: Zq = &a - &b;
391 assert_eq!(c, Zq::from((6, 11)));
392 }
393
394 #[test]
396 fn sub_first_borrowed() {
397 let a: Zq = Zq::from((4, 11));
398 let b: Z = Z::from(9);
399 let c: Zq = &a - b;
400 assert_eq!(c, Zq::from((6, 11)));
401 }
402
403 #[test]
405 fn sub_second_borrowed() {
406 let a: Zq = Zq::from((4, 11));
407 let b: Z = Z::from(9);
408 let c: Zq = a - &b;
409 assert_eq!(c, Zq::from((6, 11)));
410 }
411
412 #[test]
414 fn sub_large_numbers() {
415 let a: Zq = Zq::from((i64::MAX, u64::MAX - 58));
416 let b: Zq = Zq::from((i64::MAX - 1, i64::MAX));
417 let c: Z = Z::from(u64::MAX);
418
419 let d: Zq = a - &c;
420 let e: Zq = b - c;
421
422 assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 - 58, u64::MAX - 58)));
423 assert_eq!(e, Zq::from((-2, i64::MAX)));
424 }
425}
426
427#[cfg(test)]
428mod test_sub_between_types {
429 use crate::integer_mod_q::Zq;
430
431 #[test]
433 #[allow(clippy::op_ref)]
434 fn sub() {
435 let a: Zq = Zq::from((4, 11));
436 let b: u64 = 1;
437 let c: u32 = 1;
438 let d: u16 = 1;
439 let e: u8 = 1;
440 let f: i64 = 1;
441 let g: i32 = 1;
442 let h: i16 = 1;
443 let i: i8 = 1;
444
445 let _: Zq = &a - &b;
446 let _: Zq = &a - &c;
447 let _: Zq = &a - &d;
448 let _: Zq = &a - &e;
449 let _: Zq = &a - &f;
450 let _: Zq = &a - &g;
451 let _: Zq = &a - &h;
452 let _: Zq = &a - &i;
453
454 let _: Zq = &b - &a;
455 let _: Zq = &c - &a;
456 let _: Zq = &d - &a;
457 let _: Zq = &e - &a;
458 let _: Zq = &f - &a;
459 let _: Zq = &g - &a;
460 let _: Zq = &h - &a;
461 let _: Zq = &i - &a;
462
463 let _: Zq = &a - b;
464 let _: Zq = &a - c;
465 let _: Zq = &a - d;
466 let _: Zq = &a - e;
467 let _: Zq = &a - f;
468 let _: Zq = &a - g;
469 let _: Zq = &a - h;
470 let _: Zq = &a - i;
471
472 let _: Zq = &b - Zq::from((4, 11));
473 let _: Zq = &c - Zq::from((4, 11));
474 let _: Zq = &d - Zq::from((4, 11));
475 let _: Zq = &e - Zq::from((4, 11));
476 let _: Zq = &f - Zq::from((4, 11));
477 let _: Zq = &g - Zq::from((4, 11));
478 let _: Zq = &h - Zq::from((4, 11));
479 let _: Zq = &i - Zq::from((4, 11));
480
481 let _: Zq = Zq::from((4, 11)) - &b;
482 let _: Zq = Zq::from((4, 11)) - &c;
483 let _: Zq = Zq::from((4, 11)) - &d;
484 let _: Zq = Zq::from((4, 11)) - &e;
485 let _: Zq = Zq::from((4, 11)) - &f;
486 let _: Zq = Zq::from((4, 11)) - &g;
487 let _: Zq = Zq::from((4, 11)) - &h;
488 let _: Zq = Zq::from((4, 11)) - &i;
489
490 let _: Zq = b - &a;
491 let _: Zq = c - &a;
492 let _: Zq = d - &a;
493 let _: Zq = e - &a;
494 let _: Zq = f - &a;
495 let _: Zq = g - &a;
496 let _: Zq = h - &a;
497 let _: Zq = i - &a;
498
499 let _: Zq = Zq::from((4, 11)) - b;
500 let _: Zq = Zq::from((4, 11)) - c;
501 let _: Zq = Zq::from((4, 11)) - d;
502 let _: Zq = Zq::from((4, 11)) - e;
503 let _: Zq = Zq::from((4, 11)) - f;
504 let _: Zq = Zq::from((4, 11)) - g;
505 let _: Zq = Zq::from((4, 11)) - h;
506 let _: Zq = Zq::from((4, 11)) - i;
507
508 let _: Zq = b - Zq::from((4, 11));
509 let _: Zq = c - Zq::from((4, 11));
510 let _: Zq = d - Zq::from((4, 11));
511 let _: Zq = e - Zq::from((4, 11));
512 let _: Zq = f - Zq::from((4, 11));
513 let _: Zq = g - Zq::from((4, 11));
514 let _: Zq = h - Zq::from((4, 11));
515 let _: Zq = i - Zq::from((4, 11));
516 }
517}