code: purgatorio

ref: 27ca2618d4bc7642370feb39a83a3cff92495ca2
dir: /appl/math/sieve.b/

View raw version
implement Sieve;

include "sys.m";
	sys: Sys;
include "draw.m";
include "arg.m";
	arg: Arg;

M: con 16*1024*1024;
N: con 8*M;
T: con 2*1024*1024;

limit := array[5] of { M, N, 2*N, 3*N, 15*(N/4) };

Sieve: module
{
	init: fn(nil: ref Draw->Context, argv: list of string);
};

init(nil: ref Draw->Context, argv: list of string)
{
	sys = load Sys Sys->PATH;
	arg = load Arg Arg->PATH;

	np := 0;
	alg := 3;
	arg->init(argv);
	while((c := arg->opt()) != 0){
		case (c){
			'a' =>
				alg = int arg->arg();
		}
	}
	if(alg < 0 || alg > 4)
		alg = 3;
	lim := limit[alg];
	argv = arg->argv();
	if(argv != nil)
		lim = int hd argv;
	if(lim < 0 || lim > limit[alg])
		lim = limit[alg];
	if(lim < 6){
		if(lim > 2){
			sys->print("2\n");
			np++;
		}
		if(lim > 3){
			sys->print("3\n");
			np++;
		}
	}
	else{
		case (alg){
			0 => np = init0(lim);
			1 => np = init1(lim);
			2 => np = init2(lim);
			3 => np = init3(lim);
			4 => np = init4(lim);
		}
	}
	sys->print("%d primes < %d\n", np, lim);
}

init0(lim: int): int
{
	p := array[lim] of byte;
	for(i := 0; i < lim; i++)
		p[i] = byte 1;
	p[0] = p[1] = byte 0;
	np := 0;
	for(i = 0; i < lim; i++){
		if(p[i] == byte 1){
			np++;
			sys->print("%d\n", i);
			for(j := i+i; j < lim; j += i)
				p[j] = byte 0;
		}
	}
	return np;
}

init1(lim: int): int
{
	n := (lim+31)/32;
	p := array[n] of int;
	for(i := 0; i < n; i++)
		p[i] = int 16rffffffff;
	p[0] = int 16rfffffffc;
	np := 0;
	for(i = 0; i < lim; i++){
		if(p[i>>5] & (1<<(i&31))){
			np++;
			sys->print("%d\n", i);
			for(j := i+i; j < lim; j += i)
				p[j>>5] &= ~(1<<(j&31));
		}
	}
	return np;
}

init2(lim: int): int
{
	n := ((lim+1)/2+31)/32;
	p := array[n] of int;
	for(i := 0; i < n; i++)
		p[i] = int 16rffffffff;
	p[0] = int 16rfffffffe;
	np := 1;
	sys->print("%d\n", 2);
	for(i = 1; i < lim; i += 2){
		k := (i-1)>>1;
		if(p[k>>5] & (1<<(k&31))){
			np++;
			sys->print("%d\n", i);
			inc := i+i;
			for(j := i+i+i; j < lim; j += inc){
				k = (j-1)>>1;
				p[k>>5] &= ~(1<<(k&31));
			}
		}
	}
	return np;
}

init3(lim: int): int
{
	n := ((lim+2)/3+31)/32;
	p := array[n] of int;
	for(i := 0; i < n; i++)
		p[i] = int 16rffffffff;
	p[0] = int 16rfffffffe;
	np := 2;
	sys->print("%d\n", 2);
	sys->print("%d\n", 3);
	d := 2;
	for(i = 1; i < lim; i += d){
		k := (i-1)/3;
		if(p[k>>5] & (1<<(k&31))){
			np++;
			sys->print("%d\n", i);
			inc := 6*i;
			for(j := 5*i; j > 0 && j < lim; j += inc){
				k = (j-1)/3;
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 7*i; j > 0 && j < lim; j += inc){
				k = (j-1)/3;
				p[k>>5] &= ~(1<<(k&31));
			}
		}
		d = 6-d;
	}
	return np;
}

init4(lim: int): int
{
	n := (4*((lim+14)/15)+31)/32;
	p := array[n] of int;
	for(i := 0; i < n; i++)
		p[i] = int 16rffffffff;
	p[0] = int 16rfffffffe;
	np := 3;
	sys->print("%d\n", 2);
	sys->print("%d\n", 3);
	sys->print("%d\n", 5);
	m := -1;
	d := array[8] of { 6, 4, 2, 4, 2, 4, 6, 2 };
	for(i = 1; i < lim; i += d[m]){
		k := (17*(i%30-1))/60+8*(i/30);
		if(p[k>>5] & (1<<(k&31))){
			np++;
			sys->print("%d\n", i);
			inc := 30*i;
			for(j := 7*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 11*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 13*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 17*i; j > 0 &&  j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 19*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 23*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 29*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
			for(j = 31*i; j > 0 && j < lim; j += inc){
				k = (17*(j%30-1))/60+8*(j/30);
				p[k>>5] &= ~(1<<(k&31));
			}
		}
		m++;
		if(m == 8)
			m = 0;
	}
	return np;
}

init5(lim: int): int
{
	# you must be joking
	lim = 0;
	return 0;
}