You are on page 1of 35

Introduction to Fortran

programming

Michael L. Michelsen
Institut for Kemiteknik
January 19, 2004
Contents
1 Programming i FORTRAN 2

2 Main elements of Fortran 3


2.1 Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Character set . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Variable names . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.4 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.5 Program elements . . . . . . . . . . . . . . . . . . . . . . . . 4
2.6 Type declarations . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.7 Named constants . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.8 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.9 Assignment statements and arithmetic operations . . . . . . . 6
2.10 Standard Functions . . . . . . . . . . . . . . . . . . . . . . . . 8
2.11 Comparison operators and logical operators . . . . . . . . . . 8
2.12 Control of program flow . . . . . . . . . . . . . . . . . . . . . 9
2.13 Repetition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.14 Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.14.1 UNITS . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.14.2 FORMAT-specifications . . . . . . . . . . . . . . . . . . . 14
2.14.3 Input− and output of variables . . . . . . . . . . . . . 16
2.14.4 Implicit DO-loops . . . . . . . . . . . . . . . . . . . . . 17

3 Subprograms 18

4 Program libraries in Fortran 21

5 Global variables 23

6 LIST OF INTRINSIC FUNCTIONS 25

7 Specific Names of Generic Functions 27

8 Fortran 90/95 28
8.1 Variable names . . . . . . . . . . . . . . . . . . . . . . . . . . 28
8.2 Free format . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
8.3 New type declarations . . . . . . . . . . . . . . . . . . . . . . 28
8.4 Dynamic allocation . . . . . . . . . . . . . . . . . . . . . . . . 29
8.5 Composite variables . . . . . . . . . . . . . . . . . . . . . . . 30
8.6 Program control . . . . . . . . . . . . . . . . . . . . . . . . . 30
8.7 Array functions . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.8 Explicit Interface . . . . . . . . . . . . . . . . . . . . . . . . . 32
8.9 Operator overloading . . . . . . . . . . . . . . . . . . . . . . . 32
8.10 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

1
1 Programming i FORTRAN
The reason that we are using Fortran as our programming language is
that the language has a number of advantages, in particular for techni-
cal/scientific computations. These will be briefly described in the following.
One reason for the widespread use of Fortran is that the language has
been available since 1957. This has led to the introduction of an official
standard for the language at an early time, such that programs written
in Fortran achieved a high degree of portability and could easily be trans-
ferred between different machine types. A very large number of programs
and program libraries have since been developed, and a translation of such
programs to a newer’ language would require substantial expenses without
compensating advantages. Newer versions of Fortran all contain all essential
elements of the earlier versions such that a re−writing of older programs is
not necessary.
The main strength of Fortran is in the treatment of numerical calcula-
tions, where no high level language has better facilities. In addition Fortran
contains a comprehensive set of facilities for input and output, for the treat-
ment of text strings and for logical variables. A modular structure where the
main program and the subprograms are completely separated makes it pos-
sible to construct very large, reliable Fortran programs and to write general
library programs in Fortran. The language is easily compiled to machine
code (yielding efficient programs) and last but not least, Fortran is easily
learned and easy to use.
Clearly, Fortran has its weaknesses, in particular the earlier variants like
Fortran77. Here the names of variables cannot exceed 6 characters, all up-
percase, and all labels are numeric and therefore not informative. Compos-
ite structures are nonexisting, and Fortran is missing many of the facilities
available in Pascal for structured programming. Newer compilers have often
introduced their own extensions’ to the standard to remedy these defects,
but any use of non−standard facilities reduces the portability of a program.
In this course we shall almost exclusively be limited to Fortran77. Newer
standards, like the strongly revised Fortran 90 and its minor revision, For-
tran 95, contain Fortran77 as a subset, and due to the large amount of
existing code written in Fortran 77 (if it isn’t broke, don’t fix it) this variant
is likely to survive for some years.
In spite of the age of the language ( last of the dinosaurs’, Fortran was
been declared dead’ for more than 25 years) there is no immediate danger
than Fortran will vanish. The newer versions contain all the features missing
in Fortran 77.

2
2 Main elements of Fortran
The following pages provide a summaric account of the main elements of
Fortran 77. A more extensive description can be found in the book by Clive
G. Page, ”The professional programmers guide FORTRAN 77”, which is
freely available on the web.

2.1 Layout
One of the essential differences between Fortran and alternative languages
is the fixed column’ layout of Fortran, a left−over from the punched−card
age. A Fortran program line is divided into 4 fields, as follows:

Column 1− 5: Reserved for labels

Column 6: Any character here marks that the line is a continuation


of the previous line

Column 7−72: Program field. Used for writing program statements.

Column 73 −: Ignored. It was often used to number punched cards.


It is an extremely unpleasant experience to drop a box of unnumbered
punched cards on the floor!

Finally, lines with the character C or * in column 1 are interpreted as


comment lines and ignored as a whole.

2.2 Character set


The character set of Fortran 77 is:

26 Capital letters, A,B,C,−−−−−−−Z

13 Special characters, +−*/,.’=()$: and blank.

Finally all printable characters can be used in text strings and in


comments.

2.3 Variable names


Variable names can only contain up to 6 characters that must be either let-
ters or digits, and the first must be a letter. Almost all variants of Fortran77
(and the later standards) allow up to 31 characters, including underscore and
small letters, but their is no case sensitivity, and blanks are ignored.

3
2.4 Data types
Fortran has 6 standard data types:
INTEGER Integers (4 bytes)

REAL Floating point (4 bytes)

DOUBLE PRECISION Floating point, extended precision (8 bytes)

COMPLEX Complex floating point (2*4 bytes)

LOGICAL Boolean variable (.TRUE./.FALSE.) (4 bytes)

CHARACTER*N Text string, N characters (N bytes)

2.5 Program elements


A Fortran program has the following structure:
PROGRAM <programname>
<type declarations>
.
.
<program statements>
.
.
END
SUBROUTINE <Name>(<par1,par2,par3,...>)
<type declarations>
.
.
<program statements>
.
.
END
<TYPE> FUNCTION <Name>(<par1,par2,....>)
<type declarations>
.
.
<program statements>
.
.
END
A Fortran−program can only contain a single main program (PROGRAM),
but an in principle unlimited number of subprograms (SUBROUTINE and
FUNCTION ).

4
2.6 Type declarations
A special feature of Fortran is the use of implicit and predefined type declara-
tions. It is not necessary to provide a type declaration for Fortran variables,
and unless anything else has been defined variables starting with the letters
I, J, K, L, M and N (I-N) are predefined as INTEGER, and all others as
REAL. In addition to this, explicit declarations can be used, e.g.

INTEGER XTYP
LOGICAL USAND,STORNK
CHARACTER*20 MINFIL,FIL47A

or implicit, e.g.

IMPLICIT DOUBLE PRECISION (A-H,O-Z)

which defines all variable names with first letter A-H and O-Z as DOUBLE
PRECISION . These type declarations can of course also be mixed. In the
following examples we shall assume that the predefined types of Fortran are
used. Many Fortran77 compilers have the option (standard in Fortran 90)
of using the following declaration:

IMPLICIT NONE

which, like in Pascal and C, makes it necessary to provide a type declaration


for all variables.

2.7 Named constants


Named constants can be specified together with the type declaration by
means of the PARAMETER specification:

PARAMETER (MAXDIM=10, MAXSQ = MAXDIM*MAXDIM)

The above defines 2 constants, MAXDIM = 10 and MAXSQ = 100. It is clear


from the example that the PARAMETER specification can make use of arith-
metic expressions, but except for constants these may only contain variables
defined previously.

2.8 Arrays
Arrays can be created by means of the DIMENSION declaration, which corre-
sponds to the type declaration but only gives the index limits for the array
in question.

DIMENSION X(25),Y(20)

creates the two vectors X(1),X(2),....,X(25) and Y(1),Y(2),...Y(20),


since 1 is the default lower limit for the index (in contrast to 0 in C).

5
DIMENSION X1(-5:25)

where the lower limit (−5) is given explicitly, allows index values from −5
to 25.
Arrays can have a maximum of 7 indices. Some examples of DIMENSION
statements with several indices are given below:

DIMENSION A(30,30),B(20,20,5),AGURK7(-13:12,7)

The DIMENSION−declaration requires a preceding type declaration of the


variable (explicit, implicit or predefined), but index limits can also be spec-
ified in connection with a type declaration. The following type declarations
are thus completely equivalent:

INTEGER SPAR
DOUBLE PRECISION TALENT
DIMENSION SPAR(13),TALENT(40,50)
.
INTEGER SPAR(13)
DOUBLE PRECISION TALENT (40,50)

Named constants are frequently used for index limits, e.g.:

PARAMETER (MAX=20)
DIMENSION X(MAX),Y(MAX),Z12(MAX+1),COEF(MAX,2*MAX)

This makes it very easy to substitute new values for the limits.
Indexed variables are stored sequentially in the machine core storage.
Two−dimensional arrays are stored in socalled column order, that is, first
all the elements of the first column, then all elements of the second column,
etc. If we declare:

DIMENSION A(2,3)

the elements of A are stored (in the computer memory) in the order:

A(1,1),A(2,1),A(1,2),A(2,2),A(1,3),A(2,3)

As we shall see later, this is of importance in connection with the use of


subprograms and with input and output of matrices. For arrays with more
than two indices a similar rule applies: The leftmost index runs fastest’,
followed by the next, etc.

2.9 Assignment statements and arithmetic operations


An assignment statement in Fortran is of the form: Variable = Arithmetic
expression for example,

X12 = 3.45*T/PMAX $-$ 4.123

6
The arithmetic operations of Fortran are the usual, addition (+), sub-
traction (−), multiplication (*) and division (/), and in addition exponentia-
tion (**). It is here worthwhile to note that the exponentiation is performed
by repeated multiplication if the exponent is an integer, but by means of
the (more expensive) logarithm and the exponential when the exponent is
real. Therefore, there is a difference in the manner that
Y = X ** 3 ( Y = X * X * X)
and
Y = X ** 3.0 ( Y = EXP (3. * LOG (X)))
are calculated. The upper expression can be evaluated for any real value of
the (real) argument X whereas the latter only can be calculated when X is
positive.
”Mixed arithmetic” is allowed, and Fortran converts all arguments to
that of the higher precision (in the order INTEGER-REAL-DOUBLE PRECISION
before the operation is performed. It is necessary, though, in particular with
integers, to be careful, as pure integer divisions are rounded down.
INTEGER I,J
REAL X,Y
I = 3
J = 2
X = I/J
thus yields the result X = 1.0, since the right hand side is calculated by an
integer division (both arguments are integers) and afterwards converted to
the REAL−variable, X.
X = REAL(I)/J
which uses the conversion function REAL in contrast yields X = 1.5
Numerical constants are indirectly given a type through the presence
of a decimal point or by the use of exponential notation. The symbol E as
exponent marks a REAL, and D as exponent indicates a DOUBLE PRECISION
variable:
2 INTEGER
2.1 REAL
2.123E-3 REAL (0.002123)
2.123D-3 DOUBLE PRECISION (0.002123)

INTEGER I
DOUBLE PRECISION X
I = 3
X = 1/I
X = 1./I
X = 1.D0/I

7
The three assignment statements above result in different values for X. The
first makes an integer division, resulting in X = 0. In the next, the REAL-
division provides for a result with about 6 significant digits, and finally the
last gives a result with full precision.
The following example is more tricky:

I = 3
J = 2
X = 6.0
Y1 = I/J*X
Y2 = X*I/J

results in Y1 = 6.0, Y2 = 9.0. The reason for this is that the arithmetic
expressions are evaluated left to right. In the expression for Y1 we first
calculate I/J=1 (both operands are integers), og subsequently, we multiply.
In the calculation of Y2 the multiplication is performed first, X*I = 18.0,
and afterwards ,we perform a REAL division.

2.10 Standard Functions


Fortran contains a rich selection of standard functions (exponential, loga-
rithm, square root, trigonometric functions, etc.) Most of these exist in
a generic as well as a specific form. In the generic form, for example the
exponential, EXP, the type of the function is determined by the type of the
argument, typically REAL or DOUBLE PRECISION, whereas the specific form,
e.g. DEXP. The specific forms are a leftover from an older standard (it must
still be possible to compile old programs) and should be avoided today.

2.11 Comparison operators and logical operators


The operators used in Fortran77 for comparing variables appear clumsy. The
symbols < and > cannot be used, as they do not belong to the character
set (this is corrected in Fortran 90), and we already use = in the assignment
statements. What is available are the following:

.GT. Greater than


.GE. Greater than or equal to
.LT. Less than
.LE. Less than or equal to
.EQ. Equal to
.NE. Not equal to

for example,

8
LOGICAL MAYBE
X = 3.
Y = 2.
MAYBE = X .GT. Y
gives MAYBE the value .TRUE. The logical operators are: .AND., .OR.,
.NOT., .EQV., .NEQV. and here, their meaning should be evident.

2.12 Control of program flow


The simplest tool for flow control − and the one that has been criticised the
most − is GOTO, for example,
GOTO 500
It is simple, frequently very useful, but it should not be misused. Excessive
use of GOTO results in socalled ”spaghetti Fortran”, where nobody, not even
the author one month later, can find out what happens in the program.
Much more transparent structures are possible with the IF-THEN-ELSE con-
structs.
The simplest conditional statement is the one−sentence IF−construction:
IF (LU) <Programstatement>
Here the statement is executed if the logical expression LU has the value
.TRUE.. Otherwise the program execution just continues with the following
statement. Note that the parentheses around LU are necessary, since blanks
are not significant in Fortran. If, for example, we write:
IF LU J=3
is the consequence that the (integer) variable IFLUJ is given the value 3!
A conditional block uses IF-THEN-ENDIF:

IF (LU) THEN
.
.(statement block, i.e. one or more statements)
.
ENDIF

The block is executed if LU is true. If not, we continue after ENDIF.


The meaning of the construction:
IF (LU) THEN
blok1
ELSE
blok2
ENDIF

9
should hopefully be evident. Either blok1 or blok2 is executed, depending
on whether LU is true or false.
IF (LU1) THEN
blok1
ELSEIF (LU2) THEN
blok2
ELSEIF (LU3) THEN
blok3
ELSE
blok4
ENDIF
Only one of the four blocks is executed. The ELSE-part (but not ENDIF)
can be omitted, and in this case the structure is skipped if all the logical
expressions are false.
IF-constructions can of course be nested:
IF (X .GT. 3.) THEN
Y = 7.
ELSE
IF (X .LT. 0.) THEN
Y = 0.
ELSE
Y = X
ENDIF
ENDIF
It is permitted to jump out from an IF-THEN-ELSE construction (by means
of a GOTO), but it is not allowed to jump into the block.
Finally, Fortran contains another leftover from very early times, the
arithmetic IF−statement. It cannot be recommended for any use.

2.13 Repetition
Repeated execution of a block of statements is best done in Fortran using
DO−loops, which is best illustrated with an example:
DO 100 I = 1,N
X(I) = 0.
Y(I) = 2.
100 CONTINUE
The block between DO 100 and 100 CONTINUE is executed a total of N times,
where I sequentially assumes the values 1, 2, .....N.
The CONTINUE statement is an ”empty” statement which just serves as an
anchor for the label 100. The CONTINUE statement can be used everywhere

10
in a program, normally with the purpose of being an anchor for a label,
since a label cannot be used on a blank line. The variable I of the loop is
called the step variable, and on exit from the loop the value of I is N+1.
It is allowed in Fortran to place a comma between the label and the step
variable, i.e., the above could equally well be written:

DO 100, I = 1,N

In this manner a classical programming error, rumoured to have cost the life
of a communication satellite, is avoided: The programmer had mistakenly
written:

DO 10 I = 1.15

which in Fortran is a perfectly legal assignment statement!, where the vari-


able DO10I (remember that blanks do not count) is given the value 1.15.
With a comma after the label 10, a compilation error would result.

DO 100 I=1,N,2
Y(I) = 7. - Y(I)
100 CONTINUE

Here the loop is executed for the I−values 1,3,5,..., since the last, optional
step variable (which can be negative) indicates the step size. If N is even the
last value assumed by I is N−1, as the upper limit of the loop (N) is never
exceeded. If the final value of the loop variable is less than the starting
value and the step is positive, the loop is never − in contrast to Fortran
66 − executed. The same applies if the starting value is smaller than the
final value and the step is negative. The initial value, final value and the
step variable can be constants (as 1) or variables (as N). Fortran 77 also
permits REAL or DOUBLE PRECISION step values, but this should be done
with extreme care and is best avoided! The example below illustrates the
dangers:

DO 200 X = 0.,1.,0.1
Y = 3*X
WRITE(*,500) X,Y
200 CONTINUE

One would here expect that exactly 11 (x,y)−pairs with X varying from 0.
to 1. are written. There is, however, a risk that the only 10 values are
written, the final being 0.9!. The reason for this is that 0.1 is represented
with a finite binary precision in the computer memory and maybe rounded
to 0.1000001 such that a loop nr. 11 would exceed the upper limit of 1.0.
The problem could be solved by using 1.001 as the final value, but it is
much preferable to use only integers as the loop variables:

11
DO 200 I = 0,10
X = 0.1*I

etc.DO−loops also can be nested, e.g.:

DO 200 I = 1,N
DO 250 J = 1,M
X(I,J) = 0.
250 CONTINUE
200 CONTINUE

or, equivalently (but not recommended!):

DO 200 I=1,N
DO 200 J=1,N
X(I,J) = 0.
200 CONTINUE

A construction that is permitted but which should be avoided, is:

DO 100 I = 1,N
100 X(I) = 1.

The use of the CONTINUE gives a better overview of the program flow and
also makes it much easier to modify the content of the loop, e.g. by addition
of new statements. Virtually all Fortran 77 compilers allow (and in Fortran
90 this form is standard) an aesthetically more pleasant form, where the
label is replaced by an ENDDO: The construction avoids the non−descriptive
label 100 and is recommended.

DO I=1,N
X(I) = 1.
ENDDO

In nested loops each DO must have a corresponding ENDDO.

DO I=1,N
DO J=1,N
X(I,J) = 0.
ENDDO
ENDDO

It is permitted to jump out of loops but not to jump into loops (incl. the
final CONTINUE of the loop).

12
2.14 Input/Output
Input and output of data in Fortran are based on Fortran’s UNIT, which
are characterised by a UNIT−number. A minimum of 100 UNIT numbers
are permitted (0 to 99). In connection with output of results (or, more
rarely, input) use is made of FORMAT−specifications. These indicate the
format/layout in which the output data should be presented.
The general syntax for input or output, respectively, is:
READ (UNIT =15, FMT = 100) List of variables
WRITE (UNIT =16, FMT = 200) List of variables
where units 15 and 16 and the format specifications 100 and 200 are used
as examples. It is permitted to skip the keywords UNIT and FMT, and the
same result is obtained with the following:
READ (15,100) List of variables
WRITE (16,200) List of variables
.
. .
100 FORMAT(5I4)
200 FORMAT(I3,F8.2,2F10.4)
The FORMAT−specifications indicate the field width and the number of digits
for the data that are input or output, and these will be described later.
Input data are often read with free format. For this we use FMT = * :
READ (5,*) A,B,C,....,N
Free format can also be used for output. In the case the machine decides the
format and the layout, and the result is rarely pleasant. One should only
use free format output for control printout, debug purposes etc.

2.14.1 UNITS
Fortran uses predefined UNITS for ”Standard Input” and ”Standard Out-
put”, here the keyboard and the screen. No special precautions are required
to connect these units, and their unit number are *, e.g.:
READ (*,*) TEMP
WRITE (*,200) X,Y,Z
but in addition the predefined UNITS are associated with a pre−defined
and system dependent ”real” number, typically 5 (input) and 6 (output),
respectively. WRITE (*,200) and WRITE (6,200) are therefore equivalent
here. The last variant does have the advantage that it is easier later to
redirect the output to a disk file, provided a variable has been used to
indicate the unit number:

13
NOUT = 6
WRITE (NOUT,200) X,Y,Z
Except for the predefined, UNITs must be OPENed og CLOSEd explicitly:
OPEN ( UNIT = 11, FILE = ’MYFILE.DAT’ )
opens the disk file MYFILE.DAT as UNIT 11. It is also here allowed to skip
UNIT = (but not FILE =). The unit is closed again with:
CLOSE ( UNIT = 11) ( or CLOSE (11) )
The statements READ, WRITE, OPEN and CLOSE can be supplemented with
a variety of options that makes it possible to handle error situations and
End Of File conditions. Consult a text for these possibilities. The units you
open for your own use can be numbered freely but avoid numbers between
0 and 9 since these might clash with the predefined numbers used by the
specific compiler.

2.14.2 FORMAT-specifications
A FORMAT−specification indicates the layout to be used when a set of vari-
ables are printed (or read). The FORMAT specification consists of a mixture of
data descriptors and control descriptors. A data descriptor must be present
for every variable that has to be output or input. The most important types
are listed below:

Integers: Iw
Real and Double precision: Fw.d, Ew.d
Boolean: Lw
Tekst strings: A, Aw

Here w and d mark two positive integers (not variables!) where W is the field
width (the total number of character positions occupied by the number) and
d is the number of digits after the decimal point (where appropriate). For
floating point variables F indicates standard notation without exponent and
E is exponential notation. The A−format without the width w will print a
character variable with its actual length.
Some examples:
X = 17.34
I = 7
WRITE (*,100) I,X
WRITE (*,200) I,X
100 FORMAT (I5,F14.4)
200 FORMAT (I5,E14.4)

14
gives the following

123456789012345678901234567890 (marks column position)

7 17.3400
7 .1734E+02

X = -173.2
WRITE (*,100) X
100 FORMAT(’ X = ’,F5.1)

gives the printout:

X = *****

as the print of the character * in the entire field marks that there is too little
space available for the number. Notice that the E−format requires that w >
d+6 since space is required for the sign, the decimal point and the exponent
and its sign.
Data descriptors can be supplemented with a repeat counter that indi-
cates repeated use of the same, e.g.:

100 FORMAT(I5,3F7.2)

which corresponds to:

100 FORMAT(I5,F7.2,F7.2,F7.2)

The control descriptors are used for insertion of blanks, change of line, tab-
ulation, direct output of text strings etc. Examples of the most important
are:

5X Writes 5 blanks (3X gives 3 blanks, etc).


/ Shift to new record (line)
’Goddag’ Writes the string Goddag

Example:

Z = 5.
X = 3.14
Y = Z*X
WRITE (*,100) Y
100 FORMAT(/,’ Resultatet er: ’,F9.2,’ kr’,/)

gives the following output:

<blank line>
Resultatet er: 16.33 kr
<blank line>

15
2.14.3 Input− and output of variables
It is important to realize that in Fortran each read− or write statement
treats at least one record (text line). It is thus not possible (in Fortran 77,
it is in Fortran 90) to read half a line in one statement and the other half
in the following.
For input, the superfluous data on the individual lines in the input file
are just ignored. Missing data will lead to the subsequent records being read
until all variables have been read in.
Assume that a data file (opened as UNIT 17) has the following content:

10. 20.
15. 18.
17. 34.
145. 56.

READ (17,*) X
READ (17,*) Y

thus gives X = 10., Y = 15., since 2 records are read,

READ (17,*) X1,X2


READ (17,*) Y1,Y2

gives X1=10., X2=20., Y1=15., Y2=18.,and finally, from:

READ (17,*) X1,X2,X3


READ (17,*) Y1,Y2,Y3

X1=10.,X2=20.,X3=15. og Y1=17.,Y2=34.,Y3=145.
On output, the FORMAT−list is scanned for the individual data descrip-
tors. Superfluous descriptors are not used, but if descriptors are missing,
the FORMAT−list is just re−used from start, after a change to a new line.
Example:

X = 17.00
Y = 20.31
Z = 49.11
WRITE (*,100) X,Y,Z
100 FORMAT(F6.2,2F7.1)

gives: b17.00 20.3 49.1


whereas FORMAT(F6.2,F7.1) gives:

b17.00 20.3
b49.11

16
Finally we can mention that the FORMAT−specifications formally are text
strings and that it is possible to insert a FORMAT−construction directly in
the read/write statement. For the example above one might for example
use:

WRITE (*,’(F6.2,2F7.1)’) X,Y,Z

2.14.4 Implicit DO-loops


In connection with input and output of arrays the socalled implicit DO−loops
can be used. This method is illustrated below in a few examples:

DIMENSION A(20),B(20)\\
READ(5,100) A

corresponds to: READ(5,100) A(1),A(2),......,A(20)

READ (5,100) (A(I),I=1,10)

corresponds to: READ (5,100) A(1),A(2),A(3),.....,A(10)

READ (5,100) (A(I),B(I),I=3,7,2)

matches: READ (5,100) A(3),B(3),A(5),B(5),A(7),B(7)


and

WRITE (6,200) (I,A(I),I=1,N)


200 FORMAT(I3,F8.2)

gives the following output:

1 <A(1)>
2 <A(2)>
.
.
<N> <A(N)>

Finally, the construction below:

READ (5,*) ((A(I,J),J=1,5),I=1,5)

acts as nested DO−loops, where the I−loop is the outermost and the J−loop
the innermost, such that the input order becomes:

A(1,1),A(1,2),....A(1,5),A(2,1),A(2,2),.......

In contrast to this,READ(5,*) A reads the data in storage order’, i.e. A(1,1),


A(2,1), A(3,1), ...A(5,1), A(1,2),....

17
3 Subprograms
Two types of independent subprograms, SUBROUTINE and FUNCTION, are
available. A SUBROUTINE, the more general subprogram type, is called with

CALL <navn> (<arguments>)

for example:

CALL SOLVE3(20,X,Y,T,P,CONC12)

whereas a FUNCTION is given a value, and it cannot appear on the left hand
sign of the equality sign. An example of a call to a FUNCTION is:

Y12 = X + XKOX12(T,P)

The SUBROUTINE−program SOLVE3 could typically be constructed as follows:

SUBROUTINE SOLVE3 (NDIM,XVAR,YVAR,TEMP,P,C)


DIMENSION XVAR(NDIM),YVAR(NDIM)
LOGICAL SNYD
DIMENSION A(20),B(30)
.
. (Program block)
.
END

The subroutine SOLVE3 has a parameter list with 6 variables, the formal
parameters of the subroutine, of which two are one−dimensional arrays.
The parameter list has to be type declared (in the example, the predefined
types are used) and dimensioned. If the subprogram is a general purpose
subprogram it cannot know in advance what the declared size of the two
array arguments XVAR and YVAR, since these come from the calling program.
We therefore transfer the size of these arrays in the call as a parameter. The
example above thus corresponds to a situation where the actual arguments
X and Y are declared with:

DIMENSION X(20),Y(20)

SNYD, and the arrays A and B are, in contrast, local variables, which are
used internally in the subroutine. The values in these arrays are lost’ when
the subroutine returns to the calling program.
The example below shows a complete subroutine for calculation of the
mean value of N elements of a one−dimensional array:

SUBROUTINE MIDVAL (NDIM,N,X,XMIDL)


DIMENSION X(NDIM)
SUM = 0.0

18
DO I = 1,N
SUM = SUM + X(I)
ENDDO
XMIDL = SUM/N
END
The earlier Fortran−standard required the statement RETURN as the last line
before the terminating END, and many programmers still use the RETURN as
the next−to−last line of the subroutine. RETURN can still be used to return to
the calling program before the end of the subprogram, e.g. if the calculations
indicate that it is meaningless to continue. The statement:
IF (N .GT. NDIM) RETURN
could for example be placed as the first line of the subroutine above.
A corresponding FUNCTION−program could look as follows:
REAL FUNCTION XMIDL(NDIM,N,X)
DIMENSION X(MDIM)
SUM = 0.
DO I=1,N
SUM = SUM + X(I)
ENDDO
XMIDL = SUM/N
END
The type specification REAL is not strictly necessary since the standard def-
initions for implicit types also applies for a FUNCTION (XMID is predefined as
REAL). The call could be:
YAVE = XMIDL(20,10,YVAR)/XNUL
The purpose of a FUNCTION subprogram is to calculate a value. It is formally
permitted for a function to change its arguments, but this is rightfully con-
sidered bad taste’ and should be avoided. You should thus be careful with
oversmart’ constructions.
In standard Fortran 77 calls to subprograms cannot be recursive (a sub-
program must not call itself). In praxis this is not a limitation for the type
of problems where one would normally consider using Fortran.
An important difference between Fortran and Pascal/C is that Fortran
transfers all variables to subprograms as addresses, corresponding to the Var
specification of Pascal. There is no feature in Fortran that corresponds to
Pascal’s Value.
The parameter list to the subprogram in Fortran is of course allowed
to contain arithmetic expressions or numeric constants (as shown above),
but, equally evident, this requires that the corresponding variables are not
changed by the subprogram. Had the last statement of the subprogram
XMIDL above for example been:

19
N = N + 1

the call

YAVE = XMIDL(20,10,YVAR)/XNUL

would change the internal representation of the integer 10 to the integer 11.
A subsequent statement:

NEWVAL = 10*N13

could give rise to the mysterical’ error that N13 was multiplied by 11 instead
of by 10! The consequences of this can be quite amusing, and in particular
in connection with library programs, where the user is unaware of what goes
on internally, is it of importance to know’the problem mentioned above. The
calling conventions for library programs should always be studied carefully,
and their specifications followed strictly. Library programs are strictly what
you get is what you asked for’, not necessarily what you get is what you
wanted’.

20
4 Program libraries in Fortran
An essential strength in Fortran is the ability of the language to build mod-
ular program libraries (SUBROUTINE, FUNCTION) for the solution of specific
problems. As a simple example we shall here discuss the subroutine GAUSL,
which is used for the solution of a set of linear algebraic equations.
When a library program is used it is essential that the correct param-
eters and variables are used for communication with the subprogram. The
description below of the library program GAUSL is taken from the book by
Villadsen and Michelsen, ’Solution of Differential Equation Models by Poly-
nomial Approximation’.

”Let A be an [ N x (N+NS) ] matrix that contains the square matrix B


in its first N columns and an N x NS matrix C in columns N+1 to N+NS.
The call of GAUSL will replace C by B−1C. The B−part of matrix A is
destroyed.” The subroutine can thus be used for solution of linear algebraic
equations, e.g.,
Ux = v
where U is a non−singular N x N matrix of coefficients and v is an N−vector.
The matrix of coefficients U is copied to the upper, square N x N block of the
work area’ A, and the vector v is copied to column N+1 of A. The library
program is called (NS = 1), and x is copied back from column N+1. The
subroutine can also be used for matrix inversion. In this case the square
block of columns N+1 to 2N in A is filled with a unit matrix, and NS
= N. The following description is given in Villadsen og Michelsen: ”The

subroutine call is

CALL GAUSL (NROW,NCOL,N,NS,A)

The input parameters are:

INTEGER NROW,NCOL: Row and column dimension of the


DOUBLE PRECISION PRECISION array A
as declared in the calling program.
INTEGER N: Current size of equations to be solved.
N must be less than or equal to NROW.
INTEGER NS: Number of right hand sides for which
the system of equations is to be
solved. N+NS must be less than or
equal to NCOL.
DOUBLE PRECISION ARRAY A: The coefficient matrix B, augmented
by the right hand side matrix C in
columns N+1 to N+NS.

21
The output is:

DOUBLE PRECISION ARRAY A: The last NS columns of A (i.e.


columns N+1 to N+NS) contains the
solution to the system of equations.
The input matrices are destroyed.

When the subroutine is used it is particularly important to realize what


the parameters NROW and NCOL stand for. The subroutine is a general purpose
program that should be able to handle problems of any size , and the matrix
A should just be though of as a ”work area”. It is not important that there is
exact agreement between the size of A and the size of the actual problem to
be solved. A must just be large enough to contain the necessary information.
Assume for example that we, in a computer program, are required to solve
sets of algebraic equations repeatedly, with a variable number of equations,
e.g. form 2 to 10, but only with a single right hand side. If we therefore
declare A with the dimensions (10,11), i.e.

DOUBLE PRECISION A(10,11)

A will be able to contain all the problems we wish to solve. he parame-


ters NROW and NCOL in the call to GAUSL are the actual row− and column
dimensions in the type declaration for A in the calling program. Thus, in
the example above, we should use NROW=10 and NCOL=11. The reason that
we need the values of NROW and NCOL is: In FORTRAN all the subprogram
parameters are transferred as addresses, i.e. information about where the
arguments are located in the computer memory (corresponding to Var in
Pascal). For an array the address of the first element of the array is trans-
ferred, whether the array is one-dimensional or multi−dimensional. The
subprogram therefore needs information that enables it to locate e.g. the
(I,J)−element of a two−dimensional array.
Multidimensional arrays in Fortran are stored in column order, that
is, all elements of the firstcolumn followed by all elements of the second,
etc. This is in contrast to Pascal and C who both use row order. A
two−dimensional array declared as DIMENSION A(4,3) thus has its ele-
ments stored in the order (2,1), (3,1), (4,1), (1,2), (2,2),......
(4,3). The element A(1,2) is thus the 5th element of the array, and
in general for two−dimensional arrays the (I,J)−element is element nr.
(J-1)*NROW + I, where NROW is the row dimension of the array (4 in the
example). When the subprogram knows the location of the first element
as the number of rows in a two−dimensional matrix it is able to locate all
elements.
In GAUSL A is ”dimensioned” as DOUBLE PRECISION A(NROW,NCOL). This
”dimensioning” does not serve to create an array but only to describe

22
to the subroutine the datastructure of the argument A, i.e. that A is a
2−dimensional array of double precision values, organised with NROW rows
and NCOL columns. This enables the subroutine to find the elements of the
array in the computer memory. Actually the number of columns, NCOL, is ac-
tually not needed by the subroutine (except for debug purposes) and in For-
tran 77 it is possible to use the following specification for two−dimensional
arrays that are transferred in a parameter list:
DOUBLE PRECISION A(NROW,*)
where the * only serves to indicate that A has two indexes. Similarly, one-
dimensional arrays can be declared in the subprogram as: DOUBLE PRECISION
VEC(*). The subroutine now ”knows” that VEC is a one-dimensional array
and does not need additional information to locate the elements in the array.
Had VEC not been declared as a vector the compiler would have assumed
that VEC(I) was a call to the function VEC with the (integer) argument I.
Local arrays in subprograms are created in the conventional manner and
(in Fortran 77) with fixed size. Such local arrays are − as all other local
variables − lost, when the subprogram returns.

5 Global variables
In addition to the parameter list the communication between the main pro-
grams and its subprograms or internally between the subprograms can take
place through a ”back door”, the COMMON blocks. COMMON−blocks are the
global variables of Fortran, and they are created using declarations like:
INTEGER NVAL
REAL X,Y,Z, A(10)
COMMON /VARBL1/ X,Y,Z,A,NVAL
in all the program elements, where these variables are to be used. VARBL1
is the name of the COMMON−block, and it is permitted to create an arbitrary
number of named COMMON−blocks. The content of the COMMON−block is in
reality the addresses of its variables, and the name of the individual variables
is without importance since only their position counts. Assume for example
that the variables in the COMMON−block in the main program are given
the values:
NVAL = 5
X = 3.22
Y = 2.11
.
.
CALL FUP(T)
.

23
and that the subroutine FUP contains the above COMMON−block,

SUBROUTINE FUP(T)
INTEGER N
REAL T,A,B,C,D(10)
COMMON / VARBL1 / A,B,C,D,N

On entrance to the subroutine the value of A will be 3.22, the value of N


is 5, etc., and there are thus rich possibilities for making errors if different
names for the variables in the block are used in different subprograms. In
particular, disastrous effects can take place if variables of different types are
swapped, e.g.

COMMON / VARBL1 / N,B,C,D,A

where we have managed to associate the real variable A with the integer
NVAL. Errors of this type easily appears when new variables are added to
existing COMMON−blocks if one forgets to correct all occurrences of the block.
A small example:

PROGRAM MESS
COMMON /TOTAL/ N,A
N = 513000000
A = 0.1415
CALL KLUDR
END
SUBROUTINE KLUDR
COMMON /TOTAL/ A,N
PRINT *,A
WRITE(*,100) A,N
100 FORMAT(’ A = ’,D12.2,’ N = ’,I20)
END

yields the output: A = 0.16D−19 N = 1041294688

COMMON−blocks could be considered a ”bad habit” but at the same time a


very convenient and often unavoidable habit since parameter lists containing
hundreds of variables are not nice either. Fortran90 ’modules’ are a superior
alternative.

24
APPENDIX 1.

6 LIST OF INTRINSIC FUNCTIONS

The table below shows the number of arguments for each function
and what data types are permitted. When more than one argument
is allowed all must have the same data type.

The data type codes are:

I=Integer, R=Real, D=Double precision, Cx=Complex, Ch=Character, L=Logical.

The data type that the function returns is shown on the left;
an asterisk here indicates that it has the same data type as
the arguments.

R = ABS(Cx) Takes the modulus of a complex number


(i.e. the square root of the sum of
the squares of the two components).
* = ABS(IRD) Absolute value of a number (i.e. it
changes the sign if negative).
* = ACOS(RD) Arc$-$cosine; the result is in the
range 0 to + .
R = AIMAG(Cx) Extracts the imaginary component of
a complex number.
Use REAL to extract the real component.
* = AINT(RD) Truncates the fractional part (i.e.
as does INT) but preserves the data type.
* = ANINT(RD) Rounds to the nearest whole number.
* = ASIN(RD) Arc$-$sine; the result is in the range
- pi/2 to + pi/2.
* = ATAN(RD) Arc$-$tangent; the result is in the range
-pi/2 to + pi/2.
* = ATAN2(RD,RD) Arctangent of A1/A2 resolved into the
correct quadrant, the result is in the range
-pi to + pi. It is an error to have both
arguments zero.
Ch = CHAR(I) Returns Nth character in local character
code table.
Cx = CMPLX(IRDCx) Converts to complex.
Cx = CMPLX(IRD,IRD) Converts to complex.
Cx = CONJG(Cx) Computes the complex conjugate of a

25
complex number.
* = COS(RDCx) Cosine of the angle in radians.
* = COSH(RD) Hyperbolic cosine.
D = DBLE(IRDCx) Converts to double precision.
* = DIM(IRD,IRD) Returns the positive difference of A1
and A2, i.e. if A1 > A2 it returns (A1-A2),
otherwise zero.
D = DPROD(R,R) Computes the double precision product
of two real values.
* = EXP(RDCx) Returns the exponential, i.e. e to
the power of the argument. This is
the inverse of the natural logarithm.
I = ICHAR(Ch) Returns position of first character of
the string in the local character code table.
I = INDEX(Ch,Ch) Searches first string and returns position
of second string within it, otherwise zero.
I = INT(IRDCx) Converts to integer by truncation.
I = LEN(Ch) Returns length of the character argument.
L = LGE(Ch,Ch) Lexical comparison using ASCII character
code: returns true if A1 >= A2.
L = LGT(Ch,Ch) Lexical comparison using ASCII character
code: returns true if A1 > A2.
L = LLE(Ch,Ch) Lexical comparison using ASCII character
code: returns true if A1 <= A2.
L = LLT(Ch,Ch) Lexical comparison using ASCII character
code: returns true if A1 < A2.
* = LOG(RDCx) Natural logarithm, i.e. log to base e
(where e=2.718281828...).
* = LOG10(RD) Logarithm to base 10.
* = MAX(IRD,IRD,.) Returns the largest of its arguments.
* = MIN(IRD,IRD,.) Returns the smallest of its arguments.
* = MOD(IRD,IRD) Returns A1 modulo A2, i.e. the remainder
after dividing A1 by A2.
I = NINT(RD) Converts to integer by rounding to the
nearest whole number.
R = REAL(IRDCx) Converts to real.
* = SIGN(IRD,IRD) Performs sign transfer: if A2 is negative
the result is -A1, if A2 is zero or
positive the result is A1.
* = SIN(RDCx) Sine of the angle in radians.
* = SINH(RD) Hyperbolic sine.
* = SQRT(RDCx) Square root.
* = TAN(RD) Tangent of the angle in radians.
* = TANH(RD) Hyperbolic tangent.

26
7 Specific Names of Generic Functions
Specific names are still needed when the function name is used
as the actual argument of another procedure. The specific name
must then also be declared in an INTRINSIC statement.
This table lists all the specific names which are still useful
in Fortran 77. The other functions either do not have generic
names or cannot be passed as actual arguments.

GENERIC --------------SPECIFIC NAMES---------------


NAME INTEGER REAL DOUBLE COMPLEX
PRECISION

ABS IABS ABS DABS CABS


ACOS ACOS DACOS
AINT AINT DINT
ANINT ANINT DNINT
ASIN ASIN DASIN
ATAN ATAN DATAN
ATAN2 ATAN2 DATAN2
COS COS DCOS CCOS
COSH COSH DCOSH
DIM IDIM DIM DDIM
EXP EXP DEXP CEXP
LOG ALOG DLOG CLOG
LOG10 ALOG10 DLOG10
MOD MOD AMOD DMOD
NINT NINT IDNINT
SIGN ISIGN SIGN DSIGN
SIN SIN DSIN CSIN
SINH SINH DSHIN
SQRT SQRT DSQRT CSQRT
TAN TAN DTAN
TANH TANH DTANH

27
8 Fortran 90/95
In contrast to earlier revisions of Fortran, Fortran 90 should rather be consid-
ered a completely new language, which contains practically all the features
missing in the earlier versions. It is worthwhile mentioning, though, that
Fortran 77 is still a legal subset of Fortran 90, with the important conse-
quence that programs and program libraries written in Fortran 77 can still
be used. There is, therefore no reason to re−invent the wheel or to rewrite
working libraries (”if it aint broke, don’t fix it”). The latest published revi-
sion, Fortran 95, only contains minor corrections to Fortran 90, and F2K is
on the way.
Unfortunately, from a teaching point of view, Fortran 90 is also a much
more complex language, and an introductory course would realistically match
a load of 5 points. With expe−rience from practical use of Fortran 77 it is
possible for you on your own hand to gradually learn and apply the new
features. Here one should notice that it is possible on the Internet to find
comprehensive − and completely free − material, even in the form of com-
plete courses, that describe the facilities in Fortran 90 and the essential
differences between Fortran 77 and Fortran 90. A modest selection is given
below.

8.1 Variable names


Fortran 90 permits names of up to 31 characters, and a more comprehensive
character set can be used, including the underscore. It is permitted to use
capital as well as small letters, but Fortran is still not case sensitive.

8.2 Free format


It is still possible to used the column based format in Fortran 90, but an
alternative possibility is ”free format”, where statements can be placed any-
where on the line. Continuation of a line is marked by a & at the end of the
line and it is permitted to use also a & at the beginning of the next line.
Comment lines are marked by ! and trailing comments are permitted. Most
commercial compilers will treat at file with the extension .f, .for or .f77 as a
”fixed format” file and one with the extension .f90 or .f95 as a ”free format”.
Otherwise, compilation options like /fixed or /free will do the job.

8.3 New type declarations


Fortran 90 uses a new form for the type declaration, with a double colon:

REAL, DIMENSION (20) :: X,Y,Z


REAL, DIMENSION (:,:),ALLOCATABLE :: My_Matrix
INTEGER, PARAMETER :: NUMBER = 10

28
but the conventional type declarations still can be used. The example above
declares 3 vectors with 20 elements each, a two−dimensional array which
has not been given a size yet, and an integer constant.

8.4 Dynamic allocation


One of the most important drawbacks of Fortran 77 is the need to dimension
all variables ”in advance” which means that the dimensioning must corre-
spond to the largest possible size of the problem. The actual sizes to be
used is often first known at run−time. Assume for example that we need
a two−dimensional array with N rows and M columns, where N and M are
either read in or the result of some previous calculation. In Fortran 77 it
would be necessary to dimension the array to the largest possible values of
N and M, which is inelegant as well as a waste of space. A variety of ”tricks”
have been used, e.g. large one−dimensional workarrays that are ”packed”
as a number of one− and two−dimensional arrays, but this appears at the
cost of a considerable amount of bookkeeping and consequently many possi-
bilities for making errors. In Fortran 90 the solution is simple. The array is
type declared with the attribute ALLOCATABLE, cf. the example above with
the variable My Matrix, which at the time of declaration has not been given
a size yet. This is done later with

ALLOCATE (My_Matrix(N,M),STAT=IALLOC)

(where N and M gives the actual sizes and the variable IALLOC will get the
value 0 if the allocation succeeds). Later, when the array is no longer needed
the storage can be returned to the system with:

DEALLOCATE (My_Matrix)

An alternative and simple form for dynamic allocation are ”Automatic Ar-
rays”, which can only be used for local variables in subprograms:

CALL SUB (N,X,Y)


.
.
.
SUBROUTINE SUB (N,X,Y)
REAL, DIMENSION (*):: X,Y
REAL, DIMENSION (N):: Z

Here, Z is a local vector, ”created” at execution time with the desired size.
In Fortran 77 a fixed size, sufficiently large, was needed.
Finally, we can use pointers for dynamic allocation, but this will not be
described here.

29
8.5 Composite variables
Composite variables correspond to the RECORD of Pascal and the STRUCTURE
of C. An example of a type declaration is shown below:
TYPE :: ADDRESS
CHARACTER*20 ROAD_NAME
INTEGER ROAD_NUMBER
INTEGER ZIPCODE
CHARACTER*20 COUNTRY
END TYPE ADDRESS
TYPE (ADDRESS) PARTICIPANT(20)
.
.
PARTICIPANT{1)\%ROAD_NAME =’Lundtoftevej’
PARTICIPANT{1)\%ROAD_NUMBER = 100’
PARTICIPANT{1)\%ZIPCODE = 2820
PARTICIPANT{1)\%COUNTRY =’Denmark’
First, we define the variable type ADDRESS with 4 elements, and afterwards
we create an array, PARTICIPANT, with 20 elements of type ADDRESS. The
individual elements − that may themself be indexed − are indicated with
the %−sign.

8.6 Program control


In contrast to Fortran 77, Fortran 90 permits to use DO/ENDDO for loops.
Fortran 90 introduces two new facilities for loop control: CYCLE, which ter-
minates the present iteration and continues with the next, and EXIT, which
terminates the loop itself and continue with the first executable statement
after the loop. Loops without counter, i.e. DO ... ENDDO are permitted,
and these can only be terminated by means of an EXIT or by a jump to a
label outside the loop.
An alternative to IF-THEN-ELSEIF is the SELECT CASE−construction, as
illustrated in the example below:
WRITE (*,*) ENTER N_SEL
READ(*,*) NSEL
SELECT CASE (NSEL)
CASE (1)
PRINT *,’ YOU TYPED THE NUMBER ONE !
CASE (2)
PRINT *,’ YOU TYPED THE NUMBER TWO
CASE (3:5)
PRINT *,’ YOU TYPED A NUMBER BETWEEN 3 AND 5
CASE DEFAULT

30
PRINT *,’ YOU TYPED A NUMBER <1 OR >5
END SELECT

Using IF-THEN-ELSE the above would be

IF (NSEL == 1) THEN
PRINT *,’ YOU TYPED .....
ELSEIF (NSEL == 2) THEN
PRINT *,’ YOU TYPED ....
ELSEIF (NSEL >= 3 .AND. NSEL <= 5) THEN
.....
ELSE
.....
ENDIF

Here we note that Fortran 90 permits the usee of <, > etc. as alternative
to the still valid .LT., .GT. etc.

8.7 Array functions


Fortran 90 has an extensive set of new functions that facilitate the handling
of indexed variables without the conventional use of DO−loops. Some exam-
ples are given below, where we also demonstrate that trailing comments are
permitted in Fortran 90:

REAL, DIMENSION (10):: X,Y,Z


REAL, DIMENSION (15,10):: A,B,C
.
.
X = 0. ! Sets all elements in X = 0
Y = X ! Sets all elements in Y = the !
! corresponding in X
Z = 3.*X ! Forms Z by multiplaton of X by 3
Z(2:6)= X(1:5) ! Z(2)=X(1), Z(3)= X(2),... Z(6) = X(5)

C(1:N,1:L) = MATMUL (A(1:N,1:M),B(1:M,1:L))


!
! MATMUL forms the matrix product of two conformant matrices
!

Note that he last line is the solution to problem 3 from the course. The
matrix product is a standard function in Fortran 90. Note also that the
:−notation permits us to work with array sections. This is necessary in the
above case, since C = MATMUL (A,B) is not permitted as the matrices here
are not conformant (B must have as many rows as A has columns).

31
The array−section notation is very powerful and compact, and the lan-
guage contains a large number of functions for use with arrays.

8.8 Explicit Interface


A well known problem when learning Fortran 77 is the syntax for communi-
cation with subprograms, which have arrays as arguments. A well−known
example is CALL GAUSL, where in Fortran 77 it is necessary to transfer the
dimensions (or, at least the first dimension) in the argument list:
DIMENSION A(15,15)
.
.
CALL GAUSL(15,15,N,1,A)
.
.
SUBROUTINE GAUSL(ND,NR,N,NS,A)
DIMENSION A(ND,NR)
.
In Fortran 90 the corresponding construction could be:

CALL GAUSL(N,1,A)
.
SUBROUTINE GAUSL(N,NS,A)
DIMENSION A(:,:)
The dimensions of A which are necessary for the internal address calcula-
tions of the subprogram, are actually transferred as hidden arguments. This
does require the presence of an INTERFACE BLOCK for GAUSL in the calling
program, or that GAUSL is a declared in a module (to be described later).

8.9 Operator overloading


In connection with the introduction of the TYPE−construction for self−defined
variable types it is often necessary to define algebraic procedures for such
variables. One such example could be a new variable type capable of calcu-
lating in double double’ precision,
TYPE QUAD
DOUBLE PRECISION HI
DOUBLE PRECISION LO
END TYPE QUAD

If, in a program we have defined 4 variables, A, B, C and D, by:

TYPE (QUAD) A,B,C,D

32
it would be very convenient for us to be able to use these variables for
arithmetic calculations in a similar manner as we use the built−in types,
e.g.,

D = A*B + C

This requires that we define ( overloads’) the operators * and + such that
they have a meaning in connection with the treatment of the new variable
types. This of course also is the case for other algebraic operations, logical
comparisons and the standard functions of Fortran if we wish an applicability
corresponding to that of the built−in types.
If we had to do something similar in Fortran 77 a much more cumbersome
approach would be required. The quad’−variables would typically be defined
as indexed double precision variables, i.e.

DOUBLE PRECISION A(2),B(2),C(2),D(2),SUM1(2)......


.
.
CALL MULT (A,B,C)
CALL ADD (B,C,D)

A complete rewriting of existing programs would be required, not to men-


tion that the treatment of arrays of quad−variables would create further
problems.
The example above does not come out of the blue sky. It is possible on
the Internet to find several free Fortran 90−’packs’, that defines variables
with extended precision and the required subprograms for the algebraic op-
erations, standard functions, etc. Such routines are conveniently packed in
the form of a MODULE subprogram.

8.10 Modules
Modules are probably the most radical new element in Fortran 90. Modules
are independent program elements that can be used for a variety of purposes,
such as type definitions, library programs, definition of global variables (re-
placement of COMMON) and INTERFACE BLOCKS. Modules are compiled sep-
arately and are used by means of the statement USE <ModuleName>, which
must precede all other declarations:

USE QUADROUPLE_PRECISION
IMPLICIT TYPE (QUAD) (A$-$H,O$-$Z)
.
D = A*B+C

Our new variables have thus been introduced just by the replacement of
IMPLICIT DOUBLE PRECISION with IMPLICIT TYPE QUAD and by the use of

33
USE QUADROUPLE PRECISION . A small remaining problem is that READ/WRITE
(which have a variable number of arguments) cannot in a simple manner in-
corporate the new types, but usually a printout with 30 decimal places is
fortunately not of high interest.

34

You might also like