From c58dbab47cf28ec8120dda808909bbeb91fd5f6e Mon Sep 17 00:00:00 2001 From: mhostetter Date: Tue, 30 Aug 2022 13:02:17 -0400 Subject: [PATCH] Add `seed` kwarg to `random_prime()` Fixes #371 --- src/galois/_prime.py | 22 +++++++++++++--------- tests/test_primes.py | 9 +++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/galois/_prime.py b/src/galois/_prime.py index 460204f86..8551ddbb3 100644 --- a/src/galois/_prime.py +++ b/src/galois/_prime.py @@ -237,7 +237,7 @@ def next_prime(n: int) -> int: @export -def random_prime(bits: int) -> int: +def random_prime(bits: int, seed: Optional[int] = None) -> int: r""" Returns a random prime :math:`p` with :math:`b` bits, such that :math:`2^b \le p < 2^{b+1}`. @@ -250,6 +250,9 @@ def random_prime(bits: int) -> int: ---------- bits The number of bits in the prime :math:`p`. + seed + Non-negative integer used to initialize the PRNG. The default is `None` which means that unpredictable + entropy will be pulled from the OS to be used as the seed. Returns ------- @@ -268,23 +271,24 @@ def random_prime(bits: int) -> int: -------- Generate a random 1024-bit prime. - .. ipython:: + .. ipython:: python - In [2]: p = galois.random_prime(1024); p - Out[2]: 236861787926957382206996886087214592029752524078026392358936844479667423570833116126506927878773110287700754280996224768092589904231910149528080012692722763539766058401127758399272786475279348968866620857161889678512852050561604969208679095086283103827661300743342847921567132587459205365243815835763830067933 + p = galois.random_prime(1024, seed=1); p + galois.is_prime(p) - In [3]: galois.is_prime(p) - Out[3]: True + Verify that :math:`p` is prime using the OpenSSL library. - .. code-block:: + .. code-block:: console - $ openssl prime 236861787926957382206996886087214592029752524078026392358936844479667423570833116126506927878773110287700754280996224768092589904231910149528080012692722763539766058401127758399272786475279348968866620857161889678512852050561604969208679095086283103827661300743342847921567132587459205365243815835763830067933 - 1514D68EDB7C650F1FF713531A1A43255A4BE6D66EE1FDBD96F4EB32757C1B1BAF16A5933E24D45FAD6C6A814F3C8C14F3CB98F24FEA74C43C349D6FA3AB76EB0156811A1FBAA64EB4AC525CCEF9278AF78886DC6DBF46C4463A34C0E53B0FA2F784BB2DC5FDF076BB6E145AA15AA6D616ACC1D5F95B8BE757670B9AAF53292DD (236861787926957382206996886087214592029752524078026392358936844479667423570833116126506927878773110287700754280996224768092589904231910149528080012692722763539766058401127758399272786475279348968866620857161889678512852050561604969208679095086283103827661300743342847921567132587459205365243815835763830067933) is prime + $ openssl prime 327845897586213436751081882871255331286648902836386839087617368608439574698192016043769533823474001379935585889197488144338014865193967937011638431094821943416361149113909692569658970713864593781874423564706915495970135894084612689487074397782022398597547611189482697523681694691585678818112329605903872356773 + 1D2DE38DE88C67E1EAFDEEAE77C40B8709ED9C275522C6D5578976B1ABCBE7E0F8C6DE1271EEC6EB3827649164189788F9F3A622AEA5F4039761EC708B5841DE88566D9B5BAF49BA92DCE5A300297A9E0E890E4103ED2AD4B5E0553CE56E8C34758CD45900125DBA1553AE73AA0CBD6018A2A8713D46E475BF058D1AAA52EF1A5 (327845897586213436751081882871255331286648902836386839087617368608439574698192016043769533823474001379935585889197488144338014865193967937011638431094821943416361149113909692569658970713864593781874423564706915495970135894084612689487074397782022398597547611189482697523681694691585678818112329605903872356773) is prime """ verify_isinstance(bits, int) + verify_isinstance(seed, int, optional=True) if not bits > 0: raise ValueError(f"Argument `bits` must be positive, not {bits}.") + random.seed(seed) while True: p = random.randint(2**bits, 2**(bits + 1) - 1) if is_prime(p): diff --git a/tests/test_primes.py b/tests/test_primes.py index 151194bfa..8f498e724 100644 --- a/tests/test_primes.py +++ b/tests/test_primes.py @@ -61,6 +61,8 @@ def test_next_prime(next_prime): def test_random_prime_exceptions(): with pytest.raises(TypeError): galois.random_prime(10.0) + with pytest.raises(TypeError): + galois.random_prime(10, seed=1.0) with pytest.raises(ValueError): galois.random_prime(0) with pytest.raises(ValueError): @@ -74,6 +76,13 @@ def test_random_prime(): assert galois.is_prime(n) == True +def test_random_prime_deterministic(): + p1 = galois.random_prime(10, seed=1) + p2 = galois.random_prime(10, seed=1) + assert p1 == 1153 + assert p2 == 1153 + + def test_mersenne_exponents_exceptions(): with pytest.raises(TypeError): galois.mersenne_exponents(10.0)