/rust/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.6/src/biguint/multiplication.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use super::addition::{__add2, add2}; |
2 | | use super::subtraction::sub2; |
3 | | use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits}; |
4 | | |
5 | | use crate::big_digit::{self, BigDigit, DoubleBigDigit}; |
6 | | use crate::Sign::{self, Minus, NoSign, Plus}; |
7 | | use crate::{BigInt, UsizePromotion}; |
8 | | |
9 | | use core::cmp::Ordering; |
10 | | use core::iter::Product; |
11 | | use core::ops::{Mul, MulAssign}; |
12 | | use num_traits::{CheckedMul, FromPrimitive, One, Zero}; |
13 | | |
14 | | #[inline] |
15 | 0 | pub(super) fn mac_with_carry( |
16 | 0 | a: BigDigit, |
17 | 0 | b: BigDigit, |
18 | 0 | c: BigDigit, |
19 | 0 | acc: &mut DoubleBigDigit, |
20 | 0 | ) -> BigDigit { |
21 | 0 | *acc += DoubleBigDigit::from(a); |
22 | 0 | *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c); |
23 | 0 | let lo = *acc as BigDigit; |
24 | 0 | *acc >>= big_digit::BITS; |
25 | 0 | lo |
26 | 0 | } |
27 | | |
28 | | #[inline] |
29 | 0 | fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { |
30 | 0 | *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b); |
31 | 0 | let lo = *acc as BigDigit; |
32 | 0 | *acc >>= big_digit::BITS; |
33 | 0 | lo |
34 | 0 | } |
35 | | |
36 | | /// Three argument multiply accumulate: |
37 | | /// acc += b * c |
38 | 0 | fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { |
39 | 0 | if c == 0 { |
40 | 0 | return; |
41 | 0 | } |
42 | 0 |
|
43 | 0 | let mut carry = 0; |
44 | 0 | let (a_lo, a_hi) = acc.split_at_mut(b.len()); |
45 | | |
46 | 0 | for (a, &b) in a_lo.iter_mut().zip(b) { |
47 | 0 | *a = mac_with_carry(*a, b, c, &mut carry); |
48 | 0 | } |
49 | | |
50 | 0 | let (carry_hi, carry_lo) = big_digit::from_doublebigdigit(carry); |
51 | | |
52 | 0 | let final_carry = if carry_hi == 0 { |
53 | 0 | __add2(a_hi, &[carry_lo]) |
54 | | } else { |
55 | 0 | __add2(a_hi, &[carry_hi, carry_lo]) |
56 | | }; |
57 | 0 | assert_eq!(final_carry, 0, "carry overflow during multiplication!"); |
58 | 0 | } |
59 | | |
60 | 0 | fn bigint_from_slice(slice: &[BigDigit]) -> BigInt { |
61 | 0 | BigInt::from(biguint_from_vec(slice.to_vec())) |
62 | 0 | } |
63 | | |
64 | | /// Three argument multiply accumulate: |
65 | | /// acc += b * c |
66 | | #[allow(clippy::many_single_char_names)] |
67 | 0 | fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { |
68 | 0 | // Least-significant zeros have no effect on the output. |
69 | 0 | if let Some(&0) = b.first() { |
70 | 0 | if let Some(nz) = b.iter().position(|&d| d != 0) { |
71 | 0 | b = &b[nz..]; |
72 | 0 | acc = &mut acc[nz..]; |
73 | 0 | } else { |
74 | 0 | return; |
75 | | } |
76 | 0 | } |
77 | 0 | if let Some(&0) = c.first() { |
78 | 0 | if let Some(nz) = c.iter().position(|&d| d != 0) { |
79 | 0 | c = &c[nz..]; |
80 | 0 | acc = &mut acc[nz..]; |
81 | 0 | } else { |
82 | 0 | return; |
83 | | } |
84 | 0 | } |
85 | | |
86 | 0 | let acc = acc; |
87 | 0 | let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) }; |
88 | | |
89 | | // We use four algorithms for different input sizes. |
90 | | // |
91 | | // - For small inputs, long multiplication is fastest. |
92 | | // - If y is at least least twice as long as x, split using Half-Karatsuba. |
93 | | // - Next we use Karatsuba multiplication (Toom-2), which we have optimized |
94 | | // to avoid unnecessary allocations for intermediate values. |
95 | | // - For the largest inputs we use Toom-3, which better optimizes the |
96 | | // number of operations, but uses more temporary allocations. |
97 | | // |
98 | | // The thresholds are somewhat arbitrary, chosen by evaluating the results |
99 | | // of `cargo bench --bench bigint multiply`. |
100 | | |
101 | 0 | if x.len() <= 32 { |
102 | | // Long multiplication: |
103 | 0 | for (i, xi) in x.iter().enumerate() { |
104 | 0 | mac_digit(&mut acc[i..], y, *xi); |
105 | 0 | } |
106 | 0 | } else if x.len() * 2 <= y.len() { |
107 | 0 | // Karatsuba Multiplication for factors with significant length disparity. |
108 | 0 | // |
109 | 0 | // The Half-Karatsuba Multiplication Algorithm is a specialized case of |
110 | 0 | // the normal Karatsuba multiplication algorithm, designed for the scenario |
111 | 0 | // where y has at least twice as many base digits as x. |
112 | 0 | // |
113 | 0 | // In this case y (the longer input) is split into high2 and low2, |
114 | 0 | // at m2 (half the length of y) and x (the shorter input), |
115 | 0 | // is used directly without splitting. |
116 | 0 | // |
117 | 0 | // The algorithm then proceeds as follows: |
118 | 0 | // |
119 | 0 | // 1. Compute the product z0 = x * low2. |
120 | 0 | // 2. Compute the product temp = x * high2. |
121 | 0 | // 3. Adjust the weight of temp by adding m2 (* NBASE ^ m2) |
122 | 0 | // 4. Add temp and z0 to obtain the final result. |
123 | 0 | // |
124 | 0 | // Proof: |
125 | 0 | // |
126 | 0 | // The algorithm can be derived from the original Karatsuba algorithm by |
127 | 0 | // simplifying the formula when the shorter factor x is not split into |
128 | 0 | // high and low parts, as shown below. |
129 | 0 | // |
130 | 0 | // Original Karatsuba formula: |
131 | 0 | // |
132 | 0 | // result = (z2 * NBASE ^ (m2 × 2)) + ((z1 - z2 - z0) * NBASE ^ m2) + z0 |
133 | 0 | // |
134 | 0 | // Substitutions: |
135 | 0 | // |
136 | 0 | // low1 = x |
137 | 0 | // high1 = 0 |
138 | 0 | // |
139 | 0 | // Applying substitutions: |
140 | 0 | // |
141 | 0 | // z0 = (low1 * low2) |
142 | 0 | // = (x * low2) |
143 | 0 | // |
144 | 0 | // z1 = ((low1 + high1) * (low2 + high2)) |
145 | 0 | // = ((x + 0) * (low2 + high2)) |
146 | 0 | // = (x * low2) + (x * high2) |
147 | 0 | // |
148 | 0 | // z2 = (high1 * high2) |
149 | 0 | // = (0 * high2) |
150 | 0 | // = 0 |
151 | 0 | // |
152 | 0 | // Simplified using the above substitutions: |
153 | 0 | // |
154 | 0 | // result = (z2 * NBASE ^ (m2 × 2)) + ((z1 - z2 - z0) * NBASE ^ m2) + z0 |
155 | 0 | // = (0 * NBASE ^ (m2 × 2)) + ((z1 - 0 - z0) * NBASE ^ m2) + z0 |
156 | 0 | // = ((z1 - z0) * NBASE ^ m2) + z0 |
157 | 0 | // = ((z1 - z0) * NBASE ^ m2) + z0 |
158 | 0 | // = (x * high2) * NBASE ^ m2 + z0 |
159 | 0 | let m2 = y.len() / 2; |
160 | 0 | let (low2, high2) = y.split_at(m2); |
161 | 0 |
|
162 | 0 | // (x * high2) * NBASE ^ m2 + z0 |
163 | 0 | mac3(acc, x, low2); |
164 | 0 | mac3(&mut acc[m2..], x, high2); |
165 | 0 | } else if x.len() <= 256 { |
166 | | // Karatsuba multiplication: |
167 | | // |
168 | | // The idea is that we break x and y up into two smaller numbers that each have about half |
169 | | // as many digits, like so (note that multiplying by b is just a shift): |
170 | | // |
171 | | // x = x0 + x1 * b |
172 | | // y = y0 + y1 * b |
173 | | // |
174 | | // With some algebra, we can compute x * y with three smaller products, where the inputs to |
175 | | // each of the smaller products have only about half as many digits as x and y: |
176 | | // |
177 | | // x * y = (x0 + x1 * b) * (y0 + y1 * b) |
178 | | // |
179 | | // x * y = x0 * y0 |
180 | | // + x0 * y1 * b |
181 | | // + x1 * y0 * b |
182 | | // + x1 * y1 * b^2 |
183 | | // |
184 | | // Let p0 = x0 * y0 and p2 = x1 * y1: |
185 | | // |
186 | | // x * y = p0 |
187 | | // + (x0 * y1 + x1 * y0) * b |
188 | | // + p2 * b^2 |
189 | | // |
190 | | // The real trick is that middle term: |
191 | | // |
192 | | // x0 * y1 + x1 * y0 |
193 | | // |
194 | | // = x0 * y1 + x1 * y0 - p0 + p0 - p2 + p2 |
195 | | // |
196 | | // = x0 * y1 + x1 * y0 - x0 * y0 - x1 * y1 + p0 + p2 |
197 | | // |
198 | | // Now we complete the square: |
199 | | // |
200 | | // = -(x0 * y0 - x0 * y1 - x1 * y0 + x1 * y1) + p0 + p2 |
201 | | // |
202 | | // = -((x1 - x0) * (y1 - y0)) + p0 + p2 |
203 | | // |
204 | | // Let p1 = (x1 - x0) * (y1 - y0), and substitute back into our original formula: |
205 | | // |
206 | | // x * y = p0 |
207 | | // + (p0 + p2 - p1) * b |
208 | | // + p2 * b^2 |
209 | | // |
210 | | // Where the three intermediate products are: |
211 | | // |
212 | | // p0 = x0 * y0 |
213 | | // p1 = (x1 - x0) * (y1 - y0) |
214 | | // p2 = x1 * y1 |
215 | | // |
216 | | // In doing the computation, we take great care to avoid unnecessary temporary variables |
217 | | // (since creating a BigUint requires a heap allocation): thus, we rearrange the formula a |
218 | | // bit so we can use the same temporary variable for all the intermediate products: |
219 | | // |
220 | | // x * y = p2 * b^2 + p2 * b |
221 | | // + p0 * b + p0 |
222 | | // - p1 * b |
223 | | // |
224 | | // The other trick we use is instead of doing explicit shifts, we slice acc at the |
225 | | // appropriate offset when doing the add. |
226 | | |
227 | | // When x is smaller than y, it's significantly faster to pick b such that x is split in |
228 | | // half, not y: |
229 | 0 | let b = x.len() / 2; |
230 | 0 | let (x0, x1) = x.split_at(b); |
231 | 0 | let (y0, y1) = y.split_at(b); |
232 | 0 |
|
233 | 0 | // We reuse the same BigUint for all the intermediate multiplies and have to size p |
234 | 0 | // appropriately here: x1.len() >= x0.len and y1.len() >= y0.len(): |
235 | 0 | let len = x1.len() + y1.len() + 1; |
236 | 0 | let mut p = BigUint { data: vec![0; len] }; |
237 | 0 |
|
238 | 0 | // p2 = x1 * y1 |
239 | 0 | mac3(&mut p.data, x1, y1); |
240 | 0 |
|
241 | 0 | // Not required, but the adds go faster if we drop any unneeded 0s from the end: |
242 | 0 | p.normalize(); |
243 | 0 |
|
244 | 0 | add2(&mut acc[b..], &p.data); |
245 | 0 | add2(&mut acc[b * 2..], &p.data); |
246 | 0 |
|
247 | 0 | // Zero out p before the next multiply: |
248 | 0 | p.data.truncate(0); |
249 | 0 | p.data.resize(len, 0); |
250 | 0 |
|
251 | 0 | // p0 = x0 * y0 |
252 | 0 | mac3(&mut p.data, x0, y0); |
253 | 0 | p.normalize(); |
254 | 0 |
|
255 | 0 | add2(acc, &p.data); |
256 | 0 | add2(&mut acc[b..], &p.data); |
257 | 0 |
|
258 | 0 | // p1 = (x1 - x0) * (y1 - y0) |
259 | 0 | // We do this one last, since it may be negative and acc can't ever be negative: |
260 | 0 | let (j0_sign, j0) = sub_sign(x1, x0); |
261 | 0 | let (j1_sign, j1) = sub_sign(y1, y0); |
262 | 0 |
|
263 | 0 | match j0_sign * j1_sign { |
264 | 0 | Plus => { |
265 | 0 | p.data.truncate(0); |
266 | 0 | p.data.resize(len, 0); |
267 | 0 |
|
268 | 0 | mac3(&mut p.data, &j0.data, &j1.data); |
269 | 0 | p.normalize(); |
270 | 0 |
|
271 | 0 | sub2(&mut acc[b..], &p.data); |
272 | 0 | } |
273 | 0 | Minus => { |
274 | 0 | mac3(&mut acc[b..], &j0.data, &j1.data); |
275 | 0 | } |
276 | 0 | NoSign => (), |
277 | | } |
278 | | } else { |
279 | | // Toom-3 multiplication: |
280 | | // |
281 | | // Toom-3 is like Karatsuba above, but dividing the inputs into three parts. |
282 | | // Both are instances of Toom-Cook, using `k=3` and `k=2` respectively. |
283 | | // |
284 | | // The general idea is to treat the large integers digits as |
285 | | // polynomials of a certain degree and determine the coefficients/digits |
286 | | // of the product of the two via interpolation of the polynomial product. |
287 | 0 | let i = y.len() / 3 + 1; |
288 | 0 |
|
289 | 0 | let x0_len = Ord::min(x.len(), i); |
290 | 0 | let x1_len = Ord::min(x.len() - x0_len, i); |
291 | 0 |
|
292 | 0 | let y0_len = i; |
293 | 0 | let y1_len = Ord::min(y.len() - y0_len, i); |
294 | 0 |
|
295 | 0 | // Break x and y into three parts, representating an order two polynomial. |
296 | 0 | // t is chosen to be the size of a digit so we can use faster shifts |
297 | 0 | // in place of multiplications. |
298 | 0 | // |
299 | 0 | // x(t) = x2*t^2 + x1*t + x0 |
300 | 0 | let x0 = bigint_from_slice(&x[..x0_len]); |
301 | 0 | let x1 = bigint_from_slice(&x[x0_len..x0_len + x1_len]); |
302 | 0 | let x2 = bigint_from_slice(&x[x0_len + x1_len..]); |
303 | 0 |
|
304 | 0 | // y(t) = y2*t^2 + y1*t + y0 |
305 | 0 | let y0 = bigint_from_slice(&y[..y0_len]); |
306 | 0 | let y1 = bigint_from_slice(&y[y0_len..y0_len + y1_len]); |
307 | 0 | let y2 = bigint_from_slice(&y[y0_len + y1_len..]); |
308 | 0 |
|
309 | 0 | // Let w(t) = x(t) * y(t) |
310 | 0 | // |
311 | 0 | // This gives us the following order-4 polynomial. |
312 | 0 | // |
313 | 0 | // w(t) = w4*t^4 + w3*t^3 + w2*t^2 + w1*t + w0 |
314 | 0 | // |
315 | 0 | // We need to find the coefficients w4, w3, w2, w1 and w0. Instead |
316 | 0 | // of simply multiplying the x and y in total, we can evaluate w |
317 | 0 | // at 5 points. An n-degree polynomial is uniquely identified by (n + 1) |
318 | 0 | // points. |
319 | 0 | // |
320 | 0 | // It is arbitrary as to what points we evaluate w at but we use the |
321 | 0 | // following. |
322 | 0 | // |
323 | 0 | // w(t) at t = 0, 1, -1, -2 and inf |
324 | 0 | // |
325 | 0 | // The values for w(t) in terms of x(t)*y(t) at these points are: |
326 | 0 | // |
327 | 0 | // let a = w(0) = x0 * y0 |
328 | 0 | // let b = w(1) = (x2 + x1 + x0) * (y2 + y1 + y0) |
329 | 0 | // let c = w(-1) = (x2 - x1 + x0) * (y2 - y1 + y0) |
330 | 0 | // let d = w(-2) = (4*x2 - 2*x1 + x0) * (4*y2 - 2*y1 + y0) |
331 | 0 | // let e = w(inf) = x2 * y2 as t -> inf |
332 | 0 |
|
333 | 0 | // x0 + x2, avoiding temporaries |
334 | 0 | let p = &x0 + &x2; |
335 | 0 |
|
336 | 0 | // y0 + y2, avoiding temporaries |
337 | 0 | let q = &y0 + &y2; |
338 | 0 |
|
339 | 0 | // x2 - x1 + x0, avoiding temporaries |
340 | 0 | let p2 = &p - &x1; |
341 | 0 |
|
342 | 0 | // y2 - y1 + y0, avoiding temporaries |
343 | 0 | let q2 = &q - &y1; |
344 | 0 |
|
345 | 0 | // w(0) |
346 | 0 | let r0 = &x0 * &y0; |
347 | 0 |
|
348 | 0 | // w(inf) |
349 | 0 | let r4 = &x2 * &y2; |
350 | 0 |
|
351 | 0 | // w(1) |
352 | 0 | let r1 = (p + x1) * (q + y1); |
353 | 0 |
|
354 | 0 | // w(-1) |
355 | 0 | let r2 = &p2 * &q2; |
356 | 0 |
|
357 | 0 | // w(-2) |
358 | 0 | let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0); |
359 | 0 |
|
360 | 0 | // Evaluating these points gives us the following system of linear equations. |
361 | 0 | // |
362 | 0 | // 0 0 0 0 1 | a |
363 | 0 | // 1 1 1 1 1 | b |
364 | 0 | // 1 -1 1 -1 1 | c |
365 | 0 | // 16 -8 4 -2 1 | d |
366 | 0 | // 1 0 0 0 0 | e |
367 | 0 | // |
368 | 0 | // The solved equation (after gaussian elimination or similar) |
369 | 0 | // in terms of its coefficients: |
370 | 0 | // |
371 | 0 | // w0 = w(0) |
372 | 0 | // w1 = w(0)/2 + w(1)/3 - w(-1) + w(-2)/6 - 2*w(inf) |
373 | 0 | // w2 = -w(0) + w(1)/2 + w(-1)/2 - w(inf) |
374 | 0 | // w3 = -w(0)/2 + w(1)/6 + w(-1)/2 - w(-2)/6 + 2*w(inf) |
375 | 0 | // w4 = w(inf) |
376 | 0 | // |
377 | 0 | // This particular sequence is given by Bodrato and is an interpolation |
378 | 0 | // of the above equations. |
379 | 0 | let mut comp3: BigInt = (r3 - &r1) / 3u32; |
380 | 0 | let mut comp1: BigInt = (r1 - &r2) >> 1; |
381 | 0 | let mut comp2: BigInt = r2 - &r0; |
382 | 0 | comp3 = ((&comp2 - comp3) >> 1) + (&r4 << 1); |
383 | 0 | comp2 += &comp1 - &r4; |
384 | 0 | comp1 -= &comp3; |
385 | | |
386 | | // Recomposition. The coefficients of the polynomial are now known. |
387 | | // |
388 | | // Evaluate at w(t) where t is our given base to get the result. |
389 | | // |
390 | | // let bits = u64::from(big_digit::BITS) * i as u64; |
391 | | // let result = r0 |
392 | | // + (comp1 << bits) |
393 | | // + (comp2 << (2 * bits)) |
394 | | // + (comp3 << (3 * bits)) |
395 | | // + (r4 << (4 * bits)); |
396 | | // let result_pos = result.to_biguint().unwrap(); |
397 | | // add2(&mut acc[..], &result_pos.data); |
398 | | // |
399 | | // But with less intermediate copying: |
400 | 0 | for (j, result) in [&r0, &comp1, &comp2, &comp3, &r4].iter().enumerate().rev() { |
401 | 0 | match result.sign() { |
402 | 0 | Plus => add2(&mut acc[i * j..], result.digits()), |
403 | 0 | Minus => sub2(&mut acc[i * j..], result.digits()), |
404 | 0 | NoSign => {} |
405 | | } |
406 | | } |
407 | | } |
408 | 0 | } |
409 | | |
410 | 0 | fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { |
411 | 0 | let len = x.len() + y.len() + 1; |
412 | 0 | let mut prod = BigUint { data: vec![0; len] }; |
413 | 0 |
|
414 | 0 | mac3(&mut prod.data, x, y); |
415 | 0 | prod.normalized() |
416 | 0 | } |
417 | | |
418 | 0 | fn scalar_mul(a: &mut BigUint, b: BigDigit) { |
419 | 0 | match b { |
420 | 0 | 0 => a.set_zero(), |
421 | 0 | 1 => {} |
422 | | _ => { |
423 | 0 | if b.is_power_of_two() { |
424 | 0 | *a <<= b.trailing_zeros(); |
425 | 0 | } else { |
426 | 0 | let mut carry = 0; |
427 | 0 | for a in a.data.iter_mut() { |
428 | 0 | *a = mul_with_carry(*a, b, &mut carry); |
429 | 0 | } |
430 | 0 | if carry != 0 { |
431 | 0 | a.data.push(carry as BigDigit); |
432 | 0 | } |
433 | | } |
434 | | } |
435 | | } |
436 | 0 | } |
437 | | |
438 | 0 | fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { |
439 | 0 | // Normalize: |
440 | 0 | if let Some(&0) = a.last() { |
441 | 0 | a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; |
442 | 0 | } |
443 | 0 | if let Some(&0) = b.last() { |
444 | 0 | b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; |
445 | 0 | } |
446 | | |
447 | 0 | match cmp_slice(a, b) { |
448 | | Ordering::Greater => { |
449 | 0 | let mut a = a.to_vec(); |
450 | 0 | sub2(&mut a, b); |
451 | 0 | (Plus, biguint_from_vec(a)) |
452 | | } |
453 | | Ordering::Less => { |
454 | 0 | let mut b = b.to_vec(); |
455 | 0 | sub2(&mut b, a); |
456 | 0 | (Minus, biguint_from_vec(b)) |
457 | | } |
458 | 0 | Ordering::Equal => (NoSign, BigUint::ZERO), |
459 | | } |
460 | 0 | } |
461 | | |
462 | | macro_rules! impl_mul { |
463 | | ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( |
464 | | impl Mul<$Other> for $Self { |
465 | | type Output = BigUint; |
466 | | |
467 | | #[inline] |
468 | 0 | fn mul(self, other: $Other) -> BigUint { |
469 | 0 | match (&*self.data, &*other.data) { |
470 | 0 | // multiply by zero |
471 | 0 | (&[], _) | (_, &[]) => BigUint::ZERO, |
472 | | // multiply by a scalar |
473 | 0 | (_, &[digit]) => self * digit, |
474 | 0 | (&[digit], _) => other * digit, |
475 | | // full multiplication |
476 | 0 | (x, y) => mul3(x, y), |
477 | | } |
478 | 0 | } Unexecuted instantiation: <num_bigint::biguint::BigUint as core::ops::arith::Mul>::mul Unexecuted instantiation: <num_bigint::biguint::BigUint as core::ops::arith::Mul<&num_bigint::biguint::BigUint>>::mul Unexecuted instantiation: <&num_bigint::biguint::BigUint as core::ops::arith::Mul>::mul Unexecuted instantiation: <&num_bigint::biguint::BigUint as core::ops::arith::Mul<num_bigint::biguint::BigUint>>::mul |
479 | | } |
480 | | )*} |
481 | | } |
482 | | impl_mul! { |
483 | | impl Mul<BigUint> for BigUint; |
484 | | impl Mul<BigUint> for &BigUint; |
485 | | impl Mul<&BigUint> for BigUint; |
486 | | impl Mul<&BigUint> for &BigUint; |
487 | | } |
488 | | |
489 | | macro_rules! impl_mul_assign { |
490 | | ($(impl MulAssign<$Other:ty> for BigUint;)*) => {$( |
491 | | impl MulAssign<$Other> for BigUint { |
492 | | #[inline] |
493 | 0 | fn mul_assign(&mut self, other: $Other) { |
494 | 0 | match (&*self.data, &*other.data) { |
495 | 0 | // multiply by zero |
496 | 0 | (&[], _) => {}, |
497 | 0 | (_, &[]) => self.set_zero(), |
498 | | // multiply by a scalar |
499 | 0 | (_, &[digit]) => *self *= digit, |
500 | 0 | (&[digit], _) => *self = other * digit, |
501 | | // full multiplication |
502 | 0 | (x, y) => *self = mul3(x, y), |
503 | | } |
504 | 0 | } Unexecuted instantiation: <num_bigint::biguint::BigUint as core::ops::arith::MulAssign<&num_bigint::biguint::BigUint>>::mul_assign Unexecuted instantiation: <num_bigint::biguint::BigUint as core::ops::arith::MulAssign>::mul_assign |
505 | | } |
506 | | )*} |
507 | | } |
508 | | impl_mul_assign! { |
509 | | impl MulAssign<BigUint> for BigUint; |
510 | | impl MulAssign<&BigUint> for BigUint; |
511 | | } |
512 | | |
513 | | promote_unsigned_scalars!(impl Mul for BigUint, mul); |
514 | | promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign); |
515 | | forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigUint, mul); |
516 | | forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigUint, mul); |
517 | | forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigUint, mul); |
518 | | |
519 | | impl Mul<u32> for BigUint { |
520 | | type Output = BigUint; |
521 | | |
522 | | #[inline] |
523 | 0 | fn mul(mut self, other: u32) -> BigUint { |
524 | 0 | self *= other; |
525 | 0 | self |
526 | 0 | } |
527 | | } |
528 | | impl MulAssign<u32> for BigUint { |
529 | | #[inline] |
530 | 0 | fn mul_assign(&mut self, other: u32) { |
531 | 0 | scalar_mul(self, other as BigDigit); |
532 | 0 | } |
533 | | } |
534 | | |
535 | | impl Mul<u64> for BigUint { |
536 | | type Output = BigUint; |
537 | | |
538 | | #[inline] |
539 | 0 | fn mul(mut self, other: u64) -> BigUint { |
540 | 0 | self *= other; |
541 | 0 | self |
542 | 0 | } |
543 | | } |
544 | | impl MulAssign<u64> for BigUint { |
545 | | cfg_digit!( |
546 | | #[inline] |
547 | | fn mul_assign(&mut self, other: u64) { |
548 | | if let Some(other) = BigDigit::from_u64(other) { |
549 | | scalar_mul(self, other); |
550 | | } else { |
551 | | let (hi, lo) = big_digit::from_doublebigdigit(other); |
552 | | *self = mul3(&self.data, &[lo, hi]); |
553 | | } |
554 | | } |
555 | | |
556 | | #[inline] |
557 | 0 | fn mul_assign(&mut self, other: u64) { |
558 | 0 | scalar_mul(self, other); |
559 | 0 | } |
560 | | ); |
561 | | } |
562 | | |
563 | | impl Mul<u128> for BigUint { |
564 | | type Output = BigUint; |
565 | | |
566 | | #[inline] |
567 | 0 | fn mul(mut self, other: u128) -> BigUint { |
568 | 0 | self *= other; |
569 | 0 | self |
570 | 0 | } |
571 | | } |
572 | | |
573 | | impl MulAssign<u128> for BigUint { |
574 | | cfg_digit!( |
575 | | #[inline] |
576 | | fn mul_assign(&mut self, other: u128) { |
577 | | if let Some(other) = BigDigit::from_u128(other) { |
578 | | scalar_mul(self, other); |
579 | | } else { |
580 | | *self = match super::u32_from_u128(other) { |
581 | | (0, 0, c, d) => mul3(&self.data, &[d, c]), |
582 | | (0, b, c, d) => mul3(&self.data, &[d, c, b]), |
583 | | (a, b, c, d) => mul3(&self.data, &[d, c, b, a]), |
584 | | }; |
585 | | } |
586 | | } |
587 | | |
588 | | #[inline] |
589 | 0 | fn mul_assign(&mut self, other: u128) { |
590 | 0 | if let Some(other) = BigDigit::from_u128(other) { |
591 | 0 | scalar_mul(self, other); |
592 | 0 | } else { |
593 | 0 | let (hi, lo) = big_digit::from_doublebigdigit(other); |
594 | 0 | *self = mul3(&self.data, &[lo, hi]); |
595 | 0 | } |
596 | 0 | } |
597 | | ); |
598 | | } |
599 | | |
600 | | impl CheckedMul for BigUint { |
601 | | #[inline] |
602 | 0 | fn checked_mul(&self, v: &BigUint) -> Option<BigUint> { |
603 | 0 | Some(self.mul(v)) |
604 | 0 | } |
605 | | } |
606 | | |
607 | | impl_product_iter_type!(BigUint); |
608 | | |
609 | | #[test] |
610 | | fn test_sub_sign() { |
611 | | use crate::BigInt; |
612 | | use num_traits::Num; |
613 | | |
614 | | fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt { |
615 | | let (sign, val) = sub_sign(a, b); |
616 | | BigInt::from_biguint(sign, val) |
617 | | } |
618 | | |
619 | | let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); |
620 | | let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); |
621 | | let a_i = BigInt::from(a.clone()); |
622 | | let b_i = BigInt::from(b.clone()); |
623 | | |
624 | | assert_eq!(sub_sign_i(&a.data, &b.data), &a_i - &b_i); |
625 | | assert_eq!(sub_sign_i(&b.data, &a.data), &b_i - &a_i); |
626 | | } |