Skip to content

Commit 13d33f3

Browse files
committed
Add comprehensive doctests to find_mod_inverse function
- Added detailed docstring explaining modular multiplicative inverse - Included 10 valid test cases with verification calculations - Added 3 error cases testing ValueError for non-coprime inputs - Added Wikipedia reference for educational value - All doctests pass locally (python -m doctest -v) - Passes ruff, mypy, and pre-commit hooks Contributes to #9943
1 parent a71618f commit 13d33f3

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

ciphers/cryptomath_module.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,62 @@
22

33

44
def find_mod_inverse(a: int, m: int) -> int:
5+
"""
6+
Find the modular multiplicative inverse of a modulo m.
7+
8+
The modular multiplicative inverse of a modulo m is an integer x such that:
9+
(a * x) % m = 1
10+
11+
This function uses the Extended Euclidean Algorithm to find the inverse.
12+
An inverse exists if and only if a and m are coprime (gcd(a, m) = 1).
13+
14+
Args:
15+
a: The integer to find the inverse of
16+
m: The modulus
17+
18+
Returns:
19+
The modular multiplicative inverse of a modulo m
20+
21+
Raises:
22+
ValueError: If gcd(a, m) != 1 (inverse does not exist)
23+
24+
Reference:
25+
https://en.wikipedia.org/wiki/Modular_multiplicative_inverse
26+
27+
Examples:
28+
>>> find_mod_inverse(3, 7)
29+
5
30+
>>> (3 * 5) % 7 # Verify: 3 * 5 ≡ 1 (mod 7)
31+
1
32+
>>> find_mod_inverse(3, 10)
33+
7
34+
>>> (3 * 7) % 10 # Verify: 3 * 7 ≡ 1 (mod 10)
35+
1
36+
>>> find_mod_inverse(4, 11)
37+
3
38+
>>> (4 * 3) % 11 # Verify: 4 * 3 ≡ 1 (mod 11)
39+
1
40+
>>> find_mod_inverse(7, 26)
41+
15
42+
>>> (7 * 15) % 26 # Verify: 7 * 15 ≡ 1 (mod 26)
43+
1
44+
>>> find_mod_inverse(1, 5)
45+
1
46+
>>> find_mod_inverse(5, 11)
47+
9
48+
>>> find_mod_inverse(2, 4)
49+
Traceback (most recent call last):
50+
...
51+
ValueError: mod inverse of 2 and 4 does not exist
52+
>>> find_mod_inverse(6, 9)
53+
Traceback (most recent call last):
54+
...
55+
ValueError: mod inverse of 6 and 9 does not exist
56+
>>> find_mod_inverse(10, 20)
57+
Traceback (most recent call last):
58+
...
59+
ValueError: mod inverse of 10 and 20 does not exist
60+
"""
561
if gcd_by_iterative(a, m) != 1:
662
msg = f"mod inverse of {a!r} and {m!r} does not exist"
763
raise ValueError(msg)

0 commit comments

Comments
 (0)