From 4e097659bac894306ecceb19f0b278b84851addf Mon Sep 17 00:00:00 2001 From: serendipity-crypto Date: Sun, 8 Sep 2024 15:43:35 +0800 Subject: [PATCH] improve `CarryingMul` and `WideningMul` --- .../src/modulus/barrett/internal_macros.rs | 51 +++++++++++-------- algebra/src/modulus/shoup/internal_macros.rs | 2 +- .../src/primitive/widening/carrying_mul.rs | 36 +++++++++---- .../src/primitive/widening/widening_mul.rs | 30 ++++++++--- 4 files changed, 81 insertions(+), 38 deletions(-) diff --git a/algebra/src/modulus/barrett/internal_macros.rs b/algebra/src/modulus/barrett/internal_macros.rs index 46d05aaa..31c9c123 100644 --- a/algebra/src/modulus/barrett/internal_macros.rs +++ b/algebra/src/modulus/barrett/internal_macros.rs @@ -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 @@ -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())) } } @@ -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())) } } diff --git a/algebra/src/modulus/shoup/internal_macros.rs b/algebra/src/modulus/shoup/internal_macros.rs index 4f0d6b60..7df02b81 100644 --- a/algebra/src/modulus/shoup/internal_macros.rs +++ b/algebra/src/modulus/shoup/internal_macros.rs @@ -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)) diff --git a/algebra/src/primitive/widening/carrying_mul.rs b/algebra/src/primitive/widening/carrying_mul.rs index 5b13c0cf..aa665f28 100644 --- a/algebra/src/primitive/widening/carrying_mul.rs +++ b/algebra/src/primitive/widening/carrying_mul.rs @@ -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. /// @@ -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")] @@ -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 + } + } } }; } diff --git a/algebra/src/primitive/widening/widening_mul.rs b/algebra/src/primitive/widening/widening_mul.rs index f68ed7ac..866210a6 100644 --- a/algebra/src/primitive/widening/widening_mul.rs +++ b/algebra/src/primitive/widening/widening_mul.rs @@ -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")] @@ -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 + } + } } }; }