From 20e754033a81ea9bcb63cc99204a57f122a2b443 Mon Sep 17 00:00:00 2001 From: Gerald Teschl Date: Wed, 27 Nov 2024 22:51:53 +0100 Subject: [PATCH] Small improvements --- kryptools/dlp.py | 2 +- kryptools/dlp_bsgs.py | 2 +- kryptools/factor_ecm.py | 2 +- kryptools/la.py | 21 ++++++++------------- kryptools/poly.py | 23 +++++++++-------------- tests/test_primes.py | 18 +++++++++++++++++- 6 files changed, 37 insertions(+), 31 deletions(-) diff --git a/kryptools/dlp.py b/kryptools/dlp.py index 25ac778..c6b98fd 100644 --- a/kryptools/dlp.py +++ b/kryptools/dlp.py @@ -43,7 +43,7 @@ def _dlog_switch(a: int, b: int, n: int, m: int, verbose: int = 0) -> int: # compare the theoreticaly expected running times ob bsgs and ic; the constant 6 is determined experimentally if log(m) - 6 < 2 * sqrt(log(n) * log(log(n))): if verbose > 1: - print(f"BS GS: {a}^x == {b} (order={m})") + print(f"BS GS: {a}^x = {b} (order={m})") return dlog_bsgs(a, b, n, m, verbose=max(0, verbose - 1)) if verbose > 1: print(f"Quadratic sieve: {a}^x == {b} (order={m})") diff --git a/kryptools/dlp_bsgs.py b/kryptools/dlp_bsgs.py index 97c887b..053414e 100644 --- a/kryptools/dlp_bsgs.py +++ b/kryptools/dlp_bsgs.py @@ -43,7 +43,7 @@ def dlog_bsgs(a: int, b: int, n: int, m: int = None, verbose: int = 0) -> int: giant_step = b for l in range(1, mm): giant_step = (giant_step * giant_stride) % n - if show and not k % show and k: + if show and not l % show and l: print(".", end="") if giant_step in baby_steps: if verbose: diff --git a/kryptools/factor_ecm.py b/kryptools/factor_ecm.py index 5da5827..83bd6d4 100644 --- a/kryptools/factor_ecm.py +++ b/kryptools/factor_ecm.py @@ -115,7 +115,7 @@ def factor_ecm(n: int, B1: int | None = None, B2: int | None = None, curves: int v = (4 * sigma) % n try: c = (pow(v - u, 3, n) * (3 * u + v) * pow(4 * u**3 * v, -1, n) - 2) % n - except: + except ValueError: if verbose > 1: print("\nFactor found.") m = gcd(u, n) diff --git a/kryptools/la.py b/kryptools/la.py index f97d308..4028a98 100644 --- a/kryptools/la.py +++ b/kryptools/la.py @@ -127,15 +127,10 @@ def applyfunc(self, func): tmp.map(func) return tmp - def _guess_ring(self): + def _guess_zero(self): zero = 0 * self.matrix[0][0] - try: - ring = type(zero) - one = ring(1) - except: - ring = None - one = zero**0 - return zero, one, ring + one = zero**0 + return zero, one def norm2(self) -> float: "Squared Frobenius/Euclidean norm." @@ -213,7 +208,7 @@ def __rmul__(self, other) -> "Matrix": def rref(self) -> "Matrix": "Compute the reduced echelon form of a matrix M." - zero, one = self._guess_ring()[:2] + zero, one = self._guess_zero() n, m = self.cols, self.rows R = self[:, :] i = 0 @@ -239,7 +234,7 @@ def rref(self) -> "Matrix": def det(self) -> int: "Compute the determinant of a matrix M." - zero, one = self._guess_ring()[:2] + zero, one = self._guess_zero() if self.rows != self.cols: raise ValueError("Matrix must be square!") n, m = self.cols, self.rows @@ -270,7 +265,7 @@ def inv(self) -> "Matrix": "Compute the inverse of a square matrix M." if self.rows != self.cols: raise ValueError("Matrix must be square!") - zero, one = self._guess_ring()[:2] + zero, one = self._guess_zero() n = self.cols MM = self.__class__([[zero for _ in range(2*n)] for _ in range(n)]) for i in range(n): @@ -298,7 +293,7 @@ def zeros(self, m: int = None, n: int = None): n, m = self.cols, self.rows elif not n: n = m - zero = self._guess_ring()[0] + zero = self._guess_zero()[0] return self.__class__([[zero for j in range(n)] for i in range(m)]) def eye(self, m: int = None, n: int = None): @@ -311,7 +306,7 @@ def delta(i, j): n, m = self.cols, self.rows elif not n: n = m - zero, one = self._guess_ring()[:2] + zero, one = self._guess_zero() return self.__class__([[delta(i, j) for j in range(n)] for i in range(m)]) diff --git a/kryptools/poly.py b/kryptools/poly.py index 46ee0f1..dc7961d 100644 --- a/kryptools/poly.py +++ b/kryptools/poly.py @@ -114,15 +114,10 @@ def applyfunc(self, func) -> "Poly": def _check_type(self, other): return isinstance(other, int) or (isinstance(other, Number) and isinstance(self.coeff[0], Number)) or type(other) == type(self.coeff[0]) - def _guess_ring(self): + def _guess_zero(self): zero = 0 * self.coeff[0] - try: - ring = type(zero) - one = ring(1) - except: - ring = None - one = zero**0 - return zero, one, ring + one = zero**0 + return zero, one def __add__(self, other: "Poly") -> "Poly": zero = 0 * self.coeff[0] @@ -230,9 +225,9 @@ def __mod__(self, other: "Poly") -> "Poly": def divmod(self, other: "Poly") -> ("Poly", "Poly"): "Polynom division with remainder." - zero, one, ring = self._guess_ring() + zero, one = self._guess_zero() if isinstance(other, list): - other = self.__class__(other, ring=ring) + other = self.__class__(other) elif not isinstance(other, self.__class__): raise NotImplementedError(f"Cannot divide {self} and {other}.") if not other: @@ -260,9 +255,9 @@ def divmod(self, other: "Poly") -> ("Poly", "Poly"): def mod(self, other: "Poly") -> None: "Reduce with respect to a given polynomial." - one, ring = self._guess_ring()[1:] + one = self._guess_zero()[1] if isinstance(other, list): - other = self.__class__(other, ring=ring) + other = self.__class__(other) elif not isinstance(other, self.__class__): raise NotImplementedError(f"Cannot divide {self} and {other}.") if not other: @@ -289,9 +284,9 @@ def inv(self, other: "Poly" = None) -> "Poly": "Inverse modulo a given polynomial." if not other: other = self.modulus - zero, one, ring = self._guess_ring() + zero, one = self._guess_zero() if isinstance(other, list): - other = self.__class__(other, ring=ring) + other = self.__class__(other) elif not isinstance(other, self.__class__): raise NotImplementedError(f"Cannot invert {self} modulo {other}.") if not other: diff --git a/tests/test_primes.py b/tests/test_primes.py index 18ae75d..829b0c3 100644 --- a/tests/test_primes.py +++ b/tests/test_primes.py @@ -75,13 +75,29 @@ def test_is_prime(): assert is_prime(n) == prime_test[n] +# https://oeis.org/A000043 +OEIS_A000043 = [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, + 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, + 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, + 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, + 32582657, 37156667, 42643801, 43112609, 57885161] + + +def test_mersenne_prime(): + for p in range(1000): + if not prime_test[p]: + continue + if p > OEIS_A000043[-1]: + break + assert is_prime(2**p - 1) == (p in OEIS_A000043) + + # https://oeis.org/A005385 OEIS_A005385 = [5, 7, 11, 23, 47, 59, 83, 107, 167, 179, 227, 263, 347, 359, 383, 467, 479, 503, 563, 587, 719, 839, 863, 887, 983, 1019, 1187, 1283, 1307, 1319, 1367, 1439, 1487, 1523, 1619, 1823, 1907, 2027, 2039, 2063, 2099, 2207, 2447, 2459, 2579, 2819, 2879, 2903, 2963] - def test_is_safeprime(): for n in range(OEIS_A005385[-1]+1): assert is_safeprime(n) == (n in OEIS_A005385)