@@ -554,7 +554,7 @@ internally). See also [`prevprime`](@ref).
554
554
555
555
If `interval` is provided, primes are sought in increments of `interval`.
556
556
This can be useful to ensure the presence of certain divisors in `p-1`.
557
- The selected interval should be even .
557
+ The range of possible values for ` interval` is currently `1:typemax(Int)` .
558
558
559
559
```jldoctest
560
560
julia> nextprime(4)
@@ -569,30 +569,47 @@ julia> nextprime(4, 2)
569
569
julia> nextprime(5, 2)
570
570
7
571
571
572
- julia> nextprime(2^16-1024 +1; interval=1024)
573
- 133121
572
+ julia> nextprime(2^10 +1; interval=1024)
573
+ 12289
574
574
575
- julia> gcd(133121 - 1, 1024) # 1024 | p - 1
575
+ julia> gcd(12289 - 1, 1024) # 1024 | p - 1
576
576
1024
577
577
```
578
578
"""
579
579
function nextprime (n:: Integer , i:: Integer = 1 ; interval:: Integer = 1 )
580
- i < 0 && return prevprime (n, - i; interval= interval)
581
580
i == 0 && throw (DomainError (i))
582
- n < 2 && (n = oftype (n, 2 ))
583
- interval == 1 && (interval = 2 )
581
+ i < 0 && return prevprime (n, - i; interval= interval)
582
+ interval < 1 && throw (DomainError (interval, " interval must be >= 1" ))
583
+ # TODO : lift the following condition
584
+ interval > typemax (Int) && throw (DomainError (interval, " interval must be <= $(typemax (Int)) " ))
585
+ interval = oftype (n, interval)
586
+ if n < 2
587
+ n = interval == 1 ?
588
+ oftype (n, 2 ) :
589
+ # smallest value >= 2 whose difference from n is a multiple of interval
590
+ oftype (n, n + interval * (1 + (n- 1 )÷ (- interval)))
591
+ end
584
592
if n == 2
585
593
if i <= 1
586
594
return n
587
595
else
588
- n += one (n)
596
+ n += interval
589
597
i -= 1
590
598
end
591
599
else
592
- n += iseven (n) ? oftype (n, interval - 1 ) : zero (n)
600
+ n += iseven (n) ? interval : zero (n)
593
601
end
594
602
# n can now be safely mutated
595
- # @assert isodd(n) && n >= 3
603
+ # @assert n >= 3
604
+ if iseven (n)
605
+ @assert iseven (interval)
606
+ throw (DomainError ((n, interval),
607
+ " `n` and `interval` should not be both even (there is then no correct answer)." ))
608
+ end
609
+ # @assert isodd(n)
610
+ interval = Int (interval)
611
+ isodd (interval) && (interval = Base. checked_mul (interval, 2 ))
612
+
596
613
while true
597
614
while ! isprime (n)
598
615
n = add_! (n, interval)
@@ -614,6 +631,10 @@ The `i`-th largest prime not greater than `n` (in particular
614
631
only a pseudo-prime (the function [`isprime`](@ref) is used internally). See
615
632
also [`nextprime`](@ref).
616
633
634
+ If `interval` is provided, primes are sought in increments of `interval`.
635
+ This can be useful to ensure the presence of certain divisors in `p-1`.
636
+ The range of possible values for `interval` is currently `1:typemax(Int)`.
637
+
617
638
```jldoctest
618
639
julia> prevprime(4)
619
640
3
@@ -627,22 +648,28 @@ julia> prevprime(5, 2)
627
648
"""
628
649
function prevprime (n:: Integer , i:: Integer = 1 ; interval:: Integer = 1 )
629
650
i <= 0 && return nextprime (n, - i; interval= interval)
630
- i == 1 && n == 2 && return n
631
- # A bit ugly, but this lets us speed up prime walking 2x in the (common)
632
- # case that n >> 2, while preventing prevprime(3) from skipping 2 and giving
633
- # the wrong answer.
634
- was_one = interval == 1
635
- was_one && (interval = 2 )
636
- n -= iseven (n) ? oftype (n, interval- 1 ) : zero (n) # deep copy of n, which is mutated below
651
+ interval < 1 && throw (DomainError (interval, " interval must be >= 1" ))
652
+ interval > typemax (Int) && throw (DomainError (interval, " interval must be <= $(typemax (Int)) " ))
653
+ interval = Int (interval)
654
+
655
+ n += zero (n) # deep copy of n, which is mutated below
656
+
657
+ # A bit ugly, but this lets us skip half of the isprime tests when isodd(interval)
658
+ @inline function decrement (n)
659
+ n = add_! (n, - interval)
660
+ iseven (n) && n != 2 ? # n obviously not prime
661
+ add_! (n, - interval) :
662
+ n
663
+ end
664
+
637
665
while true
638
- n < 2 && throw (ArgumentError (" There is no prime less than or equal to $n " ))
639
- was_one && n <= 4 && (interval = 1 )
640
666
while ! isprime (n)
641
- n = add_! (n, - interval)
667
+ n < 2 && throw (ArgumentError (" There is no prime less than or equal to $n " ))
668
+ n = decrement (n)
642
669
end
643
670
i -= 1
644
671
i <= 0 && break
645
- n = add_! (n, - interval )
672
+ n = decrement (n )
646
673
end
647
674
n
648
675
end
0 commit comments