Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impl Wrapping* traits from num-traits #425

Merged
merged 4 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ subtle = { version = "2.5", default-features = false }
# optional dependencies
der = { version = "0.7", optional = true, default-features = false }
generic-array = { version = "0.14", optional = true }
num-traits = { version = "0.2", default-features = false }
rand_core = { version = "0.6.4", optional = true }
rlp = { version = "0.5", optional = true, default-features = false }
serdect = { version = "0.2", optional = true, default-features = false }
Expand All @@ -33,7 +34,6 @@ criterion = { version = "0.5", features = ["html_reports"] }
hex-literal = "0.4"
num-bigint = { package = "num-bigint-dig", version = "0.8" }
num-integer = "0.1"
num-traits = "0.2"
proptest = "1"
rand_core = { version = "0.6", features = ["std"] }
rand_chacha = "0.3"
Expand Down
6 changes: 3 additions & 3 deletions src/modular.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ mod tests {
// Reducing xR should return x
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
let product = x.mul_wide(&Modulus2::R);
let product = x.split_mul(&Modulus2::R);
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&product,
Expand All @@ -151,10 +151,10 @@ mod tests {
// Reducing xR^2 should return xR
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
let product = x.mul_wide(&Modulus2::R2);
let product = x.split_mul(&Modulus2::R2);

// Computing xR mod modulus without Montgomery reduction
let (lo, hi) = x.mul_wide(&Modulus2::R);
let (lo, hi) = x.split_mul(&Modulus2::R);
let c = hi.concat(&lo);
let red = c.rem(&NonZero::new(U256::ZERO.concat(&Modulus2::MODULUS)).unwrap());
let (hi, lo) = red.split();
Expand Down
2 changes: 1 addition & 1 deletion src/modular/dyn_residue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub struct DynResidue<const LIMBS: usize> {
impl<const LIMBS: usize> DynResidue<LIMBS> {
/// Instantiates a new `Residue` that represents this `integer` mod `MOD`.
pub const fn new(integer: &Uint<LIMBS>, residue_params: DynResidueParams<LIMBS>) -> Self {
let product = integer.mul_wide(&residue_params.r2);
let product = integer.split_mul(&residue_params.r2);
let montgomery_form = montgomery_reduction(
&product,
&residue_params.modulus,
Expand Down
2 changes: 1 addition & 1 deletion src/modular/inv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub const fn inv_montgomery_form<const LIMBS: usize>(
) -> (Uint<LIMBS>, ConstChoice) {
let (inverse, is_some) = x.inv_odd_mod(modulus);
(
montgomery_reduction(&inverse.mul_wide(r3), modulus, mod_neg_inv),
montgomery_reduction(&inverse.split_mul(r3), modulus, mod_neg_inv),
is_some,
)
}
2 changes: 1 addition & 1 deletion src/modular/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub(crate) const fn mul_montgomery_form<const LIMBS: usize>(
modulus: &Uint<LIMBS>,
mod_neg_inv: Limb,
) -> Uint<LIMBS> {
let product = a.mul_wide(b);
let product = a.split_mul(b);
montgomery_reduction::<LIMBS>(&product, modulus, mod_neg_inv)
}

Expand Down
2 changes: 1 addition & 1 deletion src/modular/residue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {

/// Internal helper function to generate a residue; this lets us cleanly wrap the constructors.
const fn generate_residue(integer: &Uint<LIMBS>) -> Self {
let product = integer.mul_wide(&MOD::R2);
let product = integer.split_mul(&MOD::R2);
let montgomery_form =
montgomery_reduction::<LIMBS>(&product, &MOD::MODULUS.0, MOD::MOD_NEG_INV);

Expand Down
10 changes: 10 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! Traits provided by this crate

pub use num_traits::{
WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub,
};

use crate::{Limb, NonZero};
use core::fmt::Debug;
use core::ops::{
Expand Down Expand Up @@ -71,6 +75,12 @@ pub trait Integer:
+ ShrAssign<u32>
+ SubMod
+ Sync
+ WrappingAdd
+ WrappingSub
+ WrappingMul
+ WrappingNeg
+ WrappingShl
+ WrappingShr
+ Zero
{
/// The value `1`.
Expand Down
33 changes: 28 additions & 5 deletions src/uint/add.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! [`Uint`] addition operations.
use crate::{Checked, CheckedAdd, ConstChoice, Limb, Uint, Wrapping, Zero};
use crate::{Checked, CheckedAdd, ConstChoice, Limb, Uint, Wrapping, WrappingAdd, Zero};
use core::ops::{Add, AddAssign};
use subtle::CtOption;

Expand Down Expand Up @@ -45,12 +45,20 @@ impl<const LIMBS: usize> Uint<LIMBS> {
}
}

impl<const LIMBS: usize> CheckedAdd<&Uint<LIMBS>> for Uint<LIMBS> {
impl<const LIMBS: usize> Add for Uint<LIMBS> {
type Output = Self;

fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
let (result, carry) = self.adc(rhs, Limb::ZERO);
CtOption::new(result, carry.is_zero())
fn add(self, rhs: Self) -> Self {
self.add(&rhs)
}
}

impl<const LIMBS: usize> Add<&Uint<LIMBS>> for Uint<LIMBS> {
type Output = Self;

fn add(self, rhs: &Self) -> Self {
self.checked_add(rhs)
.expect("attempted to add with overflow")
}
}

Expand Down Expand Up @@ -154,6 +162,21 @@ impl<const LIMBS: usize> AddAssign<&Checked<Uint<LIMBS>>> for Checked<Uint<LIMBS
}
}

impl<const LIMBS: usize> CheckedAdd<&Uint<LIMBS>> for Uint<LIMBS> {
type Output = Self;

fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
let (result, carry) = self.adc(rhs, Limb::ZERO);
CtOption::new(result, carry.is_zero())
}
}

impl<const LIMBS: usize> WrappingAdd for Uint<LIMBS> {
fn wrapping_add(&self, v: &Self) -> Self {
self.wrapping_add(v)
}
}

#[cfg(test)]
mod tests {
use crate::{CheckedAdd, Limb, U128};
Expand Down
42 changes: 36 additions & 6 deletions src/uint/boxed/add.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! [`BoxedUint`] addition operations.
use crate::{BoxedUint, CheckedAdd, Limb, Wrapping, WrappingAdd, Zero};
use core::ops::{Add, AddAssign};

use crate::{BoxedUint, CheckedAdd, Limb, Wrapping, Zero};
use subtle::{Choice, ConditionallySelectable, CtOption};

impl BoxedUint {
Expand Down Expand Up @@ -51,12 +50,28 @@ impl BoxedUint {
}
}

impl CheckedAdd<&BoxedUint> for BoxedUint {
impl Add for BoxedUint {
type Output = Self;

fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
let (result, carry) = self.adc(rhs, Limb::ZERO);
CtOption::new(result, carry.is_zero())
fn add(self, rhs: Self) -> Self {
self.add(&rhs)
}
}

impl Add<&BoxedUint> for BoxedUint {
type Output = Self;

fn add(self, rhs: &Self) -> Self {
Add::add(&self, rhs)
}
}

impl Add<&BoxedUint> for &BoxedUint {
type Output = BoxedUint;

fn add(self, rhs: &BoxedUint) -> BoxedUint {
self.checked_add(rhs)
.expect("attempted to add with overflow")
}
}

Expand Down Expand Up @@ -104,6 +119,21 @@ impl AddAssign<&Wrapping<BoxedUint>> for Wrapping<BoxedUint> {
}
}

impl CheckedAdd<&BoxedUint> for BoxedUint {
type Output = Self;

fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
let (result, carry) = self.adc(rhs, Limb::ZERO);
CtOption::new(result, carry.is_zero())
}
}

impl WrappingAdd for BoxedUint {
fn wrapping_add(&self, v: &Self) -> Self {
self.wrapping_add(v)
}
}

#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
Expand Down
63 changes: 52 additions & 11 deletions src/uint/boxed/mul.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! [`BoxedUint`] multiplication operations.
use crate::{uint::mul::mul_limbs, BoxedUint, CheckedMul, Limb, WideningMul, Wrapping, Zero};
use crate::{
uint::mul::mul_limbs, BoxedUint, CheckedMul, Limb, WideningMul, Wrapping, WrappingMul, Zero,
};
use core::ops::{Mul, MulAssign};
use subtle::{Choice, CtOption};

Expand Down Expand Up @@ -51,21 +53,36 @@ impl CheckedMul<&BoxedUint> for BoxedUint {
}
}

impl WideningMul for BoxedUint {
type Output = Self;
impl Mul<BoxedUint> for BoxedUint {
type Output = BoxedUint;

#[inline]
fn widening_mul(&self, rhs: BoxedUint) -> Self {
self.mul(&rhs)
fn mul(self, rhs: BoxedUint) -> Self {
BoxedUint::mul(&self, &rhs)
}
}

impl WideningMul<&BoxedUint> for BoxedUint {
type Output = Self;
impl Mul<&BoxedUint> for BoxedUint {
type Output = BoxedUint;

#[inline]
fn widening_mul(&self, rhs: &BoxedUint) -> Self {
self.mul(rhs)
fn mul(self, rhs: &BoxedUint) -> Self {
BoxedUint::mul(&self, rhs)
}
}

impl Mul<BoxedUint> for &BoxedUint {
type Output = BoxedUint;

fn mul(self, rhs: BoxedUint) -> Self::Output {
BoxedUint::mul(self, &rhs)
}
}

impl Mul<&BoxedUint> for &BoxedUint {
type Output = BoxedUint;

fn mul(self, rhs: &BoxedUint) -> Self::Output {
self.checked_mul(rhs)
.expect("attempted to multiply with overflow")
}
}

Expand Down Expand Up @@ -113,6 +130,30 @@ impl MulAssign<&Wrapping<BoxedUint>> for Wrapping<BoxedUint> {
}
}

impl WideningMul for BoxedUint {
type Output = Self;

#[inline]
fn widening_mul(&self, rhs: BoxedUint) -> Self {
self.mul(&rhs)
}
}

impl WideningMul<&BoxedUint> for BoxedUint {
type Output = Self;

#[inline]
fn widening_mul(&self, rhs: &BoxedUint) -> Self {
self.mul(rhs)
}
}

impl WrappingMul for BoxedUint {
fn wrapping_mul(&self, v: &Self) -> Self {
self.wrapping_mul(v)
}
}

#[cfg(test)]
mod tests {
use crate::BoxedUint;
Expand Down
2 changes: 1 addition & 1 deletion src/uint/boxed/mul_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ mod tests {
assert!(c < **p, "not reduced: {} >= {} ", c, p);

let expected = {
let (lo, hi) = a.mul_wide(&b);
let (lo, hi) = a.split_mul(&b);
let mut prod = Uint::<{ 2 * $size }>::ZERO;
prod.limbs[..$size].clone_from_slice(&lo.limbs);
prod.limbs[$size..].clone_from_slice(&hi.limbs);
Expand Down
8 changes: 7 additions & 1 deletion src/uint/boxed/neg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! [`BoxedUint`] negation operations.

use crate::{BoxedUint, Limb, WideWord, Word, Wrapping};
use crate::{BoxedUint, Limb, WideWord, Word, Wrapping, WrappingNeg};
use core::ops::Neg;
use subtle::Choice;

Expand Down Expand Up @@ -33,6 +33,12 @@ impl BoxedUint {
}
}

impl WrappingNeg for BoxedUint {
fn wrapping_neg(&self) -> Self {
self.wrapping_neg()
}
}

#[cfg(test)]
mod tests {
use crate::BoxedUint;
Expand Down
Loading