|
| 1 | +package com.thealgorithms.maths; |
| 2 | + |
| 3 | +import java.util.ArrayList; |
| 4 | +import java.util.List; |
| 5 | + |
| 6 | +/** |
| 7 | + * Implementation of the Sieve of Atkin, an optimized algorithm to generate |
| 8 | + * all prime numbers up to a given limit. |
| 9 | + * |
| 10 | + * The Sieve of Atkin uses quadratic forms and modular arithmetic to identify |
| 11 | + * prime candidates, then eliminates multiples of squares. It is more efficient |
| 12 | + * than the Sieve of Eratosthenes for large limits. |
| 13 | + */ |
| 14 | +public final class SieveOfAtkin { |
| 15 | + |
| 16 | + private SieveOfAtkin() { |
| 17 | + // Utlity class; prevent instantiation |
| 18 | + } |
| 19 | + |
| 20 | + /** |
| 21 | + * Generates a list of all prime numbers up to the specified limit |
| 22 | + * using the Sieve of Atkin algorithm. |
| 23 | + * |
| 24 | + * @param limit the upper bound up to which primes are generated; must be zero or positive |
| 25 | + * @return a list of prime numbers up to the limit; empty if the limit is less than 2 |
| 26 | + */ |
| 27 | + public static List<Integer> generatePrimes(int limit) { |
| 28 | + if (limit < 2) { |
| 29 | + return List.of(); |
| 30 | + } |
| 31 | + |
| 32 | + boolean[] sieve = new boolean[limit + 1]; |
| 33 | + int sqrtLimit = (int) Math.sqrt(limit); |
| 34 | + |
| 35 | + markQuadraticResidues(limit, sqrtLimit, sieve); |
| 36 | + eliminateMultiplesOfSquares(limit, sqrtLimit, sieve); |
| 37 | + |
| 38 | + List<Integer> primes = new ArrayList<>(); |
| 39 | + if (limit >= 2) primes.add(2); |
| 40 | + if (limit >= 3) primes.add(3); |
| 41 | + |
| 42 | + for (int i = 5; i <= limit; i++) { |
| 43 | + if (sieve[i]) primes.add(i); |
| 44 | + } |
| 45 | + |
| 46 | + return primes; |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * Marks numbers in the sieve as prime candidates based on quadratic residues. |
| 51 | + * |
| 52 | + * This method iterates over all x and y up to sqrt(limit) and applies |
| 53 | + * the three quadratic forms used in the Sieve of Atkin. Numbers satisfying |
| 54 | + * the modulo conditions are toggled in the sieve array. |
| 55 | + * |
| 56 | + * @param limit the upper bound for primes |
| 57 | + * @param sqrtLimit square root of the limit |
| 58 | + * @param sieve boolean array representing potential primes |
| 59 | + */ |
| 60 | + private static void markQuadraticResidues(int limit, int sqrtLimit, boolean[] sieve) { |
| 61 | + for (int x = 1; x <= sqrtLimit; x++) { |
| 62 | + for (int y = 1; y <= sqrtLimit; y++) { |
| 63 | + applyQuadraticForm(4 * x * x + y * y, limit, sieve, 1, 5); |
| 64 | + applyQuadraticForm(3 * x * x + y * y, limit, sieve, 7); |
| 65 | + applyQuadraticForm(3 * x * x - y * y, limit, sieve, 11, x > y); |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + /** |
| 71 | + * Toggles the sieve entry for a number if it satisfies one modulo condition. |
| 72 | + * |
| 73 | + * @param n the number to check |
| 74 | + * @param limit upper bound of primes |
| 75 | + * @param sieve boolean array representing potential primes |
| 76 | + * @param modulo the modulo condition number to check |
| 77 | + */ |
| 78 | + private static void applyQuadraticForm(int n, int limit, boolean[] sieve, int modulo) { |
| 79 | + if (n <= limit && n % 12 == modulo) { |
| 80 | + sieve[n] ^= true; |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Toggles the sieve entry for a number if it satisfies either of two modulo conditions. |
| 86 | + * |
| 87 | + * @param n the number to check |
| 88 | + * @param limit upper bound of primes |
| 89 | + * @param sieve boolean array representing potential primes |
| 90 | + * @param modulo1 first modulo condition number to check |
| 91 | + * @param modulo2 second modulo condition number to check |
| 92 | + */ |
| 93 | + private static void applyQuadraticForm(int n, int limit, boolean[] sieve, int modulo1, int modulo2) { |
| 94 | + if (n <= limit && (n % 12 == modulo1 || n % 12 == modulo2)) { |
| 95 | + sieve[n] ^= true; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + /** |
| 100 | + * Toggles the sieve entry for a number if it satisfies the modulo condition and an additional boolean condition. |
| 101 | + * |
| 102 | + * This version is used for the quadratic form 3*x*x - y*y, which requires x > y. |
| 103 | + * |
| 104 | + * @param n the number to check |
| 105 | + * @param limit upper bound of primes |
| 106 | + * @param sieve boolean array representing potential primes |
| 107 | + * @param modulo the modulo condition number to check |
| 108 | + * @param condition an additional boolean condition that must be true |
| 109 | + */ |
| 110 | + private static void applyQuadraticForm(int n, int limit, boolean[] sieve, int modulo, boolean condition) { |
| 111 | + if (condition && n <= limit && n % 12 == modulo) { |
| 112 | + sieve[n] ^= true; |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Eliminates numbers that are multiples of squares from the sieve. |
| 118 | + * |
| 119 | + * All numbers that are multiples of i*i (where i is marked as prime) are |
| 120 | + * marked non-prime to finalize the sieve. This ensures only actual primes remain. |
| 121 | + * |
| 122 | + * @param limit the upper bound for primes |
| 123 | + * @param sqrtLimit square root of the limit |
| 124 | + * @param sieve boolean array representing potential primes |
| 125 | + */ |
| 126 | + private static void eliminateMultiplesOfSquares(int limit, int sqrtLimit, boolean[] sieve) { |
| 127 | + for (int i = 5; i <= sqrtLimit; i++) { |
| 128 | + if (!sieve[i]) continue; |
| 129 | + int square = i * i; |
| 130 | + for (int j = square; j <= limit; j += square) { |
| 131 | + sieve[j] = false; |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | +} |
0 commit comments