Skip to main content

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 flint3_sys::{
23    fmpz, {fmpz_mod_sub, fmpz_mod_sub_fmpz, fmpz_mod_sub_si, fmpz_mod_sub_ui},
24};
25use std::ops::{Sub, SubAssign};
26
27impl SubAssign<&Zq> for Zq {
28    /// Computes the subtraction of `self` and `other` reusing
29    /// the memory of `self`.
30    /// [`SubAssign`] can be used on [`Zq`] in combination with
31    /// [`Zq`], [`Z`], [`i64`], [`i32`], [`i16`], [`i8`], [`u64`], [`u32`], [`u16`] and [`u8`].
32    ///
33    /// Parameters:
34    /// - `other`: specifies the value to subtract from `self`
35    ///
36    /// Returns the difference of both numbers modulo `q` as a [`Zq`].
37    ///
38    /// # Examples
39    /// ```
40    /// use qfall_math::{integer_mod_q::Zq, integer::Z};
41    ///
42    /// let mut a: Zq = Zq::from((23, 42));
43    /// let b: Zq = Zq::from((1, 42));
44    /// let c: Z = Z::from(5);
45    ///
46    /// a -= &b;
47    /// a -= b;
48    /// a -= 5;
49    /// a -= c;
50    /// ```
51    ///
52    /// # Panics ...
53    /// - if the moduli of both [`Zq`] mismatch.
54    fn sub_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_sub(
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 SubAssign<i64> for Zq {
70    /// Documentation at [`Zq::sub_assign`].
71    fn sub_assign(&mut self, other: i64) {
72        unsafe {
73            fmpz_mod_sub_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 SubAssign<u64> for Zq {
83    /// Documentation at [`Zq::sub_assign`].
84    fn sub_assign(&mut self, other: u64) {
85        unsafe {
86            fmpz_mod_sub_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 SubAssign<&Z> for Zq {
96    /// Documentation at [`Zq::sub_assign`].
97    fn sub_assign(&mut self, other: &Z) {
98        unsafe {
99            fmpz_mod_sub_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!(SubAssign, sub_assign, Zq, Zq);
110arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, Zq, Z);
111arithmetic_assign_between_types!(SubAssign, sub_assign, Zq, i64, i32 i16 i8);
112arithmetic_assign_between_types!(SubAssign, sub_assign, Zq, u64, u32 u16 u8);
113
114impl Sub for &Zq {
115    type Output = Zq;
116    /// Implements the [`Sub`] trait for two [`Zq`] values.
117    /// [`Sub`] is implemented for any combination of [`Zq`] and borrowed [`Zq`].
118    ///
119    /// Parameters:
120    /// - `other`: specifies the value to subtract from `self`
121    ///
122    /// Returns the result of the subtraction of both numbers as a [`Zq`].
123    ///
124    /// # Examples
125    /// ```
126    /// use qfall_math::integer_mod_q::Zq;
127    ///
128    /// let a: Zq = Zq::from((23, 42));
129    /// let b: Zq = Zq::from((1, 42));
130    ///
131    /// let c: Zq = &a - &b;
132    /// let d: Zq = a - b;
133    /// let e: Zq = &c - d;
134    /// let f: Zq = c - &e;
135    /// ```
136    ///
137    /// # Panics ...
138    /// - if the moduli of both [`Zq`] mismatch.
139    fn sub(self, other: Self) -> Self::Output {
140        self.sub_safe(other).unwrap()
141    }
142}
143
144impl Zq {
145    /// Implements subtraction for two [`Zq`] values.
146    ///
147    ///
148    /// Parameters:
149    /// - `other`: specifies the value to subtract from `self`
150    ///
151    /// Returns the result of the subtraction of both numbers as a [`Zq`]
152    /// or an error if the moduli mismatch.
153    ///
154    /// # Examples
155    /// ```
156    /// use qfall_math::integer_mod_q::Zq;
157    ///
158    /// let a: Zq = Zq::from((23, 42));
159    /// let b: Zq = Zq::from((1, 42));
160    ///
161    /// let c: Zq = a.sub_safe(&b).unwrap();
162    /// ```
163    /// # Errors
164    /// - Returns a [`MathError`] of type [`MathError::MismatchingModulus`] if the moduli of
165    ///   both [`Zq`] mismatch.
166    pub fn sub_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_sub(
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!(Sub, sub, Zq, Zq, Zq);
188arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Zq, Zq, Zq);
189arithmetic_between_types_zq!(Sub, sub, Zq, i64 i32 i16 i8 u64 u32 u16 u8);
190
191impl Sub<&Z> for &Zq {
192    type Output = Zq;
193
194    /// Implements the [`Sub`] trait for [`Zq`] and [`Z`] values.
195    /// [`Sub`] is implemented for any combination of owned and borrowed values.
196    ///
197    /// Parameters:
198    ///  - `other`: specifies the value to subtract from `self`
199    ///
200    /// Returns the result of the subtraction of both numbers as a [`Zq`].
201    ///
202    /// # Examples
203    /// ```
204    /// use qfall_math::integer_mod_q::Zq;
205    /// use qfall_math::integer::Z;
206    /// use std::str::FromStr;
207    ///
208    /// let a: Zq = Zq::from((42, 19));
209    /// let b: Z = Z::from(42);
210    ///
211    /// let c: Zq = &a - &b;
212    /// let d: Zq = a - b;
213    /// let e: Zq = &c - Z::from(42);
214    /// let f: Zq = c - &Z::from(42);
215    /// ```
216    fn sub(self, other: &Z) -> Self::Output {
217        let mut out: fmpz = 0;
218        unsafe {
219            fmpz_mod_sub_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!(Sub, sub, Zq, Z, Zq);
234arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Zq, Z, Zq);
235
236#[cfg(test)]
237mod test_sub_assign {
238    use crate::{integer::Z, integer_mod_q::Zq};
239
240    /// Ensure that `sub_assign` works for small numbers.
241    #[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    /// Ensure that `sub_assign` works for large numbers.
262    #[test]
263    fn correct_large() {
264        let mut a = Zq::from((i64::MAX, u64::MAX));
265        let b = Zq::from((i64::MAX - 1, u64::MAX));
266
267        a -= b;
268        assert_eq!(Zq::from((1, u64::MAX)), a);
269    }
270
271    /// Ensure that `sub_assign` is available for all types.
272    #[test]
273    fn availability() {
274        let mut a = Zq::from((3, 7));
275        let b = Zq::from((1, 7));
276        let c = Z::from(1);
277
278        a -= &b;
279        a -= b;
280        a -= &c;
281        a -= c;
282        a -= 1_u8;
283        a -= 1_u16;
284        a -= 1_u32;
285        a -= 1_u64;
286        a -= 1_i8;
287        a -= 1_i16;
288        a -= 1_i32;
289        a -= 1_i64;
290    }
291
292    /// Ensures that mismatching moduli result in a panic.
293    #[test]
294    #[should_panic]
295    fn mismatching_moduli() {
296        let mut a = Zq::from((3, 7));
297        let b = Zq::from((1, 8));
298
299        a -= b;
300    }
301}
302
303#[cfg(test)]
304mod test_sub {
305    use super::Zq;
306
307    /// Testing subtraction for two [`Zq`]
308    #[test]
309    fn sub() {
310        let a: Zq = Zq::from((11, 17));
311        let b: Zq = Zq::from((12, 17));
312        let c: Zq = a - b;
313        assert_eq!(c, Zq::from((16, 17)));
314    }
315
316    /// Testing subtraction for two borrowed [`Zq`]
317    #[test]
318    fn sub_borrow() {
319        let a: Zq = Zq::from((10, 11));
320        let b: Zq = Zq::from((1, 11));
321        let c: Zq = &a - &b;
322        assert_eq!(c, Zq::from((9, 11)));
323    }
324
325    /// Testing subtraction for borrowed [`Zq`] and [`Zq`]
326    #[test]
327    fn sub_first_borrowed() {
328        let a: Zq = Zq::from((2, 11));
329        let b: Zq = Zq::from((5, 11));
330        let c: Zq = &a - b;
331        assert_eq!(c, Zq::from((-3, 11)));
332    }
333
334    /// Testing subtraction for [`Zq`] and borrowed [`Zq`]
335    #[test]
336    fn sub_second_borrowed() {
337        let a: Zq = Zq::from((12, 11));
338        let b: Zq = Zq::from((10, 11));
339        let c: Zq = a - &b;
340        assert_eq!(c, Zq::from((2, 11)));
341    }
342
343    /// Testing subtraction for large [`Zq`]
344    #[test]
345    fn sub_large_numbers() {
346        let a: Zq = Zq::from((u32::MAX, u32::MAX - 58));
347        let b: Zq = Zq::from((i32::MAX, u32::MAX - 58));
348        let c: Zq = a - b;
349        assert_eq!(c, Zq::from((u32::MAX - (u32::MAX - 1) / 2, u32::MAX - 58)));
350    }
351
352    /// Testing subtraction for [`Zq`] with different moduli does not work
353    #[test]
354    #[should_panic]
355    fn sub_mismatching_modulus() {
356        let a: Zq = Zq::from((4, 11));
357        let b: Zq = Zq::from((1, 3));
358        let _c: Zq = a - b;
359    }
360
361    /// Testing whether sub_safe throws an error for mismatching moduli
362    #[test]
363    fn sub_safe_is_err() {
364        let a: Zq = Zq::from((4, 11));
365        let b: Zq = Zq::from((1, 3));
366        assert!(&a.sub_safe(&b).is_err());
367    }
368}
369
370#[cfg(test)]
371mod test_sub_between_z_and_zq {
372    use super::Z;
373    use crate::integer_mod_q::Zq;
374
375    /// Testing subtraction for [`Q`] and [`Z`]
376    #[test]
377    fn sub() {
378        let a: Zq = Zq::from((4, 11));
379        let b: Z = Z::from(9);
380        let c: Zq = a - b;
381        assert_eq!(c, Zq::from((6, 11)));
382    }
383
384    /// Testing subtraction for both borrowed [`Q`] and [`Z`]
385    #[test]
386    fn sub_borrow() {
387        let a: Zq = Zq::from((4, 11));
388        let b: Z = Z::from(9);
389        let c: Zq = &a - &b;
390        assert_eq!(c, Zq::from((6, 11)));
391    }
392
393    /// Testing subtraction for borrowed [`Q`] and [`Z`]
394    #[test]
395    fn sub_first_borrowed() {
396        let a: Zq = Zq::from((4, 11));
397        let b: Z = Z::from(9);
398        let c: Zq = &a - b;
399        assert_eq!(c, Zq::from((6, 11)));
400    }
401
402    /// Testing subtraction for [`Q`] and borrowed [`Z`]
403    #[test]
404    fn sub_second_borrowed() {
405        let a: Zq = Zq::from((4, 11));
406        let b: Z = Z::from(9);
407        let c: Zq = a - &b;
408        assert_eq!(c, Zq::from((6, 11)));
409    }
410
411    /// Testing subtraction for large numbers
412    #[test]
413    fn sub_large_numbers() {
414        let a: Zq = Zq::from((i64::MAX, u64::MAX - 58));
415        let b: Zq = Zq::from((i64::MAX - 1, i64::MAX));
416        let c: Z = Z::from(u64::MAX);
417
418        let d: Zq = a - &c;
419        let e: Zq = b - c;
420
421        assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 - 58, u64::MAX - 58)));
422        assert_eq!(e, Zq::from((-2, i64::MAX)));
423    }
424}
425
426#[cfg(test)]
427mod test_sub_between_types {
428    use crate::integer_mod_q::Zq;
429
430    /// Testing subition between different types
431    #[test]
432    #[allow(clippy::op_ref)]
433    fn sub() {
434        let a: Zq = Zq::from((4, 11));
435        let b: u64 = 1;
436        let c: u32 = 1;
437        let d: u16 = 1;
438        let e: u8 = 1;
439        let f: i64 = 1;
440        let g: i32 = 1;
441        let h: i16 = 1;
442        let i: i8 = 1;
443
444        let _: Zq = &a - &b;
445        let _: Zq = &a - &c;
446        let _: Zq = &a - &d;
447        let _: Zq = &a - &e;
448        let _: Zq = &a - &f;
449        let _: Zq = &a - &g;
450        let _: Zq = &a - &h;
451        let _: Zq = &a - &i;
452
453        let _: Zq = &b - &a;
454        let _: Zq = &c - &a;
455        let _: Zq = &d - &a;
456        let _: Zq = &e - &a;
457        let _: Zq = &f - &a;
458        let _: Zq = &g - &a;
459        let _: Zq = &h - &a;
460        let _: Zq = &i - &a;
461
462        let _: Zq = &a - b;
463        let _: Zq = &a - c;
464        let _: Zq = &a - d;
465        let _: Zq = &a - e;
466        let _: Zq = &a - f;
467        let _: Zq = &a - g;
468        let _: Zq = &a - h;
469        let _: Zq = &a - i;
470
471        let _: Zq = &b - Zq::from((4, 11));
472        let _: Zq = &c - Zq::from((4, 11));
473        let _: Zq = &d - Zq::from((4, 11));
474        let _: Zq = &e - Zq::from((4, 11));
475        let _: Zq = &f - Zq::from((4, 11));
476        let _: Zq = &g - Zq::from((4, 11));
477        let _: Zq = &h - Zq::from((4, 11));
478        let _: Zq = &i - Zq::from((4, 11));
479
480        let _: Zq = Zq::from((4, 11)) - &b;
481        let _: Zq = Zq::from((4, 11)) - &c;
482        let _: Zq = Zq::from((4, 11)) - &d;
483        let _: Zq = Zq::from((4, 11)) - &e;
484        let _: Zq = Zq::from((4, 11)) - &f;
485        let _: Zq = Zq::from((4, 11)) - &g;
486        let _: Zq = Zq::from((4, 11)) - &h;
487        let _: Zq = Zq::from((4, 11)) - &i;
488
489        let _: Zq = b - &a;
490        let _: Zq = c - &a;
491        let _: Zq = d - &a;
492        let _: Zq = e - &a;
493        let _: Zq = f - &a;
494        let _: Zq = g - &a;
495        let _: Zq = h - &a;
496        let _: Zq = i - &a;
497
498        let _: Zq = Zq::from((4, 11)) - b;
499        let _: Zq = Zq::from((4, 11)) - c;
500        let _: Zq = Zq::from((4, 11)) - d;
501        let _: Zq = Zq::from((4, 11)) - e;
502        let _: Zq = Zq::from((4, 11)) - f;
503        let _: Zq = Zq::from((4, 11)) - g;
504        let _: Zq = Zq::from((4, 11)) - h;
505        let _: Zq = Zq::from((4, 11)) - i;
506
507        let _: Zq = b - Zq::from((4, 11));
508        let _: Zq = c - Zq::from((4, 11));
509        let _: Zq = d - Zq::from((4, 11));
510        let _: Zq = e - Zq::from((4, 11));
511        let _: Zq = f - Zq::from((4, 11));
512        let _: Zq = g - Zq::from((4, 11));
513        let _: Zq = h - Zq::from((4, 11));
514        let _: Zq = i - Zq::from((4, 11));
515    }
516}