Given a positive integer n, find all the prime numbers smaller than or equal to the given n.
Examples:
Input: n = 10
Output: [2, 3, 5, 7]Input: n = 20
Output: [2, 3, 5, 7, 11, 13, 17, 19]
Note: In this article, we've discussed the Sieve of Atkin approach to solve the problem. The other approaches to solve this problem are Sieve of Eratosthenes and Sieve of Sundaram.
Sieve of Atkin vs Sieve of Eratosthenes
The Sieve of Atkin is an advanced algorithm for generating all prime numbers up to a given n. It has a better theoretical asymptotic complexity than the Sieve of Eratosthenes. The Sieve of Eratosthenes runs in O(N log log N) time, while the Sieve of Atkin is often cited as having O(N) theoretical complexity, although in practice Eratosthenes is usually faster for typical input sizes.
How Sieve of Atkin Algorithm Works
Unlike the Sieve of Eratosthenes, which marks multiples of prime numbers as composite, the Sieve of Atkin uses three quadratic equations along with specific modulo conditions to determine whether a number can be prime.
Initially, every number from 0 to n is assumed to be non-prime. Then algorithm works as follows:
Case 1: Handle 2 and 3 separately
The numbers 2 and 3 are prime and are added directly to the answer. Let x and y be positive integers such that: 1 ≤ x, y ≤ √n
Case 2: Numbers of the form 4x² + y²
For every valid pair (x, y), compute: k = 4x² + y²
If k ≤ n and k % 12 is either 1 or 5 then toggle the status of k.
That is:
- If k is currently marked non-prime, mark it as prime.
- If k is already marked prime, mark it as non-prime.
Case 3: Numbers of the form 3x² + y²
Compute: k = 3x² + y²
If k ≤ n and k % 12 = 7 then toggle the status of k.
Case 4: Numbers of the form 3x² − y²
Compute: k = 3x² − y²
If x > y and k ≤ n and k % 12 = 11 then toggle the status of k.
After Steps 2, 3, and 4, the numbers marked as true become potential prime candidates.
Why Do We Toggle?
A number may be generated multiple times by the quadratic equations.
- If a number is generated an odd number of times, it remains marked as prime.
- If it is generated an even number of times, it becomes non-prime.
This property helps separate most primes from composites.
Case 5: Remove multiples of prime squares
Some composite numbers may still survive the previous filters. For every number p ≥ 5 that is currently marked as prime: Mark all multiples of p² as non-prime. That is, mark: p², 2p², 3p², ... as composite.
This removes all numbers that are divisible by the square of a prime.
Final Step
After removing multiples of prime squares, every number still marked as true is a prime number.
Example:
For n = 20, the prime numbers obtained are: [2, 3, 5, 7, 11, 13, 17, 19]
Illustration of Sieve of Atkin Algorithm
Consider n as 20 and let's see how the Sieve of Atkin algorithm generates prime numbers up to 20:

Step 1: Initially, all numbers are marked as non-prime except 2 and 3.
Step 2: Using the three quadratic expressions shown in the table:
- 4x² + y²
- 3x² + y²
- 3x² − y² (where x > y)
we generate the candidate values:
5, 8, 13, 20, 17, 20
7, 7, 12, 19, 13, 16
11
Step 3: Apply the Atkin conditions,
- First column: n % 12 = 1 or 5
- Second column: n % 12 = 7
- Third column: n % 12 = 11
After toggling, the prime candidates are: [5, 7, 11, 13, 17, 19]
Step 4: Remove multiples of prime squares. Since 5² = 25 > 20, no numbers are removed.
Including the special primes 2 and 3, the final prime numbers up to 20 are: [2, 3, 5, 7, 11, 13, 17, 19]
#include <iostream>
#include <vector>
using namespace std;
vector<int> sieveOfAtkin(int n) {
vector<bool> isPrime(n + 1, false);
// Handle 2 and 3 separately
if (n >= 2) isPrime[2] = true;
if (n >= 3) isPrime[3] = true;
for (int x = 1; x * x <= n; x++) {
int xx = x * x;
for (int y = 1; y * y <= n; y++) {
int yy = y * y;
// Case 1: 4x² + y², n % 12 = 1 or 5
int num = 4 * xx + yy;
if (num <= n && (num % 12 == 1 || num % 12 == 5))
isPrime[num] = !isPrime[num];
// Case 2: 3x² + y², n % 12 = 7
num = 3 * xx + yy;
if (num <= n && num % 12 == 7)
isPrime[num] = !isPrime[num];
// Case 3: 3x² − y², n % 12 = 11
num = 3 * xx - yy;
if (x > y && num <= n && num % 12 == 11)
isPrime[num] = !isPrime[num];
}
}
// Case 4: Remove multiples of prime squares
for (int p = 5; p * p <= n; p++) {
if (!isPrime[p]) continue;
for (int multiple = p * p; multiple <= n; multiple += p * p)
isPrime[multiple] = false;
}
// Collect all primes
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (isPrime[i])
primes.push_back(i);
}
return primes;
}
int main() {
int n = 20;
vector<int> primes = sieveOfAtkin(n);
cout << "[";
for (int i = 0; i < (int)primes.size(); i++) {
if (i) cout << ", ";
cout << primes[i];
}
cout << "]";
return 0;
}
import java.util.ArrayList;
public class GFG {
public static ArrayList<Integer> sieveOfAtkin(int n) {
boolean[] isPrime = new boolean[n + 1];
// Handle 2 and 3 separately
if (n >= 2) isPrime[2] = true;
if (n >= 3) isPrime[3] = true;
for (int x = 1; x * x <= n; x++) {
int xx = x * x;
for (int y = 1; y * y <= n; y++) {
int yy = y * y;
// Case 1: 4x² + y², n % 12 = 1 or 5
int num = 4 * xx + yy;
if (num <= n && (num % 12 == 1 || num % 12 == 5))
isPrime[num] = !isPrime[num];
// Case 2: 3x² + y², n % 12 = 7
num = 3 * xx + yy;
if (num <= n && num % 12 == 7)
isPrime[num] = !isPrime[num];
// Case 3: 3x² − y², n % 12 = 11
num = 3 * xx - yy;
if (x > y && num <= n && num % 12 == 11)
isPrime[num] = !isPrime[num];
}
}
// Case 4: Remove multiples of prime squares
for (int p = 5; p * p <= n; p++) {
if (!isPrime[p]) continue;
for (int multiple = p * p; multiple <= n; multiple += p * p)
isPrime[multiple] = false;
}
// Collect all primes
ArrayList<Integer> primes = new ArrayList<>();
for (int i = 2; i <= n; i++) {
if (isPrime[i])
primes.add(i);
}
return primes;
}
public static void main(String[] args) {
int n = 20;
ArrayList<Integer> primes = sieveOfAtkin(n);
System.out.print("[");
for (int i = 0; i < primes.size(); i++) {
if (i != 0) System.out.print(", ");
System.out.print(primes.get(i));
}
System.out.print("]");
}
}
import math
def sieveOfAtkin(n):
isPrime = [False] * (n + 1)
# Handle 2 and 3 separately
if n >= 2: isPrime[2] = True
if n >= 3: isPrime[3] = True
for x in range(1, int(math.sqrt(n)) + 1):
xx = x * x
for y in range(1, int(math.sqrt(n)) + 1):
yy = y * y
# Case 1: 4x² + y², n % 12 = 1 or 5
num = 4 * xx + yy
if num <= n and (num % 12 == 1 or num % 12 == 5):
isPrime[num] = not isPrime[num]
# Case 2: 3x² + y², n % 12 = 7
num = 3 * xx + yy
if num <= n and num % 12 == 7:
isPrime[num] = not isPrime[num]
# Case 3: 3x² − y², n % 12 = 11
num = 3 * xx - yy
if x > y and num <= n and num % 12 == 11:
isPrime[num] = not isPrime[num]
# Case 4: Remove multiples of prime squares
for p in range(5, int(math.sqrt(n)) + 1):
if not isPrime[p]:
continue
for multiple in range(p * p, n + 1, p * p):
isPrime[multiple] = False
# Collect all primes
primes = [i for i in range(2, n + 1) if isPrime[i]]
return primes
def main():
n = 20
primes = sieveOfAtkin(n)
print('[', end='')
for i in range(len(primes)):
if i!= 0: print(', ', end='')
print(primes[i], end='')
print(']')
if __name__ == '__main__':
main()
using System;
using System.Collections.Generic;
public class GFG {
public static List<int> sieveOfAtkin(int n) {
bool[] isPrime = new bool[n + 1];
// Handle 2 and 3 separately
if (n >= 2) isPrime[2] = true;
if (n >= 3) isPrime[3] = true;
for (int x = 1; x * x <= n; x++) {
int xx = x * x;
for (int y = 1; y * y <= n; y++) {
int yy = y * y;
// Case 1: 4x² + y², n % 12 = 1 or 5
int num = 4 * xx + yy;
if (num <= n && (num % 12 == 1 || num % 12 == 5))
isPrime[num] =!isPrime[num];
// Case 2: 3x² + y², n % 12 = 7
num = 3 * xx + yy;
if (num <= n && num % 12 == 7)
isPrime[num] =!isPrime[num];
// Case 3: 3x² − y², n % 12 = 11
num = 3 * xx - yy;
if (x > y && num <= n && num % 12 == 11)
isPrime[num] =!isPrime[num];
}
}
// Case 4: Remove multiples of prime squares
for (int p = 5; p * p <= n; p++) {
if (!isPrime[p]) continue;
for (int multiple = p * p; multiple <= n; multiple += p * p)
isPrime[multiple] = false;
}
// Collect all primes
List<int> primes = new List<int>();
for (int i = 2; i <= n; i++) {
if (isPrime[i])
primes.Add(i);
}
return primes;
}
public static void Main(string[] args) {
int n = 20;
List<int> primes = sieveOfAtkin(n);
Console.Write("[");
for (int i = 0; i < primes.Count; i++) {
if (i!= 0) Console.Write(", ");
Console.Write(primes[i]);
}
Console.Write("]");
}
}
function sieveOfAtkin(n) {
let isPrime = Array(n + 1).fill(false);
// Handle 2 and 3 separately
if (n >= 2) isPrime[2] = true;
if (n >= 3) isPrime[3] = true;
for (let x = 1; x * x <= n; x++) {
let xx = x * x;
for (let y = 1; y * y <= n; y++) {
let yy = y * y;
// Case 1: 4x² + y², n % 12 = 1 or 5
let num = 4 * xx + yy;
if (num <= n && (num % 12 == 1 || num % 12 == 5))
isPrime[num] =!isPrime[num];
// Case 2: 3x² + y², n % 12 = 7
num = 3 * xx + yy;
if (num <= n && num % 12 == 7)
isPrime[num] =!isPrime[num];
// Case 3: 3x² − y², n % 12 = 11
num = 3 * xx - yy;
if (x > y && num <= n && num % 12 == 11)
isPrime[num] =!isPrime[num];
}
}
// Case 4: Remove multiples of prime squares
for (let p = 5; p * p <= n; p++) {
if (!isPrime[p]) continue;
for (let multiple = p * p; multiple <= n; multiple += p * p)
isPrime[multiple] = false;
}
// Collect all primes
let primes = [];
for (let i = 2; i <= n; i++) {
if (isPrime[i])
primes.push(i);
}
return primes;
}
// Driver code
let n = 20;
let primes = sieveOfAtkin(n);
console.log('[' + primes.join(', ') + ']');
Output
[2, 3, 5, 7, 11, 13, 17, 19]
Time Complexity: O(n)
Auxiliary Space: O(n)