September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -20,7 +20,11 @@ Show output on this page.
|
|||
|
||||
'''Note 2:''' If a languages in-built prime generator is extensible or is guaranteed to generate primes up to a system limit, (2<sup>31</sup> or memory overflow for example), then this may be used as long as an explanation of the limits of the prime generator is also given. (Which may include a link to/excerpt from, language documentation).
|
||||
|
||||
;nice site to check results:
|
||||
Website with vast count of primes. Small ones for the first 10000 and up to 1,000,000,000,000 aka 1E12, divided in subranges : "Each compressed file contains 10 million primes" <br>
|
||||
http://www.primos.mat.br/indexen.html
|
||||
<br>
|
||||
|
||||
;Related task:
|
||||
* The task is written so it may be useful in solving the task [[Emirp primes]] as well as others (depending on its efficiency).
|
||||
<br><br>
|
||||
<br>
|
||||
<br>
|
||||
|
|
|
|||
2
Task/Extensible-prime-generator/00META.yaml
Normal file
2
Task/Extensible-prime-generator/00META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Prime Numbers
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
(deftype CIS [v cont]
|
||||
clojure.lang.ISeq
|
||||
(first [_] v)
|
||||
(next [_] (if (nil? cont) nil (cont)))
|
||||
(more [this] (let [nv (.next this)] (if (nil? nv) (CIS. nil nil) nv)))
|
||||
(cons [this o] (clojure.core/cons o this))
|
||||
(empty [_] (if (and (nil? v) (nil? cont)) nil (CIS. nil nil)))
|
||||
(equiv [this o] (loop [cis1 this, cis2 o] (if (nil? cis1) (if (nil? cis2) true false)
|
||||
(if (or (not= (type cis1) (type cis2))
|
||||
(not= (.v cis1) (.v ^CIS cis2))
|
||||
(and (nil? (.cont cis1))
|
||||
(not (nil? (.cont ^CIS cis2))))
|
||||
(and (nil? (.cont ^CIS cis2))
|
||||
(not (nil? (.cont cis1))))) false
|
||||
(if (nil? (.cont cis1)) true
|
||||
(recur ((.cont cis1)) ((.cont ^CIS cis2))))))))
|
||||
(count [this] (loop [cis this, cnt 0] (if (or (nil? cis) (nil? (.cont cis))) cnt
|
||||
(recur ((.cont cis)) (inc cnt)))))
|
||||
clojure.lang.Seqable
|
||||
(seq [this] (if (and (nil? v) (nil? cont)) nil this))
|
||||
clojure.lang.Sequential
|
||||
Object
|
||||
(toString [this] (if (and (nil? v) (nil? cont)) "()" (.toString (seq (map identity this))))))
|
||||
|
||||
(comment " the wheel could also be a pre-determined vector as for the 2/3/5/7 wheel below...
|
||||
(def wheel
|
||||
[ 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2
|
||||
6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6
|
||||
2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 ])
|
||||
")
|
||||
|
||||
(def wheel-primes [2 3 5 7 11 13 17])
|
||||
|
||||
(def next-prime 19)
|
||||
|
||||
(def nextnext-prime 23)
|
||||
|
||||
;; calculates the vector for very large wheels such as the 92160 element version here
|
||||
;; the disadvantage is that it takes some time to calculate before the work can start...
|
||||
(def wheel
|
||||
(loop [p 2, len 1, ^bytes ptrn [1]]
|
||||
(if (>= p next-prime)
|
||||
ptrn
|
||||
(let [cptrn (cycle ptrn), [f & rcyc] cptrn,
|
||||
np (+ p f), nlen (* len (- p 1)),
|
||||
culls
|
||||
(map (fn [[f _]] f)
|
||||
(iterate (fn [[c [g & r]]] [(+ c (* p g)) r]) [(* p p) cptrn])),
|
||||
gaps (drop 1
|
||||
(for [[gp _ _ _ cnt]
|
||||
(iterate (fn [[_ v cls [g & rgs] c]]
|
||||
(let [[cl & rcls] cls, tv (+ v g),
|
||||
[sg & srgs] rgs, nc (+ c 1)]
|
||||
(if (= cl tv)
|
||||
[(+ g sg) (+ tv sg) rcls srgs nc]
|
||||
[g tv cls rgs nc])))
|
||||
[f np culls rcyc 0]) :while (<= cnt nlen)] gp))]
|
||||
(recur np nlen (vec gaps))))))
|
||||
|
||||
(def wheellmt (- (count wheel) 1))
|
||||
|
||||
(defn primes-treeFolding
|
||||
"Computes the unbounded sequence of primes using a Sieve of Eratosthenes algorithm modified from Bird."
|
||||
[]
|
||||
(letfn [(mltpls [[p pi]]
|
||||
(letfn [(nxtmltpl [c ci]
|
||||
(let [nci (if (< ci wheellmt) (+ ci 1) 0)]
|
||||
(->CIS c #(-> (nxtmltpl (+ c (* p (get wheel ci))) nci)))))]
|
||||
(nxtmltpl (* p p) pi))),
|
||||
(allmtpls [^CIS pxs]
|
||||
(->CIS (mltpls (.v pxs)) #(-> (allmtpls ((.cont pxs)))))),
|
||||
(union [^CIS xs ^CIS ys]
|
||||
(let [xv (.v xs), yv (.v ys)]
|
||||
(if (< xv yv) (->CIS xv #(-> (union ((.cont xs)) ys)))
|
||||
(if (< yv xv)
|
||||
(->CIS yv #(-> (union xs ((.cont ys)))))
|
||||
(->CIS xv #(-> (union (next xs) ((.cont ys))))))))),
|
||||
(pairs [^CIS mltplss] (let [^CIS tl ((.cont mltplss))]
|
||||
(->CIS (union (.v mltplss) (.v tl))
|
||||
#(-> (pairs ((.cont tl))))))),
|
||||
(mrgmltpls [^CIS mltplss]
|
||||
(->CIS (.v ^CIS (.v mltplss))
|
||||
#(-> (union ((.cont ^CIS (.v mltplss)))
|
||||
(mrgmltpls (pairs ((.cont mltplss)))))))),
|
||||
(minusStrtAt [n ni ^CIS cmpsts]
|
||||
(let [nn (+ n (get wheel ni)), nni (if (< ni wheellmt) (+ ni 1) 0)]
|
||||
(if (< n (.v cmpsts))
|
||||
(->CIS [n ni] #(-> (minusStrtAt nn nni cmpsts)))
|
||||
(recur nn nni ((.cont cmpsts)))))),
|
||||
(xtraprmsndxd []
|
||||
(->CIS [next-prime 0] #(-> (minusStrtAt nextnext-prime 1
|
||||
(mrgmltpls (allmtpls (xtraprmsndxd))))))),
|
||||
(stripndxs [^CIS ndxd]
|
||||
(->CIS (get (.v ndxd) 0) #(-> (stripndxs ((.cont ndxd))))))]
|
||||
(loop [i (- (count wheel-primes) 1), ff (fn [] (stripndxs (xtraprmsndxd)))]
|
||||
(if (<= i 0)
|
||||
(->CIS (get wheel-primes 0) ff)
|
||||
(recur (- i 1) (fn [] (->CIS (get wheel-primes i) ff)))))))
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
Iterable<int> primesMap() {
|
||||
Iterable<int> oddprms() sync* {
|
||||
yield(3); yield(5); // need at least 2 for initialization
|
||||
final Map<int, int> bpmap = {9: 6};
|
||||
final Iterator<int> bps = oddprms().iterator;
|
||||
bps.moveNext(); bps.moveNext(); // skip past 3 to 5
|
||||
int bp = bps.current;
|
||||
int n = bp;
|
||||
int q = bp * bp;
|
||||
while (true) {
|
||||
n += 2;
|
||||
while (n >= q || bpmap.containsKey(n)) {
|
||||
if (n >= q) {
|
||||
final int inc = bp << 1;
|
||||
bpmap[bp * bp + inc] = inc;
|
||||
bps.moveNext(); bp = bps.current; q = bp * bp;
|
||||
} else {
|
||||
final int inc = bpmap.remove(n);
|
||||
int next = n + inc;
|
||||
while (bpmap.containsKey(next)) {
|
||||
next += inc;
|
||||
}
|
||||
bpmap[next] = inc;
|
||||
}
|
||||
n += 2;
|
||||
}
|
||||
yield(n);
|
||||
}
|
||||
}
|
||||
return [2].followedBy(oddprms());
|
||||
}
|
||||
|
||||
void main() {
|
||||
print("The first 20 primes:");
|
||||
String str = "( ";
|
||||
primesMap().take(20).forEach((p)=>str += "$p "); print(str + ")");
|
||||
print("Primes between 100 and 150:");
|
||||
str = "( ";
|
||||
primesMap().skipWhile((p)=>p<100).takeWhile((p)=>p<150)
|
||||
.forEach((p)=>str += "$p "); print(str + ")");
|
||||
print("Number of primes between 7700 and 8000: ${
|
||||
primesMap().skipWhile((p)=>p<7700).takeWhile((p)=>p<8000).length
|
||||
}");
|
||||
print("The 10,000th prime: ${
|
||||
primesMap().skip(9999).first
|
||||
}");
|
||||
final start = DateTime.now().millisecondsSinceEpoch;
|
||||
final answer = primesMap().takeWhile((p)=>p<2000000).reduce((a,p)=>a+p);
|
||||
final elapsed = DateTime.now().millisecondsSinceEpoch - start;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
defmodule PrimesSoEMap do
|
||||
@typep stt :: {integer, integer, integer, Enumerable.integer, %{integer => integer}}
|
||||
|
||||
@spec advance(stt) :: stt
|
||||
defp advance {n, bp, q, bps?, map} do
|
||||
bps = if bps? === nil do Stream.drop(oddprms(), 1) else bps? end
|
||||
nn = n + 2
|
||||
if nn >= q do
|
||||
inc = bp + bp
|
||||
nbps = bps |> Stream.drop(1)
|
||||
[nbp] = nbps |> Enum.take(1)
|
||||
advance {nn, nbp, nbp * nbp, nbps, map |> Map.put(nn + inc, inc)}
|
||||
else if Map.has_key?(map, nn) do
|
||||
{inc, rmap} = Map.pop(map, nn)
|
||||
[next] =
|
||||
Stream.iterate(nn + inc, &(&1 + inc))
|
||||
|> Stream.drop_while(&(Map.has_key?(rmap, &1))) |> Enum.take(1)
|
||||
advance {nn, bp, q, bps, Map.put(rmap, next, inc)}
|
||||
else
|
||||
{nn, bp, q, bps, map}
|
||||
end end
|
||||
end
|
||||
|
||||
@spec oddprms() :: Enumerable.integer
|
||||
defp oddprms do # put first base prime cull seq in Map so never empty
|
||||
# advance base odd primes to 5 when initialized
|
||||
init = {7, 5, 25, nil, %{9 => 6}}
|
||||
[3, 5] # to avoid race, preseed with the first 2 elements...
|
||||
|> Stream.concat(
|
||||
Stream.iterate(init, &(advance &1))
|
||||
|> Stream.map(fn {p,_,_,_,_} -> p end))
|
||||
end
|
||||
|
||||
@spec primes() :: Enumerable.integer
|
||||
def primes do
|
||||
Stream.concat([2], oddprms())
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
IO.write "The first 20 primes are:\n( "
|
||||
PrimesSoEMap.primes() |> Stream.take(20) |> Enum.each(&(IO.write "#{&1} "))
|
||||
IO.puts ")"
|
||||
IO.write "The primes between 100 to 150 are:\n( "
|
||||
PrimesSoEMap.primes() |> Stream.drop_while(&(&1<100))
|
||||
|> Stream.take_while(&(&1<150)) |> Enum.each(&(IO.write "#{&1} "))
|
||||
IO.puts ")"
|
||||
IO.write "The number of primes between 7700 and 8000 is: "
|
||||
PrimesSoEMap.primes() |> Stream.drop_while(&(&1<7700))
|
||||
|> Stream.take_while(&(&1<8000)) |> Enum.count |> IO.puts
|
||||
IO.write "The 10,000th prime is: "
|
||||
PrimesSoEMap.primes() |> Stream.drop(9999)
|
||||
|> Enum.take(1) |> List.first |>IO.puts
|
||||
IO.write "The sum of all the priems to two million is: "
|
||||
testfunc =
|
||||
fn () ->
|
||||
ans =
|
||||
PrimesSoEMap.primes() |> Stream.take_while(&(&1<=2000000))
|
||||
|> Enum.sum() |> IO.puts
|
||||
ans end
|
||||
:timer.tc(testfunc)
|
||||
|> (fn {t,_} ->
|
||||
IO.puts "This test bench took #{t} microseconds." end).()
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Primes: isprime
|
||||
|
||||
PrimesGen() = Iterators.filter(isprime, Iterators.countfrom(Int64(2)))
|
||||
|
||||
print("Sum of first 100,000 primes: ")
|
||||
println(Iterators.sum(Iterators.take(PrimesGen(), 100000)))
|
||||
print("First 20 primes: ( ")
|
||||
foreach((p->print(p," ")), Iterators.take(PrimesGen(), 20))
|
||||
println(")")
|
||||
print("Primes between 100 and 150: ( ")
|
||||
for p in Iterators.filter((p->p>=100), PrimesGen()) p > 150 && break; print(p, " ") end
|
||||
println(")")
|
||||
let cnt = 0
|
||||
for p in PrimesGen()
|
||||
p > 8000 && break; if p > 7700 cnt += 1 end
|
||||
end; println("Number of primes between 7700 and 8000: ", cnt)
|
||||
end
|
||||
println("The 10,000th prime: ", Iterators.first(Iterators.drop(PrimesGen(), 9999)))
|
||||
println()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
using Printf: @printf
|
||||
@time let sm = 0
|
||||
for p in Iterators.filter(isprime, Iterators.countfrom(UInt64(2)))
|
||||
p > 2000000 && break
|
||||
sm += p
|
||||
end; @printf("%d\n", sm) end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using Printf: @printf
|
||||
|
||||
print("Sum of first 100,000 primes: ")
|
||||
println(Iterators.sum(Iterators.take(PrimesPaged(), 100000)))
|
||||
print("First 20 primes: ( ")
|
||||
foreach((p->@printf("%d ", p)), Iterators.take(PrimesPaged(), 20))
|
||||
println(")")
|
||||
print("Primes between 100 and 150: ( ")
|
||||
for p in Iterators.filter((p->p>=100), PrimesPaged()) p > 150 && break; @printf("%d ", p)) end
|
||||
println(")")
|
||||
let cnt = 0
|
||||
for p in PrimesPaged()
|
||||
p > 8000 && break; if p > 7700 cnt += 1 end
|
||||
end; println("Number of primes between 7700 and 8000: ", cnt)
|
||||
end
|
||||
@printf("The 10,000th prime: %d\n", Iterators.first(Iterators.drop(PrimesPaged(), 9999)))
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
using Printf: @printf
|
||||
@time let sm = 0
|
||||
for p in PrimesPaged()
|
||||
p > 2000000 && break
|
||||
sm += p
|
||||
end; @printf("%d\n", sm) end
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
// version 1.1.2
|
||||
// compiled with flag -Xcoroutines=enable to suppress 'experimental' warning
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun isPrime(n: Int) : Boolean {
|
||||
if (n < 2) return false
|
||||
if (n % 2 == 0) return n == 2
|
||||
|
|
@ -17,8 +12,7 @@ fun isPrime(n: Int) : Boolean {
|
|||
return true
|
||||
}
|
||||
|
||||
fun generatePrimes() =
|
||||
buildSequence {
|
||||
fun generatePrimes() = sequence {
|
||||
yield(2)
|
||||
var p = 3
|
||||
while (p <= Int.MAX_VALUE) {
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
fun primesHM(): Sequence<Int> = sequence {
|
||||
yield(2)
|
||||
fun oddprms(): Sequence<Int> = sequence {
|
||||
yield(3); yield(5) // need at least 2 for initialization
|
||||
val hm = HashMap<Int,Int>()
|
||||
hm.put(9, 6)
|
||||
val bps = oddprms().iterator(); bps.next(); bps.next() // skip past 5
|
||||
yieldAll(generateSequence(SieveState(7, 5, 25)) {
|
||||
ss ->
|
||||
var n = ss.n; var q = ss.q
|
||||
n += 2
|
||||
while ( n >= q || hm.containsKey(n)) {
|
||||
if (n >= q) {
|
||||
val inc = ss.bp shl 1
|
||||
hm.put(n + inc, inc)
|
||||
val bp = bps.next(); ss.bp = bp; q = bp * bp
|
||||
}
|
||||
else {
|
||||
val inc = hm.remove(n)!!
|
||||
var next = n + inc
|
||||
while (hm.containsKey(next)) {
|
||||
next += inc
|
||||
}
|
||||
hm.put(next, inc)
|
||||
}
|
||||
n += 2
|
||||
}
|
||||
ss.n = n; ss.q = q
|
||||
ss
|
||||
}.map { it.n })
|
||||
}
|
||||
yieldAll(oddprms())
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
primesPaged().takeWhile { it <= 1_000_000_000 }.count()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import tables
|
||||
|
||||
type PrimeType = int
|
||||
|
||||
proc primesHashTable(): iterator(): PrimeType {.closure.} =
|
||||
iterator output(): PrimeType {.closure.} =
|
||||
# some initial values to avoid race and reduce initializations...
|
||||
yield 2.PrimeType; yield 3.PrimeType; yield 5.PrimeType; yield 7.PrimeType
|
||||
var h = initTable[PrimeType,PrimeType]()
|
||||
var n = 9.PrimeType
|
||||
let bps = primesHashTable()
|
||||
var bp = bps() # advance past 2
|
||||
bp = bps(); var q = bp * bp # to initialize with 3
|
||||
while true:
|
||||
if n >= q:
|
||||
let inc = bp + bp
|
||||
h.add(n + inc, inc)
|
||||
bp = bps(); q = bp * bp
|
||||
elif h.hasKey(n):
|
||||
var inc: PrimeType
|
||||
discard h.take(n, inc)
|
||||
var nxt = n + inc
|
||||
while h.hasKey(nxt): nxt += inc # ensure no duplicates
|
||||
h.add(nxt, inc)
|
||||
else: yield n
|
||||
n += 2.PrimeType
|
||||
output
|
||||
|
||||
var num = 0
|
||||
stdout.write "The first 20 primes are: "
|
||||
var iter = primesHashTable()
|
||||
for p in iter():
|
||||
if num >= 20: break else: stdout.write(p, " "); num += 1
|
||||
echo ""
|
||||
stdout.write "The primes between 100 and 150 are: "
|
||||
iter = primesHashTable()
|
||||
for p in iter():
|
||||
if p >= 150: break
|
||||
if p >= 100: stdout.write(p, " ")
|
||||
echo ""
|
||||
num = 0
|
||||
iter = primesHashTable()
|
||||
for p in iter():
|
||||
if p > 8000: break
|
||||
if p >= 7700: num += 1
|
||||
echo "The number of primes between 7700 and 8000 is: ", num
|
||||
num = 1
|
||||
iter = primesHashTable()
|
||||
for p in iter():
|
||||
if num >= 10000:
|
||||
echo "The 10,000th prime is: ", p
|
||||
break
|
||||
num += 1
|
||||
var sum = 0
|
||||
iter = primesHashTable()
|
||||
for p in iter():
|
||||
if p >= 2_000_000:
|
||||
echo "The sum of the primes to two million is: ", sum
|
||||
break
|
||||
sum += p
|
||||
|
|
@ -0,0 +1 @@
|
|||
for p in primesPaged():
|
||||
|
|
@ -0,0 +1 @@
|
|||
for p in iter():
|
||||
|
|
@ -0,0 +1,380 @@
|
|||
unit primsieve;
|
||||
//{$O+,R+}
|
||||
{$IFDEF FPC}
|
||||
{$MODE objFPC}
|
||||
{$CODEALIGN proc=32,loop=1}
|
||||
{$IFEND}
|
||||
{segmented sieve of Erathostenes using only odd numbers}
|
||||
{using presieved sieve of small primes, to reduce the most time consuming}
|
||||
interface
|
||||
procedure InitPrime;
|
||||
procedure NextSieve;
|
||||
function SieveStart:Uint64;
|
||||
function SieveSize :LongInt;
|
||||
function Nextprime: Uint64;
|
||||
function TotalCount :Uint64;
|
||||
function PosOfPrime: Uint64;
|
||||
|
||||
implementation
|
||||
uses
|
||||
sysutils;
|
||||
const
|
||||
smlPrimes :array [0..10] of Byte = (2,3,5,7,11,13,17,19,23,29,31);
|
||||
maxPreSievePrimeNum = 7;
|
||||
maxPreSievePrime = 17;//smlPrimes[maxPreSievePrimeNum];
|
||||
cSieveSize = 16384 * 4; //<= High(Word)+1 // Level I Data Cache
|
||||
type
|
||||
tSievePrim = record
|
||||
svdeltaPrime:word;//diff between actual and new prime
|
||||
svSivOfs:word; //Offset in sieve
|
||||
svSivNum:LongWord;//1 shl (1+16+32) = 5.6e14
|
||||
end;
|
||||
tpSievePrim = ^tSievePrim;
|
||||
|
||||
var
|
||||
//sieved with primes 3..maxPreSievePrime.here about 255255 Byte
|
||||
{$ALIGN 32}
|
||||
preSieve :array[0..3*5*7*11*13*17-1] of Byte;//must be > cSieveSize
|
||||
{$ALIGN 32}
|
||||
Sieve :array[0..cSieveSize-1] of Byte;
|
||||
{$ALIGN 32}
|
||||
//prime = FoundPrimesOffset + 2*FoundPrimes[0..FoundPrimesCnt]
|
||||
FoundPrimes : array[0..12252] of Word;
|
||||
{$ALIGN 32}
|
||||
sievePrimes : array[0..78498] of tSievePrim;// 1e6^2 ->1e12
|
||||
//sievePrimes : array[0..1077863] of tSievePrim;// maximum 1e14
|
||||
FoundPrimesOffset : Uint64;
|
||||
FoundPrimesCnt,
|
||||
FoundPrimesIdx,
|
||||
FoundPrimesTotal,
|
||||
SieveNum,
|
||||
SieveMaxIdx,
|
||||
preSieveOffset,
|
||||
LastInsertedSievePrime :NativeUInt;
|
||||
|
||||
procedure CopyPreSieveInSieve; forward;
|
||||
procedure CollectPrimes; forward;
|
||||
procedure sieveOneSieve; forward;
|
||||
procedure Init0Sieve; forward;
|
||||
procedure SieveOneBlock; forward;
|
||||
|
||||
//****************************************
|
||||
procedure preSieveInit;
|
||||
var
|
||||
i,pr,j,umf : NativeInt;
|
||||
Begin
|
||||
fillchar(preSieve[0],SizeOf(preSieve),#1);
|
||||
i := 1;
|
||||
pr := 3;// starts with pr = 3
|
||||
umf := 1;
|
||||
repeat
|
||||
IF preSieve[i] =1 then
|
||||
Begin
|
||||
pr := 2*i+1;
|
||||
j := i;
|
||||
repeat
|
||||
preSieve[j] := 0;
|
||||
inc(j,pr);
|
||||
until j> High(preSieve);
|
||||
umf := umf*pr;
|
||||
end;
|
||||
inc(i);
|
||||
until (pr = maxPreSievePrime)OR(umf>High(preSieve)) ;
|
||||
preSieveOffset := 0;
|
||||
end;
|
||||
|
||||
function InsertSievePrimes(PrimPos:NativeInt):NativeInt;
|
||||
var
|
||||
j :NativeUINt;
|
||||
i,pr : NativeUInt;
|
||||
begin
|
||||
i := 0;
|
||||
//ignore first primes already sieved with
|
||||
if SieveNum = 0 then
|
||||
i := maxPreSievePrimeNum;
|
||||
pr :=0;
|
||||
j := Uint64(SieveNum)*cSieveSize*2-LastInsertedSievePrime;
|
||||
with sievePrimes[PrimPos] do
|
||||
Begin
|
||||
pr := FoundPrimes[i]*2+1;
|
||||
svdeltaPrime := pr+j;
|
||||
j := pr;
|
||||
end;
|
||||
inc(PrimPos);
|
||||
for i := i+1 to FoundPrimesCnt-1 do
|
||||
Begin
|
||||
IF PrimPos > High(sievePrimes) then
|
||||
BREAK;
|
||||
with sievePrimes[PrimPos] do
|
||||
Begin
|
||||
pr := FoundPrimes[i]*2+1;
|
||||
svdeltaPrime := (pr-j);
|
||||
j := pr;
|
||||
end;
|
||||
inc(PrimPos);
|
||||
end;
|
||||
LastInsertedSievePrime :=Uint64(SieveNum)*cSieveSize*2+pr;
|
||||
result := PrimPos;
|
||||
end;
|
||||
|
||||
procedure CalcSievePrimOfs(lmt:NativeUint);
|
||||
//lmt High(sievePrimes)
|
||||
var
|
||||
i,pr : NativeUInt;
|
||||
sq : Uint64;
|
||||
begin
|
||||
pr := 0;
|
||||
i := 0;
|
||||
repeat
|
||||
with sievePrimes[i] do
|
||||
Begin
|
||||
pr := pr+svdeltaPrime;
|
||||
IF sqr(pr) < (cSieveSize*2) then
|
||||
Begin
|
||||
svSivNum := 0;
|
||||
svSivOfs := (pr*pr-1) DIV 2;
|
||||
end
|
||||
else
|
||||
Begin
|
||||
SieveMaxIdx := i;
|
||||
pr := pr-svdeltaPrime;
|
||||
BREAK;
|
||||
end;
|
||||
end;
|
||||
inc(i);
|
||||
until i > lmt;
|
||||
|
||||
for i := i to lmt do
|
||||
begin
|
||||
with sievePrimes[i] do
|
||||
Begin
|
||||
pr := pr+svdeltaPrime;
|
||||
sq := sqr(pr);
|
||||
svSivNum := sq DIV (2*cSieveSize);
|
||||
svSivOfs := ( (sq - Uint64(svSivNum)*(2*cSieveSize))-1)DIV 2;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure sievePrimesInit;
|
||||
var
|
||||
i,j,pr,PrimPos:NativeInt;
|
||||
Begin
|
||||
LastInsertedSievePrime := 0;
|
||||
preSieveOffset := 0;
|
||||
SieveNum :=0;
|
||||
CopyPreSieveInSieve;
|
||||
//normal sieving of first sieve
|
||||
i := 1; // start with 3
|
||||
repeat
|
||||
while Sieve[i] = 0 do
|
||||
inc(i);
|
||||
pr := 2*i+1;
|
||||
inc(i);
|
||||
j := ((pr*pr)-1) DIV 2;
|
||||
if j > High(Sieve) then
|
||||
BREAK;
|
||||
repeat
|
||||
Sieve[j] := 0;
|
||||
inc(j,pr);
|
||||
until j > High(Sieve);
|
||||
until false;
|
||||
|
||||
CollectPrimes;
|
||||
PrimPos := InsertSievePrimes(0);
|
||||
LastInsertedSievePrime := FoundPrimes[PrimPos]*2+1;
|
||||
|
||||
IF PrimPos < High(sievePrimes) then
|
||||
Begin
|
||||
Init0Sieve;
|
||||
//Erste Sieb nochmals, aber ohne Eintrag
|
||||
sieveOneBlock;
|
||||
repeat
|
||||
sieveOneBlock;
|
||||
dec(SieveNum);
|
||||
PrimPos := InsertSievePrimes(PrimPos);
|
||||
inc(SieveNum);
|
||||
until PrimPos > High(sievePrimes);
|
||||
end;
|
||||
Init0Sieve;
|
||||
end;
|
||||
|
||||
procedure Init0Sieve;
|
||||
begin
|
||||
FoundPrimesTotal :=0;
|
||||
preSieveOffset := 0;
|
||||
SieveNum :=0;
|
||||
CalcSievePrimOfs(High(sievePrimes));
|
||||
end;
|
||||
|
||||
procedure CopyPreSieveInSieve;
|
||||
var
|
||||
lmt : NativeInt;
|
||||
Begin
|
||||
lmt := preSieveOffset+cSieveSize;
|
||||
lmt := lmt-(High(preSieve)+1);
|
||||
IF lmt<= 0 then
|
||||
begin
|
||||
Move(preSieve[preSieveOffset],Sieve[0],cSieveSize);
|
||||
if lmt <> 0 then
|
||||
inc(preSieveOffset,cSieveSize)
|
||||
else
|
||||
preSieveOffset := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Move(preSieve[preSieveOffset],Sieve[0],cSieveSize-lmt);
|
||||
Move(preSieve[0],Sieve[cSieveSize-lmt],lmt);
|
||||
preSieveOffset := lmt
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure sieveOneSieve;
|
||||
var
|
||||
sp:tpSievePrim;
|
||||
pSieve :pByte;
|
||||
i,j,pr,sn,dSievNum :NativeUint;
|
||||
|
||||
Begin
|
||||
pr := 0;
|
||||
sn := sieveNum;
|
||||
sp := @sievePrimes[0];
|
||||
pSieve := @Sieve[0];
|
||||
For i := SieveMaxIdx downto 0 do
|
||||
with sp^ do
|
||||
begin
|
||||
pr := pr+svdeltaPrime;
|
||||
IF svSivNum = sn then
|
||||
Begin
|
||||
j := svSivOfs;
|
||||
repeat
|
||||
pSieve[j] := 0;
|
||||
inc(j,pr);
|
||||
until j > High(Sieve);
|
||||
dSievNum := j DIV cSieveSize;
|
||||
svSivOfs := j-dSievNum*cSieveSize;
|
||||
svSivNum := sn+dSievNum;
|
||||
// svSivNum := svSivNum+dSievNum;
|
||||
end;
|
||||
inc(sp);
|
||||
end;
|
||||
i := SieveMaxIdx+1;
|
||||
repeat
|
||||
if i > High(SievePrimes) then
|
||||
BREAK;
|
||||
with sp^ do
|
||||
begin
|
||||
if svSivNum > sn then
|
||||
Begin
|
||||
SieveMaxIdx := I-1;
|
||||
Break;
|
||||
end;
|
||||
pr := pr+svdeltaPrime;
|
||||
j := svSivOfs;
|
||||
repeat
|
||||
Sieve[j] := 0;
|
||||
inc(j,pr);
|
||||
until j > High(Sieve);
|
||||
dSievNum := j DIV cSieveSize;
|
||||
svSivOfs := j-dSievNum*cSieveSize;
|
||||
svSivNum := sn+dSievNum;
|
||||
end;
|
||||
inc(i);
|
||||
inc(sp);
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure CollectPrimes;
|
||||
//extract primes to FoundPrimes
|
||||
//
|
||||
var
|
||||
pSieve : pbyte;
|
||||
pFound : pWord;
|
||||
i,idx : NativeUint;
|
||||
Begin
|
||||
FoundPrimesOffset := SieveNum*2*cSieveSize;
|
||||
FoundPrimesIdx := 0;
|
||||
pFound :=@FoundPrimes[0];
|
||||
i := 0;
|
||||
idx := 0;
|
||||
IF SieveNum = 0 then
|
||||
//include small primes used to pre-sieve
|
||||
Begin
|
||||
repeat
|
||||
pFound[idx]:= (smlPrimes[idx]-1) DIV 2;
|
||||
inc(idx);
|
||||
until smlPrimes[idx]>maxPreSievePrime;
|
||||
i := (smlPrimes[idx] -1) DIV 2;
|
||||
end;
|
||||
//grabbing the primes without if then -> reduces time extremly
|
||||
//primes are born to let branch-prediction fail.
|
||||
pSieve:= @Sieve[Low(Sieve)];
|
||||
repeat
|
||||
//store every value until a prime aka 1 is found
|
||||
pFound[idx]:= i;
|
||||
inc(idx,pSieve[i]);
|
||||
inc(i);
|
||||
until i>High(Sieve);
|
||||
FoundPrimesCnt:= idx;
|
||||
inc(FoundPrimesTotal,Idx);
|
||||
end;
|
||||
|
||||
procedure SieveOneBlock;
|
||||
begin
|
||||
CopyPreSieveInSieve;
|
||||
sieveOneSieve;
|
||||
CollectPrimes;
|
||||
inc(SieveNum);
|
||||
end;
|
||||
|
||||
procedure NextSieve;
|
||||
Begin
|
||||
SieveOneBlock;
|
||||
end;
|
||||
|
||||
function Nextprime:Uint64;
|
||||
Begin
|
||||
result := FoundPrimes[FoundPrimesIdx]*2+1+FoundPrimesOffset;
|
||||
if (FoundPrimesIdx=0) AND (sievenum = 1) then
|
||||
inc(result);
|
||||
inc(FoundPrimesIdx);
|
||||
If FoundPrimesIdx>= FoundPrimesCnt then
|
||||
SieveOneBlock;
|
||||
end;
|
||||
|
||||
function PosOfPrime: Uint64;
|
||||
Begin
|
||||
result := FoundPrimesTotal-FoundPrimesCnt+FoundPrimesIdx;
|
||||
end;
|
||||
|
||||
function TotalCount :Uint64;
|
||||
begin
|
||||
result := FoundPrimesTotal;
|
||||
end;
|
||||
|
||||
function SieveSize :LongInt;
|
||||
Begin
|
||||
result := 2*cSieveSize;
|
||||
end;
|
||||
|
||||
function SieveStart:Uint64;
|
||||
Begin
|
||||
result := (SieveNum-1)*2*cSieveSize;
|
||||
end;
|
||||
|
||||
procedure InitPrime;
|
||||
Begin
|
||||
Init0Sieve;
|
||||
SieveOneBlock;
|
||||
end;
|
||||
|
||||
begin
|
||||
preSieveInit;
|
||||
sievePrimesInit;
|
||||
InitPrime;
|
||||
end.
|
||||
{compiler: fpc/3.2.0/ppcx64 -Xs -O4 "%f"
|
||||
50851378 in 1000079360 dauerte 529 ms
|
||||
455052800 in 10000007168 dauerte 6297 ms
|
||||
4118057696 in 100000071680 dauerte 93783 ms
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
program test;
|
||||
uses
|
||||
primsieve;
|
||||
|
||||
var
|
||||
i : NativeInt;
|
||||
cnt : Uint64;
|
||||
Begin
|
||||
writeln('First 25 primes');
|
||||
For i := 1 to 25 do
|
||||
write(Nextprime:3);
|
||||
writeln;
|
||||
Writeln;
|
||||
writeln('Primes betwenn 100 and 150');
|
||||
repeat
|
||||
i := NextPrime
|
||||
until i > 100;
|
||||
repeat
|
||||
write(i:4);
|
||||
i := NextPrime;
|
||||
until i>150;
|
||||
writeln;
|
||||
Writeln;
|
||||
repeat
|
||||
i := NextPrime
|
||||
until i > 7700;
|
||||
cnt := 0;
|
||||
repeat
|
||||
inc(cnt);
|
||||
i := NextPrime;
|
||||
until i> 8000;
|
||||
writeln('between 7700 and 8000 are ',cnt,' primes');
|
||||
Writeln;
|
||||
writeln(' i.th prime');
|
||||
cnt := 10000;
|
||||
repeat
|
||||
while TotalCount < cnt do
|
||||
NextSieve;
|
||||
repeat
|
||||
i := NextPrime;
|
||||
until PosOfPrime = cnt;
|
||||
writeln(cnt:10,i:12);
|
||||
cnt := cnt*10;
|
||||
until cnt >100*1000*1000;
|
||||
end.
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
-- demo/rosetta/Extensible_prime_generator.exw
|
||||
sequence primes = {2,3,5,7}
|
||||
atom sieved = 10
|
||||
|
||||
|
|
@ -54,6 +55,6 @@ for i=1 to 8 do
|
|||
while length(primes)<k do
|
||||
add_block()
|
||||
end while
|
||||
printf(1,"The %dth prime is : %d\n",{k,primes[k]})
|
||||
printf(1,"The %,dth prime is : %d\n",{k,primes[k]})
|
||||
end for
|
||||
?time()-t0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
from itertools import count, takewhile, islice
|
||||
|
||||
def prime_sieve():
|
||||
sieved = count(2)
|
||||
prime = next(sieved)
|
||||
yield prime
|
||||
primes = [prime]
|
||||
for x in sieved:
|
||||
if any(x % prime == 0 for prime in primes):
|
||||
continue
|
||||
yield x
|
||||
primes.append(x)
|
||||
|
||||
if __name__ == '__main__':
|
||||
def leq_150(x): return x <= 150
|
||||
def leq_8000(x): return x <= 8000
|
||||
|
||||
print("Show the first twenty primes.\n =",
|
||||
list(islice(prime_sieve(), 20)))
|
||||
print("Show the primes between 100 and 150\n =",
|
||||
[x for x in takewhile(leq_150, prime_sieve()) if x >= 100])
|
||||
print("Show the number of primes between 7,700 and 8,000.\n =",
|
||||
sum(1 for x in takewhile(leq_8000, prime_sieve()) if x >= 7700))
|
||||
print("Show the 10,000th prime.\n =",
|
||||
next(islice(prime_sieve(), 10000-1, 10000)))
|
||||
|
|
@ -11,5 +11,6 @@ fn main() {
|
|||
.collect::<Vec<_>>());
|
||||
let diff = count_primes_paged(8000) - count_primes_paged(7700);
|
||||
println!("There are {} primes between 7,700 and 8,000", diff);
|
||||
println!("The 10,000th prime is {}", primes_paged().nth(10_000).unwrap());
|
||||
// rust enumerations are zero base, so need to subtract 1!!!
|
||||
println!("The 10,000th prime is {}", primes_paged().nth(10_000 - 1).unwrap());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,6 @@ const proc: main is func
|
|||
writeln("Number of primes between 7,700 and 8,000: " <& count);
|
||||
repeat
|
||||
aPrime := getPrime;
|
||||
until primeNum = 10000;
|
||||
until primeNum = 9999; # discard up to and including the 9,999 prime!
|
||||
writeln("The 10,000th prime: " <& getPrime);
|
||||
end func;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
var nt = frequire('ntheory')
|
||||
|
||||
say ("First 20: ", nt.primes(nt.nth_prime(20)).join(' '))
|
||||
say ("Between 100 and 150: ", nt.primes(100,150).join(' '))
|
||||
say (nt.prime_count(7700,8000), " primes between 7700 and 8000")
|
||||
say ("10,000th prime: ", nt.nth_prime(10_000))
|
||||
say ("First 20: ", 20.nth_prime.primes.join(' '))
|
||||
say ("Between 100 and 150: ", primes(100,150).join(' '))
|
||||
say (prime_count(7700,8000), " primes between 7700 and 8000")
|
||||
say ("10,000th prime: ", nth_prime(10_000))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
|
||||
func soeDictOdds() -> UnfoldSequence<Int, Int> {
|
||||
var bp = 5; var q = 25
|
||||
var bps: UnfoldSequence<Int, Int>.Iterator? = nil
|
||||
var dict = [9: 6] // Dictionary<Int, Int>(9 => 6)
|
||||
return sequence(state: 2, next: { n in
|
||||
if n < 9 { if n < 3 { n = 3; return 2 }; defer {n += 2}; return n }
|
||||
while n >= q || dict[n] != nil {
|
||||
if n >= q {
|
||||
let inc = bp + bp
|
||||
dict[n + inc] = inc
|
||||
if bps == nil {
|
||||
bps = soeDictOdds().makeIterator()
|
||||
bp = (bps?.next())!; bp = (bps?.next())!; bp = (bps?.next())! // skip 2/3/5...
|
||||
}
|
||||
bp = (bps?.next())!; q = bp * bp // guaranteed never nil
|
||||
} else {
|
||||
let inc = dict[n] ?? 0
|
||||
dict[n] = nil
|
||||
var next = n + inc
|
||||
while dict[next] != nil { next += inc }
|
||||
dict[next] = inc
|
||||
}
|
||||
n += 2
|
||||
}
|
||||
defer { n += 2 }; return n
|
||||
})
|
||||
}
|
||||
|
||||
print("The first 20 primes are: ", terminator: "")
|
||||
soeDictOdds().lazy.prefix(20).forEach { print($0, "", terminator: "") }
|
||||
print()
|
||||
|
||||
print("The primes between 100 and 150 are: ", terminator: "")
|
||||
soeDictOdds().lazy.drop(while: { $0 < Prime(100) }).lazy.prefix(while: { $0 <= 150 })
|
||||
.forEach { print($0, "", terminator: "") }
|
||||
print()
|
||||
|
||||
print("The number of primes from 7700 to 8000 is :", terminator: "")
|
||||
print(soeDictOdds().lazy.drop(while: { $0 < 7700 }).lazy.prefix(while: { $0 <= 8000 })
|
||||
.lazy.reduce(0, { a, _ in a + 1 }))
|
||||
|
||||
print("The 10,000th prime is: ", terminator: "")
|
||||
print((soeDictOdds().lazy.dropFirst(9999).first { $0 == $0 })!)
|
||||
|
||||
print("The sum of primes to 2 million is: ", terminator: "")
|
||||
|
||||
let start = NSDate()
|
||||
let answr = soeDictOdds().lazy.prefix(while: { $0 <= 2000000 })
|
||||
.reduce(0, { a, p in a + Int64(p) })
|
||||
let elpsd = -start.timeIntervalSinceNow
|
||||
|
||||
print(answr)
|
||||
print(String(format: "This test took %.3f milliseconds.", elpsd * 1000))
|
||||
Loading…
Add table
Add a link
Reference in a new issue