Skip to content

Commit

Permalink
Merge cea2295 into 4deaf52
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Sep 5, 2019
2 parents 4deaf52 + cea2295 commit cc0433a
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 2 deletions.
128 changes: 126 additions & 2 deletions src/Primes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ module Primes

using Base.Iterators: repeated

import Base: iterate, eltype, IteratorSize, IteratorEltype
using Base: BitSigned
using Base.Checked: checked_neg

export isprime, primes, primesmask, factor, ismersenneprime, isrieselprime,
nextprime, prevprime, prime, prodfactors, radical, totient
nextprime, nextprimes, prevprime, prevprimes, prime, prodfactors, radical, totient

include("factorization.jl")

Expand Down Expand Up @@ -528,6 +529,11 @@ function totient(n::Integer)
totient(factor(abs(n)))
end

# add: checked add (when makes sense), result of same type as first argument

add(n::BigInt, x::Int) = n+x
add(n::Integer, x::Int) = Base.checked_add(n, oftype(n, x))

# add_! : "may" mutate the Integer argument (only for BigInt currently)

# modify a BigInt in-place
Expand All @@ -541,7 +547,7 @@ function add_!(n::BigInt, x::Int)
end

# checked addition, without mutation
add_!(n::Integer, x::Int) = Base.checked_add(n, oftype(n, x))
add_!(n::Integer, x::Int) = add(n, x)

"""
nextprime(n::Integer, i::Integer=1; interval::Integer=1)
Expand Down Expand Up @@ -664,4 +670,122 @@ julia> prime(3)
prime(::Type{T}, i::Integer) where {T<:Integer} = i < 0 ? throw(DomainError(i)) : nextprime(T(2), i)
prime(i::Integer) = prime(Int, i)


struct NextPrimes{T<:Integer}
start::T
end

function iterate(np::NextPrimes,
state = p = np.start < 2 ? np.start : add(np.start, -1)
)
p = nextprime(add(state, 1))
(p, p)
end

IteratorSize(::Type{<:NextPrimes}) = Base.IsInfinite()
IteratorEltype(::Type{<:NextPrimes}) = Base.HasEltype()

eltype(::Type{NextPrimes{T}}) where {T} = T

"""
nextprimes(start::Integer)
Return an iterator over all primes greater than or equal to `start`,
in ascending order.
"""
nextprimes(start::Integer) = NextPrimes(start)

"""
nextprimes(T::Type=Int)
Return an iterator over all primes, with type `T`.
Equivalent to `nextprimes(T(1))`.
"""
nextprimes(::Type{T}=Int) where {T<:Integer} = nextprimes(one(T))

"""
nextprimes(start::Integer, n::Integer)
Return an array of the first `n` primes greater than or equal to `start`.
# Example
```
julia> nextprimes(10, 3)
3-element Array{Int64,1}:
11
13
17
```
"""
nextprimes(start::T, n::Integer) where {T<:Integer} =
collect(T, Iterators.take(nextprimes(start), n))

struct PrevPrimes{T<:Integer}
start::T
end

function iterate(np::PrevPrimes,
state = np.start+one(np.start) # allow wrap-around
)
c = state-one(state)
if isone(c)
nothing
else
p = prevprime(c)
(p, p)
end
end

IteratorSize(::Type{<:PrevPrimes}) = Base.SizeUnknown()
Iteratoreltype(::Type{<:PrevPrimes}) = Base.HasEltype()

eltype(::Type{PrevPrimes{T}}) where {T} = T

"""
prevprimes(start::Integer)
Return an iterator over all primes less than or equal to `start`,
in descending order.
# Example
```
julia> collect(prevprimes(10))
4-element Array{Int64,1}:
7
5
3
2
```
"""
prevprimes(start::Integer) = PrevPrimes(max(one(start), start))

"""
prevprimes(start::Integer, n::Integer)
Return an array of the first `n` primes less than or equal to `start`,
in descending order. When there are less than `n` primes less than or
equal to `start`, those primes are returned without an error.
# Example
```
julia> prevprimes(10, 3)
3-element Array{Int64,1}:
7
5
3
julia> prevprimes(10, 10)
3-element Array{Int64,1}:
7
5
3
2
```
"""
prevprimes(start::T, n::Integer) where {T<:Integer} =
collect(T, Iterators.take(prevprimes(start), n))

end # module
34 changes: 34 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,37 @@ for T in (Int, UInt, BigInt)
@test prodfactors(factor(Set, T(123456))) == 3858
@test prod(factor(T(123456))) == 123456
end

@testset "nextprimes(::$T)" for T = (Int32, Int64, BigInt)
for (i, p) in enumerate(nextprimes(T))
@test nextprime(0, i) == p
i > 20 && break
end
@test nextprimes() == nextprimes(Int)
for (i, p) in enumerate(nextprimes(T(5)))
@test nextprime(T(5), i) == p
i > 20 && break
end
@test nextprimes(T(5), 10) == [nextprime(T(5), i) for i=1:10]
@test nextprimes(1, 1)[1] == nextprimes(2, 1)[1] == 2
@test nextprimes(3, 1)[1] == 3
@test nextprimes(4, 1)[1] == nextprimes(5, 1)[1] == 5
end


@testset "prevprimes(::$T)" for T = (Int32, Int64, BigInt)
for (i, p) in enumerate(prevprimes(T(500)))
@test prevprime(T(500), i) == p
i > 20 && break
end
@test prevprimes(T(500), 10) == [prevprime(T(500), i) for i=1:10]
@test prevprimes(6, 1)[1] == prevprimes(5, 1)[1] == 5
@test prevprimes(4, 1)[1] == prevprimes(3, 1)[1] == 3
@test prevprimes(2, 1)[1] == 2
let p8 = collect(prevprimes(typemax(Int8)))
@test length(p8) == 31
@test p8[end] == 2
@test p8[1] == 127
end

end

0 comments on commit cc0433a

Please sign in to comment.