Skip to content

Commit 187ec9e

Browse files
authored
Merge pull request #56 from JuliaMath/rf/nextprimes
add nextprimes/prevprimes iterators (fix #55)
2 parents 1d818f4 + bef0d8a commit 187ec9e

File tree

2 files changed

+165
-2
lines changed

2 files changed

+165
-2
lines changed

src/Primes.jl

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ module Primes
44

55
using Base.Iterators: repeated
66

7+
import Base: iterate, eltype, IteratorSize, IteratorEltype
78
using Base: BitSigned
89
using Base.Checked: checked_neg
910

1011
export isprime, primes, primesmask, factor, ismersenneprime, isrieselprime,
11-
nextprime, prevprime, prime, prodfactors, radical, totient
12+
nextprime, nextprimes, prevprime, prevprimes, prime, prodfactors, radical, totient
1213

1314
include("factorization.jl")
1415

@@ -528,6 +529,11 @@ function totient(n::Integer)
528529
totient(factor(abs(n)))
529530
end
530531

532+
# add: checked add (when makes sense), result of same type as first argument
533+
534+
add(n::BigInt, x::Int) = n + x
535+
add(n::Integer, x::Int) = Base.checked_add(n, oftype(n, x))
536+
531537
# add_! : "may" mutate the Integer argument (only for BigInt currently)
532538

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

543549
# checked addition, without mutation
544-
add_!(n::Integer, x::Int) = Base.checked_add(n, oftype(n, x))
550+
add_!(n::Integer, x::Int) = add(n, x)
545551

546552
"""
547553
nextprime(n::Integer, i::Integer=1; interval::Integer=1)
@@ -691,4 +697,117 @@ julia> prime(3)
691697
prime(::Type{T}, i::Integer) where {T<:Integer} = i < 0 ? throw(DomainError(i)) : nextprime(T(2), i)
692698
prime(i::Integer) = prime(Int, i)
693699

700+
701+
struct NextPrimes{T<:Integer}
702+
start::T
703+
end
704+
705+
function iterate(np::NextPrimes, state=np.start)
706+
p = nextprime(state)
707+
(p, add(p, 1))
708+
end
709+
710+
IteratorSize(::Type{<:NextPrimes}) = Base.IsInfinite()
711+
IteratorEltype(::Type{<:NextPrimes}) = Base.HasEltype()
712+
713+
eltype(::Type{NextPrimes{T}}) where {T} = T
714+
715+
"""
716+
nextprimes(start::Integer)
717+
718+
Return an iterator over all primes greater than or equal to `start`,
719+
in ascending order.
720+
"""
721+
nextprimes(start::Integer) = NextPrimes(start)
722+
723+
"""
724+
nextprimes(T::Type=Int)
725+
726+
Return an iterator over all primes, with type `T`.
727+
Equivalent to `nextprimes(T(1))`.
728+
"""
729+
nextprimes(::Type{T}=Int) where {T<:Integer} = nextprimes(one(T))
730+
731+
"""
732+
nextprimes(start::Integer, n::Integer)
733+
734+
Return an array of the first `n` primes greater than or equal to `start`.
735+
736+
# Example
737+
738+
```
739+
julia> nextprimes(10, 3)
740+
3-element Array{Int64,1}:
741+
11
742+
13
743+
17
744+
```
745+
"""
746+
nextprimes(start::T, n::Integer) where {T<:Integer} =
747+
collect(T, Iterators.take(nextprimes(start), n))
748+
749+
struct PrevPrimes{T<:Integer}
750+
start::T
751+
end
752+
753+
function iterate(np::PrevPrimes, state=np.start)
754+
if isone(state)
755+
nothing
756+
else
757+
p = prevprime(state)
758+
(p, p-one(p))
759+
end
760+
end
761+
762+
IteratorSize(::Type{<:PrevPrimes}) = Base.SizeUnknown()
763+
IteratorEltype(::Type{<:PrevPrimes}) = Base.HasEltype()
764+
765+
eltype(::Type{PrevPrimes{T}}) where {T} = T
766+
767+
"""
768+
prevprimes(start::Integer)
769+
770+
Return an iterator over all primes less than or equal to `start`,
771+
in descending order.
772+
773+
# Example
774+
775+
```
776+
julia> collect(prevprimes(10))
777+
4-element Array{Int64,1}:
778+
7
779+
5
780+
3
781+
2
782+
```
783+
"""
784+
prevprimes(start::Integer) = PrevPrimes(max(one(start), start))
785+
786+
"""
787+
prevprimes(start::Integer, n::Integer)
788+
789+
Return an array of the first `n` primes less than or equal to `start`,
790+
in descending order. When there are less than `n` primes less than or
791+
equal to `start`, those primes are returned without an error.
792+
793+
# Example
794+
795+
```
796+
julia> prevprimes(10, 3)
797+
3-element Array{Int64,1}:
798+
7
799+
5
800+
3
801+
802+
julia> prevprimes(10, 10)
803+
3-element Array{Int64,1}:
804+
7
805+
5
806+
3
807+
2
808+
```
809+
"""
810+
prevprimes(start::T, n::Integer) where {T<:Integer} =
811+
collect(T, Iterators.take(prevprimes(start), n))
812+
694813
end # module

test/runtests.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,47 @@ for T in (Int, UInt, BigInt)
405405
@test prodfactors(factor(Set, T(123456))) == 3858
406406
@test prod(factor(T(123456))) == 123456
407407
end
408+
409+
@testset "nextprimes(::$T)" for T = (Int32, Int64, BigInt)
410+
for (i, p) in enumerate(nextprimes(T))
411+
@test nextprime(0, i) == p
412+
i > 20 && break
413+
end
414+
@test nextprimes() == nextprimes(Int)
415+
for (i, p) in enumerate(nextprimes(T(5)))
416+
@test nextprime(T(5), i) == p
417+
i > 20 && break
418+
end
419+
@test nextprimes(T(5), 10) == [nextprime(T(5), i) for i=1:10]
420+
@test nextprimes(1, 1)[1] == nextprimes(2, 1)[1] == 2
421+
@test nextprimes(3, 1)[1] == 3
422+
@test nextprimes(4, 1)[1] == nextprimes(5, 1)[1] == 5
423+
@test eltype(nextprimes(10)) == Int
424+
@test eltype(nextprimes(big(10))) == BigInt
425+
@test Base.IteratorEltype(nextprimes(10)) == Base.HasEltype()
426+
@test Base.IteratorSize(nextprimes(10)) == Base.IsInfinite()
427+
428+
end
429+
430+
431+
@testset "prevprimes(::$T)" for T = (Int32, Int64, BigInt)
432+
for (i, p) in enumerate(prevprimes(T(500)))
433+
@test prevprime(T(500), i) == p
434+
i > 20 && break
435+
end
436+
@test prevprimes(T(500), 10) == [prevprime(T(500), i) for i=1:10]
437+
@test prevprimes(6, 1)[1] == prevprimes(5, 1)[1] == 5
438+
@test prevprimes(4, 1)[1] == prevprimes(3, 1)[1] == 3
439+
@test prevprimes(2, 1)[1] == 2
440+
@test isempty(prevprimes(1, 1))
441+
let p8 = collect(prevprimes(typemax(Int8)))
442+
@test length(p8) == 31
443+
@test p8[end] == 2
444+
@test p8[1] == 127
445+
@test eltype(p8) == Int8
446+
end
447+
@test eltype(prevprimes(10)) == Int
448+
@test eltype(prevprimes(big(10))) == BigInt
449+
@test Base.IteratorEltype(prevprimes(10)) == Base.HasEltype()
450+
@test Base.IteratorSize(prevprimes(10)) == Base.SizeUnknown()
451+
end

0 commit comments

Comments
 (0)