@@ -11,7 +11,7 @@ use crate::{BigInt, UsizePromotion};
11
11
use core:: cmp:: Ordering ;
12
12
use core:: iter:: Product ;
13
13
use core:: ops:: { Mul , MulAssign } ;
14
- use num_traits:: { CheckedMul , One , Zero } ;
14
+ use num_traits:: { CheckedMul , FromPrimitive , One , Zero } ;
15
15
16
16
#[ inline]
17
17
pub ( super ) fn mac_with_carry (
@@ -155,28 +155,28 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
155
155
156
156
// We reuse the same BigUint for all the intermediate multiplies and have to size p
157
157
// appropriately here: x1.len() >= x0.len and y1.len() >= y0.len():
158
- let len = x1. len ( ) + y1. len ( ) + 1 ;
158
+ let len = x1. len ( ) + y1. len ( ) ;
159
159
let mut p = BigUint { data : vec ! [ 0 ; len] } ;
160
160
161
161
// p2 = x1 * y1
162
- mac3 ( & mut p. data [ .. ] , x1, y1) ;
162
+ mac3 ( & mut p. data , x1, y1) ;
163
163
164
164
// Not required, but the adds go faster if we drop any unneeded 0s from the end:
165
165
p. normalize ( ) ;
166
166
167
- add2 ( & mut acc[ b..] , & p. data [ .. ] ) ;
168
- add2 ( & mut acc[ b * 2 ..] , & p. data [ .. ] ) ;
167
+ add2 ( & mut acc[ b..] , & p. data ) ;
168
+ add2 ( & mut acc[ b * 2 ..] , & p. data ) ;
169
169
170
170
// Zero out p before the next multiply:
171
171
p. data . truncate ( 0 ) ;
172
172
p. data . resize ( len, 0 ) ;
173
173
174
174
// p0 = x0 * y0
175
- mac3 ( & mut p. data [ .. ] , x0, y0) ;
175
+ mac3 ( & mut p. data , x0, y0) ;
176
176
p. normalize ( ) ;
177
177
178
- add2 ( & mut acc[ .. ] , & p. data [ .. ] ) ;
179
- add2 ( & mut acc[ b..] , & p. data [ .. ] ) ;
178
+ add2 ( acc, & p. data ) ;
179
+ add2 ( & mut acc[ b..] , & p. data ) ;
180
180
181
181
// p1 = (x1 - x0) * (y1 - y0)
182
182
// We do this one last, since it may be negative and acc can't ever be negative:
@@ -188,13 +188,13 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
188
188
p. data . truncate ( 0 ) ;
189
189
p. data . resize ( len, 0 ) ;
190
190
191
- mac3 ( & mut p. data [ .. ] , & j0. data [ .. ] , & j1. data [ .. ] ) ;
191
+ mac3 ( & mut p. data , & j0. data , & j1. data ) ;
192
192
p. normalize ( ) ;
193
193
194
- sub2 ( & mut acc[ b..] , & p. data [ .. ] ) ;
194
+ sub2 ( & mut acc[ b..] , & p. data ) ;
195
195
}
196
196
Minus => {
197
- mac3 ( & mut acc[ b..] , & j0. data [ .. ] , & j1. data [ .. ] ) ;
197
+ mac3 ( & mut acc[ b..] , & j0. data , & j1. data ) ;
198
198
}
199
199
NoSign => ( ) ,
200
200
}
@@ -321,25 +321,41 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
321
321
}
322
322
323
323
fn mul3 ( x : & [ BigDigit ] , y : & [ BigDigit ] ) -> BigUint {
324
- let len = x. len ( ) + y. len ( ) + 1 ;
324
+ let len = x. len ( ) + y. len ( ) ;
325
325
let mut prod = BigUint { data : vec ! [ 0 ; len] } ;
326
326
327
- mac3 ( & mut prod. data [ .. ] , x, y) ;
327
+ mac3 ( & mut prod. data , x, y) ;
328
328
prod. normalized ( )
329
329
}
330
330
331
- fn scalar_mul ( a : & mut [ BigDigit ] , b : BigDigit ) -> BigDigit {
332
- let mut carry = 0 ;
333
- for a in a. iter_mut ( ) {
334
- * a = mul_with_carry ( * a, b, & mut carry) ;
331
+ fn scalar_mul ( a : & mut BigUint , b : BigDigit ) {
332
+ match b {
333
+ 0 => a. set_zero ( ) ,
334
+ 1 => { }
335
+ _ => {
336
+ if b. is_power_of_two ( ) {
337
+ * a <<= b. trailing_zeros ( ) ;
338
+ } else {
339
+ let mut carry = 0 ;
340
+ for a in a. data . iter_mut ( ) {
341
+ * a = mul_with_carry ( * a, b, & mut carry) ;
342
+ }
343
+ if carry != 0 {
344
+ a. data . push ( carry as BigDigit ) ;
345
+ }
346
+ }
347
+ }
335
348
}
336
- carry as BigDigit
337
349
}
338
350
339
351
fn sub_sign ( mut a : & [ BigDigit ] , mut b : & [ BigDigit ] ) -> ( Sign , BigUint ) {
340
352
// Normalize:
341
- a = & a[ ..a. iter ( ) . rposition ( |& x| x != 0 ) . map_or ( 0 , |i| i + 1 ) ] ;
342
- b = & b[ ..b. iter ( ) . rposition ( |& x| x != 0 ) . map_or ( 0 , |i| i + 1 ) ] ;
353
+ if let Some ( & 0 ) = a. last ( ) {
354
+ a = & a[ ..a. iter ( ) . rposition ( |& x| x != 0 ) . map_or ( 0 , |i| i + 1 ) ] ;
355
+ }
356
+ if let Some ( & 0 ) = b. last ( ) {
357
+ b = & b[ ..b. iter ( ) . rposition ( |& x| x != 0 ) . map_or ( 0 , |i| i + 1 ) ] ;
358
+ }
343
359
344
360
match cmp_slice ( a, b) {
345
361
Ordering :: Greater => {
@@ -356,22 +372,55 @@ fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) {
356
372
}
357
373
}
358
374
359
- forward_all_binop_to_ref_ref ! ( impl Mul for BigUint , mul) ;
360
- forward_val_assign ! ( impl MulAssign for BigUint , mul_assign) ;
361
-
362
- impl < ' a , ' b > Mul < & ' b BigUint > for & ' a BigUint {
363
- type Output = BigUint ;
375
+ macro_rules! impl_mul {
376
+ ( $( impl <$( $a: lifetime) ,* > Mul <$Other: ty> for $Self: ty; ) * ) => { $(
377
+ impl <$( $a) ,* > Mul <$Other> for $Self {
378
+ type Output = BigUint ;
379
+
380
+ #[ inline]
381
+ fn mul( self , other: $Other) -> BigUint {
382
+ match ( & * self . data, & * other. data) {
383
+ // multiply by zero
384
+ ( & [ ] , _) | ( _, & [ ] ) => BigUint :: zero( ) ,
385
+ // multiply by a scalar
386
+ ( _, & [ digit] ) => self * digit,
387
+ ( & [ digit] , _) => other * digit,
388
+ // full multiplication
389
+ ( x, y) => mul3( x, y) ,
390
+ }
391
+ }
392
+ }
393
+ ) * }
394
+ }
395
+ impl_mul ! {
396
+ impl <> Mul <BigUint > for BigUint ;
397
+ impl <' b> Mul <& ' b BigUint > for BigUint ;
398
+ impl <' a> Mul <BigUint > for & ' a BigUint ;
399
+ impl <' a, ' b> Mul <& ' b BigUint > for & ' a BigUint ;
400
+ }
364
401
365
- #[ inline]
366
- fn mul ( self , other : & BigUint ) -> BigUint {
367
- mul3 ( & self . data [ ..] , & other. data [ ..] )
368
- }
402
+ macro_rules! impl_mul_assign {
403
+ ( $( impl <$( $a: lifetime) ,* > MulAssign <$Other: ty> for BigUint ; ) * ) => { $(
404
+ impl <$( $a) ,* > MulAssign <$Other> for BigUint {
405
+ #[ inline]
406
+ fn mul_assign( & mut self , other: $Other) {
407
+ match ( & * self . data, & * other. data) {
408
+ // multiply by zero
409
+ ( & [ ] , _) => { } ,
410
+ ( _, & [ ] ) => self . set_zero( ) ,
411
+ // multiply by a scalar
412
+ ( _, & [ digit] ) => * self *= digit,
413
+ ( & [ digit] , _) => * self = other * digit,
414
+ // full multiplication
415
+ ( x, y) => * self = mul3( x, y) ,
416
+ }
417
+ }
418
+ }
419
+ ) * }
369
420
}
370
- impl < ' a > MulAssign < & ' a BigUint > for BigUint {
371
- #[ inline]
372
- fn mul_assign ( & mut self , other : & ' a BigUint ) {
373
- * self = & * self * other
374
- }
421
+ impl_mul_assign ! {
422
+ impl <> MulAssign <BigUint > for BigUint ;
423
+ impl <' a> MulAssign <& ' a BigUint > for BigUint ;
375
424
}
376
425
377
426
promote_unsigned_scalars ! ( impl Mul for BigUint , mul) ;
@@ -392,14 +441,7 @@ impl Mul<u32> for BigUint {
392
441
impl MulAssign < u32 > for BigUint {
393
442
#[ inline]
394
443
fn mul_assign ( & mut self , other : u32 ) {
395
- if other == 0 {
396
- self . data . clear ( ) ;
397
- } else {
398
- let carry = scalar_mul ( & mut self . data [ ..] , other as BigDigit ) ;
399
- if carry != 0 {
400
- self . data . push ( carry) ;
401
- }
402
- }
444
+ scalar_mul ( self , other as BigDigit ) ;
403
445
}
404
446
}
405
447
@@ -416,27 +458,18 @@ impl MulAssign<u64> for BigUint {
416
458
#[ cfg( not( u64_digit) ) ]
417
459
#[ inline]
418
460
fn mul_assign ( & mut self , other : u64 ) {
419
- if other == 0 {
420
- self . data . clear ( ) ;
421
- } else if other <= u64:: from ( BigDigit :: max_value ( ) ) {
422
- * self *= other as BigDigit
461
+ if let Some ( other) = BigDigit :: from_u64 ( other) {
462
+ scalar_mul ( self , other) ;
423
463
} else {
424
464
let ( hi, lo) = big_digit:: from_doublebigdigit ( other) ;
425
- * self = mul3 ( & self . data [ .. ] , & [ lo, hi] )
465
+ * self = mul3 ( & self . data , & [ lo, hi] ) ;
426
466
}
427
467
}
428
468
429
469
#[ cfg( u64_digit) ]
430
470
#[ inline]
431
471
fn mul_assign ( & mut self , other : u64 ) {
432
- if other == 0 {
433
- self . data . clear ( ) ;
434
- } else {
435
- let carry = scalar_mul ( & mut self . data [ ..] , other as BigDigit ) ;
436
- if carry != 0 {
437
- self . data . push ( carry) ;
438
- }
439
- }
472
+ scalar_mul ( self , other) ;
440
473
}
441
474
}
442
475
@@ -454,26 +487,25 @@ impl MulAssign<u128> for BigUint {
454
487
#[ cfg( not( u64_digit) ) ]
455
488
#[ inline]
456
489
fn mul_assign ( & mut self , other : u128 ) {
457
- if other == 0 {
458
- self . data . clear ( ) ;
459
- } else if other <= u128:: from ( BigDigit :: max_value ( ) ) {
460
- * self *= other as BigDigit
490
+ if let Some ( other) = BigDigit :: from_u128 ( other) {
491
+ scalar_mul ( self , other) ;
461
492
} else {
462
- let ( a, b, c, d) = u32_from_u128 ( other) ;
463
- * self = mul3 ( & self . data [ ..] , & [ d, c, b, a] )
493
+ * self = match u32_from_u128 ( other) {
494
+ ( 0 , 0 , c, d) => mul3 ( & self . data , & [ d, c] ) ,
495
+ ( 0 , b, c, d) => mul3 ( & self . data , & [ d, c, b] ) ,
496
+ ( a, b, c, d) => mul3 ( & self . data , & [ d, c, b, a] ) ,
497
+ } ;
464
498
}
465
499
}
466
500
467
501
#[ cfg( u64_digit) ]
468
502
#[ inline]
469
503
fn mul_assign ( & mut self , other : u128 ) {
470
- if other == 0 {
471
- self . data . clear ( ) ;
472
- } else if other <= BigDigit :: max_value ( ) as u128 {
473
- * self *= other as BigDigit
504
+ if let Some ( other) = BigDigit :: from_u128 ( other) {
505
+ scalar_mul ( self , other) ;
474
506
} else {
475
507
let ( hi, lo) = big_digit:: from_doublebigdigit ( other) ;
476
- * self = mul3 ( & self . data [ .. ] , & [ lo, hi] )
508
+ * self = mul3 ( & self . data , & [ lo, hi] ) ;
477
509
}
478
510
}
479
511
}
@@ -502,6 +534,6 @@ fn test_sub_sign() {
502
534
let a_i = BigInt :: from ( a. clone ( ) ) ;
503
535
let b_i = BigInt :: from ( b. clone ( ) ) ;
504
536
505
- assert_eq ! ( sub_sign_i( & a. data[ .. ] , & b. data[ .. ] ) , & a_i - & b_i) ;
506
- assert_eq ! ( sub_sign_i( & b. data[ .. ] , & a. data[ .. ] ) , & b_i - & a_i) ;
537
+ assert_eq ! ( sub_sign_i( & a. data, & b. data) , & a_i - & b_i) ;
538
+ assert_eq ! ( sub_sign_i( & b. data, & a. data) , & b_i - & a_i) ;
507
539
}
0 commit comments