在python中生成素数的最快方法是使用primesieve-python
,这是对C / C ++库primesieve
(http://primesieve.org/)的绑定。您可以使用
import primesieve
it = primesieve.Iterator()
prime = it.next_prime()
prime = it.next_prime()
我们可以使用PyCall
从Julia调用这个python库。但是,我希望通过直接调用C函数primesieve_next_prime
来迭代素数会更快。对于那些不了解C的人来说,这样做有多容易?
答案 0 :(得分:2)
我继续把它包起来,把那个例子翻译成朱莉娅。
这只是快速和脏(它不使用Julia迭代器接口,这会更好,我只是让它与C API匹配)
几点:因为涉及C分配的内存,我设置了一个终结器,这样如果迭代器对象超出范围并被垃圾收集,C分配的内存仍将被释放。我也做了它,以便它可以被明确释放(并防止尝试释放内存两次)
此外,模块和每个函数都有一个文档字符串(我也应该为该类型添加)。它使用Ref
将指向结构的指针传递给C.
当我运行它时,我得到以下结果:
julia> @time example()
Sum of the primes below 10^10 = 2220820311119164929
5.836645 seconds (609 allocations: 16.324 KB)
我希望这是正确的结果!
这是我快速包装迭代器接口:
"""
Wrapper for primesieves library
Copyright 2016 Scott Paul Jones
MIT Licensed
"""
module PrimeSieves
export PrimeSieveIterator, skipto, next, previous, free
const global psilib = "libprimesieve.dylib"
type PrimeSieveIterator
i::Csize_t
last_idx::Csize_t
primes::Ptr{UInt64}
primes_pimpl::Ptr{UInt64}
start::UInt64
stop::UInt64
stop_hint::UInt64
tiny_cache_size::UInt64
is_error::Cint
function PrimeSieveIterator()
piter = new(0,0,C_NULL,C_NULL,0,0,0,0,0)
ccall((:primesieve_init, psilib), Void, (Ref{PrimeSieveIterator},), piter)
finalizer(piter, free)
piter
end
end
""" Free all memory """
function free(piter::PrimeSieveIterator)
# Make sure it isn't freed twice
if piter.primes != C_NULL
ccall((:primesieve_free_iterator, psilib), Void, (Ref{PrimeSieveIterator},), piter)
piter.primes = C_NULL
piter.primes_pimpl = C_NULL
end
nothing
end
""" Set the primesieve iterator to start """
skipto(piter::PrimeSieveIterator, start::Integer, stop_hint::Integer) =
ccall((:primesieve_skipto, psilib), Void,
(Ref{PrimeSieveIterator}, UInt64, UInt64), piter, start, stop_hint)
""" Get the next prime """
function Base.next(piter::PrimeSieveIterator)
(piter.i-1) >= piter.last_idx &&
ccall((:primesieve_generate_next_primes, psilib), Void, (Ref{PrimeSieveIterator},), piter)
unsafe_load(piter.primes, piter.i += 1)
end
""" Get the previous prime """
function previous(piter::PrimeSieveIterator)
if piter.i == 0
ccall((:primesieve_generate_previous_primes, psilib),
Void, (Ref{PrimeSieveIterator},), piter)
else
piter.i -= 1
end
unsafe_load(piter.primes, piter.i + 1)
end
end
示例代码为:
using PrimeSieves
function example()
pit = PrimeSieveIterator()
sum = UInt64(0)
# iterate over the primes below 10^10
while (prime = next(pit)) < UInt64(10000000000)
sum += prime
end
free(pit)
println("Sum of the primes below 10^10 = ", sum)
end
example()