@@ -21,6 +21,18 @@ use std::sync::Arc;
21
21
#[ cfg( feature = "zeroize" ) ]
22
22
use zeroize:: Zeroize ;
23
23
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
+
24
36
/// Parameters to efficiently go to/from the Montgomery form for an odd modulus whose size and value
25
37
/// are both chosen at runtime.
26
38
#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -159,6 +171,18 @@ impl BoxedResidue {
159
171
}
160
172
}
161
173
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
+
162
186
/// Instantiates a new [`BoxedResidue`] that represents an integer modulo the provided params.
163
187
#[ cfg( feature = "std" ) ]
164
188
pub fn new_with_arc ( mut integer : BoxedUint , residue_params : Arc < BoxedResidueParams > ) -> Self {
0 commit comments