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}