malachite_q/arithmetic/
div.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// CheckedDiv implementation by Park Joon-Kyu.
4//
5// Uses code adopted from the GNU MP Library.
6//
7//      Copyright © 1991, 1994-1996, 2000, 2001, 2015, 2018 Free Software Foundation, Inc.
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::Rational;
16use core::ops::{Div, DivAssign};
17use malachite_base::num::arithmetic::traits::{
18    CheckedDiv, DivExact, DivExactAssign, Gcd, Reciprocal,
19};
20use malachite_base::num::basic::traits::Zero;
21
22impl Div<Self> for Rational {
23    type Output = Self;
24
25    /// Divides a [`Rational`] by another [`Rational`], taking both by value.
26    ///
27    /// $$
28    /// f(x, y) = \frac{x}{y}.
29    /// $$
30    ///
31    /// # Worst-case complexity
32    /// $T(n) = O(n (\log n)^2 \log\log n)$
33    ///
34    /// $M(n) = O(n \log n)$
35    ///
36    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
37    /// other.significant_bits())`.
38    ///
39    /// # Panics
40    /// Panics if the second [`Rational`] is zero.
41    ///
42    /// # Examples
43    /// ```
44    /// use malachite_base::num::basic::traits::Two;
45    /// use malachite_q::Rational;
46    ///
47    /// assert_eq!(Rational::TWO / Rational::TWO, 1);
48    /// assert_eq!(
49    ///     (Rational::from_signeds(22, 7) / Rational::from_signeds(99, 100)).to_string(),
50    ///     "200/63"
51    /// );
52    /// ```
53    fn div(self, other: Self) -> Self {
54        if other == 0u32 {
55            panic!("division by zero");
56        } else if self == 0u32 {
57            return Self::ZERO;
58        } else if self == 1u32 {
59            return other.reciprocal();
60        } else if other == 1u32 {
61            return self;
62        }
63        let g_1 = (&self.numerator).gcd(&other.numerator);
64        let g_2 = (&other.denominator).gcd(&self.denominator);
65        Self {
66            sign: self.sign == other.sign,
67            numerator: (self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2),
68            denominator: (other.numerator).div_exact(g_1) * (self.denominator).div_exact(g_2),
69        }
70    }
71}
72
73impl Div<&Self> for Rational {
74    type Output = Self;
75
76    /// Divides a [`Rational`] by another [`Rational`], taking the first by value and the second by
77    /// reference.
78    ///
79    /// $$
80    /// f(x, y) = \frac{x}{y}.
81    /// $$
82    ///
83    /// # Worst-case complexity
84    /// $T(n) = O(n (\log n)^2 \log\log n)$
85    ///
86    /// $M(n) = O(n \log n)$
87    ///
88    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
89    /// other.significant_bits())`.
90    ///
91    /// # Panics
92    /// Panics if the second [`Rational`] is zero.
93    ///
94    /// # Examples
95    /// ```
96    /// use malachite_base::num::basic::traits::Two;
97    /// use malachite_q::Rational;
98    ///
99    /// assert_eq!(Rational::TWO / &Rational::TWO, 1);
100    /// assert_eq!(
101    ///     (Rational::from_signeds(22, 7) / &Rational::from_signeds(99, 100)).to_string(),
102    ///     "200/63"
103    /// );
104    /// ```
105    #[inline]
106    fn div(self, other: &Self) -> Self {
107        if *other == 0u32 {
108            panic!("division by zero");
109        } else if self == 0u32 {
110            Self::ZERO
111        } else {
112            (other / self).reciprocal()
113        }
114    }
115}
116
117impl Div<Rational> for &Rational {
118    type Output = Rational;
119
120    /// Divides a [`Rational`] by another [`Rational`], taking the first by reference and the second
121    /// by value.
122    ///
123    /// $$
124    /// f(x, y) = \frac{x}{y}.
125    /// $$
126    ///
127    /// # Worst-case complexity
128    /// $T(n) = O(n (\log n)^2 \log\log n)$
129    ///
130    /// $M(n) = O(n \log n)$
131    ///
132    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
133    /// other.significant_bits())`.
134    ///
135    /// # Panics
136    /// Panics if the second [`Rational`] is zero.
137    ///
138    /// # Examples
139    /// ```
140    /// use malachite_base::num::basic::traits::Two;
141    /// use malachite_q::Rational;
142    ///
143    /// assert_eq!(&Rational::TWO / Rational::TWO, 1);
144    /// assert_eq!(
145    ///     (&Rational::from_signeds(22, 7) / Rational::from_signeds(99, 100)).to_string(),
146    ///     "200/63"
147    /// );
148    /// ```
149    fn div(self, other: Rational) -> Rational {
150        if other == 0u32 {
151            panic!("division by zero");
152        } else if *self == 0u32 {
153            return Rational::ZERO;
154        } else if *self == 1u32 {
155            return other.reciprocal();
156        } else if other == 1u32 {
157            return self.clone();
158        }
159        let g_1 = (&self.numerator).gcd(&other.numerator);
160        let g_2 = (&other.denominator).gcd(&self.denominator);
161        Rational {
162            sign: self.sign == other.sign,
163            numerator: (&self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2),
164            denominator: (other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2),
165        }
166    }
167}
168
169impl Div<&Rational> for &Rational {
170    type Output = Rational;
171
172    /// Divides a [`Rational`] by another [`Rational`], taking both by reference.
173    ///
174    /// $$
175    /// f(x, y) = \frac{x}{y}.
176    /// $$
177    ///
178    /// # Worst-case complexity
179    /// $T(n) = O(n (\log n)^2 \log\log n)$
180    ///
181    /// $M(n) = O(n \log n)$
182    ///
183    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
184    /// other.significant_bits())`.
185    ///
186    /// # Panics
187    /// Panics if the second [`Rational`] is zero.
188    ///
189    /// # Examples
190    /// ```
191    /// use malachite_base::num::basic::traits::Two;
192    /// use malachite_q::Rational;
193    ///
194    /// assert_eq!(&Rational::TWO / &Rational::TWO, 1);
195    /// assert_eq!(
196    ///     (&Rational::from_signeds(22, 7) / &Rational::from_signeds(99, 100)).to_string(),
197    ///     "200/63"
198    /// );
199    /// ```
200    fn div(self, other: &Rational) -> Rational {
201        if *other == 0u32 {
202            panic!("division by zero");
203        } else if *self == 0u32 {
204            return Rational::ZERO;
205        } else if *self == 1u32 {
206            return other.reciprocal();
207        } else if *other == 1u32 {
208            return self.clone();
209        }
210        let g_1 = (&self.numerator).gcd(&other.numerator);
211        let g_2 = (&other.denominator).gcd(&self.denominator);
212        Rational {
213            sign: self.sign == other.sign,
214            numerator: (&self.numerator).div_exact(&g_1) * (&other.denominator).div_exact(&g_2),
215            denominator: (&other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2),
216        }
217    }
218}
219
220impl CheckedDiv<Self> for Rational {
221    type Output = Self;
222
223    /// Divides a [`Rational`] by another [`Rational`], taking both by value. Returns `None` when
224    /// the second [`Rational`] is zero, `Some` otherwise.
225    ///
226    /// $$
227    /// f(x, y) = \begin{cases}
228    ///     \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\
229    ///     \text{None} & \text{otherwise}
230    /// \end{cases}
231    /// $$
232    ///
233    /// # Worst-case complexity
234    /// $T(n) = O(n (\log n)^2 \log\log n)$
235    ///
236    /// $M(n) = O(n \log n)$
237    ///
238    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
239    /// other.significant_bits())`.
240    ///
241    /// # Examples
242    /// ```
243    /// use malachite_base::num::arithmetic::traits::CheckedDiv;
244    /// use malachite_base::num::basic::traits::{Two, Zero};
245    /// use malachite_q::Rational;
246    ///
247    /// assert_eq!(Rational::TWO.checked_div(Rational::TWO).unwrap(), 1);
248    /// assert_eq!(Rational::TWO.checked_div(Rational::ZERO), None);
249    /// assert_eq!(
250    ///     (Rational::from_signeds(22, 7).checked_div(Rational::from_signeds(99, 100)))
251    ///         .unwrap()
252    ///         .to_string(),
253    ///     "200/63"
254    /// );
255    /// ```
256    fn checked_div(self, other: Self) -> Option<Self> {
257        if other == 0u32 {
258            return None;
259        } else if self == 0u32 {
260            return Some(Self::ZERO);
261        } else if self == 1u32 {
262            return Some(other.reciprocal());
263        } else if other == 1u32 {
264            return Some(self);
265        }
266        let g_1 = (&self.numerator).gcd(&other.numerator);
267        let g_2 = (&other.denominator).gcd(&self.denominator);
268        Some(Self {
269            sign: self.sign == other.sign,
270            numerator: (self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2),
271            denominator: (other.numerator).div_exact(g_1) * (self.denominator).div_exact(g_2),
272        })
273    }
274}
275
276impl CheckedDiv<&Self> for Rational {
277    type Output = Self;
278
279    /// Divides a [`Rational`] by another [`Rational`], taking the first by value and the second by
280    /// reference. Returns `None` when the second [`Rational`] is zero, `Some` otherwise.
281    ///
282    /// $$
283    /// f(x, y) = \begin{cases}
284    ///     \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\
285    ///     \text{None} & \text{otherwise}
286    /// \end{cases}
287    /// $$
288    ///
289    /// # Worst-case complexity
290    /// $T(n) = O(n (\log n)^2 \log\log n)$
291    ///
292    /// $M(n) = O(n \log n)$
293    ///
294    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
295    /// other.significant_bits())`.
296    ///
297    /// # Examples
298    /// ```
299    /// use malachite_base::num::arithmetic::traits::CheckedDiv;
300    /// use malachite_base::num::basic::traits::{Two, Zero};
301    /// use malachite_q::Rational;
302    ///
303    /// assert_eq!(Rational::TWO.checked_div(&Rational::TWO).unwrap(), 1);
304    /// assert_eq!(Rational::TWO.checked_div(&Rational::ZERO), None);
305    /// assert_eq!(
306    ///     (Rational::from_signeds(22, 7).checked_div(&Rational::from_signeds(99, 100)))
307    ///         .unwrap()
308    ///         .to_string(),
309    ///     "200/63"
310    /// );
311    /// ```
312    #[inline]
313    fn checked_div(self, other: &Self) -> Option<Self> {
314        if other == &0u32 {
315            None
316        } else if self == 0u32 {
317            Some(Self::ZERO)
318        } else {
319            (other.checked_div(self)).map(Self::reciprocal)
320        }
321    }
322}
323
324impl CheckedDiv<Rational> for &Rational {
325    type Output = Rational;
326
327    /// Divides a [`Rational`] by another [`Rational`], taking the first by reference and the second
328    /// by value. Returns `None` when the second [`Rational`] is zero, `Some` otherwise.
329    ///
330    /// $$
331    /// f(x, y) = \begin{cases}
332    ///     \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\
333    ///     \text{None} & \text{otherwise}
334    /// \end{cases}
335    /// $$
336    ///
337    /// # Worst-case complexity
338    /// $T(n) = O(n (\log n)^2 \log\log n)$
339    ///
340    /// $M(n) = O(n \log n)$
341    ///
342    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
343    /// other.significant_bits())`.
344    ///
345    /// # Examples
346    /// ```
347    /// use malachite_base::num::arithmetic::traits::CheckedDiv;
348    /// use malachite_base::num::basic::traits::{Two, Zero};
349    /// use malachite_q::Rational;
350    ///
351    /// assert_eq!((&Rational::TWO).checked_div(Rational::TWO).unwrap(), 1);
352    /// assert_eq!((&Rational::TWO).checked_div(Rational::ZERO), None);
353    /// assert_eq!(
354    ///     (&Rational::from_signeds(22, 7))
355    ///         .checked_div(Rational::from_signeds(99, 100))
356    ///         .unwrap()
357    ///         .to_string(),
358    ///     "200/63"
359    /// );
360    /// ```
361    fn checked_div(self, other: Rational) -> Option<Rational> {
362        if other == 0u32 {
363            return None;
364        } else if *self == 0u32 {
365            return Some(Rational::ZERO);
366        } else if *self == 1u32 {
367            return Some(other.reciprocal());
368        } else if other == 1u32 {
369            return Some(self.clone());
370        }
371        let g_1 = (&self.numerator).gcd(&other.numerator);
372        let g_2 = (&other.denominator).gcd(&self.denominator);
373        Some(Rational {
374            sign: self.sign == other.sign,
375            numerator: (&self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2),
376            denominator: (other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2),
377        })
378    }
379}
380
381impl CheckedDiv<&Rational> for &Rational {
382    type Output = Rational;
383
384    /// Divides a [`Rational`] by another [`Rational`], taking both by reference. Returns `None`
385    /// when the second [`Rational`] is zero, `Some` otherwise.
386    ///
387    /// $$
388    /// f(x, y) = \begin{cases}
389    ///     \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\
390    ///     \text{None} & \text{otherwise}
391    /// \end{cases}
392    /// $$
393    ///
394    /// # Worst-case complexity
395    /// $T(n) = O(n (\log n)^2 \log\log n)$
396    ///
397    /// $M(n) = O(n \log n)$
398    ///
399    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
400    /// other.significant_bits())`.
401    ///
402    /// # Examples
403    /// ```
404    /// use malachite_base::num::arithmetic::traits::CheckedDiv;
405    /// use malachite_base::num::basic::traits::{Two, Zero};
406    /// use malachite_q::Rational;
407    ///
408    /// assert_eq!((&Rational::TWO).checked_div(&Rational::TWO).unwrap(), 1);
409    /// assert_eq!((&Rational::TWO).checked_div(&Rational::ZERO), None);
410    /// assert_eq!(
411    ///     (&Rational::from_signeds(22, 7))
412    ///         .checked_div(&Rational::from_signeds(99, 100))
413    ///         .unwrap()
414    ///         .to_string(),
415    ///     "200/63"
416    /// );
417    /// ```
418    fn checked_div(self, other: &Rational) -> Option<Rational> {
419        if *other == 0u32 {
420            return None;
421        } else if *self == 0u32 {
422            return Some(Rational::ZERO);
423        } else if *self == 1u32 {
424            return Some(other.reciprocal());
425        } else if *other == 1u32 {
426            return Some(self.clone());
427        }
428        let g_1 = (&self.numerator).gcd(&other.numerator);
429        let g_2 = (&other.denominator).gcd(&self.denominator);
430        Some(Rational {
431            sign: self.sign == other.sign,
432            numerator: (&self.numerator).div_exact(&g_1) * (&other.denominator).div_exact(&g_2),
433            denominator: (&other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2),
434        })
435    }
436}
437
438impl DivAssign<Self> for Rational {
439    /// Divides a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the right-hand
440    /// side by value.
441    ///
442    /// $$
443    /// x \gets \frac{x}{y}.
444    /// $$
445    ///
446    /// # Worst-case complexity
447    /// $T(n) = O(n (\log n)^2 \log\log n)$
448    ///
449    /// $M(n) = O(n \log n)$
450    ///
451    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
452    /// other.significant_bits())`.
453    ///
454    /// # Panics
455    /// Panics if the second [`Rational`] is zero.
456    ///
457    /// # Examples
458    /// ```
459    /// use malachite_base::num::basic::traits::Two;
460    /// use malachite_q::Rational;
461    ///
462    /// let mut x = Rational::TWO;
463    /// x /= Rational::TWO;
464    /// assert_eq!(x, 1);
465    ///
466    /// let mut x = Rational::from_signeds(22, 7);
467    /// x /= Rational::from_signeds(99, 100);
468    /// assert_eq!(x.to_string(), "200/63");
469    /// ```
470    fn div_assign(&mut self, other: Self) {
471        if other == 0u32 {
472            panic!("division by zero");
473        } else if *self == 0u32 || other == 1u32 {
474            return;
475        } else if *self == 1u32 {
476            *self = other.reciprocal();
477            return;
478        }
479        self.sign = self.sign == other.sign;
480        let g_1 = (&self.numerator).gcd(&other.numerator);
481        let g_2 = (&other.denominator).gcd(&self.denominator);
482        self.numerator.div_exact_assign(&g_1);
483        self.denominator.div_exact_assign(&g_2);
484        self.numerator *= (other.denominator).div_exact(g_2);
485        self.denominator *= (other.numerator).div_exact(g_1);
486    }
487}
488
489impl DivAssign<&Self> for Rational {
490    /// Divides a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the right-hand
491    /// side by reference.
492    ///
493    /// $$
494    /// x \gets \frac{x}{y}.
495    /// $$
496    ///
497    /// # Worst-case complexity
498    /// $T(n) = O(n (\log n)^2 \log\log n)$
499    ///
500    /// $M(n) = O(n \log n)$
501    ///
502    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
503    /// other.significant_bits())`.
504    ///
505    /// # Panics
506    /// Panics if the second [`Rational`] is zero.
507    ///
508    /// # Examples
509    /// ```
510    /// use malachite_base::num::basic::traits::Two;
511    /// use malachite_q::Rational;
512    ///
513    /// let mut x = Rational::TWO;
514    /// x /= &Rational::TWO;
515    /// assert_eq!(x, 1);
516    ///
517    /// let mut x = Rational::from_signeds(22, 7);
518    /// x /= &Rational::from_signeds(99, 100);
519    /// assert_eq!(x.to_string(), "200/63");
520    /// ```
521    fn div_assign(&mut self, other: &Self) {
522        if *other == 0u32 {
523            panic!("division by zero");
524        } else if *self == 0u32 || *other == 1u32 {
525            return;
526        } else if *self == 1u32 {
527            *self = other.reciprocal();
528            return;
529        }
530        self.sign = self.sign == other.sign;
531        let g_1 = (&self.numerator).gcd(&other.numerator);
532        let g_2 = (&other.denominator).gcd(&self.denominator);
533        self.numerator.div_exact_assign(&g_1);
534        self.denominator.div_exact_assign(&g_2);
535        self.numerator *= (&other.denominator).div_exact(g_2);
536        self.denominator *= (&other.numerator).div_exact(g_1);
537    }
538}