Professional Documents
Culture Documents
programming
Michael L. Michelsen
Institut for Kemiteknik
January 19, 2004
Contents
1 Programming i FORTRAN 2
3 Subprograms 18
5 Global variables 23
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:
3
2.4 Data types
Fortran has 6 standard data types:
INTEGER Integers (4 bytes)
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.
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
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)
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)
INTEGER SPAR
DOUBLE PRECISION TALENT
DIMENSION SPAR(13),TALENT(40,50)
.
INTEGER SPAR(13)
DOUBLE PRECISION TALENT (40,50)
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)
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.
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.
IF (LU) THEN
.
.(statement block, i.e. one or more statements)
.
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
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
DO 200 I = 1,N
DO 250 J = 1,M
X(I,J) = 0.
250 CONTINUE
200 CONTINUE
DO 200 I=1,N
DO 200 J=1,N
X(I,J) = 0.
200 CONTINUE
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
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
7 17.3400
7 .1734E+02
X = -173.2
WRITE (*,100) X
100 FORMAT(’ X = ’,F5.1)
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)
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:
Example:
Z = 5.
X = 3.14
Y = Z*X
WRITE (*,100) Y
100 FORMAT(/,’ Resultatet er: ’,F9.2,’ kr’,/)
<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
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)
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:
DIMENSION A(20),B(20)\\
READ(5,100) A
1 <A(1)>
2 <A(2)>
.
.
<N> <A(N)>
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),.......
17
3 Subprograms
Two types of independent subprograms, SUBROUTINE and FUNCTION, are
available. A SUBROUTINE, the more general subprogram type, is called with
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 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:
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’.
subroutine call is
21
The output is:
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
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
24
APPENDIX 1.
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 that the function returns is shown on the left;
an asterisk here indicates that it has the same data type as
the arguments.
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.
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.
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.
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:
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.
30
PRINT *,’ YOU TYPED A NUMBER <1 OR >5
END SELECT
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.
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.
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).
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.
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