In college, before video games, we would amuse our- selves by posing programming exercises. One of the favorites was to write the shortest self-reproducing program. Since this is an exercise divorced from reality, the usual vehicle was FORTRAN. Actually, FORTRAN was the language of choice for the same reason that three-legged races are popular.
Ken Thompson, Communications of the ACM. 27 (8), 761–763, 1984.
This is the second part of the basic introductin to FORTRAN programming series.
Control Statements
Relational operators
Relational operators are used for comparison between variables
< or .lt. : less than
<= or .le. : less than or equal to
> or .gt. : greater than
>= or .ge. :greater than or equal to
== or .eq. : equal to
/= or .ne. : not equal to
Logical operators
Logical operator are used to perfrom
.and. : Logical multiplication ( and)
.or. : Logical addition (or)
.not. : Logical negation (not)
CONDITIONAL STATEMENTS
The If construct allows the execution of a sequence of statements (block) to depend on a condition. The if construct is a compound statement.
Syntax:
If (scalar-logical-expr) then
block1
else
block2
end if
Example
A 1 D Escher world
The program allows you to move an X character in a one-dimensional world 30 characters long. The world space is on a circle so that
the endpoints of the line are stuck together. In this example, the statement GOTO is used to repeat the input of the movement.
PROGRAM EschelWorld !======================================================= ! ! MOVING IN A ONE DIMENSIONAL CYCLIC WORLD ! USING NINT FUNCTIONS ! ! Roccatano (c) 2023 !======================================================= CHARACTER(len=32) :: map,mapt REAL :: L,pos,step,corr,zero=0 map="|------------------------------|" L=30 pos=L/2.0 ip=ANINT(pos)+1 mapt=map mapt(ip:ip)="x" print *,"You are now in the center of your world" write(6,'(F5.1,1x,A32,F5.1," x=",F5.1)',advance="no") zero,mapt,L,pos 10 write(6,'(" Insert a step ->")',advance="no") READ(5,*) step pos=pos+step IF (pos >L) THEN corr=L*NINT(pos/L) if (corr > pos) THEN pos = corr-pos ELSE pos = pos - corr END IF ELSEIF (pos <= 0) THEN corr=L*NINT(pos/L) if (corr > pos) THEN print *,"Here" pos = L+pos-corr ELSE pos = L-(pos-corr) END IF END IF ip=ANINT(pos)+1 mapt=map mapt(ip:ip)="x" write(6,'(F5.1,1x,A32,F5.1," x=",F5.1)',advance="no") zero,mapt,L,pos GOTO 10 END PROGRAM EschelWorld
EXAMPLE OF OUTPUT
You are now in the center of your world 0.0 |--------------x---------------| 30.0 x= 15.0 Insert a step ->4 0.0 |------------------x-----------| 30.0 x= 19.0 Insert a step ->5 0.0 |-----------------------x------| 30.0 x= 24.0 Insert a step ->6 0.0 |-----------------------------x| 30.0 x= 30.0 Insert a step ->10 0.0 |---------x--------------------| 30.0 x= 10.0 Insert a step ->20 0.0 |-----------------------------x| 30.0 x= 30.0 Insert a step ->2 0.0 |-x----------------------------| 30.0 x= 2.0 Insert a step ->3 0.0 |----x-------------------------| 30.0 x= 5.0 Insert a step ->4 0.0 |--------x---------------------| 30.0 x= 9.0 Insert a step ->5 0.0 |-------------x----------------| 30.0 x= 14.0 Insert a step ->6 0.0 |-------------------x----------| 30.0 x= 20.0 Insert a step ->-3 0.0 |----------------x-------------| 30.0 x= 17.0 Insert a step ->-4 0.0 |------------x-----------------| 30.0 x= 13.0 Insert a step ->-7 0.0 |-----x------------------------| 30.0 x= 6.0 Insert a step ->
LOOP STATMENTS
The loop are important structure in programming as they allow to repeat a set of instructions for a given number of time. Fortran does have the DO-LOOP and the DO WHILE-LOOP staments
DO-statment
Synthax
DO variable = expr1, expr2 [,expr3]
<block of statements>
END DO
Example
Build up the pitagoric table of the first num (<= 20) elements.
PROGRAM PitagoricTable
INTEGER :: num
PARAMETER (num=12)
INTEGER :: tavola(num,num)
WRITE(*,50)
WRITE(*,60) (i,i=1,num)
DO i=1,num
DO j=1,num
tavola(i,j)=i*j
END DO
END DO
DO i=1,num
WRITE(*,70) i,(tavola(i,j),j=1,num)
END DO
50 FORMAT(20X,'PITAGORIC TABLE ')
60 FORMAT(5X,20I5)
70 FORMAT(i2,3X,20I5)
END PROGRAM PitagoricTable
OUTPUT PITAGORIC TABLE 1 2 3 4 5 6 7 8 9 10 11 12 1 1 2 3 4 5 6 7 8 9 10 11 12 2 2 4 6 8 10 12 14 16 18 20 22 24 3 3 6 9 12 15 18 21 24 27 30 33 36 4 4 8 12 16 20 24 28 32 36 40 44 48 5 5 10 15 20 25 30 35 40 45 50 55 60 6 6 12 18 24 30 36 42 48 54 60 66 72 7 7 14 21 28 35 42 49 56 63 70 77 84 8 8 16 24 32 40 48 56 64 72 80 88 96 9 9 18 27 36 45 54 63 72 81 90 99 108 10 10 20 30 40 50 60 70 80 90 100 110 120 11 11 22 33 44 55 66 77 88 99 110 121 132 12 12 24 36 48 60 72 84 96 108 120 132 144
Fortran 90/95 use a DO construct to have the computer execute the same statements more than once. A do construct can be exited by using the EXIT or CYCLE statement.
Example
Search of the Prime numbers using the Sieve of Eratosthenes
PROGRAM PrimeSieve !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! The Sieve of Eratosthenes ! ! 1994 (c) Roccatano !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTEGER MAXNUM PARAMETER( MAXNUM= 1000) LOGICAL:: flag(MAXNUM) INTEGER :: primo,conto,SQMAX DO i=2,MAXNUM flag(i)=.TRUE. END DO SQMAX=INT(SQRT(float(MAXNUM))) DO i=2,SQMAX IF (flag(i)) THEN DO k=2*i,MAXNUM,i flag(k)=.FALSE. END DO END IF END DO DO i=2,MAXNUM IF (flag(i)) WRITE(6,100,advance="no") i END DO 100 FORMAT(1X,I6) END PROGRAM PrimeSieve
OUTPUT 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
I/O STATEMENTS
A Fortran program can input and output data from the keyboard or a file to the screen, printer or file. Access to multiple files, or in general multiple input/output devices, is controlled by assigning a device number that uniquely identifies the device. For example, the keyboard and screen are standard input and output devices, and they are identified with the numbers 5 and 6, respectively. The input/output to files requires assigning the device number to a specific file, which is done with the command open. The syntax of the command is the following:
open(unit=infile, file=’indata.dat’, access=’sequential’, action=’read’) ! read a file open(unit=outfile, file=’outdata.dat’, access=’sequential’, action=’write’)! Write a file
Standard input-output channels do not require the open statement. It is possible to input-output data from /to a file using the standard devices 5 and 6, respectively. For this purpose, you need to use the redirection command of the Unix OS as follows:
./program.exe < input.dat > output.log
In this case, the program Integral reads parameters in the input file input.dat and output.log. The access to the file is terminated, and the device number is released by the statement close(devnum) where devnum is the device number used in the open statement.
Reading lines from an open file is performed using the statement READ(devnum,format). The asterisks (*,*) following READ represent the default format for output, i.e., the outcome is, e.g. written out on the screen.
The writing of data to a device is performed by using the statement PRINT devnum, format or WRITE(devnum,format).
The asterisks (*,*) following WRITE represent the default format for output, i.e., the output is, e.g. written out on the screen.
The format is defined between apostrophes in the read/write command or a numbered label line. In this case, the line contains a FORMAT statement.
10 FORMAT (E15.8,E15.8,E15.8, 5X,'ERROR=',E15.8)
Each format code defines how the data should be read and written. The following table reports the meanings of the one-letter format command.
FORMAT SPECIFICATIONS
I/O program example
An example of a reading and writing file is given in the following example.
Program IOofAllocatedarr ! ! Example of I/O Staments and automatic memory allocations ! of arrays ! ! Implicit none real(8), allocable :: data (:,:) real(8), allocable :: rowsum (:) integer :: rows, i, j ! File unit numbers integer, parameter :: infile=15 integer, parameter :: outile=16 ! Allocate matrices rows=5 allocate (infield(3,rows)) allocate(rowsum(rows)) ! Open the file 'indata.dat' for reading open(unit=infile, file=’indata.dat’, access=’sequential’, action=’read’) ! open the file 'outdta.dat' for writing open(unit=outfile, file=’outdata.dat’, access=’sequential’, action=’write’) ! Read input from file do i=1, rews read(infile, *) (data(j,i),j=1,3) rowsum(i)= data(1,i)+data(2,i)+data(3,i) write(outfile,*) rowsum(i) end do ! Close files close(infile) close(outfile) deallocate (data) deallocate (rowsum) stop end program IOofAllocatedarr