qfall_math/integer_mod_q/z_q/arithmetic/
sub.rs

1// Copyright © 2023 Phil Milewski
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementation of the [`Sub`] trait for [`Zq`] values.
10
11use 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    /// Computes the subtraction of `self` and `other` reusing
30    /// the memory of `self`.
31    /// [`SubAssign`] can be used on [`Zq`] in combination with
32    /// [`Zq`], [`Z`], [`i64`], [`i32`], [`i16`], [`i8`], [`u64`], [`u32`], [`u16`] and [`u8`].
33    ///
34    /// Parameters:
35    /// - `other`: specifies the value to subtract from `self`
36    ///
37    /// Returns the difference of both numbers modulo `q` as a [`Zq`].
38    ///
39    /// # Examples
40    /// ```
41    /// use qfall_math::{integer_mod_q::Zq, integer::Z};
42    ///
43    /// let mut a: Zq = Zq::from((23, 42));
44    /// let b: Zq = Zq::from((1, 42));
45    /// let c: Z = Z::from(5);
46    ///
47    /// a -= &b;
48    /// a -= b;
49    /// a -= 5;
50    /// a -= c;
51    /// ```
52    ///
53    /// # Panics ...
54    /// - if the moduli of both [`Zq`] mismatch.
55    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    /// Documentation at [`Zq::sub_assign`].
72    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    /// Documentation at [`Zq::sub_assign`].
85    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    /// Documentation at [`Zq::sub_assign`].
98    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    /// Implements the [`Sub`] trait for two [`Zq`] values.
118    /// [`Sub`] is implemented for any combination of [`Zq`] and borrowed [`Zq`].
119    ///
120    /// Parameters:
121    /// - `other`: specifies the value to subtract from `self`
122    ///
123    /// Returns the result of the subtraction of both numbers as a [`Zq`].
124    ///
125    /// # Examples
126    /// ```
127    /// use qfall_math::integer_mod_q::Zq;
128    ///
129    /// let a: Zq = Zq::from((23, 42));
130    /// let b: Zq = Zq::from((1, 42));
131    ///
132    /// let c: Zq = &a - &b;
133    /// let d: Zq = a - b;
134    /// let e: Zq = &c - d;
135    /// let f: Zq = c - &e;
136    /// ```
137    ///
138    /// # Panics ...
139    /// - if the moduli of both [`Zq`] mismatch.
140    fn sub(self, other: Self) -> Self::Output {
141        self.sub_safe(other).unwrap()
142    }
143}
144
145impl Zq {
146    /// Implements subtraction for two [`Zq`] values.
147    ///
148    ///
149    /// Parameters:
150    /// - `other`: specifies the value to subtract from `self`
151    ///
152    /// Returns the result of the subtraction of both numbers as a [`Zq`]
153    /// or an error if the moduli mismatch.
154    ///
155    /// # Examples
156    /// ```
157    /// use qfall_math::integer_mod_q::Zq;
158    ///
159    /// let a: Zq = Zq::from((23, 42));
160    /// let b: Zq = Zq::from((1, 42));
161    ///
162    /// let c: Zq = a.sub_safe(&b).unwrap();
163    /// ```
164    /// # Errors
165    /// - Returns a [`MathError`] of type [`MathError::MismatchingModulus`] if the moduli of
166    ///   both [`Zq`] mismatch.
167    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    /// Implements the [`Sub`] trait for [`Zq`] and [`Z`] values.
196    /// [`Sub`] is implemented for any combination of owned and borrowed values.
197    ///
198    /// Parameters:
199    ///  - `other`: specifies the value to subtract from `self`
200    ///
201    /// Returns the result of the subtraction of both numbers as a [`Zq`].
202    ///
203    /// # Examples
204    /// ```
205    /// use qfall_math::integer_mod_q::Zq;
206    /// use qfall_math::integer::Z;
207    /// use std::str::FromStr;
208    ///
209    /// let a: Zq = Zq::from((42, 19));
210    /// let b: Z = Z::from(42);
211    ///
212    /// let c: Zq = &a - &b;
213    /// let d: Zq = a - b;
214    /// let e: Zq = &c - Z::from(42);
215    /// let f: Zq = c - &Z::from(42);
216    /// ```
217    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    /// Ensure that `sub_assign` works for small numbers.
242    #[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    /// Ensure that `sub_assign` works for large numbers.
263    #[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    /// Ensure that `sub_assign` is available for all types.
273    #[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    /// Ensures that mismatching moduli result in a panic.
294    #[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    /// Testing subtraction for two [`Zq`]
309    #[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    /// Testing subtraction for two borrowed [`Zq`]
318    #[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    /// Testing subtraction for borrowed [`Zq`] and [`Zq`]
327    #[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    /// Testing subtraction for [`Zq`] and borrowed [`Zq`]
336    #[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    /// Testing subtraction for large [`Zq`]
345    #[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    /// Testing subtraction for [`Zq`] with different moduli does not work
354    #[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    /// Testing whether sub_safe throws an error for mismatching moduli
363    #[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    /// Testing subtraction for [`Q`] and [`Z`]
377    #[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    /// Testing subtraction for both borrowed [`Q`] and [`Z`]
386    #[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    /// Testing subtraction for borrowed [`Q`] and [`Z`]
395    #[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    /// Testing subtraction for [`Q`] and borrowed [`Z`]
404    #[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    /// Testing subtraction for large numbers
413    #[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    /// Testing subition between different types
432    #[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}