malachite_nz/integer/arithmetic/
sub_mul.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5//      Copyright © 2001, 2004, 2005, 2012 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::integer::Integer;
14use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place;
15use crate::natural::arithmetic::mul::limb::{
16    limbs_mul_limb_with_carry_to_out, limbs_slice_mul_limb_with_carry_in_place,
17};
18use crate::natural::arithmetic::mul::{
19    limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len,
20};
21use crate::natural::arithmetic::sub::{
22    limbs_slice_sub_in_place_right, limbs_sub_greater_in_place_left, limbs_sub_limb_in_place,
23    limbs_sub_limb_to_out,
24};
25use crate::natural::arithmetic::sub_mul::{
26    limbs_sub_mul_limb_same_length_in_place_left, limbs_sub_mul_limb_same_length_in_place_right,
27};
28use crate::natural::comparison::cmp::limbs_cmp;
29use crate::natural::logic::not::limbs_not_in_place;
30use crate::platform::{DoubleLimb, Limb};
31use alloc::vec::Vec;
32use core::cmp::Ordering::*;
33use malachite_base::num::arithmetic::traits::{
34    AddMul, AddMulAssign, NegAssign, SubMul, SubMulAssign, WrappingAddAssign, WrappingSubAssign,
35};
36use malachite_base::slices::slice_test_zero;
37
38// Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, returning the
39// limbs of the absolute value and the sign (true means non-negative). `xs` and `ys` should be
40// nonempty and have no trailing zeros, and `z` should be nonzero.
41//
42// # Worst-case complexity
43// $T(n) = O(n)$
44//
45// $M(n) = O(1)$
46//
47// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
48//
49// This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are
50// positive, `sub` is negative, and `w` is returned instead of overwriting the first input. `w_sign`
51// is also returned.
52pub_crate_test! {limbs_overflowing_sub_mul_limb(
53    xs: &[Limb],
54    ys: &[Limb],
55    z: Limb
56) -> (Vec<Limb>, bool) {
57    let mut result;
58    let sign = if xs.len() >= ys.len() {
59        result = xs.to_vec();
60        limbs_overflowing_sub_mul_limb_greater_in_place_left(&mut result, ys, z)
61    } else {
62        result = ys.to_vec();
63        limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, &mut result, z)
64    };
65    (result, sign)
66}}
67
68// Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the
69// limbs of the absolute value to the first (left) slice and returning the sign (true means non-
70// negative). `xs` and `ys` should be nonempty and have no trailing zeros, and `z` should be
71// nonzero.
72//
73// # Worst-case complexity
74// $T(n) = O(n)$
75//
76// $M(m) = O(m)$
77//
78// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
79// ys.len() - xs.len())`.
80//
81// This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are
82// positive, `sub` is negative, and `w_sign` is returned.
83pub_crate_test! {limbs_overflowing_sub_mul_limb_in_place_left(
84    xs: &mut Vec<Limb>,
85    ys: &[Limb],
86    z: Limb,
87) -> bool {
88    let xs_len = xs.len();
89    let ys_len = ys.len();
90    if xs_len >= ys_len {
91        limbs_overflowing_sub_mul_limb_greater_in_place_left(xs, ys, z)
92    } else {
93        let (ys_lo, ys_hi) = ys.split_at(xs_len);
94        // submul of absolute values
95        let mut borrow = limbs_sub_mul_limb_same_length_in_place_left(xs, ys_lo, z);
96        // ys bigger than xs, so want ys * limb - xs. Submul has given xs - ys * limb, so take twos'
97        // complement and use an limbs_mul_limb_with_carry_to_out for the rest. -(-borrow * b ^ n +
98        // xs - ys * limb) = (borrow - 1) * b ^ n + ~(xs - ys * limb) + 1
99        limbs_not_in_place(xs);
100        if !limbs_slice_add_limb_in_place(xs, 1) {
101            borrow.wrapping_sub_assign(1);
102        }
103        // If borrow - 1 == -1, then hold that -1 for later.
104        // limbs_sub_mul_limb_same_length_in_place_left never returns borrow == Limb::MAX, so that
105        // value always indicates a -1.
106        let negative_one = borrow == Limb::MAX;
107        if negative_one {
108            borrow.wrapping_add_assign(1);
109        }
110        xs.resize(ys_len + 1, 0);
111        let xs_hi = &mut xs[xs_len..];
112        let (xs_hi_last, xs_hi_init) = xs_hi.split_last_mut().unwrap();
113        *xs_hi_last =
114            limbs_mul_limb_with_carry_to_out::<DoubleLimb, Limb>(xs_hi_init, ys_hi, z, borrow);
115        // Apply any -1 from above. The value at xs_hi is non-zero because z != 0 and the high limb
116        // of ys will be non-zero.
117        if negative_one {
118            assert!(!limbs_sub_limb_in_place(xs_hi, 1));
119        }
120        false
121    }
122}}
123
124// xs.len() >= ys.len()
125fn limbs_overflowing_sub_mul_limb_greater_in_place_left(
126    xs: &mut Vec<Limb>,
127    ys: &[Limb],
128    z: Limb,
129) -> bool {
130    let xs_len = xs.len();
131    let ys_len = ys.len();
132    xs.push(0);
133    // submul of absolute values
134    let (xs_lo, xs_hi) = xs.split_at_mut(ys_len);
135    let mut borrow = limbs_sub_mul_limb_same_length_in_place_left(xs_lo, ys, z);
136    // If xs bigger than ys, then propagate borrow through it.
137    if xs_len != ys_len {
138        borrow = Limb::from(limbs_sub_limb_in_place(xs_hi, borrow));
139    }
140    if borrow == 0 {
141        true
142    } else {
143        // Borrow out of xs, take twos' complement negative to get absolute value, flip sign of xs.
144        let (xs_last, xs_init) = xs.split_last_mut().unwrap();
145        *xs_last = borrow.wrapping_sub(1);
146        limbs_not_in_place(xs_init);
147        limbs_slice_add_limb_in_place(xs, 1);
148        false
149    }
150}
151
152// Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the
153// limbs of the absolute value to the second (right) slice and returning the sign (true means non-
154// negative). `xs` and `ys` should be nonempty and have no trailing zeros, and `z` should be
155// nonzero.
156//
157// # Worst-case complexity
158// $T(n) = O(n)$
159//
160// $M(m) = O(m)$
161//
162// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
163// ys.len() - xs.len())`.
164//
165// This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are
166// positive, `sub` is negative, the limbs of the result are written to the second input rather than
167// the first, and `w_sign` is returned.
168pub_test! {limbs_overflowing_sub_mul_limb_in_place_right(
169    xs: &[Limb],
170    ys: &mut Vec<Limb>,
171    z: Limb,
172) -> bool {
173    let xs_len = xs.len();
174    let ys_len = ys.len();
175    if xs_len >= ys_len {
176        ys.resize(xs_len + 1, 0);
177        // submul of absolute values
178        let (xs_lo, xs_hi) = xs.split_at(ys_len);
179        let (ys_lo, ys_hi) = ys.split_at_mut(ys_len);
180        let mut borrow = limbs_sub_mul_limb_same_length_in_place_right(xs_lo, ys_lo, z);
181        // If xs bigger than ys, then propagate borrow through it.
182        if xs_len != ys_len {
183            borrow = Limb::from(limbs_sub_limb_to_out(ys_hi, xs_hi, borrow));
184        }
185        if borrow == 0 {
186            true
187        } else {
188            // Borrow out of ys, take twos' complement negative to get absolute value, flip sign of
189            // ys.
190            let (ys_last, ys_init) = ys.split_last_mut().unwrap();
191            *ys_last = borrow.wrapping_sub(1);
192            limbs_not_in_place(ys_init);
193            limbs_slice_add_limb_in_place(ys, 1);
194            false
195        }
196    } else {
197        limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, ys, z)
198    }
199}}
200
201// xs.len() < ys.len()
202fn limbs_overflowing_sub_mul_limb_smaller_in_place_right(
203    xs: &[Limb],
204    ys: &mut Vec<Limb>,
205    z: Limb,
206) -> bool {
207    ys.push(0);
208    let (ys_lo, ys_hi) = ys.split_at_mut(xs.len());
209    // submul of absolute values
210    let mut borrow = limbs_sub_mul_limb_same_length_in_place_right(xs, ys_lo, z);
211    // ys bigger than xs, so want ys * z - xs. Submul has given xs - ys * z, so take twos'
212    // complement and use an limbs_mul_limb_with_carry_to_out for the rest. -(-borrow * b ^ n + xs
213    // - ys * z) = (borrow - 1) * b ^ n + ~(xs - ys * z) + 1
214    limbs_not_in_place(ys_lo);
215    if !limbs_slice_add_limb_in_place(ys_lo, 1) {
216        borrow.wrapping_sub_assign(1);
217    }
218    // If borrow - 1 == -1, then hold that -1 for later.
219    // limbs_sub_mul_limb_same_length_in_place_left never returns borrow == Limb::MAX, so that value
220    // always indicates a -1.
221    let negative_one = borrow == Limb::MAX;
222    if negative_one {
223        borrow.wrapping_add_assign(1);
224    }
225    let (ys_hi_last, ys_hi_init) = ys_hi.split_last_mut().unwrap();
226    *ys_hi_last = limbs_slice_mul_limb_with_carry_in_place(ys_hi_init, z, borrow);
227    if negative_one {
228        assert!(!limbs_sub_limb_in_place(ys_hi, 1));
229    }
230    false
231}
232
233// Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the
234// limbs of the absolute value to whichever input is longer. The first `bool` returned is `false` if
235// the result is written to the first input, and `true` if it is written to the second. The second
236// `bool` is the sign of the result (true means non-negative). `xs` and `ys` should be nonempty and
237// have no trailing zeros, and `z` should be nonzero.
238//
239// # Worst-case complexity
240// $T(n) = O(n)$
241//
242// $M(n) = O(1)$
243//
244// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
245//
246// This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are
247// positive, `sub` is negative, the result is written to the longer input, and `w_sign` is returned.
248pub_crate_test! {limbs_overflowing_sub_mul_limb_in_place_either(
249    xs: &mut Vec<Limb>,
250    ys: &mut Vec<Limb>,
251    z: Limb,
252) -> (bool, bool) {
253    if xs.len() >= ys.len() {
254        (
255            false,
256            limbs_overflowing_sub_mul_limb_greater_in_place_left(xs, ys, z),
257        )
258    } else {
259        (
260            true,
261            limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, ys, z),
262        )
263    }
264}}
265
266// Given the limbs of three `Natural`s x, y, and z, calculates x - y * z, returning the limbs of the
267// absolute value and the sign (true means non-negative). All of the input slices should be
268// non-empty and have no trailing zeros.
269//
270// # Worst-case complexity
271// $T(n, m) = O(m + n \log n \log\log n)$
272//
273// $M(n, m) = O(m + n \log n)$
274//
275// where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is
276// `xs.len()`.
277//
278// # Panics
279// Panics if `ys` or `zs` are empty.
280//
281// This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are
282// positive, `sub` is negative, and `w` is returned instead of overwriting the first input. `w_sign`
283// is also returned.
284pub_crate_test! {limbs_overflowing_sub_mul(
285    xs: &[Limb],
286    ys: &[Limb],
287    zs: &[Limb]
288) -> (Vec<Limb>, bool) {
289    let mut xs = xs.to_vec();
290    let sign = limbs_overflowing_sub_mul_in_place_left(&mut xs, ys, zs);
291    (xs, sign)
292}}
293
294// Given the limbs of three `Natural`s x, y, and z, calculates x - y * z, writing the limbs of the
295// absolute value to the first (left) slice and returning the sign (true means non-negative). All of
296// the input slices should be non-empty and have no trailing zeros.
297//
298// # Worst-case complexity
299// $T(n, m) = O(m + n \log n \log\log n)$
300//
301// $M(n, m) = O(n \log n)$
302//
303// where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is
304// `xs.len()`.
305//
306// # Panics
307// Panics if `ys` or `zs` are empty.
308//
309// This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are
310// positive, `sub` is negative, and `w_sign` is returned.
311pub_crate_test! {limbs_overflowing_sub_mul_in_place_left(
312    xs: &mut Vec<Limb>,
313    ys: &[Limb],
314    zs: &[Limb],
315) -> bool {
316    if ys.len() >= zs.len() {
317        limbs_overflowing_sub_mul_greater_in_place_left(xs, ys, zs)
318    } else {
319        limbs_overflowing_sub_mul_greater_in_place_left(xs, zs, ys)
320    }
321}}
322
323// zs.len() >= ys.len()
324fn limbs_overflowing_sub_mul_greater_in_place_left(
325    xs: &mut Vec<Limb>,
326    ys: &[Limb],
327    zs: &[Limb],
328) -> bool {
329    let xs_len = xs.len();
330    let product_len = ys.len() + zs.len();
331    let mut product = vec![0; product_len];
332    let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ys.len(), zs.len())];
333    if limbs_mul_greater_to_out(&mut product, ys, zs, &mut mul_scratch) == 0 {
334        product.pop();
335    }
336    assert_ne!(*product.last().unwrap(), 0);
337    if limbs_cmp(xs, &product) == Less {
338        if xs_len < product_len {
339            xs.resize(product.len(), 0);
340        }
341        assert!(!limbs_slice_sub_in_place_right(
342            &product,
343            &mut xs[..product.len()],
344            xs_len,
345        ));
346        false
347    } else {
348        assert!(!limbs_sub_greater_in_place_left(xs, &product));
349        !slice_test_zero(xs)
350    }
351}
352
353impl SubMul<Self, Self> for Integer {
354    type Output = Self;
355
356    /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking all three by
357    /// value.
358    ///
359    /// $f(x, y, z) = x - yz$.
360    ///
361    /// # Worst-case complexity
362    /// $T(n, m) = O(m + n \log n \log\log n)$
363    ///
364    /// $M(n) = O(n \log n)$
365    ///
366    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
367    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
368    ///
369    /// # Examples
370    /// ```
371    /// use malachite_base::num::arithmetic::traits::{Pow, SubMul};
372    /// use malachite_nz::integer::Integer;
373    ///
374    /// assert_eq!(
375    ///     Integer::from(10u32).sub_mul(Integer::from(3u32), Integer::from(-4)),
376    ///     22
377    /// );
378    /// assert_eq!(
379    ///     (-Integer::from(10u32).pow(12))
380    ///         .sub_mul(Integer::from(-0x10000), -Integer::from(10u32).pow(12)),
381    ///     -65537000000000000i64
382    /// );
383    /// ```
384    #[inline]
385    fn sub_mul(mut self, y: Self, z: Self) -> Self {
386        self.sub_mul_assign(y, z);
387        self
388    }
389}
390
391impl<'a> SubMul<Self, &'a Self> for Integer {
392    type Output = Self;
393
394    /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first two by
395    /// value and the third by reference.
396    ///
397    /// $f(x, y, z) = x - yz$.
398    ///
399    /// # Worst-case complexity
400    /// $T(n, m) = O(m + n \log n \log\log n)$
401    ///
402    /// $M(n) = O(n \log n)$
403    ///
404    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
405    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
406    ///
407    /// # Examples
408    /// ```
409    /// use malachite_base::num::arithmetic::traits::{Pow, SubMul};
410    /// use malachite_nz::integer::Integer;
411    ///
412    /// assert_eq!(
413    ///     Integer::from(10u32).sub_mul(Integer::from(3u32), &Integer::from(-4)),
414    ///     22
415    /// );
416    /// assert_eq!(
417    ///     (-Integer::from(10u32).pow(12))
418    ///         .sub_mul(Integer::from(-0x10000), &-Integer::from(10u32).pow(12)),
419    ///     -65537000000000000i64
420    /// );
421    /// ```
422    #[inline]
423    fn sub_mul(mut self, y: Self, z: &'a Self) -> Self {
424        self.sub_mul_assign(y, z);
425        self
426    }
427}
428
429impl<'a> SubMul<&'a Self, Self> for Integer {
430    type Output = Self;
431
432    /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first and
433    /// third by value and the second by reference.
434    ///
435    /// $f(x, y, z) = x - yz$.
436    ///
437    /// # Worst-case complexity
438    /// $T(n, m) = O(m + n \log n \log\log n)$
439    ///
440    /// $M(n) = O(n \log n)$
441    ///
442    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
443    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
444    ///
445    /// # Examples
446    /// ```
447    /// use malachite_base::num::arithmetic::traits::{Pow, SubMul};
448    /// use malachite_nz::integer::Integer;
449    ///
450    /// assert_eq!(
451    ///     Integer::from(10u32).sub_mul(&Integer::from(3u32), Integer::from(-4)),
452    ///     22
453    /// );
454    /// assert_eq!(
455    ///     (-Integer::from(10u32).pow(12))
456    ///         .sub_mul(&Integer::from(-0x10000), -Integer::from(10u32).pow(12)),
457    ///     -65537000000000000i64
458    /// );
459    /// ```
460    #[inline]
461    fn sub_mul(mut self, y: &'a Self, z: Self) -> Self {
462        self.sub_mul_assign(y, z);
463        self
464    }
465}
466
467impl SubMul<&Self, &Self> for Integer {
468    type Output = Self;
469
470    /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first by value
471    /// and the second and third by reference.
472    ///
473    /// $f(x, y, z) = x - yz$.
474    ///
475    /// # Worst-case complexity
476    /// $T(n, m) = O(m + n \log n \log\log n)$
477    ///
478    /// $M(n) = O(n \log n)$
479    ///
480    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
481    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
482    ///
483    /// # Examples
484    /// ```
485    /// use malachite_base::num::arithmetic::traits::{Pow, SubMul};
486    /// use malachite_nz::integer::Integer;
487    ///
488    /// assert_eq!(
489    ///     Integer::from(10u32).sub_mul(&Integer::from(3u32), &Integer::from(-4)),
490    ///     22
491    /// );
492    /// assert_eq!(
493    ///     (-Integer::from(10u32).pow(12))
494    ///         .sub_mul(&Integer::from(-0x10000), &-Integer::from(10u32).pow(12)),
495    ///     -65537000000000000i64
496    /// );
497    /// ```
498    #[inline]
499    fn sub_mul(mut self, y: &Self, z: &Self) -> Self {
500        self.sub_mul_assign(y, z);
501        self
502    }
503}
504
505impl SubMul<&Integer, &Integer> for &Integer {
506    type Output = Integer;
507
508    /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking all three by
509    /// reference.
510    ///
511    /// $f(x, y, z) = x - yz$.
512    ///
513    /// # Worst-case complexity
514    /// $T(n, m) = O(m + n \log n \log\log n)$
515    ///
516    /// $M(n, m) = O(m + n \log n)$
517    ///
518    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
519    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
520    ///
521    /// # Examples
522    /// ```
523    /// use malachite_base::num::arithmetic::traits::{Pow, SubMul};
524    /// use malachite_nz::integer::Integer;
525    ///
526    /// assert_eq!(
527    ///     (&Integer::from(10u32)).sub_mul(&Integer::from(3u32), &Integer::from(-4)),
528    ///     22
529    /// );
530    /// assert_eq!(
531    ///     (&-Integer::from(10u32).pow(12))
532    ///         .sub_mul(&Integer::from(-0x10000), &-Integer::from(10u32).pow(12)),
533    ///     -65537000000000000i64
534    /// );
535    /// ```
536    fn sub_mul(self, y: &Integer, z: &Integer) -> Integer {
537        if self.sign == (y.sign != z.sign) {
538            Integer {
539                sign: self.sign,
540                abs: (&self.abs).add_mul(&y.abs, &z.abs),
541            }
542        } else {
543            let (abs, abs_result_sign) = self.abs.add_mul_neg(&y.abs, &z.abs);
544            Integer {
545                sign: (self.sign == abs_result_sign) || abs == 0,
546                abs,
547            }
548        }
549    }
550}
551
552impl SubMulAssign<Self, Self> for Integer {
553    /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking both
554    /// [`Integer`]s on the right-hand side by value.
555    ///
556    /// $x \gets x - yz$.
557    ///
558    /// # Worst-case complexity
559    /// $T(n, m) = O(m + n \log n \log\log n)$
560    ///
561    /// $M(n) = O(n \log n)$
562    ///
563    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
564    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
565    ///
566    /// # Examples
567    /// ```
568    /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign};
569    /// use malachite_nz::integer::Integer;
570    ///
571    /// let mut x = Integer::from(10u32);
572    /// x.sub_mul_assign(Integer::from(3u32), Integer::from(-4));
573    /// assert_eq!(x, 22);
574    ///
575    /// let mut x = -Integer::from(10u32).pow(12);
576    /// x.sub_mul_assign(Integer::from(-0x10000), -Integer::from(10u32).pow(12));
577    /// assert_eq!(x, -65537000000000000i64);
578    /// ```
579    fn sub_mul_assign(&mut self, y: Self, z: Self) {
580        self.add_mul_assign(-y, z);
581    }
582}
583
584impl<'a> SubMulAssign<Self, &'a Self> for Integer {
585    /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking the
586    /// first [`Integer`] on the right-hand side by value and the second by reference.
587    ///
588    /// $x \gets x - yz$.
589    ///
590    /// # Worst-case complexity
591    /// $T(n, m) = O(m + n \log n \log\log n)$
592    ///
593    /// $M(n) = O(n \log n)$
594    ///
595    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
596    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
597    ///
598    /// # Examples
599    /// ```
600    /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign};
601    /// use malachite_nz::integer::Integer;
602    ///
603    /// let mut x = Integer::from(10u32);
604    /// x.sub_mul_assign(Integer::from(3u32), &Integer::from(-4));
605    /// assert_eq!(x, 22);
606    ///
607    /// let mut x = -Integer::from(10u32).pow(12);
608    /// x.sub_mul_assign(Integer::from(-0x10000), &(-Integer::from(10u32).pow(12)));
609    /// assert_eq!(x, -65537000000000000i64);
610    /// ```
611    fn sub_mul_assign(&mut self, y: Self, z: &'a Self) {
612        self.add_mul_assign(-y, z);
613    }
614}
615
616impl<'a> SubMulAssign<&'a Self, Self> for Integer {
617    /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking the
618    /// first [`Integer`] on the right-hand side by reference and the second by value.
619    ///
620    /// $x \gets x + yz$.
621    ///
622    /// # Worst-case complexity
623    /// $T(n, m) = O(m + n \log n \log\log n)$
624    ///
625    /// $M(n) = O(n \log n)$
626    ///
627    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
628    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
629    ///
630    /// # Examples
631    /// ```
632    /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign};
633    /// use malachite_nz::integer::Integer;
634    ///
635    /// let mut x = Integer::from(10u32);
636    /// x.sub_mul_assign(&Integer::from(3u32), Integer::from(-4));
637    /// assert_eq!(x, 22);
638    ///
639    /// let mut x = -Integer::from(10u32).pow(12);
640    /// x.sub_mul_assign(&Integer::from(-0x10000), -Integer::from(10u32).pow(12));
641    /// assert_eq!(x, -65537000000000000i64);
642    /// ```
643    fn sub_mul_assign(&mut self, y: &'a Self, z: Self) {
644        self.add_mul_assign(y, -z);
645    }
646}
647
648impl<'a, 'b> SubMulAssign<&'a Self, &'b Self> for Integer {
649    /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking both
650    /// [`Integer`]s on the right-hand side by reference.
651    ///
652    /// $x \gets x - yz$.
653    ///
654    /// # Worst-case complexity
655    /// $T(n, m) = O(m + n \log n \log\log n)$
656    ///
657    /// $M(n) = O(n \log n)$
658    ///
659    /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(),
660    /// z.significant_bits())`, and $m$ is `self.significant_bits()`.
661    ///
662    /// # Examples
663    /// ```
664    /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign};
665    /// use malachite_nz::integer::Integer;
666    ///
667    /// let mut x = Integer::from(10u32);
668    /// x.sub_mul_assign(&Integer::from(3u32), &Integer::from(-4));
669    /// assert_eq!(x, 22);
670    ///
671    /// let mut x = -Integer::from(10u32).pow(12);
672    /// x.sub_mul_assign(&Integer::from(-0x10000), &(-Integer::from(10u32).pow(12)));
673    /// assert_eq!(x, -65537000000000000i64);
674    /// ```
675    fn sub_mul_assign(&mut self, y: &'a Self, z: &'b Self) {
676        self.neg_assign();
677        self.add_mul_assign(y, z);
678        self.neg_assign();
679    }
680}