Sieve of Atkin

Last Updated : 23 Jul, 2025

Given a positive integer limit. Your task is to find all the prime numbers smaller than or equal to the given limit.

Examples: 

Input:  limit = 10
Output: 2, 3, 5, 7

Input:  limit = 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 a modern algorithm for finding all prime numbers up to a specified integer. Compared with the ancient Sieve of Eratosthenes, which marks off multiples of primes, it does some preliminary work and then marks off multiples of squares of primes, that's why it has a better theoretical asymptotic complexity with complexity of (N / (log (log N))). Please note that Sieve of Eratosthenes has time complexity O(N*log(log(N)))

How Sieve of Atkin Algorithm Works 

The Sieve of Atkin algorithm works similarly to Sieve of Eratosthenes to filter out the composite numbers from a list of numbers, but this algorithm works in terms of modulo-60 remainders. So we first assume all the numbers within limit to be composite, and then apply filter or sieve on them. If while any filter, the number appears to be prime, we mark it as prime and move on to the next number.

The filter or sieve in this algorithms works mainly 4 cases or layers:

  • Case 1: If limit is greater than 2 or 3:
    • The algorithm treats 2, and 3 as special cases and just adds them to the set of primes to start with.
  • Let x and y be positive integers ranging from 1 up through √limit.
  • Case 2: if 4x2+ y2 = n is odd and modulo-12 remainder is 1 or 5
    • If a number gives a remainder of one of {1, 13, 17, 29, 37, 41, 49, 53} when divided by 60, then it must give a remainder of either 1 or 5 when divided by 12 (Why? because 1 %12 = 1, 13 % 12 = 1, 17 % 12 = 1, 29 % 12 = 1, ..). Therefore, for this filter as well, we have to check if the number is 1 or 5 when taken modulo with 12.
    • Also, these numbers are prime if and only if the number of solutions to 4x2 + y2=n is odd and the number is square-free. 
    • A square-free integer is one that is not divisible by any perfect square other than 1.
  • Case 3: if 3x2+y2 = n is odd and modulo-6 remainder is 1
    • All numbers with modulo-60 remainder 7, 19, 31, or 43 have a modulo-6 remainder of 1. 
    • These numbers are prime if and only if the number of solutions to 3x2 + y2 = n is odd and the number is square-free.
  • Case 4: if 3x2-y2=n is odd and modulo-12 remainder is 11
    • All numbers with modulo-60 remainder 11, 23, 47, or 59 have a modulo-12 remainder of 11. 
    • These numbers are prime if and only if the number of solutions to 3x2 - y2 = n is odd and the number is square-free.
  • Case 5: Filtering out all the residual primes which have not yet been found
    • Due to the filtering of the Sieve of Atkin algorithm, there might be some prime numbers who have been discarded or not found in the above cases.
    • So to find out those, select all non-primes within limit, and mark all their squares as non-primes.

At the end of all of the filters above, the positions in the Sieve with a true value will be the list of primes within limit.

Illustration of Sieve of Atkin Algorithm

Consider limit as 20 and lets see how Sieve of Atkin algorithm generates primes up to 20:

Step 0: The status for all the numbers at the start is false. The special numbers are 2, 3, and 5, which are known to be prime.
Step 1: Generate values for the conditions.  

atkins

Step 2: Flipping the status according to condition.
The above values of n in the table generated in the x, y loop will be tested for modulo conditions.

  • Column 1: if (column1 value) % 12 == 1 or 5, then flip the sieve status for that number.
  • Column 2: if (column2 value) % 12 == 7, then flip the sieve status for that number.
  • Column 3: if (column3 value) % 12 == 11, then flip the sieve status for that number.

Note: Notice that we are taking mod with 12 in place of 60. This is because if we take mod 60 then we have to consider as many r as 1, 13, 17, 29, 37, 41, 49, or 53 and for all these r, mod 12 is 1 or 5. (done only to reduce the expression size)
Step 3: Checking for Square free Condition: 
If any number in our list is the square of any number, then remove it.
Step 4: Creating an array of prime numbers for which status is true i.e. 2 3 5 7 11 13 17 19
Step 5: Print the output on the screen.

Step By Step Appraoch:

  1. Create a results list, filled with 2, 3, and 5.
  2. Create a sieve list with an entry for each positive integer; all entries in this list should initially be marked non-prime.
  3. For each entry number n in the sieve list, with modulo-sixty remainder r: 
    1. If r is 1, 13, 17, 29, 37, 41, 49, or 53, flip the entry for each possible solution to 4x2 + y2 = n.
    2. If r is 7, 19, 31, or 43, flip the entry for each possible solution to 3x2 + y2 = n.
    3. If r is 11, 23, 47, or 59, flip the entry for each possible solution to 3x2 - y2 = n when x > y.
    4. If r is something else, ignore it completely...
  4. Start with the lowest number in the sieve list.
  5. Take the next number in the sieve list, still marked prime.
  6. Include the number in the results list.
  7. Square the number and mark all multiples of that square as non-prime. Note that the multiples that can be factored by 2, 3, or 5 need not be marked, as these will be ignored in the final enumeration of primes.
  8. Repeat steps four through seven.

Below is the given the implementation:

C++
#include <bits/stdc++.h>
using namespace std;

// Function to generate primes
// till limit using Sieve of Atkin
vector<int> sieveOfAtkin(int limit) {

    // intialise the arr array
    // with initial 0 values
    vector<int> arr(limit + 1);

    // mark 2 and 3 as prime
    if (limit > 2) arr[2] = 1;
    if (limit > 3) arr[3] = 1;

    // check for all three conditions
    for(int x = 1; x * x <= limit; x++) {
        for(int y = 1; y * y <= limit; y++) {

            // condition 1
            int n = (4 * x * x) + (y * y);
            if(n <= limit && (n % 12 == 1 || n % 12 == 5)) 
                arr[n] = (arr[n] + 1) % 2;

            // condition 2
            n = (3 * x * x) + (y * y);
            if(n <= limit && n % 12 == 7) 
                arr[n] = (arr[n] + 1) % 2;

            // condition 3
            n = (3 * x * x) - (y * y);
            if(x > y && n <= limit && n % 12 == 11) 
                arr[n] = (arr[n] + 1) % 2;
        }
    }

    // Mark all multiples
    // of squares as non-prime
    for (int i = 5; i * i <= limit; i++) {
        if (arr[i] == 0) continue;
        for (int j = i * i; j <= limit; j += i * i)
            arr[j] = 0;
    }

    // store all prime numbers
    vector<int> primes;
    for (int i = 2; i <= limit; i++) {
        if (arr[i] == 1) {
            primes.push_back(i);
        }
    }
    return primes;
}

int main() {
    int limit = 20;
    vector<int> primes = sieveOfAtkin(limit);
    for(int prime : primes) {
        cout << prime << " ";
    }
    return 0;
}
Java
import java.util.*;

public class GfG {

    // Function to generate primes
    // till limit using Sieve of Atkin
    static ArrayList<Integer> sieveOfAtkin(int limit) {
    
        // intialise the arr array
        // with initial 0 values
        int[] arr = new int[limit + 1];
        Arrays.fill(arr, 0);
    
        // mark 2 and 3 as prime
        if (limit > 2) arr[2] = 1;
        if (limit > 3) arr[3] = 1;
    
        // check for all three conditions
        for (int x = 1; x * x <= limit; x++) {
            for (int y = 1; y * y <= limit; y++) {
    
                // condition 1
                int n = (4 * x * x) + (y * y);
                if (n <= limit && (n % 12 == 1 || n % 12 == 5))
                    arr[n] = (arr[n] + 1) % 2;
    
                // condition 2
                n = (3 * x * x) + (y * y);
                if (n <= limit && n % 12 == 7)
                    arr[n] = (arr[n] + 1) % 2;
    
                // condition 3
                n = (3 * x * x) - (y * y);
                if (x > y && n <= limit && n % 12 == 11)
                    arr[n] = (arr[n] + 1) % 2;
            }
        }
    
        // Mark all multiples
        // of squares as non-prime
        for (int i = 5; i * i <= limit; i++) {
            if (arr[i] == 0) continue;
            for (int j = i * i; j <= limit; j += i * i)
                arr[j] = 0;
        }
    
        // store all prime numbers
        ArrayList<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= limit; i++) {
            if (arr[i] == 1) {
                primes.add(i);
            }
        }
        return primes;
    }
    
    public static void main(String[] args) {
        int limit = 20;
        ArrayList<Integer> primes = sieveOfAtkin(limit);
        for (int prime : primes) {
            System.out.print(prime + " ");
        }
    }
}
Python
# Function to generate primes
# till limit using Sieve of Atkin
def sieveOfAtkin(str_limit):
    limit = str_limit

    # intialise the arr array
    # with initial 0 values
    arr = [0] * (limit + 1)

    # mark 2 and 3 as prime
    if limit > 2:
        arr[2] = 1
    if limit > 3:
        arr[3] = 1

    # check for all three conditions
    for x in range(1, int(limit**0.5) + 1):
        for y in range(1, int(limit**0.5) + 1):
    
            # condition 1
            n = (4 * x * x) + (y * y)
            if n <= limit and (n % 12 == 1 or n % 12 == 5):
                arr[n] = (arr[n] + 1) % 2
    
            # condition 2
            n = (3 * x * x) + (y * y)
            if n <= limit and n % 12 == 7:
                arr[n] = (arr[n] + 1) % 2
    
            # condition 3
            n = (3 * x * x) - (y * y)
            if x > y and n <= limit and n % 12 == 11:
                arr[n] = (arr[n] + 1) % 2
    
    # Mark all multiples
    # of squares as non-prime
    for i in range(5, limit + 1):
        if i * i > limit:
            break
        if arr[i] == 0:
            continue
        for j in range(i * i, limit + 1, i * i):
            arr[j] = 0
    
    # store all prime numbers
    primes = []
    for i in range(2, limit + 1):
        if arr[i] == 1:
            primes.append(i)
    return primes

if __name__ == "__main__":
    limit = 20
    primes = sieveOfAtkin(limit)
    print(" ".join(map(str, primes)))
C#
using System;
using System.Collections.Generic;

public class GfG {

    // Function to generate primes
    // till limit using Sieve of Atkin
    public static List<int> sieveOfAtkin(int limit) {
    
        // intialise the arr array
        // with initial 0 values
        int[] arr = new int[limit + 1];
        for (int i = 0; i <= limit; i++) {
            arr[i] = 0;
        }
    
        // mark 2 and 3 as prime
        if (limit > 2) arr[2] = 1;
        if (limit > 3) arr[3] = 1;
    
        // check for all three conditions
        for (int x = 1; x * x <= limit; x++) {
            for (int y = 1; y * y <= limit; y++) {
    
                // condition 1
                int n = (4 * x * x) + (y * y);
                if (n <= limit && (n % 12 == 1 || n % 12 == 5))
                    arr[n] = (arr[n] + 1) % 2;
    
                // condition 2
                n = (3 * x * x) + (y * y);
                if (n <= limit && n % 12 == 7)
                    arr[n] = (arr[n] + 1) % 2;
    
                // condition 3
                n = (3 * x * x) - (y * y);
                if (x > y && n <= limit && n % 12 == 11)
                    arr[n] = (arr[n] + 1) % 2;
            }
        }
    
        // Mark all multiples
        // of squares as non-prime
        for (int i = 5; i * i <= limit; i++) {
            if (arr[i] == 0) continue;
            for (int j = i * i; j <= limit; j += i * i)
                arr[j] = 0;
        }
    
        // store all prime numbers
        List<int> primes = new List<int>();
        for (int i = 2; i <= limit; i++) {
            if (arr[i] == 1) {
                primes.Add(i);
            }
        }
        return primes;
    }
    
    public static void Main(string[] args) {
        int limit = 20;
        List<int> primes = sieveOfAtkin(limit);
        foreach (int prime in primes) {
            Console.Write(prime + " ");
        }
    }
}
JavaScript
// Function to generate primes
// till limit using Sieve of Atkin
function sieveOfAtkin(limit) {

    // intialise the arr array
    // with initial 0 values
    let arr = new Array(limit + 1).fill(0);

    // mark 2 and 3 as prime
    if (limit > 2) arr[2] = 1;
    if (limit > 3) arr[3] = 1;

    // check for all three conditions
    for (let x = 1; x * x <= limit; x++) {
        for (let y = 1; y * y <= limit; y++) {
    
            // condition 1
            let n = (4 * x * x) + (y * y);
            if (n <= limit && (n % 12 === 1 || n % 12 === 5))
                arr[n] = (arr[n] + 1) % 2;
    
            // condition 2
            n = (3 * x * x) + (y * y);
            if (n <= limit && n % 12 === 7)
                arr[n] = (arr[n] + 1) % 2;
    
            // condition 3
            n = (3 * x * x) - (y * y);
            if (x > y && n <= limit && n % 12 === 11)
                arr[n] = (arr[n] + 1) % 2;
        }
    }

    // Mark all multiples
    // of squares as non-prime
    for (let i = 5; i * i <= limit; i++) {
        if (arr[i] === 0) continue;
        for (let j = i * i; j <= limit; j += i * i)
            arr[j] = 0;
    }

    // store all prime numbers
    let primes = [];
    for (let i = 2; i <= limit; i++) {
        if (arr[i] === 1) {
            primes.push(i);
        }
    }
    return primes;
}

function main() {
    let limit = 20;
    let primes = sieveOfAtkin(limit);
    console.log(primes.join(" "));
}

main();

Output
2 3 5 7 11 13 17 19 

Time complexity: O(limit)
Auxiliary space: O(limit)

Comment