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}