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