shithub: purgatorio

ref: 42dfac6916ebbdac65cbec8b3e1a80c3ee41423c
dir: /appl/math/primes.b/

View raw version
implement Primes;

#
# primes starting [ending]
#
# Subject to the Lucent Public License 1.02
#

include "draw.m";

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

include "sys.m";
	sys: Sys;
include "math.m";
	maths: Math;

bigx: con 9.007199254740992e15;
pt := array[] of {
	2,
	3,
	5,
	7,
	11,
	13,
	17,
	19,
	23,
	29,
	31,
	37,
	41,
	43,
	47,
	53,
	59,
	61,
	67,
	71,
	73,
	79,
	83,
	89,
	97,
	101,
	103,
	107,
	109,
	113,
	127,
	131,
	137,
	139,
	149,
	151,
	157,
	163,
	167,
	173,
	179,
	181,
	191,
	193,
	197,
	199,
	211,
	223,
	227,
	229,
};
wheel := array[] of {
	10.0,
	2.0,
	4.0,
	2.0,
	4.0,
	6.0,
	2.0,
	6.0,
	4.0,
	2.0,
	4.0,
	6.0,
	6.0,
	2.0,
	6.0,
	4.0,
	2.0,
	6.0,
	4.0,
	6.0,
	8.0,
	4.0,
	2.0,
	4.0,
	2.0,
	4.0,
	8.0,
	6.0,
	4.0,
	6.0,
	2.0,
	4.0,
	6.0,
	2.0,
	6.0,
	6.0,
	4.0,
	2.0,
	4.0,
	6.0,
	2.0,
	6.0,
	4.0,
	2.0,
	4.0,
	2.0,
	10.0,
	2.0,
};
BITS: con 8;
TABLEN: con 1000;
table := array[TABLEN] of byte;
bittab := array[8] of {
	byte 1,
	byte 2,
	byte 4,
	byte 8,
	byte 16,
	byte 32,
	byte 64,
	byte 128,
};

init(nil: ref Draw->Context, args: list of string)
{
	sys = load Sys Sys->PATH;
	maths = load Math Math->PATH;

	if(len args <= 1){
		sys->fprint(sys->fildes(2), "usage: primes starting [ending]\n");
		raise "fail:usage";
	}
	args = tl args;
	nn := real hd args;
	limit := bigx;
	if(tl args != nil){
		limit = real hd tl args;
		if(limit < nn)
			exit;
		if(limit > bigx)
			ouch();
	}
	if(nn < 0.0 || nn > bigx)
		ouch();
	if(nn == 0.0)
		nn = 1.0;
	if(nn < 230.0){
		for(i := 0; i < len pt; i++){
			r := real pt[i];
			if(r < nn)
				continue;
			if(r > limit)
				exit;
			sys->print("%d\n", pt[i]);
			if(limit >= bigx)
				exit;
		}
		nn = 230.0;
	}
	(t, nil) := maths->modf(nn/2.0);
	nn = 2.0*real t+1.0;
	for(;;){
		# 
		# clear the sieve table.
		#  
		for(i := 0; i < len table; i++)
			table[i] = byte 0;
		# 
		# run the sieve
		#  
		v := maths->sqrt(nn+real (TABLEN*BITS));
		mark(nn, 3);
		mark(nn, 5);
		mark(nn, 7);
		i = 0;
		for(k := 11.0; k <= v; k += wheel[i]){
			mark(nn, int k);
			i++;
			if(i >= len wheel)
				i = 0;
		}
		# 
		# now get the primes from the table and print them
		#  
		for(i = 0; i < TABLEN*BITS; i += 2){
			if(int table[i>>3]&int bittab[i&8r7])
				continue;
			temp := nn+real i;
			if(temp > limit)
				exit;
			sys->print("%d\n", int temp);
			if(limit >= bigx)
				exit;
		}
		nn += real (TABLEN*BITS);
	}
}

mark(nn: real, k: int)
{
	(it1, nil) := maths->modf(nn/real k);
	j := int (real k*real it1-nn);
	if(j < 0)
		j += k;
	for(; j < len table*BITS; j += k)
		table[j>>3] |= bittab[j&8r7];
}

ouch()
{
	sys->fprint(sys->fildes(2), "primes: limits exceeded\n");
	raise "fail:ouch";
}