qfall_math/integer/z/arithmetic/
div.rs

1// Copyright © 2023 Niklas Siemer and Sven Moog
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 [`Div`] trait for [`Z`] values.
10
11use super::super::Z;
12use crate::macros::arithmetics::{
13    arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
14    arithmetic_trait_mixed_borrowed_owned,
15};
16use crate::rational::Q;
17use flint_sys::fmpz::{fmpz_cdiv_q, fmpz_fdiv_q, fmpz_tdiv_qr};
18use std::ops::Div;
19
20impl Z {
21    /// Divides `self` by `other` and the result is rounded down.
22    ///
23    /// Parameters:
24    /// - `other`: specifies the value to divide `self` by
25    ///
26    /// Returns the quotient of both numbers as a [`Z`] floored.
27    ///
28    /// # Examples
29    /// ```
30    /// use qfall_math::integer::Z;
31    ///
32    /// let a: Z = Z::from(42);
33    /// let b: Z = Z::from(20);
34    ///
35    /// let c = a.div_floor(&b);
36    /// let d = a.div_floor(20);
37    ///
38    /// assert_eq!(Z::from(2), c);
39    /// assert_eq!(Z::from(2), d);
40    /// ```
41    ///
42    /// # Panics ...
43    /// - if the divisor is `0`.
44    pub fn div_floor(&self, other: impl Into<Z>) -> Self {
45        let other: Z = other.into();
46        assert!(!other.is_zero(), "Tried to divide {self} by zero.");
47        let mut out = Z::default();
48        unsafe {
49            fmpz_fdiv_q(&mut out.value, &self.value, &other.value);
50        }
51        out
52    }
53
54    /// Divides `self` by `other` and the result is rounded up.
55    ///
56    /// Parameters:
57    /// - `other`: specifies the value to divide `self` by
58    ///
59    /// Returns the quotient of both numbers as a [`Z`] ceiled.
60    ///
61    /// # Examples
62    /// ```
63    /// use qfall_math::integer::Z;
64    ///
65    /// let a: Z = Z::from(42);
66    /// let b: Z = Z::from(20);
67    ///
68    /// let c = a.div_ceil(&b);
69    /// let d = a.div_ceil(20);
70    ///
71    /// assert_eq!(Z::from(3), c);
72    /// assert_eq!(Z::from(3), d);
73    /// ```
74    ///
75    /// # Panics ...
76    /// - if the divisor is `0`.
77    pub fn div_ceil(&self, other: impl Into<Z>) -> Self {
78        let other: Z = other.into();
79        assert!(!other.is_zero(), "Tried to divide {self} by zero.");
80        let mut out = Z::default();
81        unsafe {
82            fmpz_cdiv_q(&mut out.value, &self.value, &other.value);
83        }
84        out
85    }
86
87    /// Divides `self` by `other` and returns a result if it is integer.
88    ///
89    /// Parameters:
90    /// - `other`: specifies the value to divide `self` by
91    ///
92    /// Returns the quotient of both numbers as a [`Z`] or [`None`]
93    /// if the quotient is not integer.
94    ///
95    /// # Examples
96    /// ```
97    /// use qfall_math::integer::Z;
98    ///
99    /// let a_0: Z = Z::from(40);
100    /// let a_1: Z = Z::from(42);
101    /// let b: Z = Z::from(20);
102    ///
103    /// let c_0 = a_0.div_exact(&b).unwrap();
104    /// let c_1 = a_1.div_exact(&b);
105    ///
106    /// assert_eq!(Z::from(2), c_0);
107    /// assert!(c_1.is_none());
108    /// ```
109    ///
110    /// # Panics ...
111    /// - if the divisor is `0`.
112    pub fn div_exact(&self, other: impl Into<Z>) -> Option<Self> {
113        let other: Z = other.into();
114        assert!(!other.is_zero(), "Tried to divide {self} by zero.");
115
116        let mut quotient = Z::default();
117        let mut reminder = Z::default();
118        unsafe {
119            fmpz_tdiv_qr(
120                &mut quotient.value,
121                &mut reminder.value,
122                &self.value,
123                &other.value,
124            );
125        }
126
127        if reminder != Z::ZERO {
128            None
129        } else {
130            Some(quotient)
131        }
132    }
133}
134
135impl Div for &Z {
136    type Output = Q;
137    /// Implements the [`Div`] trait for two [`Z`] values s.t. its value is rounded down.
138    /// [`Div`] is implemented for any combination of [`Z`] and borrowed [`Z`].
139    ///
140    /// Parameters:
141    /// - `other`: specifies the value to divide `self` by
142    ///
143    /// Returns the quotient of both numbers as a [`Z`] floored.
144    ///
145    /// # Examples
146    /// ```
147    /// use qfall_math::integer::Z;
148    /// use qfall_math::rational::Q;
149    ///
150    /// let a = Z::from(42);
151    /// let b = Z::from(20);
152    ///
153    /// let c: Q = &a / &b;
154    /// let d: Q = a / b;
155    ///
156    /// assert_eq!(Q::from((21, 10)), c);
157    /// assert_eq!(Q::from((21, 10)), d);
158    /// ```
159    ///
160    /// # Panics ...
161    /// - if the divisor is `0`.
162    fn div(self, other: Self) -> Self::Output {
163        Q::from((self, other))
164    }
165}
166
167arithmetic_trait_borrowed_to_owned!(Div, div, Z, Z, Q);
168arithmetic_trait_mixed_borrowed_owned!(Div, div, Z, Z, Q);
169arithmetic_between_types!(Div, div, Z, Q, i64 i32 i16 i8 u64 u32 u16 u8 f32 f64);
170
171#[test]
172fn same() {
173    let a = Z::from(4) / 2;
174    let b = 4 / Z::from(2);
175
176    println!("{a}, {b}");
177
178    assert_eq!(a, b);
179}
180
181impl Div<&Q> for &Z {
182    type Output = Q;
183
184    /// Implements the [`Div`] trait for [`Z`] and [`Q`] values.
185    /// [`Div`] is implemented for any combination of owned and borrowed values.
186    ///
187    /// Parameters:
188    ///  - `other`: specifies the value to divide `self` by
189    ///
190    /// Returns the ratio of both numbers as a [`Q`].
191    ///
192    /// # Examples
193    /// ```
194    /// use qfall_math::rational::Q;
195    /// use qfall_math::integer::Z;
196    /// use std::str::FromStr;
197    ///
198    /// let a: Z = Z::from(-42);
199    /// let b: Q = Q::from((42, 19));
200    ///
201    /// let c: Q = &a / &b;
202    /// let d: Q = a / b;
203    /// let e: Q = &Z::from(42) / d;
204    /// let f: Q = Z::from(42) / &e;
205    /// ```
206    ///
207    /// # Panics ...
208    /// - if the divisor is `0`.
209    fn div(self, other: &Q) -> Self::Output {
210        assert!(!other.is_zero(), "Tried to divide {self} by zero.");
211        Q::from(self.clone()) / other
212    }
213}
214
215arithmetic_trait_borrowed_to_owned!(Div, div, Z, Q, Q);
216arithmetic_trait_mixed_borrowed_owned!(Div, div, Z, Q, Q);
217
218#[cfg(test)]
219mod test_div_floor {
220    use super::Z;
221    use crate::integer_mod_q::Modulus;
222
223    /// Tests that `div_floor` is available for other types.
224    #[test]
225    #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
226    fn availability() {
227        let value = Z::from(100);
228
229        value.div_floor(3_u8);
230        value.div_floor(3_u16);
231        value.div_floor(3_u32);
232        value.div_floor(3_u64);
233        value.div_floor(3_i8);
234        value.div_floor(3_i16);
235        value.div_floor(3_i32);
236        value.div_floor(3_i64);
237        value.div_floor(Z::from(10));
238        value.div_floor(Modulus::from(10));
239
240        value.div_floor(&3_u8);
241        value.div_floor(&3_u16);
242        value.div_floor(&3_u32);
243        value.div_floor(&3_u64);
244        value.div_floor(&3_i8);
245        value.div_floor(&3_i16);
246        value.div_floor(&3_i32);
247        value.div_floor(&3_i64);
248        value.div_floor(&Z::from(10));
249        value.div_floor(&Modulus::from(10));
250    }
251
252    /// Checks whether `div_floor` correctly rounds non-exact quotients down
253    #[test]
254    fn floored() {
255        let small = Z::from(-11);
256        let large = Z::from(i64::MAX);
257        let divisor = Z::from(2);
258
259        let res_0 = small.div_floor(&divisor);
260        let res_1 = large.div_floor(&divisor);
261
262        assert_eq!(Z::from(-6), res_0);
263        assert_eq!(Z::from(i64::MAX >> 1), res_1);
264    }
265
266    /// Checks whether `div_floor` correctly computes exact quotients
267    #[test]
268    fn exact() {
269        let small = Z::from(10);
270        let large = Z::from(i64::MIN);
271        let divisor = Z::from(2);
272
273        let res_0 = Z::ZERO.div_floor(&divisor);
274        let res_1 = small.div_floor(&divisor);
275        let res_2 = large.div_floor(&divisor);
276
277        assert_eq!(Z::ZERO, res_0);
278        assert_eq!(Z::from(5), res_1);
279        assert_eq!(Z::from(i64::MIN >> 1), res_2);
280    }
281
282    /// Checks whether `div_floor` panics if the divisor is `0`
283    #[test]
284    #[should_panic]
285    fn division_by_zero() {
286        let a = Z::from(100);
287
288        let _ = a.div_floor(&Z::ZERO);
289    }
290}
291
292#[cfg(test)]
293mod test_div_ceil {
294    use super::Z;
295    use crate::integer_mod_q::Modulus;
296
297    /// Tests that `div_ceil` is available for other types.
298    #[test]
299    #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
300    fn availability() {
301        let value = Z::from(100);
302
303        value.div_ceil(3_u8);
304        value.div_ceil(3_u16);
305        value.div_ceil(3_u32);
306        value.div_ceil(3_u64);
307        value.div_ceil(3_i8);
308        value.div_ceil(3_i16);
309        value.div_ceil(3_i32);
310        value.div_ceil(3_i64);
311        value.div_ceil(Z::from(10));
312        value.div_ceil(Modulus::from(10));
313
314        value.div_ceil(&3_u8);
315        value.div_ceil(&3_u16);
316        value.div_ceil(&3_u32);
317        value.div_ceil(&3_u64);
318        value.div_ceil(&3_i8);
319        value.div_ceil(&3_i16);
320        value.div_ceil(&3_i32);
321        value.div_ceil(&3_i64);
322        value.div_ceil(&Z::from(10));
323        value.div_ceil(&Modulus::from(10));
324    }
325
326    /// Checks whether `div_ceil` correctly rounds non-exact quotients down
327    #[test]
328    fn ceiled() {
329        let small = Z::from(-11);
330        let large = Z::from(i64::MAX);
331        let divisor = Z::from(2);
332
333        let res_0 = small.div_ceil(&divisor);
334        let res_1 = large.div_ceil(&divisor);
335
336        assert_eq!(Z::from(-5), res_0);
337        assert_eq!(Z::from((i64::MAX >> 1) + 1), res_1);
338    }
339
340    /// Checks whether `div_ceil` correctly computes exact quotients
341    #[test]
342    fn exact() {
343        let small = Z::from(10);
344        let large = Z::from(i64::MIN);
345        let divisor = Z::from(2);
346
347        let res_0 = Z::ZERO.div_ceil(&divisor);
348        let res_1 = small.div_ceil(&divisor);
349        let res_2 = large.div_ceil(&divisor);
350
351        assert_eq!(Z::ZERO, res_0);
352        assert_eq!(Z::from(5), res_1);
353        assert_eq!(Z::from(i64::MIN >> 1), res_2);
354    }
355
356    /// Checks whether `div_ceil` panics if the divisor is `0`
357    #[test]
358    #[should_panic]
359    fn division_by_zero() {
360        let a = Z::from(100);
361
362        let _ = a.div_ceil(&Z::ZERO);
363    }
364}
365
366#[cfg(test)]
367mod test_div_exact {
368    use super::Z;
369    use crate::integer_mod_q::Modulus;
370
371    /// Tests that `div_exact` is available for other types.
372    #[test]
373    #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
374    fn availability() {
375        let value = Z::from(100);
376
377        value.div_exact(3_u8);
378        value.div_exact(3_u16);
379        value.div_exact(3_u32);
380        value.div_exact(3_u64);
381        value.div_exact(3_i8);
382        value.div_exact(3_i16);
383        value.div_exact(3_i32);
384        value.div_exact(3_i64);
385        value.div_exact(Z::from(10));
386        value.div_exact(Modulus::from(10));
387
388        value.div_exact(&3_u8);
389        value.div_exact(&3_u16);
390        value.div_exact(&3_u32);
391        value.div_exact(&3_u64);
392        value.div_exact(&3_i8);
393        value.div_exact(&3_i16);
394        value.div_exact(&3_i32);
395        value.div_exact(&3_i64);
396        value.div_exact(&Z::from(10));
397        value.div_exact(&Modulus::from(10));
398    }
399
400    /// Checks whether `div_exact` outputs [`None`] if the quotient is not integer
401    #[test]
402    fn non_exact() {
403        let small = Z::from(-11);
404        let large = Z::from(i64::MAX);
405        let divisor = Z::from(2);
406
407        let res_0 = small.div_exact(&divisor);
408        let res_1 = large.div_exact(&divisor);
409
410        assert!(res_0.is_none());
411        assert!(res_1.is_none());
412    }
413
414    /// Checks whether `div_exact` correctly computes exact quotients
415    #[test]
416    fn exact() {
417        let small = Z::from(10);
418        let large = Z::from(i64::MIN);
419        let divisor = Z::from(2);
420
421        let res_0 = Z::ZERO.div_exact(&divisor).unwrap();
422        let res_1 = small.div_exact(&divisor).unwrap();
423        let res_2 = large.div_exact(&divisor).unwrap();
424
425        assert_eq!(Z::ZERO, res_0);
426        assert_eq!(Z::from(5), res_1);
427        assert_eq!(Z::from(i64::MIN >> 1), res_2);
428    }
429
430    /// Checks whether `div_exact` panics if the divisor is `0`
431    #[test]
432    #[should_panic]
433    fn division_by_zero() {
434        let a = Z::from(100);
435
436        let _ = a.div_exact(&Z::ZERO);
437    }
438}
439
440#[cfg(test)]
441mod test_div_between_types {
442    use crate::integer::Z;
443    use crate::rational::Q;
444
445    /// Testing division between different types
446    #[test]
447    #[allow(clippy::op_ref)]
448    fn div() {
449        let a: Z = Z::from(42);
450        let b: u64 = 5;
451        let c: u32 = 5;
452        let d: u16 = 5;
453        let e: u8 = 5;
454        let f: i64 = 5;
455        let g: i32 = 5;
456        let h: i16 = 5;
457        let i: i8 = 5;
458
459        let _: Q = &a / &b;
460        let _: Q = &a / &c;
461        let _: Q = &a / &d;
462        let _: Q = &a / &e;
463        let _: Q = &a / &f;
464        let _: Q = &a / &g;
465        let _: Q = &a / &h;
466        let _: Q = &a / &i;
467
468        let _: Q = &b / &a;
469        let _: Q = &c / &a;
470        let _: Q = &d / &a;
471        let _: Q = &e / &a;
472        let _: Q = &f / &a;
473        let _: Q = &g / &a;
474        let _: Q = &h / &a;
475        let _: Q = &i / &a;
476
477        let _: Q = &a / b;
478        let _: Q = &a / c;
479        let _: Q = &a / d;
480        let _: Q = &a / e;
481        let _: Q = &a / f;
482        let _: Q = &a / g;
483        let _: Q = &a / h;
484        let _: Q = &a / i;
485
486        let _: Q = &b / Z::from(42);
487        let _: Q = &c / Z::from(42);
488        let _: Q = &d / Z::from(42);
489        let _: Q = &e / Z::from(42);
490        let _: Q = &f / Z::from(42);
491        let _: Q = &g / Z::from(42);
492        let _: Q = &h / Z::from(42);
493        let _: Q = &i / Z::from(42);
494
495        let _: Q = Z::from(42) / &b;
496        let _: Q = Z::from(42) / &c;
497        let _: Q = Z::from(42) / &d;
498        let _: Q = Z::from(42) / &e;
499        let _: Q = Z::from(42) / &f;
500        let _: Q = Z::from(42) / &g;
501        let _: Q = Z::from(42) / &h;
502        let _: Q = Z::from(42) / &i;
503
504        let _: Q = b / &a;
505        let _: Q = c / &a;
506        let _: Q = d / &a;
507        let _: Q = e / &a;
508        let _: Q = f / &a;
509        let _: Q = g / &a;
510        let _: Q = h / &a;
511        let _: Q = i / &a;
512
513        let _: Q = Z::from(42) / b;
514        let _: Q = Z::from(42) / c;
515        let _: Q = Z::from(42) / d;
516        let _: Q = Z::from(42) / e;
517        let _: Q = Z::from(42) / f;
518        let _: Q = Z::from(42) / g;
519        let _: Q = Z::from(42) / h;
520        let _: Q = Z::from(42) / i;
521
522        let _: Q = b / Z::from(42);
523        let _: Q = c / Z::from(42);
524        let _: Q = d / Z::from(42);
525        let _: Q = e / Z::from(42);
526        let _: Q = f / Z::from(42);
527        let _: Q = g / Z::from(42);
528        let _: Q = h / Z::from(42);
529        let _: Q = i / Z::from(42);
530    }
531}
532
533#[cfg(test)]
534mod test_div {
535    use super::Z;
536    use crate::rational::Q;
537    use crate::traits::Pow;
538
539    /// Testing division for two [`Z`]
540    #[test]
541    fn div() {
542        let a: Z = Z::from(42);
543        let b: Z = Z::from(4);
544        let c: Q = a / b;
545        assert_eq!(c, Q::from((21, 2)));
546    }
547
548    /// Testing division for two borrowed [`Z`]
549    #[test]
550    fn div_borrow() {
551        let a: Z = Z::from(42);
552        let b: Z = Z::from(4);
553        let c: Q = &a / &b;
554        assert_eq!(c, Q::from((21, 2)));
555    }
556
557    /// Testing division for borrowed [`Z`] and [`Z`]
558    #[test]
559    fn div_first_borrowed() {
560        let a: Z = Z::from(42);
561        let b: Z = Z::from(4);
562        let c: Q = &a / b;
563        assert_eq!(c, Q::from((21, 2)));
564    }
565
566    /// Testing division for [`Z`] and borrowed [`Z`]
567    #[test]
568    fn div_second_borrowed() {
569        let a: Z = Z::from(42);
570        let b: Z = Z::from(4);
571        let c: Q = a / &b;
572        assert_eq!(c, Q::from((21, 2)));
573    }
574
575    /// Testing division for large [`Z`]
576    #[test]
577    fn div_large_numbers() {
578        let a: Z = Z::from(i64::MAX as u64 + 1);
579        let b: Z = Z::from(2);
580        let c: Z = Z::from(i64::MIN);
581        let d: Z = Z::from(i64::MAX as u64 + 1);
582
583        let e: Q = a / b;
584        let f: Q = c / d;
585
586        assert_eq!(e, Q::from(2).pow(62).unwrap());
587        assert_eq!(f, Q::MINUS_ONE);
588    }
589}
590
591#[cfg(test)]
592mod test_div_between_z_and_q {
593    use super::Z;
594    use crate::rational::Q;
595
596    /// Ensuring division between different types is available
597    #[test]
598    fn availability() {
599        let a: Z = Z::from(42);
600        let b: Q = Q::from((5, 7));
601
602        let _: Q = &a / &b;
603        let _: Q = &a / b.clone();
604        let _: Q = a.clone() / &b;
605        let _: Q = a.clone() / b;
606        let _: Q = &a / 0.5_f32;
607        let _: Q = &a / 0.5_f64;
608        let _: Q = a.clone() / 0.5_f32;
609        let _: Q = a.clone() / 0.5_f64;
610        let _: Q = 0.5_f32 / &a;
611        let _: Q = 0.5_f64 / &a;
612        let _: Q = 0.5_f32 / a.clone();
613        let _: Q = 0.5_f64 / a.clone();
614    }
615
616    /// Ensures that division is performed the right way around
617    #[test]
618    fn order_retained() {
619        let a = Z::from(4);
620
621        assert_eq!(2, &a / 2);
622        assert_eq!(Q::from((1, 2)), 2 / &a);
623    }
624
625    /// Testing division for [`Z`] and [`Q`]
626    #[test]
627    fn div() {
628        let a: Z = Z::from(4);
629        let b: Q = Q::from((5, 7));
630        let c: Q = a / b;
631        assert_eq!(c, Q::from((28, 5)));
632    }
633
634    /// Testing division for both borrowed [`Z`] and [`Q`]
635    #[test]
636    fn div_borrow() {
637        let a: Z = Z::from(4);
638        let b: Q = Q::from((5, 7));
639        let c: Q = &a / &b;
640        assert_eq!(c, Q::from((28, 5)));
641    }
642
643    /// Testing division for borrowed [`Z`] and [`Q`]
644    #[test]
645    fn div_first_borrowed() {
646        let a: Z = Z::from(4);
647        let b: Q = Q::from((5, 7));
648        let c: Q = &a / b;
649        assert_eq!(c, Q::from((28, 5)));
650    }
651
652    /// Testing division for [`Z`] and borrowed [`Q`]
653    #[test]
654    fn div_second_borrowed() {
655        let a: Z = Z::from(4);
656        let b: Q = Q::from((5, 7));
657        let c: Q = a / &b;
658        assert_eq!(c, Q::from((28, 5)));
659    }
660
661    /// Testing division for large numbers
662    #[test]
663    fn div_large_numbers() {
664        let a: Z = Z::from(u64::MAX);
665        let b: Q = Q::from((1, u64::MAX));
666        let c: Q = Q::from((u64::MAX, 2));
667
668        let d: Q = &a / b;
669        let e: Q = a / c;
670
671        assert_eq!(d, Q::from(u64::MAX) / Q::from((1, u64::MAX)));
672        assert_eq!(e, Q::from(u64::MAX) / Q::from((u64::MAX, 2)));
673    }
674}