Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
|
|
@ -0,0 +1,36 @@
|
|||
BEGIN # Legendre prime counting function - translation of EasyLang/Go non-memoised version #
|
||||
|
||||
PR read "primes.incl.a68" PR # include RC prime utilities #
|
||||
|
||||
OP PI = ( INT n )INT:
|
||||
IF n < 2 THEN 0
|
||||
ELIF n = 2 THEN 1
|
||||
ELSE
|
||||
INT root n = ENTIER sqrt( n );
|
||||
[]INT primes = EXTRACTPRIMESUPTO root n FROMPRIMESIEVE PRIMESIEVE root n;
|
||||
INT prime count = UPB primes;
|
||||
|
||||
PROC phi = ( INT x, a in )INT:
|
||||
BEGIN
|
||||
INT a := a in, sum := 0;
|
||||
BOOL continue := TRUE;
|
||||
WHILE a > 1 AND continue DO
|
||||
INT pa = primes[ a ];
|
||||
IF x <= pa THEN
|
||||
continue := FALSE
|
||||
ELSE
|
||||
a -:= 1;
|
||||
sum +:= phi( x OVER pa, a )
|
||||
FI
|
||||
OD;
|
||||
IF continue THEN x - ( x OVER 2 ) - sum ELSE 1 FI
|
||||
END;
|
||||
|
||||
phi( n, prime count ) + prime count - 1
|
||||
FI;
|
||||
|
||||
FOR i FROM 0 TO 9 DO
|
||||
INT n = 10 ^ i;
|
||||
print( ( "10^", whole( i, 0 ), " ", whole( PI n, 0 ), newline ) )
|
||||
OD
|
||||
END
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
scope # Legendre prime counting function - translation of EasyLang/Go non-memoised version
|
||||
|
||||
# generate and return a register containing the primes up to sieveSize
|
||||
local proc primeSieve( sieveSize :: number ) :: register
|
||||
local sieve; create register sieve( sieveSize ); # "vector" to be sieved
|
||||
sieve[ 1 ] := false;
|
||||
for sPos from 2 to sieveSize do sieve[ sPos ] := true od;
|
||||
# sieve the primes
|
||||
for sPos from 2 to entier( sqrt( sieveSize ) ) do
|
||||
if sieve[ sPos ] then
|
||||
for p from sPos * sPos to sieveSize by sPos do
|
||||
sieve[ p ] := false
|
||||
od
|
||||
fi
|
||||
od;
|
||||
return sieve
|
||||
end;
|
||||
|
||||
# construct a sieve of primes up to the maximum we will need
|
||||
local constant psRoot1e9 := primeSieve( sqrt 1e9 );
|
||||
|
||||
# returns a sequence of primes extracted from a prime sieve
|
||||
local proc primesUpTo( n :: number, sieve :: register ) :: sequence
|
||||
local result := seq(); # sequence of primes - initially empty
|
||||
for sPos from 1 to n do
|
||||
if sieve[ sPos ] then insert sPos into result fi
|
||||
od;
|
||||
return result
|
||||
end;
|
||||
|
||||
local proc pix( n :: integer ) :: integer
|
||||
local result := 0;
|
||||
if n = 2 then result := 1
|
||||
elif n > 2 then
|
||||
local constant rootN := entier sqrt n;
|
||||
local constant primes := primesUpTo( rootN, psRoot1e9 );
|
||||
local constant primeCount := size primes;
|
||||
|
||||
local proc phi( x :: integer, aIn :: integer ) :: integer
|
||||
local a, sum, found1 := aIn, 0, false;
|
||||
while a > 1 and not found1 do
|
||||
local constant pa := primes[ a ];
|
||||
if x <= pa then
|
||||
found1 := true
|
||||
else
|
||||
a -:= 1;
|
||||
sum +:= phi( x \ pa, a )
|
||||
fi
|
||||
od;
|
||||
return if found1 then 1 else x - ( x \ 2 ) - sum fi
|
||||
end;
|
||||
|
||||
result := phi( n, primeCount ) + primeCount - 1
|
||||
fi;
|
||||
return result
|
||||
end;
|
||||
|
||||
for i from 0 to 9 do
|
||||
local n := 10 ^ i;
|
||||
printf( "10^%d %d\n", i, pix( n ) )
|
||||
od
|
||||
epocs
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// compile with --fast for maximum speed...
|
||||
|
||||
use Time;
|
||||
|
||||
proc countPrimes(lmt: uint(64)): int(64) {
|
||||
if lmt < 9 { // when there are no odd primes less than square root...
|
||||
if lmt < 3 { if lmt < 2 { return 0; } else { return 1; } }
|
||||
return (lmt - (lmt >> 1)): int(64);
|
||||
}
|
||||
|
||||
// Chapel doesn't have closures, so emulate them with a class...
|
||||
class LegendrePi {
|
||||
var n: uint(64);
|
||||
var dom: domain(1);
|
||||
var oprms: [dom] uint(32);
|
||||
proc init(n: uint(64)) {
|
||||
// first, an array of odd primes to the square root of n is generated...
|
||||
this.n = n;
|
||||
const sqrtn = sqrt(n: real(64)): int(64);
|
||||
const rtlmt = (sqrtn - 3) / 2; this.dom = {0 .. rtlmt};
|
||||
this.oprms = 0;
|
||||
for i in 0 .. rtlmt do this.oprms[i] = (i + i + 3): uint(32);
|
||||
var i = 0;
|
||||
for i in (0 ..) { // cull the array
|
||||
var ci = (i + i) * (i + 3) + 3; if ci > rtlmt { break; }
|
||||
const bp = i + i + 3;
|
||||
while (ci <= rtlmt) { this.oprms[ci] = 0; ci += bp; }
|
||||
}
|
||||
var psz = 0;
|
||||
for ti in 0 .. rtlmt { // compress the odd primes array...
|
||||
const tv = this.oprms[ti];
|
||||
if tv != 0 { this.oprms[psz] = tv; psz += 1; }
|
||||
}
|
||||
this.dom = { 0 ..< psz };
|
||||
}
|
||||
proc phi(x: uint(64), a: int): int(64) {
|
||||
if a <= 0 { return (x - (x >> 1)): int(64); } // take care of prime of 2
|
||||
const na = a - 1; const p = this.oprms[na]: uint(64);
|
||||
if x <= p { return 1: int(64); }
|
||||
return phi(x, na) - phi(x / p, na);
|
||||
}
|
||||
proc this(): int(64) {
|
||||
return phi(n, this.oprms.size) + this.oprms.size: int(64);
|
||||
}
|
||||
}
|
||||
return (new LegendrePi(lmt))();
|
||||
}
|
||||
|
||||
proc main() {
|
||||
var timer: Timer;
|
||||
timer.start();
|
||||
|
||||
for i in 0 .. 9 {
|
||||
writeln("π(10**", i, ") = ", countPrimesx(10: uint(64) ** i));
|
||||
}
|
||||
|
||||
timer.stop();
|
||||
|
||||
writeln("This took ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// tiny Phi Look Up for `a` of small degree...
|
||||
const tinyPhiPrimes = [ 2, 3, 5, 7, 11, 13 ]; // degree six
|
||||
const cC = tinyPhiPrimes.size - 1;
|
||||
proc product(a: [] int): int {
|
||||
var acc = 1; for v in a { acc *= v; }; return acc >> 1; }
|
||||
const tinyPhiOddCirc = product(tinyPhiPrimes);
|
||||
proc tot(a: [] int): int {
|
||||
var acc = 1; for v in a { acc *= v - 1; }; return acc; }
|
||||
const tinyPhiOddTot = tot(tinyPhiPrimes);
|
||||
proc makeTinyLUT(ps: [] int, sz: int): [] uint(32) {
|
||||
var arr: [0 .. sz - 1] uint(32) = 1;
|
||||
for p in ps {
|
||||
if p <= 2 { continue; }
|
||||
arr[p >> 1] = 0;
|
||||
for c in ((p * p) >> 1) ..< sz by p { arr[c] = 0; }
|
||||
}
|
||||
var acc = 0: uint(32);
|
||||
for i in 0 ..< sz { acc += arr[i]; arr[i] = acc; }
|
||||
return arr;
|
||||
}
|
||||
const tinyPhiLUT = makeTinyLUT(tinyPhiPrimes, tinyPhiOddCirc);
|
||||
inline proc tinyPhi(x: uint(64)): int(64) {
|
||||
const ndx = (x - 1) >> 1; const numtot = ndx / tinyPhiOddCirc: uint(64);
|
||||
return (numtot * tinyPhiOddTot +
|
||||
tinyPhiLUT[(ndx - numtot * tinyPhiOddCirc): int]): int(64);
|
||||
}
|
||||
|
||||
proc countPrimes(lmt: uint(64)): int(64) {
|
||||
if lmt < 169 { // below 169 whose sqrt is 13 is where TinyPhi doesn't work...
|
||||
if lmt < 3 { if lmt < 2 { return 0; } else { return 1; } }
|
||||
// adjust for the missing "degree" base primes
|
||||
if lmt <= 13 {
|
||||
return ((lmt - 1): int(64) >> 1) + (if (lmt < 9) then 1 else 0); }
|
||||
return 5 + tinyPhiLUT[(lmt - 1): int >> 1]: int(64);
|
||||
}
|
||||
|
||||
// Chapel doesn't have closures, so emulate them with a class...
|
||||
class LegendrePi {
|
||||
var n: uint(64);
|
||||
var dom: domain(1);
|
||||
var oprms: [dom] uint(32);
|
||||
proc init(n: uint(64)) {
|
||||
// first, an array of odd primes to the square root of n is generated...
|
||||
this.n = n;
|
||||
const sqrtn = sqrt(n: real(64)): int(64);
|
||||
const rtlmt = (sqrtn - 3) / 2; this.dom = {0 .. rtlmt};
|
||||
this.oprms = 0;
|
||||
for i in 0 .. rtlmt do this.oprms[i] = (i + i + 3): uint(32);
|
||||
var i = 0;
|
||||
for i in (0 ..) { // cull the array
|
||||
var ci = (i + i) * (i + 3) + 3; if ci > rtlmt { break; }
|
||||
const bp = i + i + 3;
|
||||
while (ci <= rtlmt) { this.oprms[ci] = 0; ci += bp; }
|
||||
}
|
||||
var psz = 0;
|
||||
for ti in 0 .. rtlmt { // compress the odd primes array...
|
||||
const tv = this.oprms[ti];
|
||||
if tv != 0 { this.oprms[psz] = tv; psz += 1; }
|
||||
}
|
||||
this.dom = { 0 ..< psz };
|
||||
}
|
||||
proc lvl(pilmt: int, m: uint(64)): int(64) {
|
||||
var acc = 0: int(64);
|
||||
for pi in cC ..< pilmt {
|
||||
const p = this.oprms[pi]: uint(64); const nm = m * p;
|
||||
if this.n <= nm * p { return acc + (pilmt - pi); }
|
||||
if pi > cC { acc -= this.lvl(pi, nm); }
|
||||
const q = this.n / nm; acc += tinyPhi(q);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
proc this(): int(64) {
|
||||
return tinyPhi(this.n) - this.lvl(this.oprms.size, 1)
|
||||
+ this.oprms.size: int(64);
|
||||
}
|
||||
}
|
||||
return (new LegendrePi(lmt))();
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
const masks = for i in 0 .. 7 do (1 << i): uint(8); // faster bit twiddling
|
||||
|
||||
proc countPrimes(lmt: uint(64)): int(64) {
|
||||
if lmt < 3 { if lmt < 2 { return 0; } else { return 1; } } // odds only!
|
||||
inline proc half(x: int): int { return (x - 1) >> 1; } // convenience function
|
||||
inline proc divide(nm: uint(64), d: uint(64)): int {
|
||||
return (nm: real(64) / d: real(64)): int; } // floating point div faster
|
||||
const sqrtn = sqrt(lmt: real(64)): uint(64);
|
||||
const mxndx = (sqrtn - 1): int / 2;
|
||||
const dom = {0 .. mxndx}; const csz = (mxndx + 8) / 8;
|
||||
var smalls = for i in dom do i: uint(32);
|
||||
var roughs = for i in dom do (i + i + 1): uint(32);
|
||||
var larges = for i in dom do ((lmt / (i + i + 1)) - 1) >> 1;
|
||||
var cullbuf: [0 ..< csz] uint(8);
|
||||
|
||||
// partial sieve loop, adjusting larges/smalls, compressing larges/roughs...
|
||||
var nobps = 0; var rilmt = mxndx;
|
||||
for bp in 3: uint(64) .. by 2 {
|
||||
const i = (bp >> 1): int; const sqri = (i + i) * (i + 1);
|
||||
if sqri > mxndx { break; } // up to quad root of counting range
|
||||
if (cullbuf[i >> 3] & masks[i & 7]) != 0 { continue; } // loop not prime
|
||||
cullbuf[i >> 3] |= masks[i & 7]; // cull bp itself as not a rough
|
||||
for ci in sqri .. mxndx by bp { // do partial sieving pass for `bp`...
|
||||
cullbuf[ci >> 3] |= masks[ci & 7]; } // cull all multiples of `bp`
|
||||
|
||||
// now adjust `larges` for latest partial sieve pass...
|
||||
var ori = 0; // compress input rough index to output one
|
||||
for iri in 0 .. rilmt {
|
||||
const r = roughs[iri]: uint(64); const rci = (r >> 1): int;
|
||||
if (cullbuf[rci >> 3] & masks[rci & 7]) != 0 {
|
||||
continue; } // skip culled roughs in last partial sieving pass
|
||||
const d = bp: uint(64) * r;
|
||||
larges[ori] = larges[iri] -
|
||||
(if d <= sqrtn then
|
||||
larges[smalls[(d >> 1): int] - nobps]
|
||||
else smalls[half(divide(lmt, d))]: uint(64)) + nobps;
|
||||
roughs[ori] = r: uint(32); ori += 1;
|
||||
}
|
||||
|
||||
var si = mxndx; // and adjust `smalls` for latest partial sieve pass...
|
||||
for bpm in bp .. (sqrtn / bp - 1) | 1 by -2 {
|
||||
const c = smalls[(bpm >> 1): int] - nobps: uint(32);
|
||||
const e = ((bpm * bp) >> 1): int;
|
||||
while si >= e { smalls[si] -= c; si -= 1; }
|
||||
}
|
||||
|
||||
nobps += 1; rilmt = ori - 1;
|
||||
}
|
||||
|
||||
var ans = larges[0]; // answer from larges, adjusting for over subtraction...
|
||||
for i in 1 .. rilmt { ans -= larges[i]; } // combine!
|
||||
ans += (rilmt + 1 + 2 * (nobps - 1)) * rilmt / 2; // adjust!
|
||||
|
||||
// add final adjustment for pairs of current roughs to cube root of range...
|
||||
for ri in (1 ..) { // break when reaches cube root of counting range...
|
||||
const p = roughs[ri]: uint(64); const q = lmt / p;
|
||||
const ei = smalls[half(divide(q, p))]: int - nobps;
|
||||
if ei <= ri { break; } // break here when no more pairs!
|
||||
for ori in ri + 1 .. ei { // for all pairs never the same prime!
|
||||
ans += smalls[half(divide(q, roughs[ori]))]: int(64); }
|
||||
// adjust for over subtractions above...
|
||||
ans -= (ei - ri): uint(64) * (nobps: uint(64) + ri: uint(64) - 1);
|
||||
}
|
||||
|
||||
return ans: int(64) + 1; // add one for only even prime of two!
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
global primes[] .
|
||||
proc mkprimes n .
|
||||
len sieve[] n
|
||||
max = sqrt n
|
||||
for d = 2 to max : if sieve[d] = 0
|
||||
for i = d * d step d to n
|
||||
sieve[i] = 1
|
||||
.
|
||||
.
|
||||
primes[] = [ ]
|
||||
for i = 2 to n
|
||||
if sieve[i] = 0 : primes[] &= i
|
||||
.
|
||||
.
|
||||
fastfunc phi x a .
|
||||
while a > 1
|
||||
pa = primes[a]
|
||||
if x <= pa : return 1
|
||||
sum += phi (x div pa) (a - 1)
|
||||
a -= 1
|
||||
.
|
||||
return x - (x div 2) - sum
|
||||
.
|
||||
func pix n .
|
||||
if n < 2 : return 0
|
||||
if n = 2 : return 1
|
||||
mkprimes floor sqrt n
|
||||
a = len primes[]
|
||||
return phi n a + a - 1
|
||||
.
|
||||
for i = 0 to 9
|
||||
n = pow 10 i
|
||||
print "10^" & i & " " & pix n
|
||||
.
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
(do ;;; Legendre prime counting function - translation of EasyLang
|
||||
|
||||
; generate and return a table containing the primes up to sieve-size
|
||||
(fn prime-sieve [sieve-size]
|
||||
(var sieve {})
|
||||
(tset sieve 1 false)
|
||||
(for [s-pos 2 sieve-size] (tset sieve s-pos true))
|
||||
(for [s-pos 2 (math.floor (math.sqrt sieve-size))]
|
||||
(when (. sieve s-pos)
|
||||
(for [p (* s-pos s-pos) sieve-size s-pos] (tset sieve p false))
|
||||
)
|
||||
)
|
||||
sieve
|
||||
)
|
||||
|
||||
; construct a sieve of primes up to the maximum we will need
|
||||
(var ps-root-1e9 (prime-sieve (math.sqrt 1e9)))
|
||||
|
||||
; returns a table of primes extracted from a prime sieve
|
||||
(fn primes-up-to [n sieve]
|
||||
(local result {})
|
||||
(for [s-pos 1 n]
|
||||
(when (. sieve s-pos) (table.insert result s-pos))
|
||||
)
|
||||
result
|
||||
)
|
||||
|
||||
(fn legendre-pi [n]
|
||||
(if (< n 2) 0
|
||||
(= n 2) 1
|
||||
;else
|
||||
(do (local root-n (math.floor (math.sqrt n)))
|
||||
(local primes (primes-up-to root-n ps-root-1e9))
|
||||
(local prime-count (length primes))
|
||||
|
||||
(fn phi [x a-in]
|
||||
(var (a sum found-1) (values a-in 0 false))
|
||||
(while (and (> a 1) (not found-1))
|
||||
(local pa (. primes a))
|
||||
(if (<= x pa)
|
||||
(set found-1 true)
|
||||
;else
|
||||
(do (set a (- a 1))
|
||||
(set sum (+ sum (phi (// x pa) a)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(if found-1
|
||||
1
|
||||
;else
|
||||
(- x (// x 2 ) sum)
|
||||
)
|
||||
)
|
||||
|
||||
(- (+ (phi n prime-count) prime-count) 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(for [i 0 9]
|
||||
(print (string.format "10^%d %d" i (legendre-pi (^ 10 i))))
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
do -- Legendre prime counting function - translation of EasyLang
|
||||
|
||||
-- generate and return a table containing the primes up to sieveSize
|
||||
local function primeSieve( sieveSize )
|
||||
local sieve = {}
|
||||
sieve[ 1 ] = false
|
||||
for sPos = 2, sieveSize do sieve[ sPos ] = true end
|
||||
-- sieve the primes
|
||||
for sPos = 2, math.floor( math.sqrt( sieveSize ) ) do
|
||||
if sieve[ sPos ] then
|
||||
for p = sPos * sPos, sieveSize, sPos do
|
||||
sieve[ p ] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
return sieve
|
||||
end
|
||||
|
||||
-- construct a sieve of primes up to the maximum we will need
|
||||
local psRoot1e9 = primeSieve( math.sqrt( 1e9 ) )
|
||||
|
||||
-- returns a table of primes extracted from a prime sieve
|
||||
local function primesUpTo( n, sieve )
|
||||
local result = {}
|
||||
for sPos = 1, n do
|
||||
if sieve[ sPos ] then table.insert( result, sPos ) end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function pi( n )
|
||||
local result = 0
|
||||
if n == 2 then result = 1
|
||||
elseif n > 2 then
|
||||
local rootN = math.floor( math.sqrt( n ) )
|
||||
local primes = primesUpTo( rootN, psRoot1e9 )
|
||||
local primeCount = # primes
|
||||
|
||||
local function phi( x, aIn )
|
||||
local a, sum, found1 = aIn, 0, false
|
||||
while a > 1 and not found1 do
|
||||
local pa = primes[ a ]
|
||||
if x <= pa then
|
||||
found1 = true
|
||||
else
|
||||
a = a - 1
|
||||
sum = sum + phi( x // pa, a )
|
||||
end
|
||||
end
|
||||
return found1 and 1 or x - ( x // 2 ) - sum
|
||||
end
|
||||
|
||||
result = phi( n, primeCount ) + primeCount - 1
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
for i = 0, 9 do
|
||||
local n = math.floor( 10 ^ i )
|
||||
print( "10^"..i.." "..pi( n ) )
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
MODULE LegendrePi; (* Legendre prime counting function *)
|
||||
(* - translation of EasyLang/Go non-memoised version *)
|
||||
IMPORT Primes, Math, Out;
|
||||
|
||||
CONST maxPrime = 32000; (* somewhat more than sqrt( 1e9 ) *)
|
||||
VAR primeSieve : ARRAY maxPrime OF BOOLEAN;
|
||||
primeList : ARRAY maxPrime OF INTEGER;
|
||||
|
||||
PROCEDURE pi( n : INTEGER ) : INTEGER;
|
||||
VAR rootN, result : INTEGER;
|
||||
|
||||
PROCEDURE phi( x, aIn : INTEGER; primes : ARRAY OF INTEGER ) : INTEGER;
|
||||
VAR a, sum, pa, count : INTEGER;
|
||||
found1 : BOOLEAN;
|
||||
BEGIN
|
||||
a := aIn;
|
||||
sum := 0;
|
||||
found1 := FALSE;
|
||||
WHILE ( a > 1 ) & ~ found1 DO
|
||||
pa := primes[ a ];
|
||||
IF x <= pa THEN
|
||||
found1 := TRUE
|
||||
ELSE
|
||||
DEC( a );
|
||||
INC( sum, phi( x DIV pa, a, primes ) )
|
||||
END
|
||||
END;
|
||||
IF found1 THEN count := 1 ELSE count := x - ( x DIV 2 ) - sum END
|
||||
RETURN count
|
||||
END phi;
|
||||
|
||||
BEGIN
|
||||
IF n < 2 THEN result := 0
|
||||
ELSIF n = 2 THEN result := 1
|
||||
ELSE
|
||||
rootN := FLOOR( Math.sqrt( FLT( n ) ) );
|
||||
Primes.extractUpTo( rootN, primeList, primeSieve );
|
||||
result := phi( n, primeList[ 0 ], primeList ) + primeList[ 0 ] - 1
|
||||
END
|
||||
RETURN result
|
||||
END pi;
|
||||
|
||||
PROCEDURE showPiForPowersOfTen;
|
||||
VAR i, n : INTEGER;
|
||||
BEGIN
|
||||
n := 1;
|
||||
FOR i := 0 TO 9 DO
|
||||
Out.String( "10^" );Out.Int( i, 0 );Out.String( " " );Out.Int( pi( n ), 0 );Out.Ln;
|
||||
n := n * 10
|
||||
END
|
||||
END showPiForPowersOfTen;
|
||||
|
||||
BEGIN
|
||||
Primes.sieve( primeSieve );
|
||||
showPiForPowersOfTen
|
||||
END LegendrePi.
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
do -- Legendre prime counting function - translation of EasyLang/Go non-memoised version
|
||||
|
||||
local int = require( "int" ) -- RC Pluto integer library, inc. prime utilities
|
||||
|
||||
local function pi( n : number ) : number
|
||||
local result = 0
|
||||
if n == 2 then result = 1
|
||||
elseif n > 2 then
|
||||
local rootN = math.floor( math.sqrt( n ) )
|
||||
local primes = int.primes( rootN )
|
||||
local pCount = # primes
|
||||
|
||||
local function phi( x : number, aIn : number ) : number
|
||||
local a, sum, found1 = aIn, 0, false
|
||||
while a > 1 and not found1 do
|
||||
local pa = primes[ a ]
|
||||
if x <= pa then
|
||||
found1 = true
|
||||
else
|
||||
a -= 1
|
||||
sum += phi( x // pa, a )
|
||||
end
|
||||
end
|
||||
return if found1 then 1 else x - ( x // 2 ) - sum end
|
||||
end
|
||||
|
||||
result = phi( n, pCount ) + pCount - 1
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
for i = 0, 9 do
|
||||
local n = math.floor( 10 ^ i )
|
||||
print( $"10^{i} {pi( n )}" )
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
from bitarray.util import gen_primes
|
||||
from math import isqrt
|
||||
from functools import cache
|
||||
from time import perf_counter
|
||||
|
||||
def countPrimes(limit):
|
||||
if limit < 2: return 0
|
||||
|
||||
rtlmtsz = isqrt(limit) + 1
|
||||
sieve = gen_primes(rtlmtsz)
|
||||
baseprms = [ pi for pi in range(rtlmtsz) if sieve[pi] ]
|
||||
nbps = len(baseprms)
|
||||
|
||||
@cache
|
||||
def phi(x, a): # termination condition means x and a can never be zero
|
||||
rslt = x
|
||||
for na in range(a - 1, -1, -1): # loop takes care of a zero termination!
|
||||
pna = baseprms[na]
|
||||
if pna * pna > x: rslt -= 1; continue # termination before x is zero
|
||||
if na: rslt -= phi(x // pna, na) # lessening recursion depth
|
||||
else: rslt -= x // pna
|
||||
return rslt
|
||||
|
||||
return phi(limit, nbps) + nbps - 1
|
||||
|
||||
start = perf_counter()
|
||||
for exp in range(10):
|
||||
print(f'10**{exp}: ', countPrimes(10**exp))
|
||||
stop = perf_counter()
|
||||
print(f"This took {(stop - start) * 1000:.0f} milliseconds.")
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
from math import isqrt
|
||||
from time import perf_counter
|
||||
|
||||
# numops = 0 # FOR TELEMETRY!!!!!
|
||||
|
||||
def countPrimes(limit):
|
||||
# global numops; numops = 0 # FOR TELEMETRY!!!!!
|
||||
|
||||
# can't odd sieve for limit less than 3
|
||||
if limit < 3: return (0 if limit < 2 else 1)
|
||||
# `>> ` is used throughout for `// 2` for efficiency...
|
||||
|
||||
# INITIALIZATION...
|
||||
|
||||
rtlmt = isqrt(limit); rtlmtsz = (rtlmt + 1) // 2
|
||||
|
||||
# note that roughs list starts at (and keeps) one to match the algorithm
|
||||
# though one is not a prime, but it is important in computation of pi and
|
||||
# that the roughs and pis lists are processed in sync...
|
||||
# roughs list of numbers culled of multiples of two here...
|
||||
roughs = [ i + i + 1 for i in range(rtlmtsz) ] # odds only; now two multiples!
|
||||
|
||||
# phis for current roughs, thus init'ed to phip2 of each rough's pi;
|
||||
# these are the "stack" values for a recursive solution...
|
||||
phis = [ (limit // r + 1) // 2 for r in roughs ] # plus 1 for phi form!
|
||||
|
||||
# List used to reference the "compressed" index of the pis list...
|
||||
phindxs = [ i for i in range(rtlmtsz) ] # plus one to get phis!
|
||||
|
||||
# MAIN PARTIAL SIEVING LOOP...
|
||||
numbps = 0; rsz = rtlmtsz; bp = roughs[1] # starts with bp of 3
|
||||
while bp * bp <= rtlmt:
|
||||
|
||||
# mark all roughs culled in this base prime partial sieving pass...
|
||||
roughs[1] = 0 # make phi by eliminating bp as well!
|
||||
for cp in range(bp * bp, rtlmt, bp + bp): # cull points
|
||||
cpi = phindxs[cp >> 1]
|
||||
if roughs[cpi] == cp: roughs[cpi] = 0 # only if not alreay eliminated
|
||||
|
||||
# MAIN INNER PROCESSING-SPLITTING LOOP...
|
||||
roi = 0
|
||||
for rii in range(rsz):
|
||||
m = roughs[rii]
|
||||
if not m: continue # skip marked!
|
||||
mbp = m * bp # odd product due to all roughs are odd!
|
||||
|
||||
# crutial pis list updating based on size of `qbp` whether
|
||||
# less than or equal to or above `rtlmt`...
|
||||
# if mbp > rtlmt: numops += 1 # FOR TELEMETRY!!!!!
|
||||
phis[roi] = phis[rii] - \
|
||||
( phis[phindxs[mbp >> 1]] if mbp <= rtlmt
|
||||
# add one to make it phi form!...
|
||||
else phindxs[(limit // mbp - 1) >> 1] + 1 )
|
||||
|
||||
roughs[roi] = m; roi += 1
|
||||
|
||||
# update phindxs list to reflect new state of roughs; the only remaining
|
||||
# valid phindx values are those corresponding to current roughs...
|
||||
maxndxsz = rtlmtsz
|
||||
for ri in range(roi - 1, 0, -1):
|
||||
strti = roughs[ri] >> 1
|
||||
phindxs[strti:maxndxsz] = [ri] * (maxndxsz - strti); maxndxsz = strti
|
||||
|
||||
bp = roughs[1]; rsz = roi; numbps += 1
|
||||
|
||||
phi = phis[0] - sum(phis[1:rsz]) # accumulate result from pis
|
||||
|
||||
# CALCULATION OF CONTRIBUTION DUE TO LARGE UNIQUE PRIME PAIRS...
|
||||
# All roughs values above one are now odd primes and above limit**(1/4) and
|
||||
# thus all products of unique pairs of these primes are odd and need to be
|
||||
# added (evens add; odds subtract - inclusion/exclusion principle)
|
||||
# as phi's to the result...
|
||||
phi += (rsz - 2) * (rsz - 1) // 2 # add all the "one"'s pairs calc may need!
|
||||
for p1i in range(1, rsz - 1):
|
||||
p1 = roughs[p1i]; qp1 = limit // p1
|
||||
endndx = phindxs[(qp1 // p1 - 1) >> 1]
|
||||
if endndx <= p1i: break
|
||||
for p2i in range(p1i + 1, endndx + 1):
|
||||
# numops += 1 # FOR TELEMETRY!!!!!
|
||||
phi += phindxs[(qp1 // roughs[p2i] - 1) >> 1]
|
||||
phi -= (endndx - p1i) * (p1i - 1) # efficient to remove what's not needed!
|
||||
|
||||
numrtprms = numbps + rsz; return phi + numrtprms - 1
|
||||
|
||||
# USAGE...
|
||||
|
||||
for i in range(10): print(f"π(10**{i}) = {countPrimes(10**i):,}")
|
||||
|
||||
count = countPrimes(limit := 100_000_000_000) # get CPU up to speed!
|
||||
start = perf_counter()
|
||||
count = countPrimes(limit := 100_000_000_000)
|
||||
stop = perf_counter()
|
||||
|
||||
# print(f"number of operations: {numops:,}") # RESULT OF TELEMETRY!!!!!
|
||||
print(f"\r\nFound {count:,} primes up to {limit:,}")
|
||||
print(f"The above calculation took {stop - start:.3f} seconds.")
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
-- 23 Aug 2025
|
||||
-- 21 Feb 2026
|
||||
include Setting
|
||||
|
||||
say 'LEGENDRE PRIME COUNTER (NO MEMOIZATION)'
|
||||
|
|
@ -13,7 +13,7 @@ end
|
|||
exit
|
||||
|
||||
Pie:
|
||||
procedure expose prim.
|
||||
procedure expose Prim. Memo.
|
||||
arg xx
|
||||
if xx < 3 then
|
||||
return 0+(xx=2)
|
||||
|
|
@ -21,13 +21,14 @@ n = Primes(Isqrt(xx))
|
|||
return Phi(xx,n)+n-1
|
||||
|
||||
Phi:
|
||||
procedure expose prim.
|
||||
procedure expose Prim.
|
||||
arg xx,yy
|
||||
if yy < 2 then
|
||||
return xx-(xx%2)*(yy=1)
|
||||
p = prim.yy
|
||||
p = Prim.yy
|
||||
if xx <= p then
|
||||
return 1
|
||||
return Phi(xx,yy-1)-Phi(xx%p,yy-1)
|
||||
|
||||
-- Primes; Isqrt
|
||||
include Math
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- 23 Aug 2025
|
||||
-- 21 Feb 2026
|
||||
include Setting
|
||||
|
||||
say 'LEGENDRE PRIME COUNTER (WITH MEMOIZATION)'
|
||||
|
|
@ -13,25 +13,26 @@ end
|
|||
exit
|
||||
|
||||
Pie:
|
||||
procedure expose prim. work.
|
||||
procedure expose Prim. Work. Memo.
|
||||
arg xx
|
||||
if xx < 3 then
|
||||
return 0+(xx=2)
|
||||
n = Primes(Isqrt(xx))
|
||||
work. = 0
|
||||
Work. = 0
|
||||
return Phi(xx,n)+n-1
|
||||
|
||||
Phi:
|
||||
procedure expose prim. work.
|
||||
procedure expose Prim. Work.
|
||||
arg xx,yy
|
||||
if yy < 2 then
|
||||
return xx-(xx%2)*(yy=1)
|
||||
p = prim.yy
|
||||
p = Prim.yy
|
||||
if xx <= p then
|
||||
return 1
|
||||
if work.xx.yy > 0 then
|
||||
return work.xx.yy
|
||||
work.xx.yy = Phi(xx,yy-1)-Phi(xx%p,yy-1)
|
||||
return work.xx.yy
|
||||
if Work.xx.yy > 0 then
|
||||
return Work.xx.yy
|
||||
Work.xx.yy = Phi(xx,yy-1)-Phi(xx%p,yy-1)
|
||||
return Work.xx.yy
|
||||
|
||||
-- Primes; Isqrt
|
||||
include Math
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- 23 Aug 2025
|
||||
-- 21 Feb 2026
|
||||
include Setting
|
||||
|
||||
say 'LEGENDRE PRIME COUNTER (SIEVING)'
|
||||
|
|
@ -12,4 +12,5 @@ do n = 0 to 8
|
|||
end
|
||||
exit
|
||||
|
||||
-- Primes
|
||||
include Math
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
// can compile with: v -cflags -march=native -cflags -O3 -prod MagicCount.v
|
||||
import time
|
||||
import math { sqrt }
|
||||
|
||||
const masks = [ u8(1), 2, 4, 8, 16, 32, 64, 128 ] // faster than bit twiddling!
|
||||
|
||||
@[inline]
|
||||
fn half(n u64) i64 { return i64((n - 1) >>> 1) } // convenience function!
|
||||
|
||||
@[inline] // floating point divide faster than integer divide!
|
||||
fn divide(nm u64, d u64) u64 { return u64(f64(nm) / f64(d)) }
|
||||
|
||||
@[direct_array_access]
|
||||
fn count_primes_to(n u64) i64 {
|
||||
if n < u64(9) { return if n < i64(2) { i64(0) } else { i64((n + 1) / 2) } }
|
||||
rtlmt := u64(sqrt(f64(n)))
|
||||
mxndx := i64((rtlmt - 1) / 2)
|
||||
arrlen := int(mxndx + 1)
|
||||
mut smalls := []u32{ len: arrlen, cap: arrlen, init: u32(index) }
|
||||
mut roughs := []u32{ len: arrlen, cap: arrlen, init: u32(index + index + 1) }
|
||||
mut larges := []i64{ len: arrlen, cap: arrlen,
|
||||
init: i64(((n / u64(index + index + 1) - 1) / 2)) }
|
||||
cullbuflen := int((mxndx + 8) / 8)
|
||||
mut cullbuf := []u8{len: cullbuflen, cap: cullbuflen, init: u8(0)}
|
||||
mut nbps := i64(0) // do partial sieving for each odd base prime to quad root...
|
||||
mut rilmt := arrlen // number of roughs start with full size!
|
||||
// start with 3; breaks when partial sieving done...
|
||||
for i := i64(1); ; i++ {
|
||||
sqri := (i + i) * (i + 1)
|
||||
if sqri > mxndx { break } // breaks here!
|
||||
if (cullbuf[i >>> 3] & masks[i & 7]) != u8(0) { continue } // not prime!
|
||||
cullbuf[i >>> 3] |= masks[i & 7] // cull bp rep!
|
||||
bp := u64(i + i + 1) // partial sieve by bp...
|
||||
for c := sqri; c < arrlen; c += i64(bp) { cullbuf[c >>> 3] |= masks[c & 7] }
|
||||
mut nri := 0 // transfer from `ori` to `nri` indexes:
|
||||
// update `roughs` and `larges` for partial sieve...
|
||||
for ori in 0 .. rilmt {
|
||||
r := roughs[ori]
|
||||
rci := i64(r >>> 1) // skip recently culled in last partial sieve...
|
||||
if (cullbuf[rci >>> 3] & masks[rci & 7]) != u8(0) { continue }
|
||||
d := u64(r) * u64(bp)
|
||||
larges[nri] = larges[ori] -
|
||||
(if d <= rtlmt { larges[i64(smalls[d >>> 1]) - nbps] }
|
||||
else { i64(smalls[half(divide(n, d))]) })
|
||||
+ nbps // adjust for over subtraction of base primes!
|
||||
roughs[nri] = r // compress for culled `larges` and `roughs`!
|
||||
nri++ // advance output `roughs` index!
|
||||
}
|
||||
mut si := mxndx // update `smalls` for partial sieve...
|
||||
for pm := ((rtlmt / bp) - 1) | 1; pm >= bp; pm -= 2 {
|
||||
c := smalls[pm >>> 1]
|
||||
e := (pm * bp) >>> 1
|
||||
for ; si >= e; si-- { smalls[si] -= (c - u32(nbps)) }
|
||||
}
|
||||
rilmt = nri // new rough size limit!
|
||||
nbps++ // for one partial sieve base prime pass!
|
||||
}
|
||||
// combine results so far; adjust for over subtraction of base prime count...
|
||||
mut ans := larges[0] + i64(((rilmt + 2 * (nbps - 1)) * (rilmt - 1) / 2))
|
||||
for ri in 1 .. rilmt { ans -= larges[ri] } // combine results so far!
|
||||
// add quotient for product of pairs of primes, quad root to cube root...
|
||||
// break controlled below
|
||||
for ri := 1; ; ri++ {
|
||||
p := u64(roughs[ri])
|
||||
m := n / p
|
||||
ei := int(smalls[half(u64(m / p))]) - nbps
|
||||
if ei <= ri { break } // break out when only multiple equal to `p`
|
||||
ans -= i64((ei - ri) * (nbps + ri - 1)) // adjust for over addition below!
|
||||
// add for products of 1st and 2nd primes...
|
||||
for sri in ri + 1 .. ei + 1 {
|
||||
ans += i64(smalls[half(divide(m, u64(roughs[sri])))]) }
|
||||
}
|
||||
return ans + 1 // add one for only even prime of two!
|
||||
}
|
||||
|
||||
start_time := time.now()
|
||||
mut pow := u64(1)
|
||||
for i in 0 .. 10 {
|
||||
println("π(10**$i) = ${count_primes_to(pow)}")
|
||||
pow *= 10 }
|
||||
duration := (time.now() - start_time).milliseconds()
|
||||
println("This took $duration milliseconds.")
|
||||
Loading…
Add table
Add a link
Reference in a new issue