I wrote the following code to list all the prime numbers upto 2 billion using Sieve’s method. I used bitmasking for flagging purpose. While I am able to get the prime numbers correctly, a few primes in the beginning are missing every time. Please help me find the bug in the program.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX 2000000000
char* listPrimes(){
int block = sqrt(MAX);
char* mark = calloc((MAX/8),sizeof(char));
int i = 2;
int j;
char mask[8];
for(j=0;j<8;j++)
mask[j] = 0;
mask[7] = 1;
mask[6] |= mask[7] << 1;
mask[5] |= mask[7] << 2;
mask[4] |= mask[7] << 3;
mask[3] |= mask[7] << 4;
mask[2] |= mask[7] << 5;
mask[1] |= mask[7] << 6;
mask[0] |= mask[7] << 7;
for(j=0;j<8;j++)
printf("%d ",mask[j]);
mark[0] |= mask[0];
mark[0] |= mask[1];
while (i < block){
for (j = 2; i*j <= block; j++)
mark[(i*j) / 8] |= mask[((i*j) % 8 )];
i++;
}
printf("\n");
printf("The block size is\t:\t%d\n",block);
j = 2;
while(j<=block){
if((mark[j / 8] & mask[j]) == 0 ){
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
mark[i / 8] |= mask[(i % 8)];
}
}
}
while((mark[++j / 8] & mask[j % 8]) != 0);
}
for(j=0;j<=MAX;j++)
if((mark[j / 8] & mask[(j % 8)]) == 0)
printf("%d\n", ((8*(j / 8)) + (j % 8)));
return mark;
}
int main(int argc,char* argv[]){
listPrimes();
return 0;
}
As ArunMK said, in the second
whileloop you mark the primejitself as a multiple ofj. And as Lee Meador said, you need to take the modulus ofjmodulo 8 for themaskindex, otherwise you access out of bounds and invoke undefined behaviour.A further point where you invoke undefined behaviour is
where you use and modify
jwithout intervening sequence point. You can avoid that by writingor, if you insist on a
whileloop with empty bodyyou can use the comma operator.
More undefined behaviour by accessing
mark[MAX/8]which is not allocated inand
Also, if
charis signed and eight bits wide,is implementation-defined (and may raise an implementation-defined signal) since the result of
(the
int128) is not representable as achar.But why are you dividing each number by all primes not exceeding the square root of the bound in the second
whileloop?That makes your algorithm not a Sieve of Eratosthenes, but a trial division.
Why don’t you use the technique from the first
whileloop there too? (And then, why two loops at all?)would not overflow (for the given value of
MAX, if that is representable as anint), and produce the correct output orders of magnitude faster.