Task: Sieve of Pritchard


C++: 



#include <cstring>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctime>

void Extend (uint32_t w[], uint32_t &w_end, uint32_t &length, uint32_t n, bool d[], uint32_t &w_end_max) {
    
    uint32_t i, j, x;
    i = 0; j = w_end;
    x = length + 1; 
    while (x <= n) {
        w[++j] = x; 
        d[x] = false;
        x = length + w[++i];
    }
    length = n; w_end = j;
    if (w_end > w_end_max) w_end_max = w_end;
}

void Delete (uint32_t w[], uint32_t length, uint32_t p, bool d[], uint32_t &imaxf) {
    
    uint32_t i, x;
    i = 0;
    x = p; 
    while (x <= length) {
        d[x] = true; 
        x = p*w[++i];
    }
    imaxf = i-1;
}

void Compress(uint32_t w[], bool d[], uint32_t to, uint32_t &w_end) {
    
    uint32_t i, j;
    j = 0;
    for (i=1; i <= to; i++) {
        if (!d[w[i]]) {
            w[++j] = w[i];
        }
    }
    if (to == w_end) {
        w_end = j;
    } else {
        for (uint32_t k=j+1; k <= to; k++) w[k] = 0;
    }
}

void Sift(uint32_t N, bool printPrimes, uint32_t &nrPrimes, uint32_t &vBound) {
    
    uint32_t *w = new uint32_t[N/4+5];
    bool *d = new bool[N+1];
    uint32_t w_end, length;
    
    
    
    
    uint32_t w_end_max, p, imaxf;
    
    w_end = 0; w[0] = 1;
    w_end_max = 0;
    length = 2;
    
    nrPrimes = 1;
    if (printPrimes) printf("%d", 2);
    p = 3;
    
    
    while (p*p <= N) {
        
        nrPrimes++;
        if (printPrimes) printf(" %d", p);
        if (length < N) {
            
            Extend (w, w_end, length, std::min(p*length,N), d, w_end_max);
        }
        Delete(w, length, p, d, imaxf);
        Compress(w, d, (length < N ? w_end : imaxf), w_end);
        
        p = w[1];
        if (p == 0) break; 
        
    }
    if (length < N) {
        
        Extend (w, w_end, length, N, d, w_end_max);
    }
    
    for (uint32_t i=1; i <= w_end; i++) {
        if (w[i] == 0 || d[w[i]]) continue;
        if (printPrimes) printf(" %d", w[i]);
        nrPrimes++;
    }
    vBound = w_end_max+1;
}

int main (int argc, char *argw[]) {
    bool error = false;
    bool printPrimes = false;
    uint32_t N, nrPrimes, vBound;
    if (argc == 3) {
        if (strcmp(argw[2], "-p") == 0) {
            printPrimes = true;
            argc--;
        } else {
            error = true;
        }
    }
    if (argc == 2) {
        N = atoi(argw[1]);
        if (N < 2 || N > 1000000000) error = true;
    } else {
        error = true;
    }
    if (error) {
        printf("call with: %s N -p where 2 <= N <= 1000000000 and -p to print the primes is optional \n", argw[0]);
        exit(1);
    }
    int start_s = clock();
    Sift(N, printPrimes, nrPrimes, vBound);
    int stop_s=clock();
    printf("\n%d primes up to %lu found in %.3f ms using array w[%d]\n", nrPrimes,
      (unsigned long)N, (stop_s-start_s)*1E3/double(CLOCKS_PER_SEC), vBound);
}






Python: 

from numpy import ndarray
from math import isqrt


def pritchard(limit):
    
    members = ndarray(limit + 1, dtype=bool)
    members.fill(False)
    members[1] = True
    steplength, prime, rtlim, nlimit = 1, 2, isqrt(limit), 2
    primes = []
    while prime <= rtlim:
        if steplength < limit:
            for w in range(1, len(members)):
                if members[w]:
                    n = w + steplength
                    while n <= nlimit:
                        members[n] = True
                        n += steplength
            steplength = nlimit

        np = 5
        mcpy = members.copy()
        for w in range(1, len(members)):
            if mcpy[w]:
                if np == 5 and w > prime:
                    np = w
                n = prime * w
                if n > nlimit:
                    break  
                members[n] = False  

        if np < prime:
            break
        primes.append(prime)
        prime = 3 if prime == 2 else np
        nlimit = min(steplength * prime, limit)  

    newprimes = [i for i in range(2, len(members)) if members[i]]
    return sorted(primes + newprimes)


print(pritchard(150))
print('Number of primes up to 1,000,000:', len(pritchard(1000000)))