Skip to main content

crypto_bigint/modular/const_monty_form/
macros.rs

1//! [`ConstMontyForm`]/[`ConstMontyParams`] support macros.
2
3#[cfg(doc)]
4use crate::modular::{ConstMontyForm, ConstMontyParams, ConstPrimeMontyParams};
5
6/// Create a type representing a modulus which impls the [`ConstMontyParams`] trait with the given
7/// name, type, value (in big endian hex), and optional documentation string.
8///
9/// # Usage
10///
11/// ```
12/// use crypto_bigint::{U256, const_monty_params};
13///
14/// const_monty_params!(
15///     MyModulus,
16///     U256,
17///     "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
18///     "Docs for my modulus"
19/// );
20/// ```
21///
22/// The modulus _must_ be odd, or this will panic.
23// TODO: use `adt_const_params` when stable to make a `ConstMontyForm` generic around a modulus
24#[macro_export]
25macro_rules! const_monty_params {
26    ($name:ident, $uint_type:ty, $value:expr) => {
27        $crate::const_monty_params!(
28            $name,
29            $uint_type,
30            $value,
31            "Modulus which impls `ConstMontyParams`"
32        );
33    };
34    ($name:ident, $uint_type:ty, $value:expr, $doc:expr) => {
35        #[doc = $doc]
36        #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
37        pub struct $name;
38        impl $crate::modular::ConstMontyParams<{ <$uint_type>::LIMBS }> for $name {
39            const LIMBS: usize = <$uint_type>::LIMBS;
40            const PARAMS: $crate::modular::FixedMontyParams<{ <$uint_type>::LIMBS }> =
41                $crate::modular::FixedMontyParams::new_vartime(
42                    $crate::Odd::<$uint_type>::from_be_hex($value),
43                );
44        }
45    };
46}
47
48/// Create a type representing a prime modulus which impls the [`ConstPrimeMontyParams`]
49/// trait with the given name, type, value (in big endian hex), multiplicative generator,
50/// and optional documentation string.
51///
52/// # Usage
53///
54/// ```
55/// use crypto_bigint::{U256, const_prime_monty_params};
56///
57/// const_prime_monty_params!(
58///     MyModulus,
59///     U256,
60///     "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
61///     7,
62///     "Docs for my modulus"
63/// );
64/// ```
65///
66/// The modulus _must_ be odd and prime, or this will panic.
67#[macro_export]
68macro_rules! const_prime_monty_params {
69    ($name:ident, $uint_type:ty, $value:expr, $generator:literal) => {
70        $crate::const_prime_monty_params!(
71            $name,
72            $uint_type,
73            $value,
74            $generator,
75            "Modulus which impls `ConstPrimeMontyParams`"
76        );
77    };
78    ($name:ident, $uint_type:ty, $value:expr, $generator:literal, $doc:expr) => {
79        $crate::const_monty_params!($name, $uint_type, $value, $doc);
80
81        impl $crate::modular::ConstPrimeMontyParams<{ <$uint_type>::LIMBS }> for $name {
82            const PRIME_PARAMS: $crate::modular::PrimeParams<{ <$uint_type>::LIMBS }> =
83                $crate::modular::PrimeParams::new_vartime(
84                    &<$name as $crate::modular::ConstMontyParams<{ <$uint_type>::LIMBS }>>::PARAMS,
85                    $generator,
86                );
87        }
88    };
89}
90
91/// Creates a type alias to [`ConstMontyForm`] with the given [`ConstMontyParams`].
92///
93/// # Usage
94///
95/// ```
96/// use crypto_bigint::{U256, modular::ConstMontyParams, const_monty_form};
97/// #
98/// # crypto_bigint::const_monty_params!(
99/// #    MyModulus,
100/// #    U256,
101/// #    "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
102/// #    "Docs for my modulus"
103/// # );
104///
105/// const_monty_form!(MyFieldElement, MyModulus, "My field element");
106/// ```
107#[macro_export]
108macro_rules! const_monty_form {
109    ($name:ident, $modulus:ident) => {
110        $crate::const_monty_form!(
111            $name,
112            $modulus,
113            "Type alias for `ConstMontyForm` specialized for a particular modulus"
114        );
115    };
116    ($name:ident, $modulus:ident, $doc:expr) => {
117        #[doc = $doc]
118        pub type $name = $crate::modular::ConstMontyForm<$modulus, { $modulus::LIMBS }>;
119    };
120}
121
122/// Deprecated legacy macro which has been replaced by [`const_monty_form!`].
123#[deprecated(since = "0.7.0", note = "use `const_monty_params!` instead")]
124#[macro_export]
125macro_rules! impl_modulus {
126    ($name:ident, $uint_type:ty, $value:expr) => {
127        $crate::const_monty_params!(
128            $name,
129            $uint_type,
130            $value,
131            "Modulus which impls `ConstMontyParams`"
132        );
133    };
134    ($name:ident, $uint_type:ty, $value:expr, $doc:expr) => {
135        $crate::const_monty_params!($name, $uint_type, $value, $doc);
136    };
137}
138
139#[cfg(test)]
140mod tests {
141    use crate::modular::ConstMontyParams;
142    use crate::{Limb, U64};
143
144    #[test]
145    fn new_params_with_valid_modulus() {
146        const_monty_params!(Mod, U64, "0000000000000003");
147        assert_eq!(
148            Mod::PARAMS.mod_leading_zeros,
149            core::cmp::min(Limb::BITS - 1, 62)
150        );
151    }
152
153    /// Make sure the deprecated macro still works
154    // TODO(tarcieri): remove this in the next breaking release
155    #[test]
156    #[allow(deprecated)]
157    fn impl_modulus_with_valid_modulus() {
158        impl_modulus!(Mod, U64, "0000000000000003");
159        assert_eq!(
160            Mod::PARAMS.mod_leading_zeros,
161            core::cmp::min(Limb::BITS - 1, 62)
162        );
163    }
164}