, . , : A) , ( ), B) , ( , A). .
A) , "Primes" (pkg add "Primes") , nextprime nextprime:
using Primes: nextprime
mutable struct PrimesGen
lastprime :: Int
PrimesGen() = new()
end
Base.eltype(::Type{PrimesGen}) = Int
function Base.iterate(PG::PrimesGen, st::Int = 1)
next = nextprime(st + 1)
next, next
end
EDIT_ADD: , @mschauer ( Julia 1.0) - , :
using Primes: isprime
PrimesGen() = Iterators.filter(isprime, Iterators.countfrom(UInt64(2)))
... END_EDIT_ADD
- :
using Printf
@time let sm = 0
for p in PrimesGen() p >= 2_000_000 && break; sm += p end
Printf.@printf("%d\n",sm)
end
:
142913828922
0.651754 seconds (327.05 k allocations: 4.990 MiB)
, 10 ( Intel x5-Z8350 1,92 ).
"" UInt64 300 , ...
) " ", , ( ) " " , :
const Prime = UInt64
const BasePrime = UInt32
const BasePrimesArray = Array{BasePrime,1}
const SieveBuffer = Array{UInt8,1}
abstract type BPAS end
mutable struct BasePrimesArrays <: BPAS
thunk :: Union{Nothing,Function}
value :: Union{Nothing,Tuple{BasePrimesArray, BPAS}}
BasePrimesArrays(thunk::Function) = new(thunk)
end
Base.eltype(::Type{BasePrimesArrays}) = BasePrime
Base.IteratorSize(::Type{BasePrimesArrays}) = Base.SizeUnknown()
function Base.iterate(BPAs::BasePrimesArrays, state::BasePrimesArrays = BPAs)
if state.thunk !== nothing
newvalue :: Union{Nothing,Tuple{BasePrimesArray, BasePrimesArrays}} =
state.thunk() :: Union{Nothing,Tuple{BasePrimesArray
, BasePrimesArrays}}
state.value = newvalue
state.thunk = nothing
return newvalue
end
state.value
end
function countComposites(cmpsts::AbstractArray{UInt8,1})
foldl((a, b) -> a + count_zeros(b), cmpsts; init = 0)
end
function composites2BasePrimesArray(low::Prime, cmpsts::SieveBuffer)
limiti = length(cmpsts) * 8
len :: Int = countComposites(cmpsts)
rslt :: BasePrimesArray = BasePrimesArray(undef, len)
i :: Int = 0
j :: Int = 1
@inbounds(
while i < limiti
if cmpsts[i >>> 3 + 1] & (1 << (i & 7)) == 0
rslt[j] = low + i + i
j += 1
end
i += 1
end)
rslt
end
function sieveComposites(low::Prime, buffer::Array{UInt8,1},
bpas::BasePrimesArrays)
lowi :: Int = (low - 3) ÷ 2
len :: Int = length(buffer)
limiti :: Int = len * 8 - 1
nexti :: Int = lowi + limiti
for bpa::BasePrimesArray in bpas
for bp::BasePrime in bpa
bpint :: Int = bp
bpi :: Int = (bpint - 3) >>> 1
starti :: Int = 2 * bpi * (bpi + 3) + 3
starti >= nexti && return
if starti >= lowi starti -= lowi
else
r :: Int = (lowi - starti) % bpint
starti = r == 0 ? 0 : bpint - r
end
lmti :: Int = limiti - 40 * bpint
@inbounds(
if bpint <= (len >>> 2) starti <= lmti
for i in 1:8
if starti > limiti break end
mask = convert(UInt8,1) << (starti & 7)
c = starti >>> 3 + 1
while c <= len
buffer[c] |= mask
c += bpint
end
starti += bpint
end
else
c = starti
while c <= limiti
buffer[c >>> 3 + 1] |= convert(UInt8,1) << (c & 7)
c += bpint
end
end)
end
end
return
end
function makeBasePrimesArrays() :: BasePrimesArrays
cmpsts :: SieveBuffer = Array{UInt8,1}(undef, 512)
function nextelem(low::Prime, bpas::BasePrimesArrays) ::
Tuple{BasePrimesArray, BasePrimesArrays}
reqdsize :: Int = 2 + isqrt(1 + low)
size :: Int = (reqdsize ÷ 4096 + 1) * 4096 ÷ 8
if size > length(cmpsts) cmpsts = Array{UInt8,1}(undef, size) end
fill!(cmpsts, 0)
sieveComposites(low, cmpsts, bpas)
arr :: BasePrimesArray = composites2BasePrimesArray(low, cmpsts)
next :: Prime = low + length(cmpsts) * 8 * 2
arr, BasePrimesArrays(() -> nextelem(next, bpas))
end
preseedarr :: BasePrimesArray =
[ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41
, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
]
nextfunc :: Function = () ->
(nextelem(convert(Prime,101), makeBasePrimesArrays()))
firstfunc :: Function = () -> (preseedarr, BasePrimesArrays(nextfunc))
BasePrimesArrays(firstfunc)
end
struct PrimesPages
baseprimes :: BasePrimesArrays
PrimesPages() = new(makeBasePrimesArrays())
end
Base.eltype(::Type{PrimesPages}) = SieveBuffer
Base.IteratorSize(::Type{PrimesPages}) = Base.IsInfinite()
function Base.iterate(PP::PrimesPages,
state :: Tuple{Prime,SieveBuffer} =
( convert(Prime,3), Array{UInt8,1}(undef,16384) ))
(low, cmpsts) = state
reqdsize :: Int = 2 + isqrt(1 + low)
size :: Int = (reqdsize ÷ 131072 + 1) * 131072 ÷ 8
if size > length(cmpsts) cmpsts = Array{UInt8,1}(undef, size) end
fill!(cmpsts, 0)
sieveComposites(low, cmpsts, PP.baseprimes)
newlow :: Prime = low + length(cmpsts) * 8 * 2
( low, cmpsts ), ( newlow, cmpsts )
end
function countPrimesTo(range::Prime) :: Int64
range < 3 && ((range < 2 && return 0) || return 1)
count :: Int64 = 1
for ( low, cmpsts ) in PrimesPages()
if low + length(cmpsts) * 8 * 2 > range
lasti :: Int = (range - low) ÷ 2
count += countComposites(@view cmpsts[1:lasti >>> 3])
count += count_zeros(cmpsts[lasti >>> 3 + 1] |
(0xFE << (lasti & 7)))
return count
end
count += countComposites(cmpsts)
end
count
end
:
using Printf
@time let sm = 0
for p in PrimesPaged() p >= 2_000_000 && break; sm += p end
Printf.@printf("%d\n",sm)
end
:
142913828922
0.016245 seconds (60 allocations: 23.891 KiB)
, " "; , :
1075207199997334
1.381198 seconds (2.35 k allocations: 103.875 KiB)
:
println(@time let count = 0
for p in PrimesPaged()
p > 1_000_000_000 && break
count += 1
end; count end)
:
6.802044 seconds (11.51 k allocations: 396.734 KiB)
50847534
, . , , :
println(@time countPrimesTo(Prime(1_000_000_000)))
:
1.959057 seconds (65 allocations: 39.266 KiB)
50847534
sumPrimesTo (, )...
x5-Z8350 1,92 .
, , , , countPrimesTo countPrimesTo. , , ( ) ( ( Hyper Threading) , , , "primesieve".
, UInt64 "" , , , .