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