Skip to content

Commit 59e1a27

Browse files
committed
Add SubResidue trait and impls for Residue and DynResidue
1 parent 023b621 commit 59e1a27

6 files changed

Lines changed: 172 additions & 0 deletions

File tree

src/uint/modular.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@ mod add;
1313
mod inv;
1414
mod mul;
1515
mod pow;
16+
mod sub;
1617

1718
/// Provides a consistent interface to add two residues of the same type together.
1819
pub trait AddResidue {
1920
/// Computes the (reduced) sum of two residues.
2021
fn add(&self, rhs: &Self) -> Self;
2122
}
2223

24+
/// Provides a consistent interface to subtract two residues of the same type.
25+
pub trait SubResidue {
26+
/// Computes the (reduced) difference of two residues.
27+
fn sub(&self, rhs: &Self) -> Self;
28+
}
29+
2330
/// Provides a consistent interface to multiply two residues of the same type together.
2431
pub trait MulResidue
2532
where

src/uint/modular/constant_mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ mod const_inv;
1414
mod const_mul;
1515
/// Exponentiation of residues with a constant modulus
1616
mod const_pow;
17+
/// Subtractions between residues with a constant modulus
18+
mod const_sub;
1719

1820
/// Macros to remove the boilerplate code when dealing with constant moduli.
1921
#[macro_use]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use core::ops::SubAssign;
2+
3+
use crate::{
4+
modular::{sub::sub_montgomery_form, SubResidue},
5+
Uint,
6+
};
7+
8+
use super::{Residue, ResidueParams};
9+
10+
impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> SubResidue for Residue<MOD, LIMBS> {
11+
fn sub(&self, rhs: &Self) -> Self {
12+
self.sub(rhs)
13+
}
14+
}
15+
16+
impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
17+
/// Adds two residues together.
18+
pub const fn sub(&self, rhs: &Self) -> Self {
19+
Residue {
20+
montgomery_form: sub_montgomery_form(
21+
&self.montgomery_form,
22+
&rhs.montgomery_form,
23+
&MOD::MODULUS,
24+
),
25+
phantom: core::marker::PhantomData,
26+
}
27+
}
28+
}
29+
30+
impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> SubAssign<&Uint<LIMBS>>
31+
for Residue<MOD, LIMBS>
32+
{
33+
fn sub_assign(&mut self, rhs: &Uint<LIMBS>) {
34+
*self -= &Residue::new(*rhs);
35+
}
36+
}
37+
38+
impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> SubAssign<&Self> for Residue<MOD, LIMBS> {
39+
fn sub_assign(&mut self, rhs: &Self) {
40+
*self = self.sub(rhs);
41+
}
42+
}
43+
44+
#[cfg(test)]
45+
mod tests {
46+
use crate::{
47+
const_residue, impl_modulus, modular::constant_mod::ResidueParams, traits::Encoding, U256,
48+
};
49+
50+
impl_modulus!(
51+
Modulus,
52+
U256,
53+
"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
54+
);
55+
56+
#[test]
57+
fn sub_overflow() {
58+
let x =
59+
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
60+
let mut x_mod = const_residue!(x, Modulus);
61+
62+
let y =
63+
U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251");
64+
65+
x_mod -= &y;
66+
67+
let expected =
68+
U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56");
69+
70+
assert_eq!(expected, x_mod.retrieve());
71+
}
72+
}

src/uint/modular/runtime_mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ mod runtime_inv;
1010
mod runtime_mul;
1111
/// Exponentiation of residues with a modulus set at runtime
1212
mod runtime_pow;
13+
/// Subtractions between residues with a modulus set at runtime
14+
mod runtime_sub;
1315

1416
/// The parameters to efficiently go to and from the Montgomery form for a modulus provided at runtime.
1517
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use core::ops::{Sub, SubAssign};
2+
3+
use crate::{
4+
modular::{sub::sub_montgomery_form, SubResidue},
5+
Uint,
6+
};
7+
8+
use super::DynResidue;
9+
10+
impl<const LIMBS: usize> SubResidue for DynResidue<LIMBS> {
11+
fn sub(&self, rhs: &Self) -> Self {
12+
debug_assert_eq!(self.residue_params, rhs.residue_params);
13+
Self {
14+
montgomery_form: sub_montgomery_form(
15+
&self.montgomery_form,
16+
&rhs.montgomery_form,
17+
&self.residue_params.modulus,
18+
),
19+
residue_params: self.residue_params,
20+
}
21+
}
22+
}
23+
24+
impl<const LIMBS: usize> SubAssign for DynResidue<LIMBS> {
25+
fn sub_assign(&mut self, rhs: Self) {
26+
self.montgomery_form = sub_montgomery_form(
27+
&self.montgomery_form,
28+
&rhs.montgomery_form,
29+
&self.residue_params.modulus,
30+
);
31+
}
32+
}
33+
34+
impl<const LIMBS: usize> SubAssign<Uint<LIMBS>> for DynResidue<LIMBS> {
35+
fn sub_assign(&mut self, rhs: Uint<LIMBS>) {
36+
self.montgomery_form = sub_montgomery_form(
37+
&self.montgomery_form,
38+
&DynResidue::new(rhs, self.residue_params).montgomery_form,
39+
&self.residue_params.modulus,
40+
);
41+
}
42+
}
43+
44+
impl<const LIMBS: usize> Sub for DynResidue<LIMBS> {
45+
type Output = DynResidue<LIMBS>;
46+
47+
fn sub(mut self, rhs: Self) -> Self::Output {
48+
self -= rhs;
49+
self
50+
}
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use crate::{
56+
modular::runtime_mod::{DynResidue, DynResidueParams},
57+
U256,
58+
};
59+
60+
#[test]
61+
fn sub_overflow() {
62+
let params = DynResidueParams::new(U256::from_be_hex(
63+
"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
64+
));
65+
66+
let x =
67+
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
68+
let mut x_mod = DynResidue::new(x, params);
69+
70+
let y =
71+
U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251");
72+
73+
x_mod -= y;
74+
75+
let expected =
76+
U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56");
77+
78+
assert_eq!(expected, x_mod.retrieve());
79+
}
80+
}

src/uint/modular/sub.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use crate::Uint;
2+
3+
pub(crate) const fn sub_montgomery_form<const LIMBS: usize>(
4+
a: &Uint<LIMBS>,
5+
b: &Uint<LIMBS>,
6+
modulus: &Uint<LIMBS>,
7+
) -> Uint<LIMBS> {
8+
a.sub_mod(b, modulus)
9+
}

0 commit comments

Comments
 (0)