use crate::{MontgomeryParameters, SquareFullInline, U256};
pub(crate) mod generic;
pub(crate) mod proth;
#[allow(unreachable_pub)]
pub use generic::to_montgomery_const;
#[inline(always)]
pub(crate) fn redc_inline<M: MontgomeryParameters<UInt = U256>>(lo: &U256, hi: &U256) -> U256 {
if proth::is_proth::<M>() {
proth::redc_inline(M::MODULUS.limb(3), lo, hi)
} else {
generic::redc_inline::<M>(lo, hi)
}
}
#[inline(always)]
pub(crate) fn square_redc_inline<M: MontgomeryParameters<UInt = U256>>(x: &U256) -> U256 {
let (lo, hi) = x.square_full_inline();
redc_inline::<M>(&lo, &hi)
}
#[inline(always)]
pub(crate) fn mul_redc_inline<M: MontgomeryParameters<UInt = U256>>(x: &U256, y: &U256) -> U256 {
if proth::is_proth::<M>() {
proth::mul_redc_inline(M::MODULUS.limb(3), x, y)
} else {
generic::mul_redc_inline::<M>(x, y)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MontgomeryParameters;
use zkp_macros_decl::u256h;
struct PrimeField();
impl MontgomeryParameters for PrimeField {
type UInt = U256;
const M64: u64 = 0xffff_ffff_ffff_ffff;
const MODULUS: U256 =
u256h!("0800000000000011000000000000000000000000000000000000000000000001");
const R1: U256 = u256h!("07fffffffffffdf0ffffffffffffffffffffffffffffffffffffffffffffffe1");
const R2: U256 = u256h!("07ffd4ab5e008810ffffffffff6f800000000001330ffffffffffd737e000401");
const R3: U256 = u256h!("038e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e");
}
#[test]
fn test_redc() {
let a = u256h!("0548c135e26faa9c977fb2eda057b54b2e0baa9a77a0be7c80278f4f03462d4c");
let b = u256h!("024385f6bebc1c496e09955db534ef4b1eaff9a78e27d4093cfa8f7c8f886f6b");
let c = u256h!("012e440f0965e7029c218b64f1010006b5c4ba8b1497c4174a32fec025c197bc");
assert_eq!(redc_inline::<PrimeField>(&a, &b), c);
}
#[test]
fn test_mul_redc() {
let a = u256h!("0548c135e26faa9c977fb2eda057b54b2e0baa9a77a0be7c80278f4f03462d4c");
let b = u256h!("024385f6bebc1c496e09955db534ef4b1eaff9a78e27d4093cfa8f7c8f886f6b");
let c = u256h!("012b854fc6321976d374ad069cfdec8bb7b2bd184259dae8f530cbb28f0805b4");
assert_eq!(mul_redc_inline::<PrimeField>(&a, &b), c);
}
}