crypto_bigint/int/
invert_mod.rs1use crate::{CtOption, Int, InvertMod, NonZero, Odd, Uint};
4
5impl<const LIMBS: usize> Int<LIMBS> {
6 #[must_use]
8 pub fn invert_odd_mod(&self, modulus: &Odd<Uint<LIMBS>>) -> CtOption<Uint<LIMBS>> {
9 let (abs, sgn) = self.abs_sign();
10 let maybe_inv = abs.invert_odd_mod(modulus);
11 let abs_inv = maybe_inv.as_inner_unchecked();
12
13 CtOption::new(
16 Uint::select(abs_inv, &modulus.wrapping_sub(abs_inv), sgn),
17 maybe_inv.is_some(),
18 )
19 }
20
21 #[must_use]
25 pub const fn invert_mod(&self, modulus: &NonZero<Uint<LIMBS>>) -> CtOption<Uint<LIMBS>> {
26 let (abs, sgn) = self.abs_sign();
27 let maybe_inv = abs.invert_mod(modulus);
28 let abs_inv = maybe_inv.as_inner_unchecked();
29
30 CtOption::new(
33 Uint::select(abs_inv, &modulus.as_ref().wrapping_sub(abs_inv), sgn),
34 maybe_inv.is_some(),
35 )
36 }
37}
38
39impl<const LIMBS: usize> InvertMod<NonZero<Uint<LIMBS>>> for Int<LIMBS>
40where
41 Uint<LIMBS>: InvertMod<Output = Uint<LIMBS>>,
42{
43 type Output = Uint<LIMBS>;
44
45 fn invert_mod(&self, modulus: &NonZero<Uint<LIMBS>>) -> CtOption<Self::Output> {
46 Self::invert_mod(self, modulus)
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::{I1024, U1024};
53
54 #[test]
55 fn test_invert_odd() {
56 let a = I1024::from_be_hex(concat![
57 "FFFDDA166EAC4B985A4BAE6865C0BAE2510C4072939ADE2D05DB444E80D6ABB1",
58 "CB85BED4F9A48A5CAE1568E61DBCF2DB884EE3363063E5291211D934EA0B9C07",
59 "4338D107815CFD7716A5B75586DDD93136A6234F98D270627F5AB344157A3527",
60 "C7D13DDB214D0A87B19D2F33D07E3D1952EB145419B92989B4CF3CD47897767B"
61 ]);
62 let m = U1024::from_be_hex(concat![
63 "D509E7854ABDC81921F669F1DC6F61359523F3949803E58ED4EA8BC16483DC6F",
64 "37BFE27A9AC9EEA2969B357ABC5C0EE214BE16A7D4C58FC620D5B5A20AFF001A",
65 "D198D3155E5799DC4EA76652D64983A7E130B5EACEBAC768D28D589C36EC749C",
66 "558D0B64E37CD0775C0D0104AE7D98BA23C815185DD43CD8B16292FD94156767"
67 ])
68 .to_odd()
69 .unwrap();
70 let expected = U1024::from_be_hex(concat![
71 "24D3C45CFFAF0D5C7620A469C3DC2F3313DDE78A0987F0CEF7EABFF4A5407219",
72 "645BBF1E19580A3619798AAA545597FCA2496DAA2DF4685D313F98F52DD151C3",
73 "48BF956F72C8BDA32FC3F3E5F955226B8D9138C6E64AA568075BA2AEDBE58ED2",
74 "173B01FCA9E1905F9C74589FB3C36D55A4CBCB7FA86CC803BE979091D3F0C431"
75 ]);
76
77 let res = a.invert_odd_mod(&m).unwrap();
78 assert_eq!(res, expected);
79
80 let res = a.invert_mod(&m.to_nz().unwrap()).unwrap();
82 assert_eq!(res, expected);
83 }
84
85 #[test]
86 fn test_invert_even() {
87 let a = I1024::from_be_hex(concat![
88 "FFFDDA166EAC4B985A4BAE6865C0BAE2510C4072939ADE2D05DB444E80D6ABB1",
89 "CB85BED4F9A48A5CAE1568E61DBCF2DB884EE3363063E5291211D934EA0B9C07",
90 "4338D107815CFD7716A5B75586DDD93136A6234F98D270627F5AB344157A3527",
91 "C7D13DDB214D0A87B19D2F33D07E3D1952EB145419B92989B4CF3CD47897767B",
92 ]);
93 let m = U1024::from_be_hex(concat![
94 "D509E7854ABDC81921F669F1DC6F61359523F3949803E58ED4EA8BC16483DC6F",
95 "37BFE27A9AC9EEA2969B357ABC5C0EE214BE16A7D4C58FC620D5B5A20AFF001A",
96 "D198D3155E5799DC4EA76652D64983A7E130B5EACEBAC768D28D589C36EC749C",
97 "558D0B64E37CD0775C0D0104AE7D98BA23C815185DD43CD8B16292FD94156000"
98 ])
99 .to_nz()
100 .unwrap();
101 let expected = U1024::from_be_hex(concat![
102 "B64AAE72443C49FD5BE587DDE82A265E8C1226D73E5AE3DC3081E6C5471EE917",
103 "5BC37EF8AE73B8D7F0365652BC335F9BC375EA303381B08D4A15E0CBBF92FDF4",
104 "D58AB97A48B1507553808DC84F9C6F656F39F81D9157AE2E1FD98C487D4D52F8",
105 "F9F1107F0F4064B074637B983CB6672DAD75067A02F0E455DBB6E2CE7D7ED8B3",
106 ]);
107
108 let res = a.invert_mod(&m).unwrap();
109 assert_eq!(res, expected);
110 }
111}