malachite_nz/integer/arithmetic/
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 alloc::vec::Vec;
11use core::iter::Product;
12use core::ops::{Mul, MulAssign};
13use malachite_base::num::basic::traits::{One, Zero};
14
15impl Mul<Integer> for Integer {
16    type Output = Integer;
17
18    /// Multiplies two [`Integer`]s, taking both by value.
19    ///
20    /// $$
21    /// f(x, y) = xy.
22    /// $$
23    ///
24    /// # Worst-case complexity
25    /// $T(n) = O(n \log n \log\log n)$
26    ///
27    /// $M(n) = O(n \log n)$
28    ///
29    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
30    /// other.significant_bits())`.
31    ///
32    /// # Examples
33    /// ```
34    /// use malachite_base::num::basic::traits::{One, Zero};
35    /// use malachite_nz::integer::Integer;
36    ///
37    /// assert_eq!(Integer::ONE * Integer::from(123), 123);
38    /// assert_eq!(Integer::from(123) * Integer::ZERO, 0);
39    /// assert_eq!(Integer::from(123) * Integer::from(-456), -56088);
40    /// assert_eq!(
41    ///     (Integer::from(-123456789000i64) * Integer::from(-987654321000i64)).to_string(),
42    ///     "121932631112635269000000"
43    /// );
44    /// ```
45    fn mul(mut self, other: Integer) -> Integer {
46        self *= other;
47        self
48    }
49}
50
51impl Mul<&Integer> for Integer {
52    type Output = Integer;
53
54    /// Multiplies two [`Integer`]s, taking the first by value and the second by reference.
55    ///
56    /// $$
57    /// f(x, y) = xy.
58    /// $$
59    ///
60    /// # Worst-case complexity
61    /// $T(n) = O(n \log n \log\log n)$
62    ///
63    /// $M(n) = O(n \log n)$
64    ///
65    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
66    /// other.significant_bits())`.
67    ///
68    /// # Examples
69    /// ```
70    /// use malachite_base::num::basic::traits::{One, Zero};
71    /// use malachite_nz::integer::Integer;
72    ///
73    /// assert_eq!(Integer::ONE * &Integer::from(123), 123);
74    /// assert_eq!(Integer::from(123) * &Integer::ZERO, 0);
75    /// assert_eq!(Integer::from(123) * &Integer::from(-456), -56088);
76    /// assert_eq!(
77    ///     (Integer::from(-123456789000i64) * &Integer::from(-987654321000i64)).to_string(),
78    ///     "121932631112635269000000"
79    /// );
80    /// ```
81    fn mul(mut self, other: &Integer) -> Integer {
82        self *= other;
83        self
84    }
85}
86
87impl Mul<Integer> for &Integer {
88    type Output = Integer;
89
90    /// Multiplies two [`Integer`]s, taking the first by reference and the second by value.
91    ///
92    /// $$
93    /// f(x, y) = xy.
94    /// $$
95    ///
96    /// # Worst-case complexity
97    /// $T(n) = O(n \log n \log\log n)$
98    ///
99    /// $M(n) = O(n \log n)$
100    ///
101    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
102    /// other.significant_bits())`.
103    ///
104    /// # Examples
105    /// ```
106    /// use malachite_base::num::basic::traits::{One, Zero};
107    /// use malachite_nz::integer::Integer;
108    ///
109    /// assert_eq!(&Integer::ONE * Integer::from(123), 123);
110    /// assert_eq!(&Integer::from(123) * Integer::ZERO, 0);
111    /// assert_eq!(&Integer::from(123) * Integer::from(-456), -56088);
112    /// assert_eq!(
113    ///     (&Integer::from(-123456789000i64) * Integer::from(-987654321000i64)).to_string(),
114    ///     "121932631112635269000000"
115    /// );
116    /// ```
117    fn mul(self, mut other: Integer) -> Integer {
118        other *= self;
119        other
120    }
121}
122
123impl Mul<&Integer> for &Integer {
124    type Output = Integer;
125
126    /// Multiplies two [`Integer`]s, taking both by reference.
127    ///
128    /// $$
129    /// f(x, y) = xy.
130    /// $$
131    ///
132    /// # Worst-case complexity
133    /// $T(n) = O(n \log n \log\log n)$
134    ///
135    /// $M(n) = O(n \log n)$
136    ///
137    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
138    /// other.significant_bits())`.
139    ///
140    /// # Examples
141    /// ```
142    /// use malachite_base::num::basic::traits::{One, Zero};
143    /// use malachite_nz::integer::Integer;
144    ///
145    /// assert_eq!(&Integer::ONE * &Integer::from(123), 123);
146    /// assert_eq!(&Integer::from(123) * &Integer::ZERO, 0);
147    /// assert_eq!(&Integer::from(123) * &Integer::from(-456), -56088);
148    /// assert_eq!(
149    ///     (&Integer::from(-123456789000i64) * &Integer::from(-987654321000i64)).to_string(),
150    ///     "121932631112635269000000"
151    /// );
152    /// ```
153    fn mul(self, other: &Integer) -> Integer {
154        let product_abs = &self.abs * &other.abs;
155        Integer {
156            sign: self.sign == other.sign || product_abs == 0,
157            abs: product_abs,
158        }
159    }
160}
161
162impl MulAssign<Integer> for Integer {
163    /// Multiplies an [`Integer`] by an [`Integer`] in place, taking the [`Integer`] on the
164    /// right-hand side by value.
165    ///
166    /// $$
167    /// x \gets = xy.
168    /// $$
169    ///
170    /// # Worst-case complexity
171    /// $T(n) = O(n \log n \log\log n)$
172    ///
173    /// $M(n) = O(n \log n)$
174    ///
175    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
176    /// other.significant_bits())`.
177    ///
178    /// # Examples
179    /// ```
180    /// use malachite_base::num::basic::traits::NegativeOne;
181    /// use malachite_nz::integer::Integer;
182    ///
183    /// let mut x = Integer::NEGATIVE_ONE;
184    /// x *= Integer::from(1000);
185    /// x *= Integer::from(2000);
186    /// x *= Integer::from(3000);
187    /// x *= Integer::from(4000);
188    /// assert_eq!(x, -24000000000000i64);
189    /// ```
190    fn mul_assign(&mut self, other: Integer) {
191        self.abs *= other.abs;
192        self.sign = self.sign == other.sign || self.abs == 0;
193    }
194}
195
196impl MulAssign<&Integer> for Integer {
197    /// Multiplies an [`Integer`] by an [`Integer`] in place, taking the [`Integer`] on the
198    /// right-hand side by reference.
199    ///
200    /// $$
201    /// x \gets = xy.
202    /// $$
203    ///
204    /// # Worst-case complexity
205    /// $T(n) = O(n \log n \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::NegativeOne;
215    /// use malachite_nz::integer::Integer;
216    ///
217    /// let mut x = Integer::NEGATIVE_ONE;
218    /// x *= &Integer::from(1000);
219    /// x *= &Integer::from(2000);
220    /// x *= &Integer::from(3000);
221    /// x *= &Integer::from(4000);
222    /// assert_eq!(x, -24000000000000i64);
223    /// ```
224    fn mul_assign(&mut self, other: &Integer) {
225        self.abs *= &other.abs;
226        self.sign = self.sign == other.sign || self.abs == 0;
227    }
228}
229
230impl Product for Integer {
231    /// Multiplies together all the [`Integer`]s in an iterator.
232    ///
233    /// $$
234    /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i.
235    /// $$
236    ///
237    /// # Worst-case complexity
238    /// $T(n) = O(n (\log n)^2 \log\log n)$
239    ///
240    /// $M(n) = O(n \log n)$
241    ///
242    /// where $T$ is time, $M$ is additional memory, and $n$ is
243    /// `Integer::sum(xs.map(Integer::significant_bits))`.
244    ///
245    /// # Examples
246    /// ```
247    /// use core::iter::Product;
248    /// use malachite_base::vecs::vec_from_str;
249    /// use malachite_nz::integer::Integer;
250    ///
251    /// assert_eq!(
252    ///     Integer::product(
253    ///         vec_from_str::<Integer>("[2, -3, 5, 7]")
254    ///             .unwrap()
255    ///             .into_iter()
256    ///     ),
257    ///     -210
258    /// );
259    /// ```
260    fn product<I>(xs: I) -> Integer
261    where
262        I: Iterator<Item = Integer>,
263    {
264        let mut stack = Vec::new();
265        for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) {
266            if x == 0 {
267                return Integer::ZERO;
268            }
269            let mut p = x;
270            for _ in 0..i.trailing_zeros() {
271                p *= stack.pop().unwrap();
272            }
273            stack.push(p);
274        }
275        let mut p = Integer::ONE;
276        for x in stack.into_iter().rev() {
277            p *= x;
278        }
279        p
280    }
281}
282
283impl<'a> Product<&'a Integer> for Integer {
284    /// Multiplies together all the [`Integer`]s in an iterator of [`Integer`] references.
285    ///
286    /// $$
287    /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i.
288    /// $$
289    ///
290    /// # Worst-case complexity
291    /// $T(n) = O(n (\log n)^2 \log\log n)$
292    ///
293    /// $M(n) = O(n \log n)$
294    ///
295    /// where $T$ is time, $M$ is additional memory, and $n$ is
296    /// `Integer::sum(xs.map(Integer::significant_bits))`.
297    ///
298    /// # Examples
299    /// ```
300    /// use core::iter::Product;
301    /// use malachite_base::vecs::vec_from_str;
302    /// use malachite_nz::integer::Integer;
303    ///
304    /// assert_eq!(
305    ///     Integer::product(vec_from_str::<Integer>("[2, -3, 5, 7]").unwrap().iter()),
306    ///     -210
307    /// );
308    /// ```
309    fn product<I>(xs: I) -> Integer
310    where
311        I: Iterator<Item = &'a Integer>,
312    {
313        let mut stack = Vec::new();
314        for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) {
315            if *x == 0 {
316                return Integer::ZERO;
317            }
318            let mut p = x.clone();
319            for _ in 0..i.trailing_zeros() {
320                p *= stack.pop().unwrap();
321            }
322            stack.push(p);
323        }
324        let mut p = Integer::ONE;
325        for x in stack.into_iter().rev() {
326            p *= x;
327        }
328        p
329    }
330}