33use core:: num:: NonZeroU32 ;
44
55use super :: UintRef ;
6- use crate :: { Choice , Limb , primitives:: u32_bits, word } ;
6+ use crate :: { Choice , Limb , primitives:: u32_bits} ;
77
88#[ cfg( feature = "alloc" ) ]
99use crate :: primitives:: u32_rem;
@@ -50,15 +50,16 @@ impl UintRef {
5050 pub ( crate ) const fn bounded_shl_assign ( & mut self , shift : u32 , shift_upper_bound : u32 ) {
5151 assert ! ( shift < shift_upper_bound, "`shift` exceeds upper bound" ) ;
5252
53- if shift_upper_bound <= Limb :: BITS {
54- self . shl_assign_limb ( shift) ;
53+ let bit_shift = if shift_upper_bound <= Limb :: BITS {
54+ shift
5555 } else {
5656 self . bounded_shl_by_limbs_assign (
5757 shift >> Limb :: LOG2_BITS ,
5858 shift_upper_bound. div_ceil ( Limb :: BITS ) ,
5959 ) ;
60- self . shl_assign_limb ( shift & ( Limb :: BITS - 1 ) ) ;
61- }
60+ shift & ( Limb :: BITS - 1 )
61+ } ;
62+ self . shl_assign_limb_with_carry ( bit_shift, Limb :: ZERO ) ;
6263 }
6364
6465 /// Left-shifts by `shift * Limb::BITS` bits where `shift < shift_upper_bound`.
@@ -107,7 +108,6 @@ impl UintRef {
107108 /// NOTE: this operation is variable time with respect to `shift` *ONLY*.
108109 ///
109110 /// When used with a fixed `shift`, this function is constant-time with respect to `self`.
110- #[ cfg( feature = "alloc" ) ]
111111 #[ inline( always) ]
112112 pub ( crate ) const fn unbounded_shl_assign_by_limbs_vartime ( & mut self , shift : u32 ) {
113113 let shift = shift as usize ;
@@ -128,7 +128,6 @@ impl UintRef {
128128 /// NOTE: this operation is variable time with respect to `shift` *ONLY*.
129129 ///
130130 /// When used with a fixed `shift`, this function is constant-time with respect to `self`.
131- #[ cfg( feature = "alloc" ) ]
132131 #[ inline( always) ]
133132 pub const fn unbounded_shl_assign_vartime ( & mut self , shift : u32 ) {
134133 let shift_limbs = shift / Limb :: BITS ;
@@ -170,7 +169,7 @@ impl UintRef {
170169 /// Left-shifts by a single bit in constant-time, returning [`Choice::TRUE`]
171170 /// if the least significant bit was set, and [`Choice::FALSE`] otherwise.
172171 #[ inline( always) ]
173- pub const fn shl1_assign ( & mut self ) -> Choice {
172+ pub const fn shl1_assign ( & mut self ) -> Limb {
174173 let mut carry = Limb :: ZERO ;
175174 let mut i = 0 ;
176175 while i < self . nlimbs ( ) {
@@ -179,25 +178,25 @@ impl UintRef {
179178 carry = new_carry;
180179 i += 1 ;
181180 }
182- word :: choice_from_lsb ( carry. 0 )
181+ carry
183182 }
184183
185184 /// Conditionally left-shifts by `shift` bits where `0 < shift < Limb::BITS`, returning
186185 /// the carry.
187186 ///
188187 /// # Panics
189188 /// - if `shift >= Limb::BITS`.
190- #[ inline]
189+ #[ inline( always ) ]
191190 pub ( crate ) const fn conditional_shl_assign_limb_nonzero (
192191 & mut self ,
193192 shift : NonZeroU32 ,
193+ mut carry : Limb ,
194194 choice : Choice ,
195195 ) -> Limb {
196196 assert ! ( shift. get( ) < Limb :: BITS ) ;
197197
198198 let lshift = shift. get ( ) ;
199199 let rshift = Limb :: BITS - lshift;
200- let mut carry = Limb :: ZERO ;
201200
202201 let mut i = 0 ;
203202 while i < self . nlimbs ( ) {
@@ -221,9 +220,19 @@ impl UintRef {
221220 /// - if `shift >= Limb::BITS`.
222221 #[ inline( always) ]
223222 pub const fn shl_assign_limb ( & mut self , shift : u32 ) -> Limb {
223+ self . shl_assign_limb_with_carry ( shift, Limb :: ZERO )
224+ }
225+
226+ /// Left-shifts by `shift` bits where `0 < shift < Limb::BITS`, returning the carry.
227+ ///
228+ /// # Panics
229+ /// - if `shift >= Limb::BITS`.
230+ #[ inline( always) ]
231+ pub const fn shl_assign_limb_with_carry ( & mut self , shift : u32 , carry : Limb ) -> Limb {
224232 let nz = Choice :: from_u32_nz ( shift) ;
225233 self . conditional_shl_assign_limb_nonzero (
226234 NonZeroU32 :: new ( nz. select_u32 ( 1 , shift) ) . expect ( "ensured non-zero" ) ,
235+ carry,
227236 nz,
228237 )
229238 }
@@ -263,9 +272,7 @@ impl UintRef {
263272
264273#[ cfg( test) ]
265274mod tests {
266- #[ cfg( feature = "alloc" ) ]
267- use crate :: Uint ;
268- use crate :: { Limb , U256 } ;
275+ use crate :: { Limb , U256 , Uint } ;
269276
270277 const N : U256 =
271278 U256 :: from_be_hex ( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" ) ;
@@ -278,17 +285,17 @@ mod tests {
278285 let mut n = N ;
279286 let carry = n. as_mut_uint_ref ( ) . shl1_assign ( ) ;
280287 assert_eq ! ( n, TWO_N ) ;
281- assert ! ( carry. to_bool ( ) ) ;
288+ assert_eq ! ( carry, Limb :: ONE ) ;
282289
283290 let mut m = U256 :: MAX ;
284291 let carry = m. as_mut_uint_ref ( ) . shl1_assign ( ) ;
285292 assert_eq ! ( m, U256 :: MAX . shl_vartime( 1 ) ) ;
286- assert ! ( carry. to_bool ( ) ) ;
293+ assert_eq ! ( carry, Limb :: ONE ) ;
287294
288295 let mut z = U256 :: ZERO ;
289296 let carry = z. as_mut_uint_ref ( ) . shl1_assign ( ) ;
290297 assert_eq ! ( z, U256 :: ZERO ) ;
291- assert ! ( ! carry. to_bool ( ) ) ;
298+ assert_eq ! ( carry, Limb :: ZERO ) ;
292299 }
293300
294301 #[ test]
@@ -324,7 +331,6 @@ mod tests {
324331 assert_eq ! ( carry, N . limbs[ U256 :: LIMBS - 1 ] . shr( 1 ) ) ;
325332 }
326333
327- #[ cfg( feature = "alloc" ) ]
328334 #[ test]
329335 fn unbounded_shl_by_limbs_vartime ( ) {
330336 let refval = Uint :: < 2 > :: from_words ( [ 1 , 99 ] ) ;
0 commit comments