Skip to content

Commit

Permalink
Attempt p7 in fortran (2)
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Oct 3, 2024
1 parent 396473d commit ea546ab
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 22 deletions.
4 changes: 2 additions & 2 deletions docs/src/fortran/lib/primes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ View source code :source:`fortran/include/primes.f90`
:returns answer: The next prime in the sequence
:rtype answer: integer

.. f:function:: expand_sieve(potential_n)
.. f:subroutine:: expand_sieve(potential_n)
A helper function that lets you pre-initialize the cache of primes to a high number.
A helper routine that lets you pre-initialize the cache of primes to a high number.
Otherwise you incur a cost of ``O(n loglogn)`` each time ``n`` doubles.

:p integer potential_n: The size you wish to expand the sieve to
Expand Down
43 changes: 24 additions & 19 deletions fortran/src/include/primes.f90
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,38 @@ module primes
integer, parameter :: bits_per_int = 32
integer, allocatable :: is_prime(:)
integer :: current_n = 0
logical :: initialized = .false.

contains

function initialize_sieve(n)
subroutine initialize_sieve(n)
integer, intent(in) :: n
integer :: size
! Calculate size of the bit array (integer array to hold bits)
size = (n / bits_per_int) + 1
allocate(is_prime(size))
is_prime = -1 ! Initialize all bits to 1 (all numbers are initially prime)
clear_prime_bit(0)
clear_prime_bit(1)
current_n = n
sieve_up_to(current_n)
end function initialize_sieve
if (.not. initialized) then
size = (n / bits_per_int) + 1
allocate(is_prime(size))
is_prime = -1 ! Initialize all bits to 1 (all numbers are initially prime)
call clear_prime_bit(0)
call clear_prime_bit(1)
current_n = n
initialized = .true.
call sieve_up_to(current_n)
end if
end subroutine initialize_sieve

function sieve_up_to(n)
subroutine sieve_up_to(n)
integer, intent(in) :: n
integer :: p, limit
limit = sqrt(real(n))
do p = 2, limit
if (get_prime_bit(p)) then
do i = p * p, n, p
clear_prime_bit(i)
call clear_prime_bit(i)
end do
end if
end do
end function sieve_up_to
end subroutine sieve_up_to

recursive integer function next_prime(last)
integer, intent(in) :: last
Expand All @@ -43,14 +47,15 @@ recursive integer function next_prime(last)
end if
end do

expand_sieve()
call expand_sieve()
next_prime = next_prime(next) ! Recursively find the next prime
end function next_prime

function expand_sieve(potential_n)
subroutine expand_sieve(potential_n)
integer, intent(in), optional :: potential_n
integer :: new_size, new_n, i

call initialize_sieve()
if (present(potential_n)) then
new_n = max(potential_n, current_n)
else
Expand All @@ -60,17 +65,17 @@ function expand_sieve(potential_n)
new_size = (new_n / bits_per_int) + 1
allocate(is_prime(new_size))
is_prime = -1 ! All bits set to 1
clear_prime_bit(is_prime, 0)
clear_prime_bit(is_prime, 1)
call clear_prime_bit(is_prime, 0)
call clear_prime_bit(is_prime, 1)
sieve_up_to(new_n)
current_n = new_n
end function expand_sieve
end subroutine expand_sieve

! Function to set a bit to 0
function clear_prime_bit(num)
subroutine clear_prime_bit(num)
integer, intent(in) :: num
is_prime(num / bits_per_int) = bitand(is_prime(num / bits_per_int), ieor(0xFFFFFFFF, 1 << (mod(num, bits_per_int))))
end function clear_prime_bit
end subroutine clear_prime_bit

! Function to check if a bit is set
logical function get_prime_bit(num) result(bit)
Expand Down
2 changes: 1 addition & 1 deletion fortran/src/p0007.f90
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ integer function p0007() result(answer)
integer :: i

answer = 1
expand_sieve(2**17)
call expand_sieve(2**17)
do i = 1, 10001
answer = next_prime(answer)
end do
Expand Down

0 comments on commit ea546ab

Please sign in to comment.