malachite_q/arithmetic/sub.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 core::ops::{Sub, SubAssign};
15use malachite_base::num::arithmetic::traits::{
16 DivExact, DivExactAssign, Gcd, GcdAssign, NegAssign, UnsignedAbs,
17};
18use malachite_nz::integer::Integer;
19
20impl Sub<Self> for Rational {
21 type Output = Self;
22
23 /// Subtracts a [`Rational`] by another [`Rational`], taking both by value.
24 ///
25 /// $$
26 /// f(x, y) = x - y.
27 /// $$
28 ///
29 /// # Worst-case complexity
30 /// $T(n) = O(n (\log n)^2 \log\log n)$
31 ///
32 /// $M(n) = O(n \log n)$
33 ///
34 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
35 /// other.significant_bits())`.
36 ///
37 /// # Examples
38 /// ```
39 /// use malachite_base::num::basic::traits::OneHalf;
40 /// use malachite_q::Rational;
41 ///
42 /// assert_eq!(Rational::ONE_HALF - Rational::ONE_HALF, 0);
43 /// assert_eq!(
44 /// (Rational::from_signeds(22, 7) - Rational::from_signeds(99, 100)).to_string(),
45 /// "1507/700"
46 /// );
47 /// ```
48 fn sub(self, other: Self) -> Self {
49 if self == 0u32 {
50 return -other;
51 } else if other == 0u32 {
52 return self;
53 }
54 let mut gcd = (&self.denominator).gcd(&other.denominator);
55 if gcd == 1u32 {
56 let diff_n = Integer::from_sign_and_abs(self.sign, self.numerator * &other.denominator)
57 - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator);
58 let diff_d = self.denominator * other.denominator;
59 Self {
60 sign: diff_n >= 0,
61 numerator: diff_n.unsigned_abs(),
62 denominator: diff_d,
63 }
64 } else {
65 let reduced_self_d = (self.denominator).div_exact(&gcd);
66 let diff_n =
67 Integer::from_sign_and_abs(
68 self.sign,
69 self.numerator * (&other.denominator).div_exact(&gcd),
70 ) - Integer::from_sign_and_abs(other.sign, other.numerator * &reduced_self_d);
71 gcd.gcd_assign(diff_n.unsigned_abs_ref());
72 if gcd == 1u32 {
73 Self {
74 sign: diff_n >= 0,
75 numerator: diff_n.unsigned_abs(),
76 denominator: other.denominator * reduced_self_d,
77 }
78 } else {
79 Self {
80 sign: diff_n >= 0,
81 numerator: diff_n.unsigned_abs().div_exact(&gcd),
82 denominator: (other.denominator).div_exact(gcd) * reduced_self_d,
83 }
84 }
85 }
86 }
87}
88
89impl Sub<&Self> for Rational {
90 type Output = Self;
91
92 /// Subtracts a [`Rational`] by another [`Rational`], taking the first by value and the second
93 /// by reference.
94 ///
95 /// $$
96 /// f(x, y) = x - y.
97 /// $$
98 ///
99 /// # Worst-case complexity
100 /// $T(n) = O(n (\log n)^2 \log\log n)$
101 ///
102 /// $M(n) = O(n \log n)$
103 ///
104 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
105 /// other.significant_bits())`.
106 ///
107 /// # Examples
108 /// ```
109 /// use malachite_base::num::basic::traits::OneHalf;
110 /// use malachite_q::Rational;
111 ///
112 /// assert_eq!(Rational::ONE_HALF - &Rational::ONE_HALF, 0);
113 /// assert_eq!(
114 /// (Rational::from_signeds(22, 7) - &Rational::from_signeds(99, 100)).to_string(),
115 /// "1507/700"
116 /// );
117 /// ```
118 #[inline]
119 fn sub(self, other: &Self) -> Self {
120 -(other - self)
121 }
122}
123
124impl Sub<Rational> for &Rational {
125 type Output = Rational;
126
127 /// Subtracts a [`Rational`] by another [`Rational`], taking the first by reference and the
128 /// second by value.
129 ///
130 /// $$
131 /// f(x, y) = x - y.
132 /// $$
133 ///
134 /// # Worst-case complexity
135 /// $T(n) = O(n (\log n)^2 \log\log n)$
136 ///
137 /// $M(n) = O(n \log n)$
138 ///
139 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
140 /// other.significant_bits())`.
141 ///
142 /// # Examples
143 /// ```
144 /// use malachite_base::num::basic::traits::OneHalf;
145 /// use malachite_q::Rational;
146 ///
147 /// assert_eq!(&Rational::ONE_HALF - Rational::ONE_HALF, 0);
148 /// assert_eq!(
149 /// (&Rational::from_signeds(22, 7) - Rational::from_signeds(99, 100)).to_string(),
150 /// "1507/700"
151 /// );
152 /// ```
153 fn sub(self, other: Rational) -> Rational {
154 if *self == 0u32 {
155 return -other;
156 } else if other == 0u32 {
157 return self.clone();
158 }
159 let mut gcd = (&self.denominator).gcd(&other.denominator);
160 if gcd == 1u32 {
161 let diff_n =
162 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 diff_d = &self.denominator * other.denominator;
165 Rational {
166 sign: diff_n >= 0,
167 numerator: diff_n.unsigned_abs(),
168 denominator: diff_d,
169 }
170 } else {
171 let reduced_self_d = (&self.denominator).div_exact(&gcd);
172 let diff_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(diff_n.unsigned_abs_ref());
178 if gcd == 1u32 {
179 Rational {
180 sign: diff_n >= 0,
181 numerator: diff_n.unsigned_abs(),
182 denominator: other.denominator * reduced_self_d,
183 }
184 } else {
185 Rational {
186 sign: diff_n >= 0,
187 numerator: diff_n.unsigned_abs().div_exact(&gcd),
188 denominator: (other.denominator).div_exact(gcd) * reduced_self_d,
189 }
190 }
191 }
192 }
193}
194
195impl Sub<&Rational> for &Rational {
196 type Output = Rational;
197
198 /// Subtracts a [`Rational`] by another [`Rational`], 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, 0);
218 /// assert_eq!(
219 /// (&Rational::from_signeds(22, 7) - &Rational::from_signeds(99, 100)).to_string(),
220 /// "1507/700"
221 /// );
222 /// ```
223 fn sub(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 diff_n =
232 Integer::from_sign_and_abs(self.sign, &self.numerator * &other.denominator)
233 - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator);
234 let diff_d = &self.denominator * &other.denominator;
235 Rational {
236 sign: diff_n >= 0,
237 numerator: diff_n.unsigned_abs(),
238 denominator: diff_d,
239 }
240 } else {
241 let reduced_self_d = (&self.denominator).div_exact(&gcd);
242 let diff_n =
243 Integer::from_sign_and_abs(
244 self.sign,
245 &self.numerator * (&other.denominator).div_exact(&gcd),
246 ) - Integer::from_sign_and_abs(other.sign, &other.numerator * &reduced_self_d);
247 gcd.gcd_assign(diff_n.unsigned_abs_ref());
248 if gcd == 1u32 {
249 Rational {
250 sign: diff_n >= 0,
251 numerator: diff_n.unsigned_abs(),
252 denominator: &other.denominator * reduced_self_d,
253 }
254 } else {
255 Rational {
256 sign: diff_n >= 0,
257 numerator: diff_n.unsigned_abs().div_exact(&gcd),
258 denominator: (&other.denominator).div_exact(gcd) * reduced_self_d,
259 }
260 }
261 }
262 }
263}
264
265impl SubAssign<Self> for Rational {
266 /// Subtracts a [`Rational`] by another [`Rational`] in place, taking the [`Rational`] on the
267 /// right-hand side by value.
268 ///
269 /// $$
270 /// x \gets x - y.
271 /// $$
272 ///
273 /// # Worst-case complexity
274 /// $T(n) = O(n (\log n)^2 \log\log n)$
275 ///
276 /// $M(n) = O(n \log n)$
277 ///
278 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
279 /// other.significant_bits())`.
280 ///
281 /// # Examples
282 /// ```
283 /// use malachite_base::num::basic::traits::OneHalf;
284 /// use malachite_q::Rational;
285 ///
286 /// let mut x = Rational::ONE_HALF;
287 /// x -= Rational::ONE_HALF;
288 /// assert_eq!(x, 0);
289 ///
290 /// let mut x = Rational::from_signeds(22, 7);
291 /// x -= Rational::from_signeds(99, 100);
292 /// assert_eq!(x.to_string(), "1507/700");
293 /// ```
294 fn sub_assign(&mut self, other: Self) {
295 if *self == 0u32 {
296 *self = -other;
297 return;
298 } else if other == 0u32 {
299 return;
300 }
301 let mut gcd = (&self.denominator).gcd(&other.denominator);
302 if gcd == 1u32 {
303 self.numerator *= &other.denominator;
304 let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator)
305 - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator);
306 self.sign = diff_n >= 0;
307 self.numerator = diff_n.unsigned_abs();
308 self.denominator *= other.denominator;
309 } else {
310 self.denominator.div_exact_assign(&gcd);
311 self.numerator *= (&other.denominator).div_exact(&gcd);
312 let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator)
313 - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator);
314 gcd.gcd_assign(diff_n.unsigned_abs_ref());
315 self.sign = diff_n >= 0;
316 if gcd == 1u32 {
317 self.numerator = diff_n.unsigned_abs();
318 self.denominator *= other.denominator;
319 } else {
320 self.numerator = diff_n.unsigned_abs().div_exact(&gcd);
321 self.denominator *= (other.denominator).div_exact(gcd);
322 }
323 }
324 }
325}
326
327impl SubAssign<&Self> for Rational {
328 /// Subtracts a [`Rational`] by another [`Rational`] in place, taking the [`Rational`] on the
329 /// right-hand side by reference.
330 ///
331 /// $$
332 /// x \gets x - y.
333 /// $$
334 ///
335 /// # Worst-case complexity
336 /// $T(n) = O(n (\log n)^2 \log\log n)$
337 ///
338 /// $M(n) = O(n \log n)$
339 ///
340 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
341 /// other.significant_bits())`.
342 ///
343 /// # Examples
344 /// ```
345 /// use malachite_base::num::basic::traits::OneHalf;
346 /// use malachite_q::Rational;
347 ///
348 /// let mut x = Rational::ONE_HALF;
349 /// x -= &Rational::ONE_HALF;
350 /// assert_eq!(x, 0);
351 ///
352 /// let mut x = Rational::from_signeds(22, 7);
353 /// x -= &Rational::from_signeds(99, 100);
354 /// assert_eq!(x.to_string(), "1507/700");
355 /// ```
356 fn sub_assign(&mut self, other: &Self) {
357 if *self == 0u32 {
358 self.clone_from(other);
359 self.neg_assign();
360 return;
361 } else if *other == 0u32 {
362 return;
363 }
364 let mut gcd = (&self.denominator).gcd(&other.denominator);
365 if gcd == 1u32 {
366 self.numerator *= &other.denominator;
367 let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator)
368 - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator);
369 self.sign = diff_n >= 0;
370 self.numerator = diff_n.unsigned_abs();
371 self.denominator *= &other.denominator;
372 } else {
373 self.denominator.div_exact_assign(&gcd);
374 self.numerator *= (&other.denominator).div_exact(&gcd);
375 let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator)
376 - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator);
377 gcd.gcd_assign(diff_n.unsigned_abs_ref());
378 self.sign = diff_n >= 0;
379 if gcd == 1u32 {
380 self.numerator = diff_n.unsigned_abs();
381 self.denominator *= &other.denominator;
382 } else {
383 self.numerator = diff_n.unsigned_abs().div_exact(&gcd);
384 self.denominator *= (&other.denominator).div_exact(gcd);
385 }
386 }
387 }
388}