Skip to content

Commit 0428a2a

Browse files
authored
Add modular inverse (#13)
1 parent c36e2b1 commit 0428a2a

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
describe("Modular inverse", function()
2+
local modular_inverse = require("math.modular_inverse")
3+
4+
it("should handle general cases", function()
5+
assert.equal(5, modular_inverse(3, 7))
6+
assert.equal(4, modular_inverse(-1, 5))
7+
assert.equal(4, modular_inverse(4, 5))
8+
assert.equal(4, modular_inverse(9, 5))
9+
assert.equal(17, modular_inverse(5, 21))
10+
assert.equal(1, modular_inverse(1, 100))
11+
end)
12+
13+
it("should handle cases when inputs are not co-prime", function()
14+
assert.equal(nil, modular_inverse(2, 2))
15+
assert.equal(nil, modular_inverse(5, 15))
16+
assert.equal(nil, modular_inverse(0, 1))
17+
end)
18+
19+
it("should throw error when modulus is zero", function()
20+
assert.has_error(function()
21+
modular_inverse(1, 0)
22+
end)
23+
end)
24+
25+
it("should throw error when modulus is negative", function()
26+
assert.has_error(function()
27+
modular_inverse(1, -1)
28+
end)
29+
end)
30+
end)

src/math/modular_inverse.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
local extended_gcd = require("math.greatest_common_divisor")
2+
3+
-- Computes the inverse of `a` modulo `m`, i.e.
4+
-- finds a number `x` such that
5+
-- (a * x) % m == 1 and 0 < x < m
6+
return function(
7+
a, -- number
8+
m -- modulus
9+
)
10+
assert(m > 0, "modulus must be positive")
11+
local gcd, x, _ = extended_gcd(a % m, m)
12+
if a ~= 0 and gcd == 1 then
13+
-- Ensure that result is in (0, m)
14+
return x % m
15+
end
16+
return nil
17+
end

0 commit comments

Comments
 (0)