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