crypto_bigint/modular/const_monty_form/
mul.rs1use core::{
4 marker::PhantomData,
5 ops::{Mul, MulAssign},
6};
7
8use crate::{
9 modular::mul::{mul_montgomery_form, square_montgomery_form, square_repeat_montgomery_form},
10 traits::Square,
11};
12
13use super::{ConstMontyForm, ConstMontyParams};
14
15impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> ConstMontyForm<MOD, LIMBS> {
16 #[must_use]
18 pub const fn mul(&self, rhs: &Self) -> Self {
19 Self {
20 montgomery_form: mul_montgomery_form(
21 &self.montgomery_form,
22 &rhs.montgomery_form,
23 &MOD::PARAMS.modulus,
24 MOD::PARAMS.mod_neg_inv(),
25 ),
26 phantom: PhantomData,
27 }
28 }
29
30 #[must_use]
32 pub const fn square(&self) -> Self {
33 Self {
34 montgomery_form: square_montgomery_form(
35 &self.montgomery_form,
36 &MOD::PARAMS.modulus,
37 MOD::PARAMS.mod_neg_inv(),
38 ),
39 phantom: PhantomData,
40 }
41 }
42
43 #[must_use]
47 pub const fn square_repeat_vartime(&self, n: u32) -> Self {
48 Self {
49 montgomery_form: square_repeat_montgomery_form::<LIMBS>(
50 &self.montgomery_form,
51 n,
52 &MOD::PARAMS.modulus,
53 MOD::PARAMS.mod_neg_inv(),
54 ),
55 phantom: PhantomData,
56 }
57 }
58}
59
60impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Mul<&ConstMontyForm<MOD, LIMBS>>
61 for &ConstMontyForm<MOD, LIMBS>
62{
63 type Output = ConstMontyForm<MOD, LIMBS>;
64 fn mul(self, rhs: &ConstMontyForm<MOD, LIMBS>) -> ConstMontyForm<MOD, LIMBS> {
65 self.mul(rhs)
66 }
67}
68
69impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Mul<ConstMontyForm<MOD, LIMBS>>
70 for &ConstMontyForm<MOD, LIMBS>
71{
72 type Output = ConstMontyForm<MOD, LIMBS>;
73 #[allow(clippy::op_ref)]
74 fn mul(self, rhs: ConstMontyForm<MOD, LIMBS>) -> ConstMontyForm<MOD, LIMBS> {
75 self * &rhs
76 }
77}
78
79impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Mul<&ConstMontyForm<MOD, LIMBS>>
80 for ConstMontyForm<MOD, LIMBS>
81{
82 type Output = ConstMontyForm<MOD, LIMBS>;
83 #[allow(clippy::op_ref)]
84 fn mul(self, rhs: &ConstMontyForm<MOD, LIMBS>) -> ConstMontyForm<MOD, LIMBS> {
85 &self * rhs
86 }
87}
88
89impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Mul<ConstMontyForm<MOD, LIMBS>>
90 for ConstMontyForm<MOD, LIMBS>
91{
92 type Output = ConstMontyForm<MOD, LIMBS>;
93 fn mul(self, rhs: ConstMontyForm<MOD, LIMBS>) -> ConstMontyForm<MOD, LIMBS> {
94 &self * &rhs
95 }
96}
97
98impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> MulAssign<&Self>
99 for ConstMontyForm<MOD, LIMBS>
100{
101 fn mul_assign(&mut self, rhs: &ConstMontyForm<MOD, LIMBS>) {
102 *self = *self * rhs;
103 }
104}
105
106impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> MulAssign<Self>
107 for ConstMontyForm<MOD, LIMBS>
108{
109 fn mul_assign(&mut self, rhs: Self) {
110 *self *= &rhs;
111 }
112}
113
114impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Square for ConstMontyForm<MOD, LIMBS> {
115 fn square(&self) -> Self {
116 ConstMontyForm::square(self)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use crate::{
123 U256, const_monty_form, const_monty_params,
124 modular::const_monty_form::{ConstMontyForm, ConstMontyParams},
125 };
126
127 const_monty_params!(
128 Modulus,
129 U256,
130 "15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409"
131 );
132
133 const_monty_form!(Fe, Modulus);
134
135 const N: U256 =
136 U256::from_be_hex("14117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685");
137 const N_MOD: ConstMontyForm<Modulus, { U256::LIMBS }> = ConstMontyForm::new(&N);
138
139 #[test]
140 fn test_mul_zero() {
141 let res = N_MOD.mul(&Fe::ZERO);
142 let expected = U256::ZERO;
143 assert_eq!(res.retrieve(), expected);
144 }
145
146 #[test]
147 fn test_mul_one() {
148 let res = N_MOD.mul(&Fe::ONE);
149 assert_eq!(res.retrieve(), N);
150 }
151
152 #[test]
153 fn test_mul_eq_add() {
154 let res = N_MOD.mul(&Fe::new(&U256::from(2u8)));
155 assert_eq!(res, N_MOD.add(&N_MOD));
156 }
157
158 #[test]
159 fn test_square_eq_mul() {
160 let res = N_MOD.square();
161 let expected = N_MOD.mul(&N_MOD);
162 assert_eq!(res, expected);
163 }
164
165 #[test]
166 fn test_square_repeat() {
167 let res = N_MOD.square_repeat_vartime(0);
168 assert_eq!(res, N_MOD);
169
170 let res = N_MOD.square_repeat_vartime(1);
171 assert_eq!(res, N_MOD.square());
172
173 let res = N_MOD.square_repeat_vartime(5);
174 let expected = N_MOD.square().square().square().square().square();
175 assert_eq!(res, expected);
176 }
177}