@@ -303,16 +303,63 @@ macro_rules! impl_mul_from {
303
303
result
304
304
}
305
305
}
306
+
307
+ impl $crate:: core_:: ops:: MulAssign <$other> for $name {
308
+ fn mul_assign( & mut self , other: $other) {
309
+ let result = * self * other;
310
+ * self = result
311
+ }
312
+ }
306
313
}
307
314
}
308
315
309
316
#[ macro_export]
310
317
#[ doc( hidden) ]
311
- macro_rules! impl_mulassign_from {
312
- ( $name: ident, $other: ident) => {
318
+ macro_rules! impl_mul_for_primitive {
319
+ ( $name: ty, $other: ident) => {
320
+ impl $crate:: core_:: ops:: Mul <$other> for $name {
321
+ type Output = $name;
322
+
323
+ fn mul( self , other: $other) -> $name {
324
+ let ( result, carry) = self . overflowing_mul_u64( other as u64 ) ;
325
+ panic_on_overflow!( carry > 0 ) ;
326
+ result
327
+ }
328
+ }
329
+
330
+ impl <' a> $crate:: core_:: ops:: Mul <& ' a $other> for $name {
331
+ type Output = $name;
332
+
333
+ fn mul( self , other: & ' a $other) -> $name {
334
+ let ( result, carry) = self . overflowing_mul_u64( * other as u64 ) ;
335
+ panic_on_overflow!( carry > 0 ) ;
336
+ result
337
+ }
338
+ }
339
+
340
+ impl <' a> $crate:: core_:: ops:: Mul <& ' a $other> for & ' a $name {
341
+ type Output = $name;
342
+
343
+ fn mul( self , other: & ' a $other) -> $name {
344
+ let ( result, carry) = self . overflowing_mul_u64( * other as u64 ) ;
345
+ panic_on_overflow!( carry > 0 ) ;
346
+ result
347
+ }
348
+ }
349
+
350
+ impl <' a> $crate:: core_:: ops:: Mul <$other> for & ' a $name {
351
+ type Output = $name;
352
+
353
+ fn mul( self , other: $other) -> $name {
354
+ let ( result, carry) = self . overflowing_mul_u64( other as u64 ) ;
355
+ panic_on_overflow!( carry > 0 ) ;
356
+ result
357
+ }
358
+ }
359
+
313
360
impl $crate:: core_:: ops:: MulAssign <$other> for $name {
314
361
fn mul_assign( & mut self , other: $other) {
315
- let result = * self * other;
362
+ let result = * self * ( other as u64 ) ;
316
363
* self = result
317
364
}
318
365
}
@@ -321,15 +368,9 @@ macro_rules! impl_mulassign_from {
321
368
322
369
#[ inline( always) ]
323
370
#[ doc( hidden) ]
324
- pub fn mul_u32 ( a : ( u64 , u64 ) , b : u64 , carry : u64 ) -> ( u64 , u64 ) {
325
- let upper = b * a. 0 ;
326
- let lower = b * a. 1 ;
327
-
328
- let ( res1, overflow1) = lower. overflowing_add ( upper << 32 ) ;
329
- let ( res2, overflow2) = res1. overflowing_add ( carry) ;
330
-
331
- let carry = ( upper >> 32 ) + overflow1 as u64 + overflow2 as u64 ;
332
- ( res2, carry)
371
+ pub fn mul_u64 ( a : u64 , b : u64 , carry : u64 ) -> ( u64 , u64 ) {
372
+ let ( hi, lo) = split_u128 ( u128:: from ( a) * u128:: from ( b) + u128:: from ( carry) ) ;
373
+ ( lo, hi)
333
374
}
334
375
335
376
#[ inline( always) ]
@@ -428,8 +469,8 @@ macro_rules! construct_uint {
428
469
429
470
let mut res = Self :: default ( ) ;
430
471
for b in value. bytes( ) . map( |b| b - 48 ) {
431
- let ( r, overflow) = res. overflowing_mul_u32 ( 10 ) ;
432
- if overflow {
472
+ let ( r, overflow) = res. overflowing_mul_u64 ( 10 ) ;
473
+ if overflow > 0 {
433
474
return Err ( $crate:: FromDecStrErr :: InvalidLength ) ;
434
475
}
435
476
let ( r, overflow) = r. overflowing_add( b. into( ) ) ;
@@ -512,6 +553,15 @@ macro_rules! construct_uint {
512
553
return true ;
513
554
}
514
555
556
+ // Whether this fits u64.
557
+ #[ inline]
558
+ fn fits_word( & self ) -> bool {
559
+ let & $name( ref arr) = self ;
560
+ for i in 1 ..$n_words { if arr[ i] != 0 { return false ; } }
561
+ return true ;
562
+ }
563
+
564
+
515
565
/// Return the least number of bits needed to represent the number
516
566
#[ inline]
517
567
pub fn bits( & self ) -> usize {
@@ -734,6 +784,11 @@ macro_rules! construct_uint {
734
784
/// Multiply with overflow, returning a flag if it does.
735
785
#[ inline( always) ]
736
786
pub fn overflowing_mul( self , other: $name) -> ( $name, bool ) {
787
+ // Fast path if other fits u64
788
+ if other. fits_word( ) {
789
+ let ( res, carry) = self . overflowing_mul_u64( other. low_u64( ) ) ;
790
+ return ( res, carry > 0 ) ;
791
+ }
737
792
uint_overflowing_mul!( $name, $n_words, self , other)
738
793
}
739
794
@@ -788,20 +843,18 @@ macro_rules! construct_uint {
788
843
}
789
844
}
790
845
791
- /// Overflowing multiplication by u32.
792
- fn overflowing_mul_u32( self , other: u32 ) -> ( Self , bool ) {
793
- let $name( ref arr) = self ;
794
- let mut ret = [ 0u64 ; $n_words] ;
795
- let mut carry = 0 ;
796
- let o = other as u64 ;
846
+ /// Overflowing multiplication by u64.
847
+ /// Returns the result and carry.
848
+ fn overflowing_mul_u64( mut self , other: u64 ) -> ( Self , u64 ) {
849
+ let mut carry = 0u64 ;
797
850
798
- for i in 0 ..$n_words {
799
- let ( res, carry2 ) = $crate:: mul_u32 ( $crate :: split ( arr [ i ] ) , o , carry) ;
800
- ret [ i ] = res;
801
- carry = carry2 ;
851
+ for d in self . 0 . iter_mut ( ) {
852
+ let ( res, c ) = $crate:: mul_u64 ( * d , other , carry) ;
853
+ * d = res;
854
+ carry = c ;
802
855
}
803
856
804
- ( $name ( ret ) , carry > 0 )
857
+ ( self , carry)
805
858
}
806
859
807
860
/// Converts from big endian representation bytes in memory.
@@ -950,56 +1003,18 @@ macro_rules! construct_uint {
950
1003
}
951
1004
}
952
1005
953
- // specialization for u32
954
- impl $crate:: core_:: ops:: Mul <u32 > for $name {
955
- type Output = $name;
956
-
957
- fn mul( self , other: u32 ) -> $name {
958
- let ( ret, overflow) = self . overflowing_mul_u32( other) ;
959
- panic_on_overflow!( overflow) ;
960
- ret
961
- }
962
- }
963
-
964
- impl <' a> $crate:: core_:: ops:: Mul <u32 > for & ' a $name {
965
- type Output = $name;
966
-
967
- fn mul( self , other: u32 ) -> $name {
968
- * self * other
969
- }
970
- }
971
-
972
- impl $crate:: core_:: ops:: MulAssign <u32 > for $name {
973
- fn mul_assign( & mut self , other: u32 ) {
974
- let result = * self * other;
975
- * self = result
976
- }
977
- }
978
-
979
1006
// all other impls
980
- impl_mul_from!( $name, u8 ) ;
981
- impl_mul_from!( $name, u16 ) ;
982
- impl_mul_from!( $name, u64 ) ;
983
- impl_mul_from!( $name, usize ) ;
984
-
985
- impl_mul_from!( $name, i8 ) ;
986
- impl_mul_from!( $name, i16 ) ;
987
- impl_mul_from!( $name, i64 ) ;
988
- impl_mul_from!( $name, isize ) ;
989
-
990
1007
impl_mul_from!( $name, $name) ;
991
-
992
- impl_mulassign_from!( $name, u8 ) ;
993
- impl_mulassign_from!( $name, u16 ) ;
994
- impl_mulassign_from!( $name, u64 ) ;
995
- impl_mulassign_from!( $name, usize ) ;
996
-
997
- impl_mulassign_from!( $name, i8 ) ;
998
- impl_mulassign_from!( $name, i16 ) ;
999
- impl_mulassign_from!( $name, i64 ) ;
1000
- impl_mulassign_from!( $name, isize ) ;
1001
-
1002
- impl_mulassign_from!( $name, $name) ;
1008
+ impl_mul_for_primitive!( $name, u8 ) ;
1009
+ impl_mul_for_primitive!( $name, u16 ) ;
1010
+ impl_mul_for_primitive!( $name, u32 ) ;
1011
+ impl_mul_for_primitive!( $name, u64 ) ;
1012
+ impl_mul_for_primitive!( $name, usize ) ;
1013
+ impl_mul_for_primitive!( $name, i8 ) ;
1014
+ impl_mul_for_primitive!( $name, i16 ) ;
1015
+ impl_mul_for_primitive!( $name, i32 ) ;
1016
+ impl_mul_for_primitive!( $name, i64 ) ;
1017
+ impl_mul_for_primitive!( $name, isize ) ;
1003
1018
1004
1019
impl <T > $crate:: core_:: ops:: Div <T > for $name where T : Into <$name> {
1005
1020
type Output = $name;
0 commit comments