Skip to content

Commit 7c6f898

Browse files
authored
primefield: support precomputed ROOT_OF_UNITY constant (#1469)
Being able to compute `ROOT_OF_UNITY` at compile time is super cool! The only problem is we're running `modpow` at compile time, and miri is slow. For large fields, it may be impractically slow. This makes it possible to define field parameters that include a precomputed `ROOT_OF_UNITY` constant.
1 parent edd7411 commit 7c6f898

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

primefield/src/macros.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,30 @@ macro_rules! monty_field_params {
3434
byte_order: $byte_order:expr,
3535
multiplicative_generator: $multiplicative_generator:expr,
3636
doc: $doc:expr
37+
) => {
38+
$crate::monty_field_params_with_root_of_unity! {
39+
name: $name,
40+
modulus: $modulus_hex,
41+
uint: $uint,
42+
byte_order: $byte_order,
43+
multiplicative_generator: $multiplicative_generator,
44+
root_of_unity: None,
45+
doc: $doc
46+
}
47+
};
48+
}
49+
50+
/// Same as [`monty_field_params!`], but with a precomputed `ROOT_OF_UNITY` constant.
51+
#[macro_export]
52+
macro_rules! monty_field_params_with_root_of_unity {
53+
(
54+
name: $name:ident,
55+
modulus: $modulus_hex:expr,
56+
uint: $uint:ty,
57+
byte_order: $byte_order:expr,
58+
multiplicative_generator: $multiplicative_generator:expr,
59+
root_of_unity: $root_of_unity:expr,
60+
doc: $doc:expr
3761
) => {
3862
use $crate::bigint::modular::ConstMontyParams;
3963

@@ -47,6 +71,7 @@ macro_rules! monty_field_params {
4771
const MODULUS_HEX: &'static str = $modulus_hex;
4872
const MULTIPLICATIVE_GENERATOR: u64 = $multiplicative_generator;
4973
const T: $uint = $crate::compute_t($name::PARAMS.modulus().as_ref());
74+
const ROOT_OF_UNITY: Option<$uint> = $root_of_unity;
5075
}
5176
};
5277
}

primefield/src/monty.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ pub trait MontyFieldParams<const LIMBS: usize>: ConstMontyParams<LIMBS> {
3838
/// This element must also be a quadratic nonresidue.
3939
const MULTIPLICATIVE_GENERATOR: u64;
4040

41-
/// `t = (modulus - 1) >> s`, where `S = (modulus - 1).trailing_zeros()`
41+
/// `T = (modulus - 1) >> S`, where `S = (modulus - 1).trailing_zeros()`
4242
const T: Uint<LIMBS>;
43+
44+
/// Optional precomputed `ROOT_OF_UNITY`, otherwise will be computed at compile-time.
45+
const ROOT_OF_UNITY: Option<Uint<LIMBS>>;
4346
}
4447

4548
/// Serialized representation of a field element.
@@ -455,7 +458,10 @@ where
455458
const TWO_INV: Self = Self::from_u64(2).const_invert();
456459
const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(MOD::MULTIPLICATIVE_GENERATOR);
457460
const S: u32 = compute_s(MOD::PARAMS.modulus().as_ref());
458-
const ROOT_OF_UNITY: Self = Self::MULTIPLICATIVE_GENERATOR.pow_vartime(&MOD::T);
461+
const ROOT_OF_UNITY: Self = match MOD::ROOT_OF_UNITY {
462+
Some(root_of_unity) => Self::from_uint_reduced(&root_of_unity),
463+
None => Self::MULTIPLICATIVE_GENERATOR.pow_vartime(&MOD::T),
464+
};
459465
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.const_invert();
460466
const DELTA: Self = Self::MULTIPLICATIVE_GENERATOR.sqn_vartime(Self::S as usize);
461467

0 commit comments

Comments
 (0)