@@ -21,6 +21,18 @@ use std::sync::Arc;
2121#[ cfg( feature = "zeroize" ) ]
2222use zeroize:: Zeroize ;
2323
24+ fn div_by_2 ( a : & BoxedUint , modulus : & BoxedUint ) -> BoxedUint {
25+ let ( half, is_odd) = a. shr1_with_carry ( ) ;
26+ let half_modulus = modulus. shr1 ( ) ;
27+
28+ let if_even = half. clone ( ) ;
29+ let if_odd = half
30+ . wrapping_add ( & half_modulus)
31+ . wrapping_add ( & BoxedUint :: one_with_precision ( a. bits_precision ( ) ) ) ;
32+
33+ BoxedUint :: conditional_select ( & if_even, & if_odd, is_odd)
34+ }
35+
2436/// Parameters to efficiently go to/from the Montgomery form for an odd modulus whose size and value
2537/// are both chosen at runtime.
2638#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -159,6 +171,18 @@ impl BoxedResidue {
159171 }
160172 }
161173
174+ /// Performs the modular division by 2, that is for given `x` returns `y`
175+ /// such that `y * 2 = x mod p`. This means:
176+ /// - if `x` is even, returns `x / 2`,
177+ /// - if `x` is odd, returns `(x + p) / 2`
178+ /// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
179+ pub fn div_by_2 ( & self ) -> Self {
180+ Self {
181+ montgomery_form : div_by_2 ( & self . montgomery_form , & self . residue_params . modulus ) ,
182+ residue_params : self . residue_params . clone ( ) ,
183+ }
184+ }
185+
162186 /// Instantiates a new [`BoxedResidue`] that represents an integer modulo the provided params.
163187 #[ cfg( feature = "std" ) ]
164188 pub fn new_with_arc ( mut integer : BoxedUint , residue_params : Arc < BoxedResidueParams > ) -> Self {
0 commit comments