crypto_bigint/uint/modular/constant_mod/
const_inv.rs1use core::marker::PhantomData;
2
3use subtle::CtOption;
4
5use crate::{modular::inv::inv_montgomery_form, traits::Invert, CtChoice, NonZero};
6
7use super::{Residue, ResidueParams};
8
9impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
10 pub const fn invert(&self) -> (Self, CtChoice) {
15 let (montgomery_form, is_some) = inv_montgomery_form(
16 &self.montgomery_form,
17 &MOD::MODULUS,
18 &MOD::R3,
19 MOD::MOD_NEG_INV,
20 );
21
22 let value = Self {
23 montgomery_form,
24 phantom: PhantomData,
25 };
26
27 (value, is_some)
28 }
29}
30
31impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Invert for Residue<MOD, LIMBS> {
32 type Output = CtOption<Self>;
33 fn invert(&self) -> Self::Output {
34 let (value, is_some) = self.invert();
35 CtOption::new(value, is_some.into())
36 }
37}
38
39impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Invert for NonZero<Residue<MOD, LIMBS>> {
40 type Output = Self;
41 fn invert(&self) -> Self::Output {
42 let (value, _is_some) = self.as_ref().invert();
44 NonZero::new(value).unwrap()
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use crate::{const_residue, impl_modulus, modular::constant_mod::ResidueParams, U256};
51
52 impl_modulus!(
53 Modulus,
54 U256,
55 "15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409"
56 );
57
58 #[test]
59 fn test_self_inverse() {
60 let x =
61 U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685");
62 let x_mod = const_residue!(x, Modulus);
63
64 let (inv, _is_some) = x_mod.invert();
65 let res = x_mod * inv;
66
67 assert_eq!(res.retrieve(), U256::ONE);
68 }
69}