Skip to content

Commit

Permalink
improve CarryingMul and WideningMul
Browse files Browse the repository at this point in the history
  • Loading branch information
serendipity-crypto committed Sep 8, 2024
1 parent bd9bfeb commit 4e09765
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 38 deletions.
51 changes: 31 additions & 20 deletions algebra/src/modulus/barrett/internal_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ macro_rules! impl_barrett_modulus {
// +--------+
// | q3 |
// +--------+
let tmp = (self as $WideT * ratio[0] as $WideT) >> Self::BITS; // tmp1
let tmp = ((self as $WideT * ratio[1] as $WideT + tmp) >> Self::BITS) as $SelfT; // q3
use $crate::{CarryingMul, WideningMul};
let tmp = self.widening_mul_hw(ratio[0]); // tmp1
let tmp = self.carrying_mul_hw(ratio[1], tmp); // q3

// Step 2.
self.wrapping_sub(tmp.wrapping_mul(modulus.value())) // r = r1 -r2
Expand Down Expand Up @@ -218,19 +219,24 @@ macro_rules! impl_barrett_modulus {
// | d | <-- value[1] * ratio[1]
// +------------------+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// +------------------+
// | q3 |
// +------------------+
let a = ratio[0] as $WideT * self[0] as $WideT;
let b_plus_a_left = ratio[1] as $WideT * self[0] as $WideT + (a >> <$SelfT>::BITS);
// +--------+
// | q3 |
// +--------+
use $crate::{CarryingMul, WideningMul};

let ah = self[0].widening_mul_hw(ratio[0]);

let b = CarryingMul::carrying_mul(self[0], ratio[1], ah);
let c = WideningMul::widening_mul(self[1], ratio[0]);

let d = self[1].wrapping_mul(ratio[1]);

let c = ratio[0] as $WideT * self[1] as $WideT;
let d = ratio[1].wrapping_mul(self[1]);
let bch = b.1 + c.1 + b.0.overflowing_add(c.0).1 as $SelfT;

let tmp = d.wrapping_add(((b_plus_a_left + c) >> <$SelfT>::BITS) as $SelfT);
let q = d.wrapping_add(bch);

// Step 2.
self[0].wrapping_sub(tmp.wrapping_mul(modulus.value()))
self[0].wrapping_sub(q.wrapping_mul(modulus.value()))
}
}

Expand Down Expand Up @@ -322,19 +328,24 @@ macro_rules! impl_barrett_modulus {
// | d | <-- value.1 * ratio[1]
// +------------------+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// +------------------+
// | q3 |
// +------------------+
let a = ratio[0] as $WideT * self.0 as $WideT;
let b_plus_a_left = ratio[1] as $WideT * self.0 as $WideT + (a >> <$SelfT>::BITS);
// +--------+
// | q3 |
// +--------+
use $crate::{CarryingMul, WideningMul};

let ah = self.0.widening_mul_hw(ratio[0]);

let b = CarryingMul::carrying_mul(self.0, ratio[1], ah);
let c = WideningMul::widening_mul(self.1, ratio[0]);

let d = self.1.wrapping_mul(ratio[1]);

let c = ratio[0] as $WideT * self.1 as $WideT;
let d = ratio[1].wrapping_mul(self.1);
let bch = b.1 + c.1 + b.0.overflowing_add(c.0).1 as $SelfT;

let tmp = d.wrapping_add(((b_plus_a_left + c) >> <$SelfT>::BITS) as $SelfT);
let q = d.wrapping_add(bch);

// Step 2.
self.0.wrapping_sub(tmp.wrapping_mul(modulus.value()))
self.0.wrapping_sub(q.wrapping_mul(modulus.value()))
}
}

Expand Down
2 changes: 1 addition & 1 deletion algebra/src/modulus/shoup/internal_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ macro_rules! impl_shoup_factor {
/// `0 ≤ wx - qp < xp/β + p < 2p < β`
#[inline]
pub fn mul_reduce_lazy(self, rhs: $SelfT, modulus: $SelfT) -> $SelfT {
let (_, hw) = $crate::WideningMul::widening_mul(self.quotient, rhs);
let hw = $crate::WideningMul::widening_mul_hw(self.quotient, rhs);
self.value
.wrapping_mul(rhs)
.wrapping_sub(hw.wrapping_mul(modulus))
Expand Down
36 changes: 27 additions & 9 deletions algebra/src/primitive/widening/carrying_mul.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
/// Carrying mul operation trait.
pub trait CarryingMul: Sized {
/// A wider type for multiplication
type WideT;

/// Calculates the "full multiplication" `self` * `rhs` + `carry` without
/// the possibility to overflow.
///
Expand All @@ -13,13 +10,21 @@ pub trait CarryingMul: Sized {
/// an additional amount of overflow. This allows for chaining together multiple multiplications
/// to create "big integers" which represent larger values.
fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self);

/// Calculates the "full multiplication" `self` * `rhs` + `carry` without
/// the possibility to overflow.
///
/// This returns only the high-order (overflow) bits of the result.
///
/// Performs "long multiplication" which takes in an extra amount to add, and may return
/// an additional amount of overflow. This allows for chaining together multiple multiplications
/// to create "big integers" which represent larger values.
fn carrying_mul_hw(self, rhs: Self, carry: Self) -> Self;
}

macro_rules! uint_carrying_mul_impl {
($SelfT:ty, $WideT:ty) => {
impl CarryingMul for $SelfT {
type WideT = $WideT;

($T:ty, $W:ty) => {
impl CarryingMul for $T {
#[inline]
fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
#[cfg(feature = "nightly")]
Expand All @@ -29,11 +34,24 @@ macro_rules! uint_carrying_mul_impl {

#[cfg(not(feature = "nightly"))]
{
let wide =
(self as Self::WideT) * (rhs as Self::WideT) + (carry as Self::WideT);
let wide = (self as $W) * (rhs as $W) + (carry as $W);
(wide as Self, (wide >> Self::BITS) as Self)
}
}

#[inline]
fn carrying_mul_hw(self, rhs: Self, carry: Self) -> Self {
#[cfg(feature = "nightly")]
{
self.carrying_mul(rhs, carry).1
}

#[cfg(not(feature = "nightly"))]
{
let wide = (self as $W) * (rhs as $W) + (carry as $W);
(wide >> Self::BITS) as Self
}
}
}
};
}
Expand Down
30 changes: 22 additions & 8 deletions algebra/src/primitive/widening/widening_mul.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/// Widening mul operation trait.
pub trait WideningMul: Sized {
/// A wider type for multiplication
type WideT;

/// Calculates the complete product `self` * `rhs` without the possibility to overflow.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
fn widening_mul(self, rhs: Self) -> (Self, Self);

/// Calculates the complete product `self` * `rhs` without the possibility to overflow.
///
/// This returns only the high-order (overflow) bits of the result.
fn widening_mul_hw(self, rhs: Self) -> Self;
}

macro_rules! uint_widening_mul_impl {
($SelfT:ty, $WideT:ty) => {
impl WideningMul for $SelfT {
type WideT = $WideT;

($T:ty, $W:ty) => {
impl WideningMul for $T {
#[inline]
fn widening_mul(self, rhs: Self) -> (Self, Self) {
#[cfg(feature = "nightly")]
Expand All @@ -24,10 +24,24 @@ macro_rules! uint_widening_mul_impl {

#[cfg(not(feature = "nightly"))]
{
let wide = (self as Self::WideT) * (rhs as Self::WideT);
let wide = (self as $W) * (rhs as $W);
(wide as Self, (wide >> Self::BITS) as Self)
}
}

#[inline]
fn widening_mul_hw(self, rhs: Self) -> Self {
#[cfg(feature = "nightly")]
{
self.widening_mul(rhs).1
}

#[cfg(not(feature = "nightly"))]
{
let wide = (self as $W) * (rhs as $W);
(wide >> Self::BITS) as Self
}
}
}
};
}
Expand Down

0 comments on commit 4e09765

Please sign in to comment.