qfall_math/integer/z/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 [`Z`] values.
10
11use super::super::Z;
12use crate::{
13    integer_mod_q::Zq,
14    macros::arithmetics::{
15        arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
16        arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
17        arithmetic_trait_mixed_borrowed_owned,
18    },
19    rational::Q,
20};
21use flint_sys::{
22    fmpq::{fmpq, fmpq_set_fmpz_frac, fmpq_sub},
23    fmpz::{fmpz, fmpz_sub, fmpz_sub_si, fmpz_sub_ui},
24    fmpz_mod::fmpz_mod_sub_fmpz,
25};
26use std::ops::{Sub, SubAssign};
27
28impl SubAssign<&Z> for Z {
29    /// Computes the subtraction of `self` and `other` reusing
30    /// the memory of `self`.
31    /// [`SubAssign`] can be used on [`Z`] in combination with
32    /// [`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 as a [`Z`].
38    ///
39    /// # Examples
40    /// ```
41    /// use qfall_math::integer::Z;
42    ///
43    /// let mut a: Z = Z::from(42);
44    /// let b: Z = Z::from(24);
45    ///
46    /// a -= &b;
47    /// a -= b;
48    /// a -= 5;
49    /// ```
50    fn sub_assign(&mut self, other: &Self) {
51        unsafe { fmpz_sub(&mut self.value, &self.value, &other.value) };
52    }
53}
54impl SubAssign<i64> for Z {
55    /// Documentation at [`Z::sub_assign`].
56    fn sub_assign(&mut self, other: i64) {
57        unsafe { fmpz_sub_si(&mut self.value, &self.value, other) };
58    }
59}
60impl SubAssign<u64> for Z {
61    /// Documentation at [`Z::sub_assign`].
62    fn sub_assign(&mut self, other: u64) {
63        unsafe { fmpz_sub_ui(&mut self.value, &self.value, other) };
64    }
65}
66
67arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, Z, Z);
68arithmetic_assign_between_types!(SubAssign, sub_assign, Z, i64, i32 i16 i8);
69arithmetic_assign_between_types!(SubAssign, sub_assign, Z, u64, u32 u16 u8);
70
71impl Sub for &Z {
72    type Output = Z;
73    /// Implements the [`Sub`] trait for two [`Z`] values.
74    /// [`Sub`] is implemented for any combination of [`Z`] and borrowed [`Z`].
75    ///
76    /// Parameters:
77    /// - `other`: specifies the value to subtract from `self`
78    ///
79    /// Returns the result of the subtraction as a [`Z`].
80    ///
81    /// # Examples
82    /// ```
83    /// use qfall_math::integer::Z;
84    ///
85    /// let a: Z = Z::from(42);
86    /// let b: Z = Z::from(24);
87    ///
88    /// let c: Z = &a - &b;
89    /// let d: Z = a - b;
90    /// let e: Z = &Z::from(42) - d;
91    /// let f: Z = Z::from(42) - &e;
92    /// ```
93    fn sub(self, other: Self) -> Self::Output {
94        let mut out = Z::default();
95        unsafe {
96            fmpz_sub(&mut out.value, &self.value, &other.value);
97        }
98        out
99    }
100}
101
102arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Z, Z);
103arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Z, Z);
104arithmetic_between_types!(Sub, sub, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
105
106impl Sub<&Q> for &Z {
107    type Output = Q;
108
109    /// Implements the [`Sub`] trait for [`Z`] and [`Q`] values.
110    /// [`Sub`] is implemented for any combination of owned and borrowed values.
111    ///
112    /// Parameters:
113    ///  - `other`: specifies the value to subtract from `self`
114    ///
115    /// Returns the result of the subtraction as a [`Q`].
116    ///
117    /// # Examples
118    /// ```
119    /// use qfall_math::rational::Q;
120    /// use qfall_math::integer::Z;
121    /// use std::str::FromStr;
122    ///
123    /// let a: Z = Z::from(-42);
124    /// let b: Q = Q::from((42, 19));
125    ///
126    /// let c: Q = &a - &b;
127    /// let d: Q = a - b;
128    /// let e: Q = &Z::from(42) - d;
129    /// let f: Q = Z::from(42) - &e;
130    /// ```
131    fn sub(self, other: &Q) -> Self::Output {
132        let mut out = Q::default();
133        let mut fmpq_1 = fmpq::default();
134        unsafe { fmpq_set_fmpz_frac(&mut fmpq_1, &self.value, &fmpz(1)) }
135        unsafe {
136            fmpq_sub(&mut out.value, &fmpq_1, &other.value);
137        }
138        out
139    }
140}
141
142arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Q, Q);
143arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Q, Q);
144arithmetic_between_types!(Sub, sub, Z, Q, f64 f32);
145
146impl Sub<&Zq> for &Z {
147    type Output = Zq;
148    /// Implements the [`Sub`] trait for [`Z`] and [`Zq`] values.
149    /// [`Sub`] is implemented for any combination of owned and borrowed values.
150    ///
151    /// Parameters:
152    ///  - `other`: specifies the value to subtract from `self`
153    ///
154    /// Returns the result of subtraction of both numbers as a [`Zq`].
155    ///
156    /// # Examples
157    /// ```
158    /// use qfall_math::integer_mod_q::Zq;
159    /// use qfall_math::integer::Z;
160    /// use std::str::FromStr;
161    ///
162    /// let a: Z = Z::from(42);
163    /// let b: Zq = Zq::from((42, 19));
164    ///
165    /// let c: Zq = &a - &b;
166    /// let d: Zq = a - b;
167    /// let e: Zq = &Z::from(42) - d;
168    /// let f: Zq = Z::from(42) - &e;
169    /// ```
170    fn sub(self, other: &Zq) -> Self::Output {
171        let mut out = fmpz(0);
172        unsafe {
173            fmpz_mod_sub_fmpz(
174                &mut out,
175                &self.value,
176                &other.value.value,
177                other.modulus.get_fmpz_mod_ctx_struct(),
178            );
179        }
180        Zq {
181            modulus: other.modulus.clone(),
182            value: Z { value: out },
183        }
184    }
185}
186
187arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Zq, Zq);
188arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Zq, Zq);
189
190#[cfg(test)]
191mod test_sub_assign {
192    use crate::integer::Z;
193
194    /// Ensure that `sub_assign` works for small numbers.
195    #[test]
196    fn correct_small() {
197        let mut a: Z = Z::MINUS_ONE;
198        let b = Z::ONE;
199        let c = Z::MINUS_ONE;
200
201        a -= &b;
202        assert_eq!(-2, a);
203        a -= &c;
204        assert_eq!(-1, a);
205        a -= &c;
206        assert_eq!(0, a);
207        a -= &c;
208        assert_eq!(1, a);
209        a -= &c;
210        assert_eq!(2, a);
211        a -= 2 * b;
212        assert_eq!(0, a);
213    }
214
215    /// Ensure that `sub_assign` works for large numbers.
216    #[test]
217    fn correct_large() {
218        let mut a: Z = Z::from(i64::MAX);
219        let b = Z::from(i64::MAX as u64 + 1);
220        let c = -1 * Z::from(u64::MAX);
221
222        a -= b;
223        assert_eq!(-1, a);
224        a -= c;
225        assert_eq!(u64::MAX - 1, a);
226    }
227
228    /// Ensure that `sub_assign` is available for all types.
229    #[test]
230    fn availability() {
231        let mut a: Z = Z::from(42);
232        let b: Z = Z::from(1);
233
234        a -= &b;
235        a -= b;
236        a -= 1_u8;
237        a -= 1_u16;
238        a -= 1_u32;
239        a -= 1_u64;
240        a -= 1_i8;
241        a -= 1_i16;
242        a -= 1_i32;
243        a -= 1_i64;
244    }
245}
246
247#[cfg(test)]
248mod test_sub_between_types {
249    use crate::integer::Z;
250
251    /// Testing subtraction between different types
252    #[test]
253    #[allow(clippy::op_ref)]
254    fn sub() {
255        let a: Z = Z::from(42);
256        let b: u64 = 1;
257        let c: u32 = 1;
258        let d: u16 = 1;
259        let e: u8 = 1;
260        let f: i64 = 1;
261        let g: i32 = 1;
262        let h: i16 = 1;
263        let i: i8 = 1;
264
265        let _: Z = &a - &b;
266        let _: Z = &a - &c;
267        let _: Z = &a - &d;
268        let _: Z = &a - &e;
269        let _: Z = &a - &f;
270        let _: Z = &a - &g;
271        let _: Z = &a - &h;
272        let _: Z = &a - &i;
273
274        let _: Z = &b - &a;
275        let _: Z = &c - &a;
276        let _: Z = &d - &a;
277        let _: Z = &e - &a;
278        let _: Z = &f - &a;
279        let _: Z = &g - &a;
280        let _: Z = &h - &a;
281        let _: Z = &i - &a;
282
283        let _: Z = &a - b;
284        let _: Z = &a - c;
285        let _: Z = &a - d;
286        let _: Z = &a - e;
287        let _: Z = &a - f;
288        let _: Z = &a - g;
289        let _: Z = &a - h;
290        let _: Z = &a - i;
291
292        let _: Z = &b - Z::from(42);
293        let _: Z = &c - Z::from(42);
294        let _: Z = &d - Z::from(42);
295        let _: Z = &e - Z::from(42);
296        let _: Z = &f - Z::from(42);
297        let _: Z = &g - Z::from(42);
298        let _: Z = &h - Z::from(42);
299        let _: Z = &i - Z::from(42);
300
301        let _: Z = Z::from(42) - &b;
302        let _: Z = Z::from(42) - &c;
303        let _: Z = Z::from(42) - &d;
304        let _: Z = Z::from(42) - &e;
305        let _: Z = Z::from(42) - &f;
306        let _: Z = Z::from(42) - &g;
307        let _: Z = Z::from(42) - &h;
308        let _: Z = Z::from(42) - &i;
309
310        let _: Z = b - &a;
311        let _: Z = c - &a;
312        let _: Z = d - &a;
313        let _: Z = e - &a;
314        let _: Z = f - &a;
315        let _: Z = g - &a;
316        let _: Z = h - &a;
317        let _: Z = i - &a;
318
319        let _: Z = Z::from(42) - b;
320        let _: Z = Z::from(42) - c;
321        let _: Z = Z::from(42) - d;
322        let _: Z = Z::from(42) - e;
323        let _: Z = Z::from(42) - f;
324        let _: Z = Z::from(42) - g;
325        let _: Z = Z::from(42) - h;
326        let _: Z = Z::from(42) - i;
327
328        let _: Z = b - Z::from(42);
329        let _: Z = c - Z::from(42);
330        let _: Z = d - Z::from(42);
331        let _: Z = e - Z::from(42);
332        let _: Z = f - Z::from(42);
333        let _: Z = g - Z::from(42);
334        let _: Z = h - Z::from(42);
335        let _: Z = i - Z::from(42);
336    }
337}
338
339#[cfg(test)]
340mod test_sub {
341    use super::Z;
342
343    /// Testing subtraction for two Z
344    #[test]
345    fn sub() {
346        let a: Z = Z::from(42);
347        let b: Z = Z::from(24);
348        let c: Z = a - b;
349        assert_eq!(c, Z::from(18));
350    }
351
352    /// Testing subtraction for two borrowed [`Z`]
353    #[test]
354    fn sub_borrow() {
355        let a: Z = Z::from(42);
356        let b: Z = Z::from(24);
357        let c: Z = &a - &b;
358        assert_eq!(c, Z::from(18));
359    }
360
361    /// Testing subtraction for borrowed [`Z`] and [`Z`]
362    #[test]
363    fn sub_first_borrowed() {
364        let a: Z = Z::from(42);
365        let b: Z = Z::from(24);
366        let c: Z = &a - b;
367        assert_eq!(c, Z::from(18));
368    }
369
370    /// Testing subtraction for [`Z`] and borrowed [`Z`]
371    #[test]
372    fn sub_second_borrowed() {
373        let a: Z = Z::from(42);
374        let b: Z = Z::from(24);
375        let c: Z = a - &b;
376        assert_eq!(c, Z::from(18));
377    }
378
379    /// Testing subtraction for large integers
380    #[test]
381    fn sub_large() {
382        let a: Z = Z::from(u64::MAX - 1);
383        let b: Z = Z::from(i64::MAX);
384        let c: Z = Z::from(738201034);
385
386        let d: Z = &a - &b;
387        let e: Z = &b - a;
388        let f: Z = b - c;
389
390        assert_eq!(d, Z::from(i64::MAX));
391        assert_eq!(e, Z::from(i64::MIN + 1));
392        assert_eq!(f, Z::from(i64::MAX - 738201034));
393    }
394}
395
396#[cfg(test)]
397mod test_sub_between_z_and_q {
398    use super::Z;
399    use crate::rational::Q;
400
401    /// Ensuring subtraction between different types is available
402    #[test]
403    fn availability() {
404        let a: Z = Z::from(42);
405        let b: Q = Q::from((5, 7));
406
407        let _: Q = &a - &b;
408        let _: Q = &a - b.clone();
409        let _: Q = a.clone() - &b;
410        let _: Q = a.clone() - b;
411        let _: Q = &a - 0.5_f32;
412        let _: Q = &a - 0.5_f64;
413        let _: Q = a.clone() - 0.5_f32;
414        let _: Q = a.clone() - 0.5_f64;
415        let _: Q = 0.5_f32 - &a;
416        let _: Q = 0.5_f64 - &a;
417        let _: Q = 0.5_f32 - a.clone();
418        let _: Q = 0.5_f64 - a.clone();
419    }
420
421    /// Ensures that division is performed the right way around
422    #[test]
423    fn order_retained() {
424        let a = Z::from(4);
425
426        assert_eq!(2, &a - 2);
427        assert_eq!(Q::from((-2, 1)), 2 - &a);
428    }
429
430    /// Testing subtraction for [`Z`] and [`Q`]
431    #[test]
432    fn sub() {
433        let a: Z = Z::from(4);
434        let b: Q = Q::from((5, 7));
435        let c: Q = a - b;
436        assert_eq!(c, Q::from((23, 7)));
437    }
438
439    /// Testing subtraction for both borrowed [`Z`] and [`Q`]
440    #[test]
441    fn sub_borrow() {
442        let a: Z = Z::from(4);
443        let b: Q = Q::from((5, 7));
444        let c: Q = &a - &b;
445        assert_eq!(c, Q::from((23, 7)));
446    }
447
448    /// Testing subtraction for borrowed [`Z`] and [`Q`]
449    #[test]
450    fn sub_first_borrowed() {
451        let a: Z = Z::from(4);
452        let b: Q = Q::from((5, 7));
453        let c: Q = &a - b;
454        assert_eq!(c, Q::from((23, 7)));
455    }
456
457    /// Testing subtraction for [`Z`] and borrowed [`Q`]
458    #[test]
459    fn sub_second_borrowed() {
460        let a: Z = Z::from(4);
461        let b: Q = Q::from((5, 7));
462        let c: Q = a - &b;
463        assert_eq!(c, Q::from((23, 7)));
464    }
465
466    /// Testing subtraction for large numbers
467    #[test]
468    fn sub_large_numbers() {
469        let a: Z = Z::from(u64::MAX);
470        let b: Q = Q::from((1, u64::MAX));
471        let c: Q = Q::from((u64::MAX, 2));
472
473        let d: Q = &a - b;
474        let e: Q = a - c;
475
476        assert_eq!(d, Q::from(u64::MAX) - Q::from((1, u64::MAX)));
477        assert_eq!(e, Q::from(u64::MAX) - Q::from((u64::MAX, 2)));
478    }
479}
480
481#[cfg(test)]
482mod test_sub_between_z_and_zq {
483    use super::Z;
484    use crate::integer_mod_q::Zq;
485
486    /// Testing subtraction for [`Z`] and [`Zq`]
487    #[test]
488    fn sub() {
489        let a: Z = Z::from(9);
490        let b: Zq = Zq::from((10, 11));
491        let c: Zq = a - b;
492        assert_eq!(c, Zq::from((10, 11)));
493    }
494
495    /// Testing subtraction for both borrowed [`Z`] and [`Zq`]
496    #[test]
497    fn sub_borrow() {
498        let a: Z = Z::from(9);
499        let b: Zq = Zq::from((4, 11));
500        let c: Zq = &a - &b;
501        assert_eq!(c, Zq::from((5, 11)));
502    }
503
504    /// Testing subtraction for borrowed [`Z`] and [`Zq`]
505    #[test]
506    fn sub_first_borrowed() {
507        let a: Z = Z::from(9);
508        let b: Zq = Zq::from((4, 11));
509        let c: Zq = &a - b;
510        assert_eq!(c, Zq::from((5, 11)));
511    }
512
513    /// Testing subtraction for [`Z`] and borrowed [`Zq`]
514    #[test]
515    fn sub_second_borrowed() {
516        let a: Z = Z::from(9);
517        let b: Zq = Zq::from((4, 11));
518        let c: Zq = a - &b;
519        assert_eq!(c, Zq::from((5, 11)));
520    }
521
522    /// Testing subtraction for large numbers
523    #[test]
524    fn sub_large_numbers() {
525        let a: Z = Z::from(u64::MAX);
526        let b: Zq = Zq::from((i64::MAX, u64::MAX - 58));
527        let c: Zq = Zq::from((i64::MAX - 1, i64::MAX));
528
529        let d: Zq = &a - b;
530        let e: Zq = a - c;
531
532        assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 + 1, u64::MAX - 58)));
533        assert_eq!(e, Zq::from((2, i64::MAX)));
534    }
535}