Skip to content

Commit ca80b71

Browse files
authored
Add div_by_2() to Monty trait (#490)
1 parent f9ef5aa commit ca80b71

File tree

5 files changed

+29
-31
lines changed

5 files changed

+29
-31
lines changed

src/modular/boxed_monty_form.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,7 @@ impl BoxedMontyForm {
220220
self.montgomery_form.clone()
221221
}
222222

223-
/// Performs the modular division by 2, that is for given `x` returns `y`
224-
/// such that `y * 2 = x mod p`. This means:
225-
/// - if `x` is even, returns `x / 2`,
226-
/// - if `x` is odd, returns `(x + p) / 2`
227-
/// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
223+
/// Performs division by 2, that is returns `x` such that `x + x = self`.
228224
pub fn div_by_2(&self) -> Self {
229225
Self {
230226
montgomery_form: div_by_2::div_by_2_boxed(&self.montgomery_form, &self.params.modulus),
@@ -259,6 +255,10 @@ impl Monty for BoxedMontyForm {
259255
fn one(params: Self::Params) -> Self {
260256
BoxedMontyForm::one(params)
261257
}
258+
259+
fn div_by_2(&self) -> Self {
260+
BoxedMontyForm::div_by_2(self)
261+
}
262262
}
263263

264264
/// Convert the given integer into the Montgomery domain.

src/modular/const_monty_form.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,8 @@ impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> ConstMontyForm<MOD, LIMBS
143143
self.montgomery_form
144144
}
145145

146-
/// Performs the modular division by 2, that is for given `x` returns `y`
147-
/// such that `y * 2 = x mod p`. This means:
148-
/// - if `x` is even, returns `x / 2`,
149-
/// - if `x` is odd, returns `(x + p) / 2`
150-
/// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
151-
pub fn div_by_2(&self) -> Self {
146+
/// Performs division by 2, that is returns `x` such that `x + x = self`.
147+
pub const fn div_by_2(&self) -> Self {
152148
Self {
153149
montgomery_form: div_by_2(&self.montgomery_form, &MOD::MODULUS),
154150
phantom: PhantomData,

src/modular/div_by_2.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
1-
use crate::Uint;
21
#[cfg(feature = "alloc")]
32
use crate::{BoxedUint, ConstantTimeSelect};
3+
use crate::{Odd, Uint};
44

5-
pub(crate) fn div_by_2<const LIMBS: usize>(a: &Uint<LIMBS>, modulus: &Uint<LIMBS>) -> Uint<LIMBS> {
6-
// We are looking for such `x` that `x * 2 = y mod modulus`,
7-
// where the given `a = M(y)` is the Montgomery representation of some `y`.
8-
// This means that in Montgomery representation it would still apply:
9-
// `M(x) + M(x) = a mod modulus`.
10-
// So we can just forget about Montgomery representation, and return whatever is
11-
// `a` divided by 2, and this will be the Montgomery representation of `x`.
12-
// (Which means that this function works regardless of whether `a`
13-
// is in Montgomery representation or not, but the algorithm below
14-
// does need `modulus` to be odd)
15-
5+
pub(crate) const fn div_by_2<const LIMBS: usize>(
6+
a: &Uint<LIMBS>,
7+
modulus: &Odd<Uint<LIMBS>>,
8+
) -> Uint<LIMBS> {
9+
// We are looking for such `b` that `b + b = a mod modulus`.
1610
// Two possibilities:
1711
// - if `a` is even, we can just divide by 2;
1812
// - if `a` is odd, we divide `(a + modulus)` by 2.
1913
// To stay within the modulus we open the parentheses turning it into `a / 2 + modulus / 2 + 1`
2014
// ("+1" because both `a` and `modulus` are odd, we lose 0.5 in each integer division).
2115
// This will not overflow, so we can just use wrapping operations.
2216

17+
// Note that this also works if `a` is a Montgomery representation modulo `modulus`
18+
// of some integer `x`.
19+
// If `b + b = a mod modulus` it means that `y + y = x mod modulus` where `y` is the integer
20+
// whose Mongtgomery representation is `b`.
21+
2322
let (half, is_odd) = a.shr1_with_carry();
24-
let half_modulus = modulus.shr1();
23+
let half_modulus = modulus.0.shr1();
2524

2625
let if_even = half;
2726
let if_odd = half
@@ -32,7 +31,7 @@ pub(crate) fn div_by_2<const LIMBS: usize>(a: &Uint<LIMBS>, modulus: &Uint<LIMBS
3231
}
3332

3433
#[cfg(feature = "alloc")]
35-
pub(crate) fn div_by_2_boxed(a: &BoxedUint, modulus: &BoxedUint) -> BoxedUint {
34+
pub(crate) fn div_by_2_boxed(a: &BoxedUint, modulus: &Odd<BoxedUint>) -> BoxedUint {
3635
debug_assert_eq!(a.bits_precision(), modulus.bits_precision());
3736

3837
let (mut half, is_odd) = a.shr1_with_carry();

src/modular/monty_form.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,8 @@ impl<const LIMBS: usize> MontyForm<LIMBS> {
180180
self.montgomery_form
181181
}
182182

183-
/// Performs the modular division by 2, that is for given `x` returns `y`
184-
/// such that `y * 2 = x mod p`. This means:
185-
/// - if `x` is even, returns `x / 2`,
186-
/// - if `x` is odd, returns `(x + p) / 2`
187-
/// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
188-
pub fn div_by_2(&self) -> Self {
183+
/// Performs division by 2, that is returns `x` such that `x + x = self`.
184+
pub const fn div_by_2(&self) -> Self {
189185
Self {
190186
montgomery_form: div_by_2(&self.montgomery_form, &self.params.modulus),
191187
params: self.params,
@@ -219,6 +215,10 @@ impl<const LIMBS: usize> Monty for MontyForm<LIMBS> {
219215
fn one(params: Self::Params) -> Self {
220216
MontyForm::one(params)
221217
}
218+
219+
fn div_by_2(&self) -> Self {
220+
MontyForm::div_by_2(self)
221+
}
222222
}
223223

224224
impl<const LIMBS: usize, P: ConstMontyParams<LIMBS>> From<&ConstMontyForm<P, LIMBS>>

src/traits.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,4 +563,7 @@ pub trait Monty:
563563

564564
/// Returns one in this representation.
565565
fn one(params: Self::Params) -> Self;
566+
567+
/// Performs division by 2, that is returns `x` such that `x + x = self`.
568+
fn div_by_2(&self) -> Self;
566569
}

0 commit comments

Comments
 (0)