Coverage for src\pqlattice\random\_prime.py: 96%
28 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-07 03:12 +0100
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-07 03:12 +0100
1import math
2import random
4from ..integer._primality import is_prime
7def _randprime(a: int, b: int, seed: int | None = None) -> int:
8 def ilog(n: int, base: float = math.e) -> int:
9 return int((n.bit_length() - 1) / math.log2(base))
11 try:
12 approx_number_of_primes_to_a = 0 if a == 0 else a // ilog(a)
13 approx_number_of_primes_to_b = 0 if b == 0 else b // ilog(b)
14 approx_number_of_primes = approx_number_of_primes_to_b - approx_number_of_primes_to_a
15 prime_proba = approx_number_of_primes / (b - a)
16 number_of_samples = int(math.log(0.001) / math.log(1 - prime_proba)) + 1
17 except ZeroDivisionError:
18 number_of_samples = b - a
20 if b - a < 1000:
21 number_of_samples = b - a
23 random.seed(seed)
24 for i in range(number_of_samples):
25 prime_candidate = random.randint(a, b)
26 if is_prime(prime_candidate):
27 return prime_candidate
28 if is_prime(a + i):
29 return a + i
31 raise ValueError(f"Couldn't find a prime number in interval [{a}, {b})")
34def randprime(kbits: int, seed: int | None = None) -> int:
35 """_summary_
37 Parameters
38 ----------
39 kbits : int
40 _description_
41 seed : int | None, optional
42 _description_, by default None
44 Returns
45 -------
46 int
47 _description_
48 """
49 a = 2 ** (kbits - 1)
50 b = 2**kbits
51 return _randprime(a, b, seed=seed)