Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modern Fortran techniques, functionalize, command line interface #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
eratos
*.o
*.mod
102 changes: 64 additions & 38 deletions Eratos.f90
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,67 @@
!@author Robert Streetman
!@date 2014-01-07 -Updated 2017-09-15
!@desc Implements Sieve of Eratosthenes to generate all primes below given integer, then returns the largest prime.
!
PROGRAM ERATOS
IMPLICIT NONE

INTEGER :: lim !Limit of prime generation
LOGICAL, ALLOCATABLE,DIMENSION(:) :: primes !Array of booleans representing integers 0-limit
INTEGER :: mid,mult,i,j !Utility counters/placeholders

!Prompt user for limit
PRINT *, 'Enter an integer n to find all primes 0 - n and return the largest: '
READ *, lim

ALLOCATE(primes(lim))
primes(1:lim) = .TRUE.
mid = lim / 2

!Generate primes
DO i = 2,mid
IF (primes(i)) THEN
mult = lim / i
!If true, this candidate will not produce a prime
DO j = 2, mult
primes(i * j) = .FALSE.
END DO
END IF
END DO

!Find first number still prime below lim
i = lim
DO WHILE (.NOT.primes(i))
i = i - 1
ENDDO

DEALLOCATE(primes)

PRINT *, 'Prime Found: ', i

END PROGRAM ERATOS

program eratos
implicit none

integer :: lim,argc
integer,allocatable :: primes(:) ! Fortran 2003 auto-allocation
character(10) :: argv ! recall int32 limit
logical :: verbose=.false.

argc = command_argument_count()
if (argc==0) stop 'specify positive integer n to find all primes 0 - n and print the largest. -v to show all primes'

call get_command_argument(1,argv); read(argv,*) lim
if (lim<=0) stop 'lim must be greater than zero'

if (argc > 1) call get_command_argument(2,argv); verbose= argv=='-v'

primes = eratos_primes(lim)

if (verbose) print '(A,10000000I9)', 'all primes found: ',primes
print *, 'largest prime found: ', maxval(primes)

contains

pure function eratos_primes(lim)

integer, intent(in) :: lim
integer,allocatable :: eratos_primes(:)

integer :: mid,mult,i,j !utility counters/placeholders
! logical(1) gives ~ 4x memory savings and 40% speedup (gfortran: -O0 and -O3)
logical(1) :: primes(lim) !array of booleans representing integers 0-limit

primes(:) = .true.
mid = lim / 2

!generate primes
do i = 2,mid
if (primes(i)) then
mult = lim / i
!if true, this candidate will not produce a prime
do concurrent (j = 2:mult)
primes(i * j) = .false.
end do
end if
end do

! collect output
allocate(eratos_primes(count(primes)))

! iterable way saves memory over one-liner pack() for large prime cases
j = 1
do concurrent (i=1:lim)
if (primes(i)) then
eratos_primes(j) = i
j = j+1
endif
enddo


end function eratos_primes


end program
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

# gfortran
FCFLAGS = -g3 -fcheck=all -fbacktrace -Wall -Wextra -Wpedantic -Warray-bounds
# ifort
#FCFLAGS = -g -traceback -check all -debug extended

#Optimization flags
FCFLAGS += -O3

eratos: Eratos.f90
$(FC) $(FCFLAGS) -o $@ $^


#Cleanup
clean:
$(RM) *.o *.mod eratos
20 changes: 16 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
# Sieve of Eratosthenes
**Updated 09-16-2017**
**Updated 03-20-2018**

The Sieve of Eratosthenes algorithm implemented in free-form Fortran 95. Finds all primes below input `n`, returns largest prime as output. [More information.](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
[Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
algorithm implemented in Fortran 2003+ style, but compatible at least back to `gfortran-4.8` etc.

Input: `1000`
Output: `997`
Finds all primes below input `n`, returns largest prime as console output.

./eratos 1000

> 997


`-v` returns all primes found.


This method is known to be memory and speed
[deficient](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithmic_complexity)
for large prime numbers.
17 changes: 0 additions & 17 deletions makefile

This file was deleted.