@@ -199,46 +199,32 @@ impl<const N: usize> PosInt<N> {
199199 d. expand ( x) ;
200200
201201 loop {
202- if u. is_odd ( ) && v. is_odd ( ) {
203- if v. less_than ( & u) {
204- u = u . sub ( & v ) ;
205- a = a . add_mod ( & c , y ) ;
206- b = b . add_mod ( & d , x ) ;
207- } else {
208- v = v . sub ( & u ) ;
209- c = c . add_mod ( & a , y ) ;
210- d = d . add_mod ( & b , x ) ;
211- }
212- }
202+ let u_and_v_are_odd = u64 :: from ( u. is_odd ( ) & v. is_odd ( ) ) ;
203+ let v_is_less_than_u = u64 :: from ( v. less_than ( & u) ) ;
204+ let v_is_not_less_than_u = ( !v_is_less_than_u ) & 1 ;
205+
206+ u = u . sub ( & v . mask ( u_and_v_are_odd & v_is_less_than_u ) ) ;
207+ a = a . add_mod ( & c . mask ( u_and_v_are_odd & v_is_less_than_u ) , y ) ;
208+ b = b . add_mod ( & d . mask ( u_and_v_are_odd & v_is_less_than_u ) , x ) ;
209+
210+ v = v . sub ( & u . mask ( u_and_v_are_odd & v_is_not_less_than_u ) ) ;
211+ c = c . add_mod ( & a . mask ( u_and_v_are_odd & v_is_not_less_than_u ) , y ) ;
212+ d = d . add_mod ( & b . mask ( u_and_v_are_odd & v_is_not_less_than_u ) , x ) ;
213213
214214 assert ! ( u. is_even( ) || v. is_even( ) ) ;
215215
216- if u. is_even ( ) {
217- u = u. shift_right_1 ( ) ;
218-
219- // The operation being done here is more simply expressed as:
220- // if a.is_odd() || b.is_odd() {
221- // a = a.add_shift_right_1(y);
222- // b = b.add_shift_right_1(x);
223- // } else {
224- // a = a.shift_right_1();
225- // b = b.shift_right_1();
226- // }
227- // To avoid variable-time operations, though, we compute it as:
228- // a = a.shift_right_1(y & mask);
229- // b = b.shift_right_1(x & mask);
230- // where mask is all ones if a or b is odd and all zeros otherwise.
231-
232- let mask_bit = ( a. words [ 0 ] | b. words [ 0 ] ) & 1 ;
233- a = a. add_shift_right_1 ( & y. mask ( mask_bit) ) ;
234- b = b. add_shift_right_1 ( & x. mask ( mask_bit) ) ;
235- } else {
236- v = v. shift_right_1 ( ) ;
216+ let u_is_even = u64:: from ( u. is_even ( ) ) ;
217+ let u_is_odd = u64:: from ( u. is_odd ( ) ) ;
218+ let a_or_b_is_odd = u64:: from ( a. is_odd ( ) | b. is_odd ( ) ) ;
219+ let c_or_d_is_odd = u64:: from ( c. is_odd ( ) | d. is_odd ( ) ) ;
237220
238- let mask_bit = ( c. words [ 0 ] | d. words [ 0 ] ) & 1 ;
239- c = c. add_shift_right_1 ( & y. mask ( mask_bit) ) ;
240- d = d. add_shift_right_1 ( & x. mask ( mask_bit) ) ;
241- }
221+ u = u. shift_right_small ( u_is_even as _ ) ;
222+ a = a. add_shift_right_small ( & y. mask ( a_or_b_is_odd & u_is_even) , u_is_even as _ ) ;
223+ b = b. add_shift_right_small ( & x. mask ( a_or_b_is_odd & u_is_even) , u_is_even as _ ) ;
224+
225+ v = v. shift_right_small ( u_is_odd as _ ) ;
226+ c = c. add_shift_right_small ( & y. mask ( c_or_d_is_odd & u_is_odd) , u_is_odd as _ ) ;
227+ d = d. add_shift_right_small ( & x. mask ( c_or_d_is_odd & u_is_odd) , u_is_odd as _ ) ;
242228
243229 if v. is_zero ( ) {
244230 match u. len_bits ( ) {
@@ -280,11 +266,13 @@ impl<const N: usize> PosInt<N> {
280266 r
281267 }
282268
283- /// Returns `self` >> 1.
284- pub ( crate ) fn shift_right_1 ( & self ) -> Self {
269+ /// Returns `self` >> `c`.
270+ ///
271+ /// `c` must be <= 63.
272+ pub ( crate ) fn shift_right_small ( & self , c : u8 ) -> Self {
285273 let mut r = Self :: zero ( ) ;
286274 r. used = self . used ;
287- low:: bignum_shr_small ( r. as_mut_words ( ) , self . as_words ( ) , 1 ) ;
275+ low:: bignum_shr_small ( r. as_mut_words ( ) , self . as_words ( ) , c ) ;
288276 r
289277 }
290278
@@ -731,15 +719,16 @@ impl<const N: usize> PosInt<N> {
731719 r
732720 }
733721
734- /// Computes (`self` + `b`) >> 1
722+ /// Computes (`self` + `b`) >> `c`
723+ // / `c` must be <= 63.
735724 #[ must_use]
736- pub ( crate ) fn add_shift_right_1 ( & self , b : & Self ) -> Self {
725+ pub ( crate ) fn add_shift_right_small ( & self , b : & Self , c : u8 ) -> Self {
737726 let mut tmp = Self :: zero ( ) ;
738727 let carry = low:: bignum_add ( & mut tmp. words , self . as_words ( ) , b. as_words ( ) ) ;
739728 tmp. used = low:: bignum_digitsize ( & tmp. words ) ;
740729
741730 let mut r = Self :: zero ( ) ;
742- low:: bignum_shr_small ( & mut r. words , tmp. as_words ( ) , 1 ) ;
731+ low:: bignum_shr_small ( & mut r. words , tmp. as_words ( ) , c & 63 ) ;
743732 r. used = tmp. used ;
744733
745734 // insert carry at top
@@ -1146,7 +1135,7 @@ mod tests {
11461135 }
11471136
11481137 #[ test]
1149- fn test_add_shift_right_1 ( ) {
1138+ fn test_add_shift_right_small ( ) {
11501139 let a = PosInt :: < 1 > {
11511140 words : [ 0x8000_0000_0000_0021 ; 1 ] ,
11521141 used : 1 ,
@@ -1155,14 +1144,14 @@ mod tests {
11551144 words : [ 0x8421_8421_8421_8421 ; 1 ] ,
11561145 used : 1 ,
11571146 } ;
1158- let c = a. add_shift_right_1 ( & b) ;
1147+ let c = a. add_shift_right_small ( & b, 1 ) ;
11591148 assert_eq ! ( c. as_words( ) , & [ 0x8210_c210_c210_c221 ] ) ;
11601149
11611150 let b = PosInt :: < 1 > {
11621151 words : [ 0x0421_8421_8421_8421 ; 1 ] ,
11631152 used : 1 ,
11641153 } ;
1165- let c = a. add_shift_right_1 ( & b) ;
1154+ let c = a. add_shift_right_small ( & b, 1 ) ;
11661155 assert_eq ! ( c. as_words( ) , & [ 0x4210_c210_c210_c221 ] ) ;
11671156 }
11681157}
0 commit comments