mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
[montgomery]: added some doc
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
use crate::modulus::barrett::BarrettPrecomp;
|
use crate::modulus::barrett::BarrettPrecomp;
|
||||||
use crate::modulus::ReduceOnce;
|
use crate::modulus::ReduceOnce;
|
||||||
|
|
||||||
|
/// Montgomery is a generic struct storing
|
||||||
|
/// an element in the Montgomery domain.
|
||||||
pub struct Montgomery<O>(O);
|
pub struct Montgomery<O>(O);
|
||||||
|
|
||||||
|
/// Implements helper methods on the struct Montgomery<O>.
|
||||||
impl<O> Montgomery<O>{
|
impl<O> Montgomery<O>{
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -21,16 +23,23 @@ impl<O> Montgomery<O>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MontgomeryPrecomp is a generic struct storing
|
||||||
|
/// precomputations for Montgomery arithmetic.
|
||||||
pub struct MontgomeryPrecomp<O>{
|
pub struct MontgomeryPrecomp<O>{
|
||||||
q: O,
|
q: O,
|
||||||
q_barrett: BarrettPrecomp<O>,
|
q_barrett: BarrettPrecomp<O>,
|
||||||
q_inv: O,
|
q_inv: O,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MontgomeryPrecomp is a set of methods implemented for MontgomeryPrecomp<u64>
|
||||||
|
/// enabling Montgomery arithmetic over u64 values.
|
||||||
impl MontgomeryPrecomp<u64>{
|
impl MontgomeryPrecomp<u64>{
|
||||||
|
|
||||||
|
/// Returns an new instance of MontgomeryPrecomp<u64>.
|
||||||
|
/// This method will fail if gcd(q, 2^64) != 1.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn new(&self, q: u64) -> MontgomeryPrecomp<u64>{
|
fn new(&self, q: u64) -> MontgomeryPrecomp<u64>{
|
||||||
|
assert!(q & 1 != 0, "Invalid argument: gcd(q={}, radix=2^64) != 1", q);
|
||||||
let mut r: u64 = 1;
|
let mut r: u64 = 1;
|
||||||
let mut q_pow = q;
|
let mut q_pow = q;
|
||||||
for _i in 0..63{
|
for _i in 0..63{
|
||||||
@@ -40,6 +49,7 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
Self{ q: q, q_barrett: BarrettPrecomp::new(q, q), q_inv: q_pow}
|
Self{ q: q, q_barrett: BarrettPrecomp::new(q, q), q_inv: q_pow}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns (lhs<<64)%q as a Montgomery<u64>.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn prepare(&self, lhs: u64) -> Montgomery<u64>{
|
fn prepare(&self, lhs: u64) -> Montgomery<u64>{
|
||||||
let mut rhs = Montgomery(0);
|
let mut rhs = Montgomery(0);
|
||||||
@@ -47,11 +57,14 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
rhs
|
rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns (lhs<<64)%q to rhs.
|
||||||
|
#[inline(always)]
|
||||||
fn prepare_assign(&self, lhs: u64, rhs: &mut Montgomery<u64>){
|
fn prepare_assign(&self, lhs: u64, rhs: &mut Montgomery<u64>){
|
||||||
self.prepare_lazy_assign(lhs, rhs);
|
self.prepare_lazy_assign(lhs, rhs);
|
||||||
rhs.value_mut().reduce_once_assign(self.q);
|
rhs.value_mut().reduce_once_assign(self.q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns (lhs<<64)%q in range [0, 2q-1] as a Montgomery<u64>.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn prepare_lazy(&self, lhs: u64) -> Montgomery<u64>{
|
fn prepare_lazy(&self, lhs: u64) -> Montgomery<u64>{
|
||||||
let mut rhs = Montgomery(0);
|
let mut rhs = Montgomery(0);
|
||||||
@@ -59,11 +72,14 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
rhs
|
rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns (lhs<<64)%q in range [0, 2q-1] to rhs.
|
||||||
|
#[inline(always)]
|
||||||
fn prepare_lazy_assign(&self, lhs: u64, rhs: &mut Montgomery<u64>){
|
fn prepare_lazy_assign(&self, lhs: u64, rhs: &mut Montgomery<u64>){
|
||||||
let (mhi, _) = lhs.widening_mul(*self.q_barrett.value_lo());
|
let (mhi, _) = lhs.widening_mul(*self.q_barrett.value_lo());
|
||||||
*rhs = Montgomery((lhs.wrapping_mul(*self.q_barrett.value_hi()).wrapping_add(mhi)).wrapping_mul(self.q).wrapping_neg());
|
*rhs = Montgomery((lhs.wrapping_mul(*self.q_barrett.value_hi()).wrapping_add(mhi)).wrapping_mul(self.q).wrapping_neg());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns lhs * rhs * (2^{64})^-1 mod q.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_external(&self, lhs: Montgomery<u64>, rhs: u64) -> u64{
|
fn mul_external(&self, lhs: Montgomery<u64>, rhs: u64) -> u64{
|
||||||
let mut r = self.mul_external_lazy(lhs, rhs);
|
let mut r = self.mul_external_lazy(lhs, rhs);
|
||||||
@@ -71,12 +87,14 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns lhs * rhs * (2^{64})^-1 mod q to rhs.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_external_assign(&self, lhs: Montgomery<u64>, rhs: &mut u64){
|
fn mul_external_assign(&self, lhs: Montgomery<u64>, rhs: &mut u64){
|
||||||
self.mul_external_lazy_assign(lhs, rhs);
|
self.mul_external_lazy_assign(lhs, rhs);
|
||||||
rhs.reduce_once_assign(self.q);
|
rhs.reduce_once_assign(self.q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns lhs * rhs * (2^{64})^-1 mod q in range [0, 2q-1].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_external_lazy(&self, lhs: Montgomery<u64>, rhs: u64) -> u64{
|
fn mul_external_lazy(&self, lhs: Montgomery<u64>, rhs: u64) -> u64{
|
||||||
let mut result = rhs;
|
let mut result = rhs;
|
||||||
@@ -84,6 +102,7 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns lhs * rhs * (2^{64})^-1 mod q in range [0, 2q-1] to rhs.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_external_lazy_assign(&self, lhs: Montgomery<u64>, rhs: &mut u64){
|
fn mul_external_lazy_assign(&self, lhs: Montgomery<u64>, rhs: &mut u64){
|
||||||
let (mhi, mlo) = lhs.value().widening_mul(*rhs);
|
let (mhi, mlo) = lhs.value().widening_mul(*rhs);
|
||||||
@@ -91,21 +110,25 @@ impl MontgomeryPrecomp<u64>{
|
|||||||
*rhs = mhi - hhi + self.q
|
*rhs = mhi - hhi + self.q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns lhs * rhs * (2^{64})^-1 mod q in range [0, 2q-1].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_internal(&self, lhs: Montgomery<u64>, rhs: Montgomery<u64>) -> Montgomery<u64>{
|
fn mul_internal(&self, lhs: Montgomery<u64>, rhs: Montgomery<u64>) -> Montgomery<u64>{
|
||||||
Montgomery(self.mul_external(lhs, *rhs.value()))
|
Montgomery(self.mul_external(lhs, *rhs.value()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns lhs * rhs * (2^{64})^-1 mod q to rhs.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_internal_assign(&self, lhs: Montgomery<u64>, rhs: &mut Montgomery<u64>){
|
fn mul_internal_assign(&self, lhs: Montgomery<u64>, rhs: &mut Montgomery<u64>){
|
||||||
self.mul_external_assign(lhs, rhs.value_mut());
|
self.mul_external_assign(lhs, rhs.value_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns lhs * rhs * (2^{64})^-1 mod q in range [0, 2q-1].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_internal_lazy(&self, lhs: Montgomery<u64>, rhs: Montgomery<u64>) -> Montgomery<u64>{
|
fn mul_internal_lazy(&self, lhs: Montgomery<u64>, rhs: Montgomery<u64>) -> Montgomery<u64>{
|
||||||
Montgomery(self.mul_external_lazy(lhs, *rhs.value()))
|
Montgomery(self.mul_external_lazy(lhs, *rhs.value()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns lhs * rhs * (2^{64})^-1 mod q in range [0, 2q-1] to rhs.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul_internal_lazy_assign(&self, lhs: Montgomery<u64>, rhs: &mut Montgomery<u64>){
|
fn mul_internal_lazy_assign(&self, lhs: Montgomery<u64>, rhs: &mut Montgomery<u64>){
|
||||||
self.mul_external_lazy_assign(lhs, rhs.value_mut());
|
self.mul_external_lazy_assign(lhs, rhs.value_mut());
|
||||||
|
|||||||
Reference in New Issue
Block a user