From bc970f0a27eae26b85bdd4d4f96081b486b44712 Mon Sep 17 00:00:00 2001 From: Saleh Mir Date: Thu, 9 Jan 2025 17:57:03 +0330 Subject: [PATCH] Implement Extended Euclidean Algorithm with igcdex function and add corresponding tests - Introduced a new function `igcdex` in `math_utils.py` to compute the extended greatest common divisor, returning coefficients and the gcd. - Added unit tests for `igcdex` in `test_math_utils.py` to ensure correctness of the implementation. - Removed the outdated `sympy` dependency from `requirements.txt` to clean up the requirements. --- jesse/math_utils.py | 39 +++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 - tests/test_math_utils.py | 6 ++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 jesse/math_utils.py create mode 100644 tests/test_math_utils.py diff --git a/jesse/math_utils.py b/jesse/math_utils.py new file mode 100644 index 000000000..a01825366 --- /dev/null +++ b/jesse/math_utils.py @@ -0,0 +1,39 @@ +def igcdex(a, b): + """Returns x, y, g such that g = x*a + y*b = gcd(a, b). + >>> igcdex(2, 3) + (-1, 1, 1) + >>> igcdex(10, 12) + (-1, 1, 2) + + >>> x, y, g = igcdex(100, 2004) + >>> x, y, g + (-20, 1, 4) + >>> x*100 + y*2004 + 4 + + """ + if (not a) and (not b): + return (0, 1, 0) + + if not a: + return (0, b // abs(b), abs(b)) + if not b: + return (a // abs(a), 0, abs(a)) + + if a < 0: + a, x_sign = -a, -1 + else: + x_sign = 1 + + if b < 0: + b, y_sign = -b, -1 + else: + y_sign = 1 + + x, y, r, s = 1, 0, 0, 1 + + while b: + (c, q) = (a % b, a // b) + (a, b, r, s, x, y) = (b, c, x - q * r, y - q * s, r, s) + + return (x * x_sign, y * y_sign, a) diff --git a/requirements.txt b/requirements.txt index 487926e9a..449e12fb9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,5 +28,4 @@ aiofiles~=0.7.0 numba~=0.61.0rc2 PyJWT~=2.8.0 cryptography~=42.0.5 -sympy~=1.6 ecdsa>=0.16.0 diff --git a/tests/test_math_utils.py b/tests/test_math_utils.py new file mode 100644 index 000000000..367d1208d --- /dev/null +++ b/tests/test_math_utils.py @@ -0,0 +1,6 @@ +import jesse.math_utils as mu + + +def test_igcdex(): + assert mu.igcdex(2, 3) == (-1, 1, 1) + assert mu.igcdex(10, 12) == (-1, 1, 2)