APPENDIX 3
Summary of the new features in Fortran 90
Below follows a short summary of the new standard. Please note that
only some more essential parts and not the whole new standard are
discussed here.
As an alternative to the old source-code (punched card oriented) form,
there is a free form, which does not take any consideration to columns
and where blanks are significant. Comments can be given on the line
if preceded by an exclamation mark !, several statements can be given
on the same line if using the semicolon ; as a separator, and statements
that continue on the next line are continued on the present line (not
the next line) with an ampersand &.
The underline symbol _ is permitted inside the names of variables,
and the length of variables must have at most 31 characters (instead
of at most 6 in the Fortran 77 standard).
Blanks become significant in the free form of the source code.
Old commands like ENDIF and GOTO can also in
the future be written either as END IF or GO TO
respectively, but of course not like EN DIF or GOT
O. To permit significant blanks in the old (fixed)
form of the source code would not be possible, since it for example
is permitted to write END in the following silly way
E N D
INCLUDE can be used to include source code from an external
file. The construct is a line where there is INCLUDE and
a character string and, perhaps, some concluding comments. Interpretation
is implementation-dependent, normally the character string is treated
as the name of the file that holds the source code that should be
included. Nesting is permitted (and the number of levels is implementation-dependent),
but recursion is not permitted for the INCLUDE statement.
As in most Algol-type languages the word END can be
complemented with the name of the routine or function like END
FUNCTION GAMMA.
The special characters < and > can now be used
< .LT. > .GT.
<= .LE. >= .GE.
== .EQ. /= .NE.
These can now be written on one line
REAL, DIMENSION (3), PARAMETER :: &
a = (/ 0.0, 0.0, 0.0 /), b = (/ 1.0, 1.0, 1.0 /)
COMPLEX, DIMENSION(10) :: john
while the variables a and b become constant vectors with 3 elements
and the floating-point values 0.0 and 1.0, respectively, while john
becomes a complex vector with 10 complex elements, not yet assigned
any values.
If you wish to use the Algol principle to specify all variables,
this is simplified by the command IMPLICIT NONE which
switches off the implicit-type rules.
Double precision has been implemented with a more general method
to give the desired precision, namely the parameter KIND
for which precision we wish, useful on all variable types.
INTEGER, PARAMETER :: LP = SELECTED_REAL_KIND(20)
REAL (KIND = LP) :: X, Y, Z
The above two statements thus declare the variables X, Y
and Z to be REAL floating-point variables with
at least 20 decimal digits accuracy with a data type that is called
LP (where LP stands for LONG PRECISION).
The new command is
SELECT CASE (expression)
CASE block-switch
block
CASE block-switch
block
CASE DEFAULT
default block
END SELECT
Typical construct:
SELECT CASE(3*I-J) ! the control variable is 3*i-j
CASE(0) ! for the value zero
: ! you execute the code here
CASE(2,4:7) ! for the variables 2, 4, 5, 6, 7
: ! you execute the code here
CASE DEFAULT ! and for all other values
! you execute the code here
: !
END SELECT
If the CASE DEFAULT is missing and none of the alternatives
is valid, the execution continues directly with the next statement
following the END SELECT, without any error message.
Another example:
INTEGER FUNCTION SIGNUM(N)
SELECT CASE (N)
CASE (:-1)
SIGNUM = -1
CASE (0)
SIGNUM = 0
CASE (1:)
SIGNUM = 1
END SELECT
END
Three new constructs are included. The first one gives in principle
an infinite loop, which however can be terminated with a conditional
GOTO-statement.
name: DO
executable statements
END DO name
The usual DO-loop has the following new simplified form
without statement number,
name: DO i = integer_expr_1, integer_expr_2 ,integer_expr_3
executable statements
END DO name
where i is called control variable, and where ,integer_expr_3
is optional. Finally there is also the DO WHILE loop
name: DO WHILE (logical_expression)
executable statements
END DO name
The name is optional but can be used for nested loops in order to
indicate which one that is to be iterated once again with the CYCLE
statement or terminated with the EXIT statement.
S1: DO
IF (X > Y ) THEN
Z = X
EXIT S1
END IF
CALL NEW(X)
END DO
N = 0
LOOP1: DO I = 1, 10
J= I
LOOP2: DO K =1, 5
L = K
N = N +1
END DO LOOP2
END DO LOOP1
In the latter case the final values from the variables will be as
follows, in full accordance with the standard, I = 11, J = 10,
K = 6, L = 5, and N = 50.
To name the loop is completely optional. Also note that this type
of name is limited to DO-loop, CASE or IF...THEN...ELSE...ENDIF
constructs. The old possibilities with statement numbers are
still available, also in the free form.
Routines can be called with keyword arguments and can use default
arguments
SUBROUTINE solve (a, b, n)
REAL, OPTIONAL, INTENT (IN) :: b
can be called with
CALL solve (n = i, a = x)
where two of the arguments are given with keywords instead of position
and where the third one has a default value. If SOLVE is
an external routine it requires making use of an INTERFACE
block in the calling program. Routines can be specified to be recursive.
RECURSIVE FUNCTION factorial (n) RESULT (fac)
but must then have a special RESULT name in order to return
the result.
CHARACTER has been expanded to include also an empty string
a = ''
and assignment of an overlapping string is now permitted
a(:5) = a(3:7)
The new intrinsic function TRIM which removes concluding
blanks is an important addition. You can now make a free choice between
the apostrophe ' and the quotation mark " in order to indicate a character
string. This can among other things be used in such a way that if
you wish to write an apostrophe inside the text, then you use the
quotation mark as indicators, and in the opposite case if you wish
to have a quotation mark inside the text you use the apostrophe as
the indicator.
At last the NAMELIST is included in the standard! This statement,
however, has to be among the specifications. In the example below
list2 is the name of the list, a and b
are real variables and i is an integer variable.
NAMELIST /list2 / a, i, x
:
READ (unit, NML = list2)
which wishes to get input data of the following form, but all variables
do not have to given, and they can be given in any order.
&list2 X = 4.3, A = 1.E20, I = -4 /
This is one of the most important parts of the new standard. An array
is defined to have a shape given by its number of dimensions, called
"rank", and the extent for each one of these. Two arrays agree if
they have the same shape. Operations are normally done element by
element. Please remember that the rank for an array is the number
of dimensions and has nothing at all to do with the mathematical rank
of a matrix!
REAL, DIMENSION(5,20) :: x, y
REAL, DIMENSION(-2:2,20) :: z
:
z = 4.0*y*sgrt(x)
We perhaps here wish to protect against negative elements of X.
This is done with the following construct
WHERE ( x >= 0.0 )
z = 4.0*y*sgrt(x)
ELSEWHERE
z = 0.0
END WHERE
Please note that ELSEWHERE has to be in one word! Compare
also with the function SUM which is discussed at the end
of the next section.
You can pick out a part of an array. Assume that the array A
is specified in the following way.
REAL, DIMENSION(-4:0, 7) :: A
With A(-3, :) you pick the second row, while with A(0:-4:-2,
1:7:2) you pick (in reverse order) its each other element in
each other column. Just as variables can form arrays, also constants
can form arrays.
REAL, DIMENSION(6) :: B
REAL, DIMENSION(2,3) :: C
B = (/ 1, 1, 2, 3, 5, 8 /)
C = RESHAPE( B, (/ 2,3 /) )
where the first argument to the intrinsic function RESHAPE
gives the value and the second argument gives the new shape. Two additional,
but optional, arguments are available to this function.
The above can also be written in a more compressed form using
the PARAMETER attribute. In the first line below the PARAMETER
attribute is compulsory (if the assignment is to be made on
the same line), but in the second line it is optional. Remember
that the PARAMETER attribute means that the quantity can
not be changed during execution of the program.
REAL, DIMENSION(6), PARAMETER :: B = (/ 11, 12, 13, 14, 15, 16 /)
REAL, DIMENSION(2,3), PARAMETER :: C = RESHAPE( B, (/ 2, 3 /) )
Any statements for real parallel computation are not included in Fortran
90. The committee believes it is necessary with additional experience
before the standardization of parallelization. See also HPF discussed
in the Appendix 8.
Fortran 90 contains four different ways to make dynamical access.
The first one is to use a pointer. See an example
on a vector and for an example on a matrix see exercise
12.3.
The second is to use an "allocatable array", i.e. with the statements
ALLOCATE and DEALLOCATE you get and return a
storage area for an array with type, rank and name (and possible
other attributes) which had been specified earlier with the additional
attribute ALLOCATABLE.
REAL, DIMENSION(:), ALLOCATABLE :: x
:
Allocate(x(N:M)) ! N and M are the integer expressions here.
:
x(j) = q ! Some assignment of the array.
CALL sub(x) ! Use of the array in a subroutine.
:
DEALLOCATE (x)
Deallocation occurs automatically (if the attribute SAVE
has not been given) when you reach RETURN or END
in the same program unit.
The third variant is an "automatic array", it is almost available
in the old Fortran, where x in the example below has to be in the
list of arguments. This is not required any more.
SUBROUTINE sub (i, j, k)
REAL, DIMENSION (i, j, k) :: x
Dimensions for x are taken from the integers in the calling program.
Finally there is an "assumed-shape array" where the storage is defined
in the calling procedure and for which only the type, rank and name
are given.
SUBROUTINE sub(a)
REAL, DIMENSION (:,:,:) :: a
According to Metcalf and Reid (1990, 1992), section 6.3 you here require
an explicit interface. This has to look as follows
INTERFACE
SUBROUTINE SUB(A)
REAL, DIMENSION (:,:,:) :: A
END SUBROUTINE SUB
END INTERFACE
If you forget the INTERFACE or if you have an erroneous
interface, then you will usually get "segmentation error", it means
that a program unit may be missing.
Some intrinsic functions are available to determine the actual
dimension limits
DO (i = LBOUND(a,1), UBOUND(a,1))
DO (j = LBOUND (a,2), UBOUND (a,2))
DO (k = LBOUND(a,3),UBOUND (a,3))
where LBOUND gives the lower limit for the specified dimension
and UBOUND gives the upper one.
The sum of the positive value of a number of elements in an array
is written
SUM ( X, MASK = X .GT. 0.0)
These statements can not be used in order to avoid division by zero
at for example summation of 1/X, that is the mask works only
with determining which numbers that are to be included in the summation,
and not whether a certain value has to be calculated or not. But in
this later case you can use the construct WHERE, see section
9.
Fortran 90 defines about 100 intrinsic functions and a few intrinsic
subroutines. Many of these functions can be used for arrays, e.g.
for reduction (SUM), construct (SPREAD), manipulation
(TRANSPOSE). Other functions permit attributes or available
parameters in the programming environment to be determined, as the
largest positive floating-point number and the largest positive integer,
as well as access to the system clock. The random numbers generator
is included. Finally, the function TRANSFER permits a certain
physical area to be transmitted to another area without type conversion.
The function SPREAD is discussed more fully in the solution
of exercise (11.1).
All intrinsic functions and subroutines are discussed in Appendix
5.
Fortran had earlier not permitted use of any user-defined type. This
has now become possible.
TYPE staff_member
CHARACTER(LEN=20) :: first_name, last_name
INTEGER :: identification, department
END TYPE
which can be used in order to describe an individual. A combination
of individuals can also be formed
TYPE(staff_member), DIMENSION(100) :: staff
Individuals can be referred to as staff(number) and a field can be
referred as staff(number)%first_name. You can also nest definitions
TYPE company
CHARACTER(LEN=20) :: company_name
TYPE(staff_member), DIMENSION(100) :: staff
END TYPE
:
TYPE(company), DIMENSION(10) :: several_companies
A numerically more interesting example is a sparse matrix A
with at most one hundred non-zero elements, which can be specified
with the following statement
TYPE NONZERO
REAL VALUE
INTEGER ROW, COLUMN
END TYPE
and
TYPE (NONZERO) :: A(100)
You then get the value of A(10) by writing A(10)%VALUE.
Assignment can be done, for example with
A(15) = NONZERO(17.0,3,7)
In order to use user-defined data types in for example COMMON,
or to make sure that two data types which look the same are treated
as identical, you can use the SEQUENCE statement, in the
latter case it is also required that no variable is specified PRIVATE.
Modules are collections of data, type definitions and procedure definitions,
which give a more secure and general replacement for the COMMON
concept.
The data type "bit" is not included in the standard, but there are
available various bit operations of integers according to an earlier
military standard MIL-STD 1753. In addition, binary, octal and hexadecimal
constants are included, as well as the possibility to use these quantities
in input/output through the three new format-letters. In a DATA
statement you can use an assignment to
B'01010101010101010101010101010101'
for binary,
O'01234567'
for octal, and
Z'ABCDEF'
for hexadecimal numbers.
Pointers have been included, but not in the usual way as a new data
type but as an attribute to the other data types. A variable with
a pointer attribute can be used as an ordinary variable and in a number
of new ways. Pointers in Fortran 90 are not memory addresses as in
many languages or in certain Fortran variants (dialects), but are
more like extra names (aliases).
Pointers are discussed in chapter 12.
The new language contains a possibility for the user to extend it
with his own concepts, for example interval arithmetics, rational
arithmetics or dynamic character strings. By defining a new data type
or operator, and overloading operations and procedures (so that you
can also use the plus + as the symbol of addition of intervals and
not only of ordinary numbers), we can create a package (a module)
without using a preprocessor. We can soon expect a number of extensions
for different applications in the form of modules from different manufacturers.
Some are already available from NAG.
Last modified: 17 April 1995
boein@nsc.liu.se |