Again I wish to emphasis that under Fortran 77 all program units are
essentially on the same level, even if the main program logically is
superior to the subroutines and functions that are called, and even though
you could write a call map that looks like a tree. In reality the
`BLOCK `
`DATA ` is on a higher level and all the other program units are on the
same level, from the Fortran system viewpoint with the main
program just a little above. The exception are the so-called statement
functions with definitions that have to be first in a program unit,
directly after the specification, and are internal to that unit and
therefore on a logically lower level. Regrettably, the typical
Fortran 77 programmer does not use statement functions.

The above means that all routine names are on the same logical level, which means that two different routines, and two different parts of a big program are not permitted to have the same name. Quite often numerical and graphical libraries include thousands of functions and subroutines, and each routine name consists of at most six characters under old Fortran standards. Therefore, there is a very great risk of a conflict of names. This problem could be partially solved by the old statement functions, since these are internal to the respective unit, and therefore different statement functions can have the same name if they are in different units. The disadvantage is that they can only treat what is in only one program line. But they can call each other in such a way that a later statement function can call an earlier statement function, but of course not the opposite.

F90 adds internal
functions and internal subroutines, providing
greater flexibility. They are specified at the end of each program
unit (but not in the `BLOCK DATA`) after the new command
`CONTAINS ` and
before the `END`. An internal subprogram can have access to the same
variables as the unit it belongs to, including the possibility of calling
the unit's other internal subprograms. It is written as an ordinary
subprogram, but it is not permitted to have any internal functions or
subroutines.
The internal function is a modern replacement for the statement function.

The usual subroutines and functions remain the same as the earlier external subroutines and external functions, but there is now a more compelling reason for this name (that is calling them external) than earlier, since now you have also internal subprograms. Previously you only had the built in (intrinsic) functions as an alternative. In addition, the number of intrinsic functions has greatly increased, and a few intrinsic subroutines have been added.

For every argument in the specification of variables for subprograms we can
now give its `INTENT ` as `IN, OUT `
or `INOUT`.
If `IN ` is valid, then
the actual argument can be an expression like `X+Y ` or
`SIN(X) ` or a
constant like 37, since the value is only to be transferred to the
subprogram, but a new value is not to be returned to the calling unit.
The variables in this case may not be assigned a new value in the
subprogram. If `OUT ` is valid, on the other hand, the actual argument
has to be a variable. At entry to the subprogram the variable is at
this stage considered to be not defined. The third case covers both
possibilities, one value on input and another on output, or possibly
the same value. In this case the actual argument must also be a
variable. If a variable has a pointer attribute then `INTENT ` may not be
given. The implementation of `INTENT ` is not yet complete in all
compilers.

One use for the new program unit `MODULE ` is to take care of global
data. As such it replaces the `BLOCK DATA`. Its other use is to make a
package of new data types. A rather long example would be a
package for interval arithmetic. Corresponding to each value `X` you have an
interval `(X_lower; X_upper)`. When using the package, you want to
give only the variable name `X ` when you mean the interval. The
variable `X` is then supposed to be a new data type, interval. The
following is in the file `interval_arithmetics.f90 `
or `intv_ari.f90`.

MODULE INTERVAL_ARITHMETICS TYPE INTERVAL REAL LOWER, UPPER END TYPE INTERVAL INTERFACE OPERATOR (+) MODULE PROCEDURE INTERVAL_ADDITION END INTERFACE INTERFACE OPERATOR (-) MODULE PROCEDURE INTERVAL_SUBTRACTION END INTERFACE INTERFACE OPERATOR (*) MODULE PROCEDURE INTERVAL_MULTIPLICATION END INTERFACE INTERFACE OPERATOR (/) MODULE PROCEDURE INTERVAL_DIVISION END INTERFACE CONTAINS FUNCTION INTERVAL_ADDITION(A, B) TYPE(INTERVAL), INTENT(IN) :: A, B TYPE(INTERVAL) :: INTERVAL_ADDITION INTERVAL_ADDITION%LOWER = A%LOWER + B%LOWER INTERVAL_ADDITION%UPPER = A%UPPER + B%UPPER END FUNCTION INTERVAL_ADDITION FUNCTION INTERVAL_SUBTRACTION(A, B) TYPE(INTERVAL), INTENT(IN) :: A, B TYPE (INTERVAL) :: INTERVAL_SUBTRACTION INTERVAL_SUBTRACTION%LOWER = A%LOWER - B%UPPER INTERVAL_SUBTRACTION%UPPER = A%UPPER - B%LOWER END FUNCTION INTERVAL_SUBTRACTION FUNCTION INTERVAL_MULTIPLICATION(A, B) ! POSITIVE NUMBERS ASSUMED TYPE(INTERVAL), INTENT(IN) :: A, B TYPE (INTERVAL) :: INTERVAL_MULTIPLICATION INTERVAL_MULTIPLICATION%LOWER = A%LOWER * B%LOWER INTERVAL_MULTIPLICATION%UPPER = A%UPPER * B%UPPER END FUNCTION INTERVAL_MULTIPLICATION FUNCTION INTERVAL_DIVISION(A, B) ! POSITIVE NUMBERS ASSUMED TYPE(INTERVAL), INTENT(IN) :: A, B TYPE(INTERVAL) :: INTERVAL_DIVISION INTERVAL_DIVISION%LOWER = A%LOWER / B%UPPER INTERVAL_DIVISION%UPPER = A%UPPER / B%LOWER END FUNCTION INTERVAL_DIVISION END MODULE INTERVAL_ARITHMETICSCompilation of the above results in the creation of the file

USE module_name, ONLY : list_of_chosen_routinesThe following is an example of a very simple main program for the test of interval arithmetics. It is from the file

USE INTERVAL_ARITHMETICS IMPLICIT NONE TYPE (INTERVAL) :: A, B, C, D, E, F A%LOWER = 6.9 A%UPPER = 7.1 B%LOWER = 10.9 B%UPPER = 11.1 WRITE (*,*) A, B C = A + B D = A - B E = A * B F = A / B WRITE (*,*) C, D WRITE (*,*) E, F ENDRunning this program on a Sun-computer with the NAG compiler results in the following output:

% f90 interval_arithmetics.f90 interval.f90 interval_arithmetics.f90: interval.f90: % a.out 6.9000001 7.0999999 10.8999996 11.1000004 17.7999992 18.2000008 -4.2000003 -3.7999997 75.2099991 78.8100052 0.6216216 0.6513762 % exitWe compiled the program with the compiler

In a module some concepts can be defined as `PRIVATE`, which means
that the program units outside of this module are not able to use this
concept. Sometimes an explicit `PUBLIC ` declaration is used, normally
`PUBLIC ` is default. The following statements

PRIVATE PUBLIC :: VAR1result in all variables being local, except

INTEGER :: IVAR PRIVATE :: IVARor as an attribute

INTEGER, PRIVATE :: IVAR

Solution.

(7.2) Generalize the modules so that the package produces a
suitable error message when it
divides by an interval that contains zero.

Solution.

(7.3) Extend the modules so that the local rounding error at the
operation is also appropriately dealt with. (This is not the case at the moment.)

Solution.

Last modified: 6 April 1999