
#include <stdio.h>
#include <stdarg.h>
#include <gmp.h>
#include <Judy.h>

unsigned cprime,swheel,ewheel;
mpz_t pi0, pi1;

Pvoid_t jprimes = (Pvoid_t) NULL; 

int isprime(mpz_t pprime) {
	mpz_t tmp;
	mpz_t **p;
	int i;

	mpz_init(tmp);

	i=cprime;
	JLF(p, jprimes, i);
	while (p) {
		if ( mpz_cmp(**p, pprime) >= 0 ) break;
		mpz_mod(tmp,pprime,**p);
		if (mpz_cmp_ui(tmp,0)==0) {
 			return 0;
		}
		mpz_mul(tmp,**p,**p); // TODO: cache this
		if (mpz_cmp(tmp, pi1) > 0 ) {
			break;
		}

	    JLN(p, jprimes, i);
	}
	return 1;				
}

#define mpz_set_z mpz_set
#define mpz_init_set_z mpz_init_set

#define PASTE_GEN(a,b) a##b
#define mjset(A, I, V, T, ST) {                     \
    JLG((T), (A), (I));                             \
	if (! (T) ) {                                   \
	    JLI((T), (A), (I));                         \
		*(T)=(mpz_t*)malloc(sizeof(mpz_t));         \
		if (*(T)) {                                 \
			PASTE_GEN(mpz_init_set,ST)(**(T), (V)); \
		}                                           \
		else {                                      \
			printf("\nmalloc error\n");             \
			exit(1);                                \
		}                                           \
	}                                               \
	else {                                          \
		PASTE_GEN(mpz_set,ST)(**(T), (V));          \
	}                                               \
}

void gpprime(mpz_t pprime, mpz_t pi0, mpz_t pi1, unsigned start, unsigned stride) {
	mpz_t **p,tmp;
	int j=0,l;

	mpz_init(tmp);
	mpz_add(tmp,pprime,pi0);	
	l=ewheel+start;

	while (mpz_cmp(tmp, pi1) <= 0) {
		if ( isprime(&tmp) ) {
			mjset(jprimes,l,tmp,p,_z);
//			gmp_printf("%9lu | %Zu\n",l,tmp);
			gmp_printf("%Zu\n",tmp);
		}			
		l+=stride;
		mpz_add(tmp,tmp,pi0);
	} 

}

int main(int argc, char **argv) {
	mpz_t **p,**q;
	mpz_t pprime,tmp;
	Word_t  count;
	mpz_t **ptmp;

	Word_t i,l;
	unsigned k,s;

	mpz_init_set_ui(pi0,  6);
	mpz_init_set_ui(pi1, 30);

	mjset(jprimes, 0,1, ptmp, _ui);
	mjset(jprimes, 1,2, ptmp, _ui);
	mjset(jprimes, 2,3, ptmp, _ui);
	mjset(jprimes, 3,5, ptmp, _ui);
	swheel=3;
	ewheel=3;
	cprime=3;

	i=-1;

	mpz_init(pprime);
	mpz_init_set_ui(tmp,1);

	if ( argc>1 ) {
		k=atoi(argv[1]); 
	}
	else {
		k=-1;
	}
	for (;k--;) {
		JLC(count, jprimes, swheel,-1);
		s=1; count++;
		gpprime(tmp, pi0, pi1, s++, count); 

		i=swheel; JLF(p, jprimes, i);
		while (i<=ewheel) {
			gpprime(**p, pi0, pi1, s++, count);

			JLN(p, jprimes, i);
		}

		mpz_set(pi0,pi1);
		JLN(p,jprimes,cprime);
		mpz_mul(pi1,pi1,**p);

		swheel=ewheel+1;
		ewheel=-1;
		JLL(p, jprimes, ewheel);

		gmp_fprintf(stderr, "pi0: %Zd pi1: %Zd, sw: %d ew: %d - %Zd\n",pi0,pi1, swheel, ewheel, **p);

	}
/*
	i=0;
	JLF(p, jprimes, i);
	while (p) {
	    gmp_printf("%Zu\n", **p);
	    JLN(p, jprimes, i);
	}
*/
	return 0;

}



