1 Overview of Fortran 90

next up previous
Next: 2 Comparison of Fortran Up: PL Chapter Previous: PL Chapter

1 Overview of Fortran 90


The diagram in Figure 1 shows the major components of Fortran 90 [1],[2]. The size of each slice of this ``pie" is roughly proportional to the number of syntax rules needed to describe the features associated with that slice, and hence is a measure of the structural complexity of those features. (These measures should not, however, be taken as an indication of conceptual or semantic complexity nor of implementation effort-syntactic complexity may or may not be related to these other forms of complexity.)

Fortran 77
Fortran 90 is a super-set of Fortran 77-all standard Fortran 77 programs are standard Fortran 90 programs. Fortran 90 therefore encompasses and is completely compatible with the existing Fortran 77 computational science infrastructure.

Source Form
To Fortran 77's `fixed' source form Fortran 90 adds another source form, called `free' source form, in which there are no column dependencies. In free source form comments need not start in column 1 and column 6 is not reserved for continuation; continuation in free source form is indicated by a trailing ampersand, on the `first' line. In both source forms an exclamation point , `!', may be used to initiate end-of-line comments (e.g., following a statement on that line) and a semicolon may be used to separate two statements on the same line. As in Fortran 77, Fortran 90 names (of variables, procedures, etc.) begin with a letter and contain letters and digits; in addition, names may have up to 31 characters, may contain underscore, `_', characters, and may contain both upper and lower case letters.

Figure 1 Fortran 90. View Figure

Control Structures
Missing from Fortran 77 is a complete set of modern control structures (it has only IF - THEN - ELSE - END IF); this is remedied in Fortran 90 with the addition of DO - END DO and SELECT CASE - END SELECT control structures. The CASE construct, which has the form:
SELECT   CASE   (expression)
         CASE   (value-list)
         CASE   (value-list)
provides ``parallel" selection control. It offers no increase in semantic power over the IF (``sequential") selection control, but in situations where it fits the problem CASE offers computational advantages over IF because only one expression is evaluated.

The new DO construct is likely to be extremely useful in computational science applications. The reason is that, in order to realize the computational benefits of data parallelism, a great many indexed do loops will be replaced by array operations. The emphasis in the use of loops will therefore shift from processing arrays to indefinite repetition operations such as ``read-test-process" and ``while" repetition. The two new forms of DO construct added in Fortran 90 therefore are:

DO                                 DO WHILE (logical-expr) 
     ...                                   ...  
     IF (logical-expr) EXIT        END DO
Indexed loops may also be terminated with END DO, in which case the loop label is not needed. (Loop labels are permitted, however, in all three forms of DO construct.)

Numeric Processing
This will be discussed in detail in section 3. The main features in this category are the numeric representation model, many intrinsic functions that return useful model values, the numeric kind system, intrinsic functions that return kind values, and generic operations.

Array Processing
This will be discussed in detail in section 4. Array operations are one of the most significant aspects of Fortran 90.

Pointers provide two important capabilities in Fortran 90- dynamic data structures and dynamic arrays. The latter is especially important for computational science because it allows arrays to be dynamically allocated (and reallocated) of the proper size and provides a means to minimize data transfers when performing operations on variable array sections.

Because of the adverse impact that pointers have on optimization, a Fortran 90 pointer may point only to (a) a data object explicitly declared as a pointer target, (b) a dynamically created object, or (c) another pointer. This makes it possible for static storage optimization technology to be be applied to data that has neither the pointer nor target attributes.

Such pointers may be used for arrays whose sizes are determined at run time, such as dynamically allocated arrays; such arrays are declared as ``deferred shape" arrays, in which the rank is specified, and thereby fixed, but the extent in each dimension is unspecified and dynamic. These dimensions will be dynamically established later. The following examples illustrate such dynamic behavior. (The ``=>" is the Fortran 90 syntax for pointer assignment, and the ALLOCATE statement is used for dynamic allocation of storage.)

REAL, TARGET  :: B(100,100)          ! Array B has the target attribute.
REAL, POINTER :: U(:,:),V(:),W(:,:)  ! Declaration of 3 pointer arrays
U => B(I:I+2,J:J+2)                  ! U points to a 3x3 section of B.
ALLOCATE ( W(M,N) )                  ! Dynamically allocate W, size MxN
V => B(:,J)                          ! V points to the Jth column of B.
V => W(I-1,1:N:2)                    ! V changed to point to (part of) 
                                     !     the I-1st row of W.

Data Structures
Arrays are probably the most important composite data objects for computational science, but more heterogeneous objects are necessary, including dynamically linked structures. In the jargon of Fortran 90, structures are objects of user-defined type, discussed briefly next and in more detail in section 5 on page 50 and section 6 on page 50. Dynamically linked structures are provided by essentially recursive user-defined types:

This is an example of a type that could be used for a doubly-liked list structure. Recursive components (PREVIOUS and NEXT in this example) must be pointers. In general, a defined type may have any number and types of components.

   REAL                   :: DATA

User-Defined Types and Operators
User-defined types and operators, together with modules, give Fortran 90 an outstanding data abstraction facility and corresponding support for this aspect of object oriented programming. A user-defined type is defined with the TYPE - END TYPE construct, and objects are declared in a manner analogous to declaration of objects of intrinsic type. A simple example of a type definition and corresponding object declaration is as follows.
TYPE RATIONAL                         ! This defines the type RATIONAL.
TYPE (RATIONAL) :: X, Y(100,100)      ! X and Y are variables of 
      ! type RATIONAL.

This might be the type defined in connection with a complete rational arithmetic data abstraction. Such an abstraction requires, in addition to the type definition, an appropriate set of operator definitions. These are done by specifying operator interfaces for user-defined functions. The following example illustrates extending the ``+" operator to addition between objects of type RATIONAL.


More details on user-defined types and operators will be discussed in sections of the next release of this chapter.

To the Fortran 77 procedure facilities Fortran 90 adds the following new features: function results may be array-valued or structure-valued (or both), procedures may be recursive, arguments may be optional or intent-in (can't be changed in the procedure), procedures may be internal to other program units, and others.

An important concept new to Fortran 90 is that of an explicit procedure interface. This means that the interface of a procedure-that is, the data types and other characteristics of the dummy arguments and (if the procedure is a function) function result-is known at the point of call. Explicit interfaces provide a long list of benefits and capabilities; for example, a function result can be array valued if (and only if) the function interface is explicit where the function is called. Procedure interfaces may be made explicit by providing an interface block for the procedure or by placing the procedure definition internal to the calling program or in a module used by the calling program.

One of the most onerous sources of programming errors historically has been the mismatching of argument data types across procedure boundaries. Such errors, guaranteed to corrupt results, are among the hardest to debug. Use of explicit interfaces is simple and prevents this problem completely; this will likely be one of the most important practical applications of interface blocks.

Fortran 90 has a new kind of program unit, the module, that is neither part of Fortran 77 nor included in most pre-90 Fortran compilers. Because of this lack of implementation history, and because modules impose more sophisticated name management requirements on implementations, modules have triggered some controversy. When this dust finally settles, however, modules are likely to be generally accepted as one of the most important and useful features of Fortran 90.

Unlike main programs and external subprograms, modules are not themselves executable program units. Rather, they contain definitions that can be conveniently accessed and used by executable program units. For example, a module might contain interface blocks for a library of external procedures and be used to make the interfaces of these library procedures explicit in an application using that library. A likely growing trend is to repackage the entire library in a module-that is, to place all of the procedure definitions in a module (assuming the procedures can be written in Fortran)-which has the twin benefits to an application of making the procedure interfaces explicit without the need for interface blocks and giving the application developer a powerful tool for namespace management.

Data related uses of modules are just as important as procedure related uses. User-defined type definitions can be placed in a module and thus made available to the other program units of an application , and indeed this is the preferred way of packaging most type definitions. Data objects, of any type, kind, and shape can be declared in a module and thus become global data objects for an application using that module. This provides a non- storage-associated global data alternative to COMMON, which can be used where storage association is a problem (e.g., in distributed memory environments). Arrays in modules can be allocatable, thus providing a means of having dynamic arrays conveniently accessible to any of the program units of the application.

A module can simultaneously contain both data related and procedure related entities. One typical such application of a module is to package a data abstraction- that is, to contain a type definition, interfaces defining operators to be used in conjunction with operands of that type, and possibly even the procedures defining operations on that type. For example the type definition for RATIONAL and the extension of ``+" to RATIONAL addition illustrated above could be packaged in a module as follows:




 ...   ! and other stuff for a complete rational arithmetic facility

This sort of comprehensive use of modules for will be described in more detail in the next release.

Input and Output
Fortran 90 adds a few additional options to the comprehensive file connection capabilities of Fortran 77. One important example is the ACTION= open specifier, which allows a file to be connected as READ or WRITE or READWRITE. The major I/O additions in Fortran 90, however, are NAMELIST and nonadvancing I/O. NAME-LIST has long been included in many Fortran compilers; the standard has finally caught up to this common practice and has identified a standard form for NAMELIST from among the various existing versions. In addition to specifying a standard NAMELIST, its inclusion in Fortran 90 will insure that NAMELIST is available in all Fortran 90 compilers.

The other major I/O addition in Fortran 90 is nonadvancing I/O, which provides the functionality of reading or writing only part of a record. Recall that each formatted sequential READ or WRITE, the only form of I/O to which nonadvancing applies, in Fortran 77 causes (at least) one entire record to be read or written; that is, the file is always positioned between records after execution of a READ or WRITE statement. Non advancing I/O is different in that the file remains positioned after the last character transferred (effectively between characters in a record rather than between records)- a nonadvancing READ does not ``skip" to the end of the record and a nonadvancing WRITE does not terminate the record (i.e., does not write an end-of-record mark). The next READ or WRITE on that file starts where the last one left off. Nonadvancing I/O is specified by including ADVANCE='NO' in the control list of the READ or WRITE statement. For example, the following nonadvancing READ statement could be used to obtain the next character from the input terminal:


Other forms of input/output considered for Fortran 90, but then not adopted, were asynchronous and parallel I/O and a variation of keyed access. Nor is there any direct database support in Fortran 90, though Fortran bindings exist to modern database facilities such as the structured query language (SQL) standard.

Obsolescent Features
Fortran 90 includes a first step toward a model for planned language evolution as opposed to unbalanced growth or ad hoc removal of features. As with most first steps, this one is small, tentative, and with an as-yet unsure outcome. The idea is to ultimately remove those features that become obsolete as the language evolves, but to officially identify such candidates as ``obsolescent" (in the process of becoming obsolete) well in advance of actual removal. This is intended to give the Fortran community (a) a chance to review the recommendations and prevent mistakes from being made and (b) time to prepare for the change in an orderly way. According to the current model, a feature listed as obsolescent in one version of the Fortran standard is a candidate for removal from the next version.

The following ten features of Fortran 90 are listed as obsolescent:

the arithmetic IF
real (and double precision) DO index variables and expressions
shared DO termination (i.e., two loops terminating on the same statement)
DO loop termination on other than END DO or CONTINUE
branching to an END IF statement from outside that IF construct
alternate return (use a return code variable instead)
the PAUSE statement ( use READ instead)
ASSIGN and assigned GOTO statements (use internal procedures instead)
assigned FORMAT specifiers (use character strings instead)
the H edit descriptor

next up previous
Next: 2 Comparison of Fortran Up: PL Chapter Previous: PL Chapter