Skip to main content
4 of 7
added 6 characters in body
barak manos
  • 1.2k
  • 1
  • 7
  • 19

Based on @MOehm's second answer, I have managed to increase RANGE to 2 billion and more:

Sieve Interface:

#include <limits.h>

// Defined by the user (must be less than 'UINT_MAX')
#define RANGE 2000000000

// The actual length required for the prime-sieve array
#define ARR_LEN (((RANGE-1)/(3*CHAR_BIT)+1))

// Assumes that all entries in 'sieve' are initialized to zero
void Init(char sieve[ARR_LEN]);

// Assumes that 'Init(sieve)' has been called and that '1 < n < RANGE'
int IsPrime(char sieve[ARR_LEN],unsigned int n);

#if RANGE >= UINT_MAX
    #error RANGE exceeds the limit
#endif

Sieve Implementation:

#include <math.h>

#define GET_BIT(sieve,n) ((sieve[(n)/(3*CHAR_BIT)]>>((n)%(3*CHAR_BIT)/3))&1)
#define SET_BIT(sieve,n) sieve[(n)/(3*CHAR_BIT)] |= 1<<((n)%(3*CHAR_BIT)/3)

static void InitOne(char sieve[ARR_LEN],int d)
{
    unsigned int i,j;
    unsigned int root = (unsigned int)sqrt((double)RANGE);

    for (i=6+d; i<=root; i+=6)
    {
        if (GET_BIT(sieve,i) == 0)
        {
            for (j=6*i; j<RANGE; j+=6*i)
            {
                SET_BIT(sieve,j-i);
                SET_BIT(sieve,j+i);
            }
        }
    }
}

void Init(char sieve[ARR_LEN])
{
    InitOne(sieve,-1);
    InitOne(sieve,+1);
}

int IsPrime(char sieve[ARR_LEN],unsigned int n)
{
    return n == 2 || n == 3 || (n%2 != 0 && n%3 != 0 && GET_BIT(sieve,n) == 0);
}

MOehm's Algorithm:

#include <stdio.h>
#include <stdlib.h>

#define MAX_HIT_COUNT (RANGE/15) /* change the division factor if necessary */

typedef struct
{
    unsigned int n;
    unsigned int x;
}
hit;

char sieve[ARR_LEN]     = {0};
hit hits[MAX_HIT_COUNT] = {0};
unsigned int hit_count  =  0;

void Sprawl(unsigned long long n,unsigned long long sum,unsigned long long p)
{
    unsigned long long x = (unsigned long long)sqrt((double)sum);
    if (x*x == sum)
    {
        if (hit_count >= MAX_HIT_COUNT)
        {
            fprintf(stderr,"Hits overflow\n");
            exit(1);
        }
        hits[hit_count].n = (unsigned int)n;
        hits[hit_count].x = (unsigned int)x;
        hit_count++;
    }

    while (p < RANGE)
    {
        if (IsPrime(sieve,(unsigned int)p))
        {
            if (n*p >= RANGE)
                break;
            Sprawl(n*p,sum+p*p,p);
        }
        p++;
    }
}

Test Case:

int hitscmp(const void *a,const void *b)
{
    const hit* aa = (const hit*)a;
    const hit* bb = (const hit*)b;
    return (aa->n > bb->n) - (aa->n < bb->n);
}

int main()
{
    unsigned int i;

    Init(sieve);

    Sprawl(1,0,2);

    qsort(hits,hit_count,sizeof(*hits),hitscmp);

    for (i=0; i<hit_count; i++)
        printf("%12u%12u\n",hits[i].n,hits[i].x);

    return 0;
}
barak manos
  • 1.2k
  • 1
  • 7
  • 19