//JavaClasses/src/main/java/mattrixwv/SieveOfEratosthenesBig.java //Matthew Ellison // Created: 06-30-21 //Modified: 08-11-24 //This class uses to Sieve of Eratosthenes to generate an infinite number of primes /* Copyright (C) 2024 Matthew Ellison This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ package com.mattrixwv.generators; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; /** * A generator for prime numbers using the Sieve of Eratosthenes algorithm, which implements the {@link Iterator} interface. * *

* This implementation generates prime numbers in an incremental fashion using a modified version of the Sieve of Eratosthenes algorithm. * The algorithm uses a map to keep track of the multiples of found prime numbers to efficiently determine the next prime. *

*/ public class SieveOfEratosthenesBig implements Iterator{ /** * The next possible prime to be found */ protected BigInteger possiblePrime; /** * A dictionary of the primes that have been found and their next multiple */ protected Map> dict; /** * Constructs a new SieveOfEratosthenes instance with an empty prime dictionary * and starts the search from the first possible prime number, 2. */ public SieveOfEratosthenesBig(){ dict = new HashMap<>(); possiblePrime = BigInteger.TWO; } /** * Indicates whether there is a next prime number available. * *

* This method always returns {@code true} as the iterator is designed to * generate primes indefinitely. *

* * @return {@code true}, as the iterator can generate an infinite number of primes */ @Override public boolean hasNext(){ return true; } /** * Returns the next prime number. * *

* The method generates the next prime number by checking and updating the * internal map of known multiples. The first prime returned is 2, and subsequent * primes are found by incrementing the possible prime number and checking its * primality using the map. *

* * @return the next prime number * @throws NoSuchElementException if the next prime cannot be represented by a {@code long} */ @Override public BigInteger next(){ BigInteger prime; if(possiblePrime.compareTo(BigInteger.TWO) <= 0){ //Return 2 and move to 3 prime = possiblePrime; possiblePrime = possiblePrime.add(BigInteger.ONE); return prime; } //Loop until you find a prime number for(;dict.containsKey(possiblePrime);possiblePrime = possiblePrime.add(BigInteger.TWO)){ //Create the next entry for all entries in the map for(BigInteger num : dict.get(possiblePrime)){ BigInteger loc = possiblePrime.add(num).add(num); if(!dict.containsKey(loc)){ ArrayList tempArray = new ArrayList<>(Arrays.asList(num)); dict.put(loc, tempArray); } else{ dict.get(loc).add(num); } } //Delete the current entry dict.remove(possiblePrime); } //Protect against overflows if(possiblePrime.compareTo(BigInteger.ZERO) < 0){ throw new NoSuchElementException("the next prime cannot be described by a long"); } //Save that the number is a prime prime = possiblePrime; //Add the next entry to the prime dictionary dict.put(prime.multiply(BigInteger.valueOf(3)), new ArrayList<>(Arrays.asList(prime))); //Move on to the next possible prime possiblePrime = possiblePrime.add(BigInteger.TWO); return prime; } }