crypto_bigint/uint/
modular.rs1mod reduction;
2
3pub mod constant_mod;
5pub mod runtime_mod;
7
8mod add;
9mod div_by_2;
10mod inv;
11mod mul;
12mod pow;
13mod sub;
14
15pub use reduction::montgomery_reduction;
16
17pub trait Retrieve {
20 type Output;
22
23 fn retrieve(&self) -> Self::Output;
25}
26
27#[cfg(test)]
28mod tests {
29 use crate::{
30 const_residue, impl_modulus,
31 modular::{
32 constant_mod::Residue, constant_mod::ResidueParams, reduction::montgomery_reduction,
33 },
34 NonZero, Uint, U256, U64,
35 };
36
37 impl_modulus!(
38 Modulus1,
39 U256,
40 "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
41 );
42
43 #[test]
44 fn test_montgomery_params() {
45 assert_eq!(
46 Modulus1::R,
47 U256::from_be_hex("1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffe")
48 );
49 assert_eq!(
50 Modulus1::R2,
51 U256::from_be_hex("0748d9d99f59ff1105d314967254398f2b6cedcb87925c23c999e990f3f29c6d")
52 );
53 assert_eq!(
54 Modulus1::MOD_NEG_INV,
55 U64::from_be_hex("fffffffeffffffff").limbs[0]
56 );
57 }
58
59 impl_modulus!(
60 Modulus2,
61 U256,
62 "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
63 );
64
65 #[test]
66 fn test_reducing_r() {
67 assert_eq!(
69 montgomery_reduction::<{ Modulus2::LIMBS }>(
70 &(Modulus2::R, Uint::ZERO),
71 &Modulus2::MODULUS,
72 Modulus2::MOD_NEG_INV
73 ),
74 Uint::ONE
75 );
76 }
77
78 #[test]
79 fn test_reducing_r2() {
80 assert_eq!(
82 montgomery_reduction::<{ Modulus2::LIMBS }>(
83 &(Modulus2::R2, Uint::ZERO),
84 &Modulus2::MODULUS,
85 Modulus2::MOD_NEG_INV
86 ),
87 Modulus2::R
88 );
89 }
90
91 #[test]
92 fn test_reducing_r2_wide() {
93 let (hi, lo) = Modulus2::R.square().split();
95 assert_eq!(
96 montgomery_reduction::<{ Modulus2::LIMBS }>(
97 &(lo, hi),
98 &Modulus2::MODULUS,
99 Modulus2::MOD_NEG_INV
100 ),
101 Modulus2::R
102 );
103 }
104
105 #[test]
106 fn test_reducing_xr_wide() {
107 let x =
109 U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
110 let product = x.mul_wide(&Modulus2::R);
111 assert_eq!(
112 montgomery_reduction::<{ Modulus2::LIMBS }>(
113 &product,
114 &Modulus2::MODULUS,
115 Modulus2::MOD_NEG_INV
116 ),
117 x
118 );
119 }
120
121 #[test]
122 fn test_reducing_xr2_wide() {
123 let x =
125 U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
126 let product = x.mul_wide(&Modulus2::R2);
127
128 let (lo, hi) = x.mul_wide(&Modulus2::R);
130 let c = hi.concat(&lo);
131 let red = c.rem(&NonZero::new(U256::ZERO.concat(&Modulus2::MODULUS)).unwrap());
132 let (hi, lo) = red.split();
133 assert_eq!(hi, Uint::ZERO);
134
135 assert_eq!(
136 montgomery_reduction::<{ Modulus2::LIMBS }>(
137 &product,
138 &Modulus2::MODULUS,
139 Modulus2::MOD_NEG_INV
140 ),
141 lo
142 );
143 }
144
145 #[test]
146 fn test_new_retrieve() {
147 let x =
148 U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
149 let x_mod = Residue::<Modulus2, { Modulus2::LIMBS }>::new(&x);
150
151 assert_eq!(x, x_mod.retrieve());
153 }
154
155 #[test]
156 fn test_residue_macro() {
157 let x =
158 U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
159 assert_eq!(
160 Residue::<Modulus2, { Modulus2::LIMBS }>::new(&x),
161 const_residue!(x, Modulus2)
162 );
163 }
164}