11//! [`BoxedUint`] multiplication operations.
22
33use crate :: {
4- BoxedUint , CheckedMul , ConcatenatingMul , CtOption , Limb , Mul , MulAssign , Uint , UintRef ,
4+ BoxedUint , CheckedMul , Choice , ConcatenatingMul , CtOption , Limb , Mul , MulAssign , Uint , UintRef ,
55 Wrapping , WrappingMul ,
6- uint:: mul:: { karatsuba, wrapping_mul_overflow} ,
76} ;
87
8+ mod helper;
9+ pub ( crate ) use helper:: BoxedMultiplier ;
10+
911impl BoxedUint {
1012 /// Multiply `self` by `rhs`.
1113 ///
1214 /// Returns a widened output with a limb count equal to the sums of the input limb counts.
1315 #[ must_use]
1416 pub fn mul ( & self , rhs : & Self ) -> Self {
15- self . wrapping_mul_carry ( rhs. as_limbs ( ) , self . nlimbs ( ) + rhs. nlimbs ( ) )
17+ self . wrapping_mul_carry ( rhs. as_uint_ref ( ) , self . nlimbs ( ) + rhs. nlimbs ( ) )
1618 . 0
1719 }
1820
1921 /// Multiply `self` by `rhs`.
2022 ///
2123 /// Returns a widened output with a limb count equal to the sums of the input limb counts.
24+ #[ must_use]
2225 pub ( crate ) fn mul_unsigned < const LIMBS : usize > ( & self , rhs : & Uint < LIMBS > ) -> Self {
23- self . wrapping_mul_carry ( rhs. as_limbs ( ) , self . nlimbs ( ) + LIMBS )
26+ self . wrapping_mul_carry ( rhs. as_uint_ref ( ) , self . nlimbs ( ) + LIMBS )
2427 . 0
2528 }
2629
2730 /// Perform wrapping multiplication, wrapping to the width of `self`.
2831 #[ must_use]
2932 pub fn wrapping_mul ( & self , rhs : & Self ) -> Self {
30- self . wrapping_mul_carry ( rhs. as_limbs ( ) , self . nlimbs ( ) ) . 0
33+ self . wrapping_mul_carry ( rhs. as_uint_ref ( ) , self . nlimbs ( ) ) . 0
3134 }
3235
3336 /// Multiply `self` by `rhs`, wrapping to the width of `self`.
3437 /// Returns `CtOption::None` if the result overflowed the precision of `self`.
3538 #[ must_use]
3639 pub fn checked_mul ( & self , rhs : & Self ) -> CtOption < Self > {
37- let ( res, carry) = self . wrapping_mul_carry ( rhs. as_limbs ( ) , self . nlimbs ( ) ) ;
38- let overflow =
39- wrapping_mul_overflow ( self . as_uint_ref ( ) , self . as_uint_ref ( ) , carry. is_nonzero ( ) ) ;
40+ let ( res, overflow) = self . overflowing_mul ( rhs. as_uint_ref ( ) , self . nlimbs ( ) ) ;
4041 CtOption :: new ( res, overflow. not ( ) )
4142 }
4243
4344 /// Perform saturating multiplication, returning `MAX` on overflow.
4445 #[ must_use]
45- pub fn saturating_mul ( & self , rhs : & BoxedUint ) -> Self {
46- let ( mut res, carry) = self . wrapping_mul_carry ( rhs. as_limbs ( ) , self . nlimbs ( ) ) ;
47- let overflow =
48- wrapping_mul_overflow ( self . as_uint_ref ( ) , rhs. as_uint_ref ( ) , carry. is_nonzero ( ) ) ;
46+ pub fn saturating_mul ( & self , rhs : & Self ) -> Self {
47+ let ( mut res, overflow) = self . overflowing_mul ( rhs. as_uint_ref ( ) , self . nlimbs ( ) ) ;
4948 res. as_mut_uint_ref ( ) . conditional_set_max ( overflow) ;
5049 res
5150 }
5251
52+ /// Multiply `self` by `rhs`, wrapping to the width of `self`.
53+ /// Returns a `Choice` indicating if the result overflowed the precision of `self`.
54+ #[ inline( always) ]
55+ #[ must_use]
56+ pub ( crate ) fn overflowing_mul ( & self , rhs : & UintRef , size : usize ) -> ( Self , Choice ) {
57+ let mut limbs = vec ! [ Limb :: ZERO ; size] ;
58+ let overflow = self
59+ . as_uint_ref ( )
60+ . overflowing_mul ( rhs, UintRef :: new_mut ( & mut limbs) ) ;
61+ ( limbs. into ( ) , overflow)
62+ }
63+
5364 #[ inline( always) ]
54- fn wrapping_mul_carry ( & self , rhs : & [ Limb ] , size : usize ) -> ( Self , Limb ) {
65+ fn wrapping_mul_carry ( & self , rhs : & UintRef , size : usize ) -> ( Self , Limb ) {
5566 let mut limbs = vec ! [ Limb :: ZERO ; size] ;
56- let carry = karatsuba:: wrapping_mul (
57- self . as_uint_ref ( ) ,
58- UintRef :: new ( rhs) ,
59- UintRef :: new_mut ( limbs. as_mut_slice ( ) ) ,
60- false ,
61- ) ;
67+ let carry = self
68+ . as_uint_ref ( )
69+ . wrapping_mul ( rhs, UintRef :: new_mut ( limbs. as_mut_slice ( ) ) ) ;
6270 ( limbs. into ( ) , carry)
6371 }
6472
@@ -78,29 +86,39 @@ impl BoxedUint {
7886 /// Returns `CtOption::None` if the result overflowed the precision of `self`.
7987 #[ must_use]
8088 pub fn checked_square ( & self ) -> CtOption < Self > {
81- let ( res, carry) = self . wrapping_square_carry ( self . nlimbs ( ) ) ;
82- let overflow =
83- wrapping_mul_overflow ( self . as_uint_ref ( ) , self . as_uint_ref ( ) , carry. is_nonzero ( ) ) ;
89+ let ( res, overflow) = self . overflowing_square ( self . nlimbs ( ) ) ;
8490 CtOption :: new ( res, overflow. not ( ) )
8591 }
8692
8793 /// Perform saturating squaring, returning `MAX` on overflow.
8894 #[ must_use]
8995 pub fn saturating_square ( & self ) -> Self {
90- let ( mut res, carry) = self . wrapping_square_carry ( self . nlimbs ( ) ) ;
91- let overflow =
92- wrapping_mul_overflow ( self . as_uint_ref ( ) , self . as_uint_ref ( ) , carry. is_nonzero ( ) ) ;
96+ let ( mut res, overflow) = self . overflowing_square ( self . nlimbs ( ) ) ;
9397 res. as_mut_uint_ref ( ) . conditional_set_max ( overflow) ;
9498 res
9599 }
96100
101+ /// Multiply `self` by itself, wrapping to the width of `self`.
102+ /// Returns a `Choice` indicating if the result overflowed the precision of `self`.
103+ #[ inline( always) ]
104+ #[ must_use]
105+ pub ( crate ) fn overflowing_square ( & self , size : usize ) -> ( Self , Choice ) {
106+ let mut limbs = vec ! [ Limb :: ZERO ; size] ;
107+ let overflow = self
108+ . as_uint_ref ( )
109+ . overflowing_square ( UintRef :: new_mut ( & mut limbs) ) ;
110+ ( limbs. into ( ) , overflow)
111+ }
112+
97113 /// Multiply `self` by itself, wrapping to the width of `self`.
98114 /// Returns a pair of the wrapped product and a Limb representing the carry.
99115 #[ inline( always) ]
116+ #[ must_use]
100117 fn wrapping_square_carry ( & self , size : usize ) -> ( Self , Limb ) {
101118 let mut limbs = vec ! [ Limb :: ZERO ; size] ;
102- let carry =
103- karatsuba:: wrapping_square ( self . as_uint_ref ( ) , UintRef :: new_mut ( limbs. as_mut_slice ( ) ) ) ;
119+ let carry = self
120+ . as_uint_ref ( )
121+ . wrapping_square ( UintRef :: new_mut ( limbs. as_mut_slice ( ) ) ) ;
104122 ( limbs. into ( ) , carry)
105123 }
106124}
@@ -152,7 +170,7 @@ impl MulAssign<BoxedUint> for BoxedUint {
152170
153171impl MulAssign < & BoxedUint > for BoxedUint {
154172 fn mul_assign ( & mut self , rhs : & BoxedUint ) {
155- * self = self . clone ( ) . mul ( rhs) ;
173+ * self = BoxedUint :: mul ( self , rhs) ;
156174 }
157175}
158176
0 commit comments