Source code for primify.prime_finder

from itertools import islice
import math
import time
from typing import Iterator, List, Optional, Set
import multiprocessing as mp
from sympy import isprime
import logging
from primify import console

logger = logging.getLogger(__file__)


[docs]class NextPrimeFinder: def __init__(self, value: int, n_workers: int = 1): self.value = int(value) self.n_workers = n_workers self.expected_n_primality_tests = max(10, int(math.log(value)))
[docs] def prime_candidates(self) -> Iterator[int]: candidate = self.value while True: if candidate % 6 in [1, 5]: yield candidate candidate += 1
[docs] @staticmethod def is_prime_worker(candidate: int, found_prime) -> Optional[int]: if not found_prime.is_set(): if isprime(candidate): logger.info(f"{candidate} is prime!") found_prime.set() return candidate logger.debug( f"Checking of {candidate} skipped since we already found the next prime" ) return
[docs] def find_next_prime(self) -> int: with mp.Pool(self.n_workers) as pool: manager = mp.Manager() found_prime = manager.Event() candidate_iter = ( (candidate, found_prime) for candidate in self.prime_candidates() ) results: Set[Optional[int]] = set() search_start = time.time() while not found_prime.is_set(): console.log( f"Performing batch of ~{self.expected_n_primality_tests} primality tests. We rarely need more than one batch.", ) result = pool.starmap( NextPrimeFinder.is_prime_worker, islice(candidate_iter, self.expected_n_primality_tests), ) results |= set(result) console.log( f"Got one! Next prime was found within {int(time.time()- search_start) + 1}s" ) pool.terminate() for result in results: # all but the prime are None if result is not None: return result return -1