Skip to main content

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