F95 Reference
F95 Reference
Concise Reference
Jerrold L. Wagener
ISBN
Table of Contents
F o r t r a n 9 0 /95 C o n c i s e R e f e r e n c e
Contents
Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
1
2
Program Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
program units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Intrinsic Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
integer data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
real data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
complex data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
logical data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
character data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
save . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
numeric computations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
character computations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
implicit declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
User-defined Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
derived-type definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
derived-type objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
structure constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
derived-type operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
private types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
sequence types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
ii
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
array-valued expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
conformability and element-by-element computation . . . . . . 26
array constants - array constructors . . . . . . . . . . . . . . . . . . . . 27
masked array assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
assumed-shape dummy arguments . . . . . . . . . . . . . . . . . . . . 30
array elements and sections . . . . . . . . . . . . . . . . . . . . . . . . . . 30
dynamic arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
array-valued functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
example - picture refinement . . . . . . . . . . . . . . . . . . . . . . . . . 36
example - Gaussian elimination . . . . . . . . . . . . . . . . . . . . . . . 37
Redundancy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
common blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
attribute statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
block data program unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
deprecated features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
inputting data (read) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
outputting data (write) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
data formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
opening and closing files . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
file inquiry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
sequential and random files . . . . . . . . . . . . . . . . . . . . . . . . . . 56
partial-record (nonadvancing) I/O . . . . . . . . . . . . . . . . . . . . . 57
list-directed and name-directed I/O . . . . . . . . . . . . . . . . . . . . 60
Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
if construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
case construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
do construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
goto statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Table of Contents
8
9
10
11
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
module structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
module use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
module applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Procedures 75
subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
host association . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
procedure arguments and argument association . . . . . . . . . . 79
interface blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
generic procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
return statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
statement functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
entry statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
intrinsic procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Intrinsic Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Syntax Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
general structure (R201-216) . . . . . . . . . . . . . . . . . . . . . . . . 109
tokens (names, operators ...) R301-313 . . . . . . . . . . . . . . . . 112
data types (R401-435) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
declarations and attributes (R501-549) . . . . . . . . . . . . . . . . 115
variables (R601-631) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
expressions (R701-743) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
control structures (R801-844) . . . . . . . . . . . . . . . . . . . . . . . 122
input, output (R901-924) . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
I/O formatting (R1001-1017) . . . . . . . . . . . . . . . . . . . . . . . . 126
program units (R1101-1112) . . . . . . . . . . . . . . . . . . . . . . . . 127
procedures (R1201-1226) . . . . . . . . . . . . . . . . . . . . . . . . . . 128
iii
iv
12
Preface
Preface
Fortran has been the principal programming language of the scientific community since
the mid-1950s and has evolved over that time. The 1978 standard version, called Fortran
77, saw extremely wide use. Fortran 90 is the next step in the evolution of Fortran; it supports all of the features of Fortran 77 as well as many new ones which can make programming easier and more efficient. The purpose of this book is to provide a concise yet
complete reference for Fortran 90.
Though there are numerous examples, this reference is neither a programming nor Fortran
90 tutorial; it assumes some familiarity with Fortran 77 programming. Though focusing
mainly on standard Fortran 90, a separate chapter on the Absoft implementation of Fortran
90 describes implementation-specific features, including extensions to support interoperability with other languages and to facilitate porting of extended Fortran 77 legacy code.
vi
Chapter 7 describes the Fortran 90 control structures. To the Fortran 77 if construct are
added: a case construct and three modern loop constructs (do while, do forever with exit, a
modern form of the indexed do).
Chapter 8 describes the Fortran 90 module program unit and its uses. This is a major addition to Fortran and provides flexible software packaging, complete with information
hiding (public, private) capabilities.
Chapter 9 describes the Fortran 90 procedure facilities. Much of this will be familiar to
Fortran programmers, but there are some significant features new in Fortran 90. These
include explicit procedure interfaces, user-defined generic procedures, module and internal procedures, and operator definition.
Chapter 10 summarizes Fortran 90's 113 intrinsic procedures. These include, in addition to
the traditional numeric and character computational functions, numeric environmental
inquiry functions, array-processing and inquiry functions, bit-processing procedures, a
few intrinsic subroutines.
Chapter 11 is the complete BNF for Fortran 90, extracted from the Fortran standard. This
is the rigorous description of the Fortran syntax, and this reference relies very heavily on
it; in many cases reference to the syntax rules in chapter 11 is the extent to which the syntax is described, with the text devoted primarily to describing the semantics and constraints related to the syntax.
Chapter 12 describes various implementation-specific values (e.g., kind values), options
(e.g., compiler options), and extensions in the Absoft implementation of Fortran 90.
This reference is intended to completely describe all of Fortran 90, but being concise it
may give short shrift to some of the more subtle details of the language. The recommended sources to pursue these details are the following:
1. The Fortran standard. A committee draft of the version of the Fortran standard currently under development is available on the Fortran standard committees web site,
http://www.ionet.net/~jwagener/j3. As of this writing standing document J3/007 is the
working draft of the Fortran 2000 standard, a very substantial subset of which is the
official definition of Fortran 90 (less five of the deprecated Fortran 90 features);
because of copyright restrictions the Fortran 90 standard cannot be posted publically.
2. The Fortran 90 Handbook, by Adams, Brainerd, Martin, Smith, and Wagener. This
book was published by McGraw-Hill in 1992, and is an exhaustive, 740-page reference on Fortran 90; its chapter organization is the same as the Fortran 90 standard and
it was intended as a readable version of that standard.
Jerry Wagener
June 1998
[email protected]
Program Structure
Program Structure
This concise reference to Fortran 90 summarizes all aspects of the language in a crisp,
concise manner. This reference is neither a programming nor Fortran 90 tutorial; it
assumes some (but not extensive) familiarity with Fortran 77 programming concepts.
This chapter summarizes various "structural" aspects of a Fortran 90 program: source
form, program units (e.g., procedures, modules), "parts" (e.g., specification part, execution
part), etc. It also indicates how to read the formal syntax rules (BNF) used throughout.
syntax
Chapters 1-9 rely heavily on, and make frequent reference to, chapter 11, which is a complete BNF description of Fortran 90; while there are numerous examples of syntax
throughout, this reference primarily lets syntax rules (each with an R number) of chapter
11 "do the talking" for a complete and rigorous account of the Fortran 90 syntax. The various chapters describe the associated semantics; no semantics are omitted, though some
(especially those related to the "deprecated" features) are indeed brief.
The characteristics of the formal BNF of chapter 11 are summarized at the beginning of
that chapter. A somewhat more informal form often will be used in chapters 1-9 in describing a feature. For example: a Fortran 90 programmer-defined name is (R304):
letter [ name-character ] ...
Square brackets ([ ]) indicate optionality and square brackets followed by three dots ([ ] ...)
indicate optionally repeated any number of times. Constraints (like the 31 limit for name
lengths) will be mentioned. In those cases where the language imposes no constraints, an
implementation might. To take an extreme example, the internal subprogram part of a
function (say) may contain, according to the BNF, [ internal-subprogram ] ... without limit;
clearly no contemporary implementation could cope with a function having ten trillion
internal functions, even if the programmer could (!?).
Chapters 1-9 will contain a number of short, illustrative examples. The predominant style
in these examples will be: keywords in all lower case (if, end), procedure and variable
names starting with a lower-case letter (x, midPoint), main program, module, and derivedtype names starting with an upper-case letter (HelloWorld, RangeArithmetic), constants in
all upper case (N, QUAD), "free-form" source (described below), and modest indentation of
internal structure. A (nonsense) example is:
program HelloWorld
use RangeArithmetic
real(QUAD) :: X(N)
type(Range) :: m1=Range(0,6)
x(1) = midPoint(m1)
! nonsense example
! this program uses a module
! a "quad-precision" array
! variable of user-defined type
There are no column restrictions in free-form source, except that lines have a 132 character limit, and an exclamation point (!) initiates an end-of-line comment (from where it
begins to the end of that line). Blanks must be used to separate keywords and names (e.g.,
the blanks are significant in program HelloWorld and use RangeArithmetic above); the other
blanks in the above example are used for purposes of readability, not because they are syntactically required by the language)1. The above program is syntactically legal Fortran 90
if (and only if) a module named RangeArithmetic exists and it defines integer constants N
and QUAD, a derived-type named Range, and a real (or integer) function named midPoint
that takes an argument of type Range.
Every Fortran program is a set of program units, each of which is a sequence of statements
- the above example has nine statements, each on a separate line. This is the normal pattern, but there are two other aspects of free-form source, both used occasionally, but sparingly, in subsequent examples: (1) two (or more) statements can appear on the same line,
separated by a semicolon (the second statement can be null if you want to simulate the C
style of ending a statement with a semicolon); (2) a statement can be continued on the next
line by ending the (first) line (before any end-of-line comment) with an ampersand (&).
program units
A Fortran program is a set of (related) individual program units (R201), consisting of one
main program (R1101), zero or more external subprograms (R203), zero or more modules
(R1104), and zero or more block data units (R1110). The Fortran standard does not specify "where" these parts reside on a computing system, but typically one or more complete
units are placed in a file; each such file is a separately-compiled compilation unit. The
order of compiling such compilation units is normally immaterial, except that a module
must be compiled before any units using that module, and the main program should be
compiled last if an executable program is to be prepared therefrom. (For small programs
everything can be placed in one file, with the modules first and the main program last.)
1. In Fortrans original fixed-form source (see chapter 5) blanks are never significant (e.g.,
never required) except in character strings, but blanks could be used freely for improving readability. Blanks could even be used within keywords and names; for example:
integer could be written int eger. In free-form source blanks are significant (token
delimiters) and must not be used within a keyword, name, or constant (except character
constants), and (one or more) must be used to separate (delimit) consecutive keywords
and names. The exceptions to this rule are that the separating blanks are optional in the
following keyword sequences: block data, double precision, else if, go to, in out, select case,
and all that start with the word end. The nonletter nondigit characters serve as delimiters
and blanks may be freely used with (on either side of) them.
Program Structure
A large program unit can be spread across multiple files and put back together with
include lines in a compilation unit. The include line, which is not a Fortran statement (but
rather a compiler directive), has the form include file-name and cannot have an end-of-line
comment; during compilation the compiler replaces the include line with the contents
(e.g., common block definitions) of the specified file. With the advent of modules in Fortran, there are not many situations in which the include line is needed.
Execution of a program begins with its main program, which may call procedures defined
in external subprogram units and modules to perform computations. In addition, modules
may provide the main program (or any of the procedures it calls) with various global
entities, such as global constants and variables, type definitions, and procedure interfaces.
Ignoring the (unnecessary and not recommended) attribute statements (R519-538) - see
chapter 5 - the eight sections of these program units are as depicted in the following diagrams.
main programs
statement (R1102)
program
use
implicit
specifications a
(R422, R1201, R501)
contains
end
external subprograms
function statement (R1216) or
subroutine statement (R1219)
statement (R1105)
statements (R1107)
statements (R540)
see noteb
statement (R1225)
statement (R1103)
a. Section 4 may also contain common (R548), data (R529), equivalence (R545), namelist (R543), and
save (R523) statements; format statements (R1001) may be included in sections 3-5 of main
programs and external subprograms, and entry statements (R1223) may be included in parts 3-5 of
external subprograms and part 7 of modules (but not in part 7 of main programs and external
subprograms).
b. Module program units do not have section 5.
c. Internal subprograms must not contain internal subprograms (but module subprograms may).
Sections 1 and 8 define the beginning and end of the program unit, and are the only sections that are not optional. Section 2 provides the program unit access to any modules it
uses. Section 3 modifies the implicit environment (or replaces it with implicit none). Section 4 is the heart of the specification part of the program unit; it is here that all the local
constants and variables are declared and any derived types and interface blocks not pro-
vided by modules are defined. Section 5 is the execution part, which represents the primary computation part of the program unit; note that modules do not have an execution
part (they are intended as a source of definitions used by other program units). Section 6 is
a keyword that marks the beginning of any internal or module subprograms (section 7);
sections 6 and 7 go together - if one is present the other must be also. Each internal or
module subprogram has the same structure as an external subprogram, except that internal
subprograms cannot themselves contain internal subprograms. Note that a module may
access other modules (and pass their definitions on to other program units using that module).
statements
A Fortran statement is made up of keywords, names, expressions, and delimiters. Keywords are predefined words that have some special meaning; most statements start with a
keyword (e.g., print, end, integer, function, etc.). Names are programmer-defined, as
described above, and are used to give unique identifiers to variables, constants, procedures, modules, etc. Expressions are the computational engines that generate computed
results; they are formed from operands and operators. Operands include constants, variables, and function calls, and are described in the next chapter and in other appropriate
places throughout; operators are either special characters (+, -, *, **, /, //, ==, /=, <, <=, >, >=)
or letters enclosed in periods (.eq., .ne., .lt., .le., .gt., .ge., .and., .or., .eqv., .neqv., .not., and
user-defined operators, R311).
Delimiters include blanks (as described above), = (for assignment - see below), % (structure component selector, R612 and chapter 3), left and right parentheses (multiple enclosing uses), single and double quotes (character constant delimiters - see chapter 2), the
comma (list separator), : and :: (other separators), ! (comment initiator), & (statement continuation), and the semicolon (statement separation).
The only statements that do not begin with a keyword are the assignment statement (R735)
and the statement function (R1226), which have similar forms; the statement function is
described in chapter 9. The assignment statement has the form
variable = expression
and has the purpose of saving the value of a computation (expression) so that the value can
be used in subsequent computations. The variable (R601-602) is where the value of the
expression (R723) is saved (the previous value of the variable is replaced); the variable may
be a scalar variable name, an array variable name (for results of an array expression - see
chapter 4), an array element, an array section (see chapter 4), a structure component (see
chapter 3), or a substring (see chapter 2). Normally the type and kind of the variable must
be the same as the type and kind of the expression value, but this rule is relaxed when
numeric values are involved (see chapter 2). The expression can represent an arbitrarily
complex computation involving operators and operands; the main features of expressions
are described in chapter 2, with expressions involving user-defined types in chapter 3 and
whole arrays (and array sections) in chapter 4.
Fortran 90 has built-in (intrinsic) data types and user-defined (derived) data types; the
latter are described in the next chapter. The intrinsic data types may be categorized as the
numeric types (integer, real, and complex) and the nonnumeric types (character and logical). Each of these may have any number of kinds, though an implementation need provide
only one kind of integer, character, and logical, and two kinds (single and double precision) of real and complex. Typical additional kinds that an implementation may provide
are long and short integers, quad precision for real and complex, additional national
character sets (the default character kind is essentially ASCII), and one-bit (or one-byte)
logically. Arrays of any of these intrinsic type/kinds are permitted, with full array operations appropriate for that type.
The kinds are specified by integer constants called kind type parameters, and allow types
to be parameterized. Thus a given program can, for example, be run with some set (or
all) of the real variables having single precision; on another run these variables could be
double precision. Across procedure boundaries both the type and type kind parameters of
associated actual and dummy arguments must match, and thus kind mechanism can be
used to provide families of generic procedures in procedure libraries. Each type has a
default kind that is used for variables for which a kind type parameter is not explicitly
declared; for example, the default real (and complex) kind is single precision and the
default character kind is (essentially) ASCII.
integer data type
The integer type is intended to represent integer numeric values, and as such is modeled
by v = sdiri, 0i<n, where for integer value v, s is the sign (+1 or -1), r is the radix (see
intrinsic function radix), n is the number of digits (see intrinsic function digits), and the ds
are digits in the base-r system.
An integer constant is specified with decimal digits, with an optional sign (+ or -) and an
optional kind parameter (R403). Examples of integer constants are:
42
135843_LONG
-687
The second of these examples illustrates how the kind parameter is specified for constants
(attached to the value by the underscore); in this case LONG is a named integer constant
having a valid kind value provided by the implementation. (See the intrinsic functions
kind, and selected-int-kind to determine the implementations kind values for integers and
see the intrinsic functions range, huge, and tiny to determine the range for any integer
kind.)
The usual operations are provided intrinsically for two integer operands: addition (+), subtraction (-), multiplication (*), division (/), and exponentiation (**). Such operations all produce (the usual) integer results, the only potentially surprising one being integer division,
which results in the truncated arithmetical result. Plus (+) and minus (-) may also be used
as unary operators with integer operands with the usual results. The other intrinsic operations on integers are the relational operators ==, /=, <, <=, >, >= (or, equivalently, .eq., .ne.,
.lt., .le., .gt., .ge.) for comparing two integer values. Respectively, these operations result
in the logical value .true. if the first integer operand value is equal to, not equal to, less
than, less than or equal to, greater than, or greater than or equal to the second integer operand value, and .false. otherwise. Examples of operations involving integer operands are:
j+k
j-k*n
! evaluated as j - (k * n)
(j - k) * n
j-k+n
! evaluated as (j - k) + n
-j+k
! evaluated as (-j) + k
-(j + k)
-j*k
! evaluated as -(j * k)
(-j) * k
j/k*n
! evaluated as (j / k) * n
j / (k * n)
k ** n
j<k
j+k>n-m
! evaluated as (j + k) > (n - m)
Note that parentheses may be used in the usual way to specify evaluation order in expressions containing multiple operations. The usual default precedence (e.g., left-to-right and
multiplication-before-addition) is used in the absence of parentheses, and the numeric
operations take precedence over the relational operations. See R723 for a rigorous description of the precise rules for evaluation of expressions involving integer operands. Additional (user-defined) operations may be provided for integers - see chapter 9.
Though (arguably) Fortran does not provide an intrinsic bit data type (but see the logical
type) a complete bit processing facility is provided via integer objects and intrinsic procedures btest, iand, ibclr, ibits, ibset, ieor, ior, ishft, icshft, mvbits, and not. These provide bitby-bit operations on non-negative scalar integer values represented by binary digits (bits)
according to the model v = bi2i, 0i<m. Integer constants may, alternatively, be specified or printed as a set of binary digits, octal digits, or hexadecimal digits, in accordance
with R407, and R1005. The rightmost bit in the integer object is b0 and, for example, the
integer value 13 (or B"1101" or O"15" or Z"D") represents the bit string . . . 0001101.
! value is 26,000,000.0
4.3
-22.9E22_QUAD
.123
123.
7E4
7D4
-1.1D-3
The fourth of these examples illustrates the use of a kind parameter in a real constant QUAD is a named integer constant having a valid kind value provided by the implementation for reals. As mentioned above, an implementation must provide at least two kinds of
real, informally known as single and double precision. (See the intrinsic functions kind
and selected-real-kind to determine the implementations kind values for reals.) Note that,
unlike for integers, a real constant may not be representable exactly; for example the real
constant 0.1, though within range for (most) real types, is not representable exactly in a
binary implementation (that is, one for which r=2 - e.g., the IEEE floating point standard).
Exactly the same intrinsic operations as for integers are provided for real operands, with
the same meanings, except that division works normally. Because of the potential noted
above for inexact representation of real values, the equality relational operators (== and /=)
may at times yield unreliable results and thus should be used with care (if at all) with
real operands. As for integers, see R723 for a detailed descriptions of the syntax and
semantics (precedence) of expressions involving intrinsic operators with real operands,
and see chapter 9 for expressions involving user-defined expressions with real operands.
The last two examples above are double precision constants; using the D (instead of E or
neither) makes the constant the double precision kind of real rather than the (default) single precision kind. The data type double precision (R502), before the advent of the kind
concept in Fortran, was the only way that double precision objects could be declared. The
double precision type is still available, but is now deprecated in favor of real(kind(1D0));
double precision and real(kind(1D0)) represent identical type/kind combinations.
complex data type
The complex type is intended to represent complex numeric values, and as such is an
ordered (real part, imaginary part) pair of reals; there is a complex kind for every real kind.
A complex constant comprises values for the real part and imaginary part, separated by a
comma and enclosed in parentheses, as described in R417. Note that integers may be used
for these values, in which case they are converted to the equivalent real value; different
kinds of reals may be used for these two values, in which case the one with the lower kind
value is converted to the equivalent value of the other kind; the kind of the complex constant is the kind of the parts (after any conversion). Examples of complex constants are:
( 1.0, -1.0 )
( 5, 5.5E5 )
( -3.3_QUAD, 4.4_QUAD )
The complex type has the same intrinsic numeric operators (+, -, *, /, **) as the other
numeric types, with the usual meanings. However, since complex values do not have a natural ordering, the equality operators (== and /=) are the only intrinsically defined relational
operators for complex. Because comparison of complex values involves comparison of
real values, the same comparison caveat applies to complex values as to real values.
Though intrinsic meanings for <, >, etc., are not provided for complex, an application may
provide such meanings as user-defined operators - see chapter 9.
Intrinsic functions real and aimag return the real and imaginary parts, respectively, of a
complex argument. Function conjg returns the complex conjugate of a complex argument,
and function cmplx allows construction of a complex value of any kind from any integer or
real values (e.g., any integer or real expressions, not just constants) and conversion of
complex values to different complex kinds. Intrinsic function int converts any integer, real
or complex argument to any kind of integer value, and function real converts any integer,
real or complex argument to any kind of real value.
logical data type
The logical type is intended to represent boolean (true, false) values. A logical constant is
either .true. or .false., optionally appended with a kind parameter, as described in R421. A
default logical value is defined to require the same storage (most often 32 bits) as a default
integer value and a default real value (both of which, by definition, require the same
amount of storage - this unit of storage is called a numeric storage unit). The role of different kinds of logical is to allow for different amounts of storage (usually less) for logical
values than is required for default logical values. One bit is adequate for representing a
true/false (1/0) value, though one byte (8 bits) is often used as well. A logical kind in
which exactly one bit is used to represent a logical value has many of the properties of a
bit data type (especially in the form of logical operations on logical arrays).
There are four intrinsic binary operators that take logical operands (.and., .or., .eqv., .neqv.)
and one unary operator (.not.). The results of these operations are shown in the following
table, where T stands for .true. and F stands for .false.
x=T
x=F
x=T
x=F
x=T
x=F
x=T
x=F
y=T
y=F
x .and. y
x .or. y
x .eqv. y
x .neqv. y
.not.y
Note that relational operations on numeric values result in logical values, which can then
be used as operands in logical operations; for example: x < y .and. y < z (meaning x<y<z).
character data type
The character type is used to represent and process character strings. Character values may
be any length, from one character to an implementation-defined (usually pretty large)
number of characters. Arrays of character strings are allowed, but each element of such an
array has the same length (same number of characters). Each character may be any one of
the characters in the implementation-defined character set (the default character kind),
which is often a subset or superset of ASCII. An implementation may provide additional
character sets, with different character kind parameters; this is often used to support
national character sets (e.g., kanji, greek, cyrillic, etc.).
A character constant is simply a character sequence delimited by (single or double) quotes
and optionally preceded by a kind parameter (R420). A (single or double) quote delimiter
may be included in a character constant by repeating it once. Examples of character constants are:
"now is the time"
'x'
GREEK_""
"He said ""OK"", and left."
! "OK" in quotes
There is just one intrinsic character operator, the concatenation operator (//); it appends the
second operand to the first, forming a longer character string:
"blue" // "whale"
! results in "bluewhale"
10
There are a number of intrinsic procedures that are very useful for a wide range of character processing, including the following functions: len, index, trim, adjustl, scan, etc. Two
such functions, char and ichar, provide conversion between characters and integers. The
characters have a collating sequence, which is a one-to-one mapping between the characters and (a subset of) the integers. Function char takes an integer argument and returns the
character associated with that integer value in the collating sequence; function ichar does
the reverse, returning the collating-sequence integer associated with the character argument.
declarations
Making a specific variable name have a specific type is known as a data object declaration,
type declaration, or just declaration for short. Declarations are used as well to establish
named constants and to type function results. The simplest form of a type declaration
(R501) is:
type-spec [ :: ] object-list
where type-spec (R502) is, for intrinsic types, the type name (integer, real, complex, logiwith an optional kind specification and, for character, an optional length
cal, character)
The :: is optional, but it makes a nice visual barrier for the more complicated declarations
(to be described below) and so will be used consistently in examples henceforth. The kind
parameters (SHORT, QUAD, GREEK) are named integer constants; the actual integer values
could be used in place of the named constants, but since kind parameter values are not
standardized, and differ from implementation to implementation, the better practice is to
have the actual value appear only once - where the named constant is defined. If the kind
value DOUBLE has the appropriate integer value, the fifth example above is equivalent to
using (the deprecated) type name double precision (without a kind specification). The
11
same declaration is obtained by using real(kind(1D0)) instead of real (DOUBLE), and indeed
the value of DOUBLE could have been specified, in its definition, as kind(1D0).
All of the objects in a character type declaration have the length specified in the type-spec,
unless overridden as illustrated by s3*30 in the next-to-last example above; s1 and s2 both
have length 20, while s3 has length 30. If the length specification is omitted, the value 1 is
assumed; if the length is omitted and the kind is not, then the kind= keyword must be used;
if both the length and kind are specified, with kind first, both the kind= and len= keywords
must be used; otherwise the kind= and len= keywords are optional (and the kind= keyword
is always optional in declarations of the other intrinsic types).
The above examples declared uninitialized scalar variables. The following examples illustrate how array objects can be declared and how objects (scalars or arrays) can be given
initial values.
integer :: i, j(10)
! j is an array of 10 elements
integer(SHORT) :: k=0
real(QUAD) :: eps=0.000001
real(DOUBLE) :: p=0D0, q2
Arrays can have up to seven dimensions, the specification of which are enclosed in parentheses, and separated by commas; each has the form [ lower : ] upper, where lower and
upper are integer values which specify the lower and upper bounds of the subscript range
for that dimension; if the optional part is omitted, the lower bound is 1. Arrays are
described in detail in chapter 4, together with additional forms of array declaration (for
dynamic and dummy argument arrays).
An initial value is specified by an initialization expression, which can by any expression
(of an appropriate type) involving only constant values, with the following two exceptions:
(1) operators must be intrinsic operators and any exponentiation operator (**) must have a
second operand of type integer; (2) a procedure call must be to an intrinsic function that
(a) can be evaluated at compile type and (b) except for the reshape, transfer, and inquiry
functions, have arguments only of type integer and character and deliver a result only of
type integer or character. A variable local to a procedure may be initialized, but that initialization is effective only at the first execution of the procedure and the variable, though
saved (see below) is not reinitialized at the beginning of subsequent executions.
12
attributes
The properties of data objects are called attributes; the most basic attribute, one that every
data object has, is type (and kind). The other attributes are optional and the two illustrated
above are the array (dimension) attribute and the initial value (data) attribute. There are 11
more attributes, the specification of which requires either the attribute form of the type
declaration statement (R501, R503) or a separate attribute-oriented statement for each
such attribute (R519-539). The attribute form of the type declaration statement is
type-spec , attribute-list :: object-list
The attribute-list can contain any of the attributes listed in R503, in any order, separated by
commas; but any given attribute can appear at most once in the list, and over half of them
are mutually exclusive (see the following table).
n
tio
liza
initialization
public
private
external
intrinsic
intent
optional
allocatable
dimension
pointer
target
save
ia
nit
c
bli
pu
te
a
riv
al
rn
te
ex
ic
ns
ri
int
en
int
na
o
pti
le
tab
a
loc
al
sio
n
me
di
er
int
po
ge
tar
t
ve
sa
parameter
Attributes public and private control the visibility of module objects and are described in
Chapter 8. Attributes external and intrinsic specify objects that are either external or intrinsic functions, respectively. Attributes intent and optional apply only to procedure dummy
arguments (see chapter 9). Attributes allocatable and dimension apply to arrays and are
discussed in chapter 4. Attributes pointer and target are used for dynamic structures,
including dynamic arrays, and are discussed in chapters 3 and 4.
13
save
The save attribute is used to retain an objects value when the object goes out of scope
and then comes back in. One example of this is local variables in a procedure; upon return
from the procedure, its local variables normally cease to exist, the space may be reallocated for another purpose, and the variables are reinstantiated when the procedure is next
executed. However, any such variable with the save attribute remains intact with its value
unchanged between executions of the procedure, ready to take up where it left off when
the procedure is next executed. Initialized variables (and named constants) automatically
have the save attribute. A module variable goes out of scope and, without the save
attribute, becomes undefined whenever all program units using that module are inactive
(i.e., not executing). Similarly the save attribute is used to retain a common block and its
variable values when all program units using that common block are inactive.
parameter
A data object with the parameter attribute must also be initialized, and that value cannot be
changed - the object is a constant; it has a name and looks like a variable, and thus it is
called a named constant. Named constants are declared identically to initialized variables,
but with the parameter attribute. Named constants may be scalars or arrays, of any type,
and are extremely important to reliable programming. A constant that appears more than
once in a program, such as an array bound value or a kind parameter, should be a named
constant, and then when a change is needed in that value the change can be made in only
one place.
Examples of declarations with specified attributes are:
integer, parameter :: DOUBLE=kind(1D0)
real(DOUBLE), parameter :: PI=3.141592653589793
integer, private :: maxCount
complex, save :: z0=(1.0,-1.0)
real, allocatable, save :: workArray(:,:)
character(40),dimension(100) :: firstName, lastName, address1, address2
real, intent(in) :: length, width
logical, optional :: codeFlag
type(Tree), pointer :: left, right
real(DOUBLE), target, dimension(400,500) :: rho1, rho2, vel_x, vel_y, vel_z
complex, external :: f1, f2
complex, pointer :: temp(:)
logical(BIT), target, intent(out) :: digitalRadar
14
numeric computations
As mentioned in chapter 1, computations are formulated as the results of expressions;
these results can then be assigned to variables, written (to the screen, the printer, or a file),
used as actual arguments in procedure calls, or used for control purposes (a logical expression as an if condition, ann array subscript, an integer expression as the final index value in
an indexed loop, etc.). In many respects, numerical expressions are the heart of Fortran
and, in addition to the four numerical types (counting both of the required real kinds) and
the numerical intrinsic operators, Fortran provides most of the elementary numerical functions and the basic vector and matrix computations as intrinsic functions. In addition, the
facilities for providing user-defined computational libraries is very powerful.
Individual expression operands are defined in R701 and include constants (including
named constants), variables (scalars and array elements), function calls, and subexpressions (expressions in parentheses). R723 defines expression structure in detail, including
operator precedence. Without the operator precedence, R723 boils down to this:
[ unary-operator ] numeric-operand [ binary-operator numeric-operand ] ...
The binary-operator precedence determines the execution order, but this can be controlled
with parentheses - that is, by making each operand a (parenthesized) subexpression, leaving only one binary-operator at the top level; unparenthesized expressions are evaluated
as if the parentheses needed to represent the operator hierarchy had been added. For
numeric expressions the operators are power-op (R708), mult-op (R709), add-op (R710),
and unary and binary user-defined operators (R704, R724) delivering numeric results.
Note that R705-707 indicates that exponentiation, **, (power-op) has precedence higher
than any other numeric operator and works right-to-left for consecutive (unparenthesized)
power-ops (R705); multiplication and division (*, /), both mult-ops, have the same precedence, which is higher than addition (+), and subtraction (-), both add-ops, and work leftto-right (R706); additional and subtraction also work left-to-right (R707).
If a numeric operation has two operands with the same type and kind, it delivers a result of
that type and kind. Otherwise, the operation is mixed-mode, and one of the two operands (xw) will have a type/kind combination that is wider than that of the other operand
(xn); in this case the value of xn will be converted to the equivalent value in the xw number
system, the computation will be made at the xw type/kind level, and the result will have the
type and kind of xw; operand value conversion is performed as described below for mixedmode assignment. Any operand of type real is wider than any operand of type integer, and
any operand of type complex is wider than any operand of type real. Of two integer kinds,
the one having the greater integer range is the wider; normally this one will have the
greater kind value as well. Of two real (or complex) kinds, the one having the greatest precision is the wider; normally this one will have the greater kind value as well. By this rule,
double precision real/complex is wider than default (single precision) real/complex.
In numeric assignment, v=e, the variable v and the expression e can be any combination of
the numeric types (integer, real, complex). The value assigned is cf (e,kind(v)) where cf is
the intrinsic conversion function int, real, or cmplx, depending on whether v is type integer,
real, or complex, respectively.
15
character computations
Character expressions (with intrinsic operators) are all of the form:
character-operand [ // character-operand ] ...
There are no intrinsic character unary operators, and concatenation (//) is the only intrinsic
character binary operator. Concatenation works left-to-right, but it doesn't matter since
concatenation is associative (A//(B//C) has the same result as (A//B)//C). The length of a concatenation result is sum of lengths of the two operands.
Character operands can be character constants, character variables (including character
array elements), functions delivering character results, character expressions in parenthesis, and substrings (R609-611). The form of a substring is:
parent-string ( [ lower ] : [ upper ] )
where a parent-string can be a scalar character variable, a character array element, a character component of a structure, or a character constant; it cannot be a general character
expression, a character functional call, or substring itself. Lower and upper, which may be
arbitrary integer expressions, define the portion of the parent string that comprises the substring; both lower and upper must have values greater than zero and less than or equal to
the length of the parent string. The length of the substring is upper-lower+1 (actually,
max(0,upper-lower+1)) and comprises the characters from index lower in the parent string
up to and including index upper. If lower==upper, then the substring is just one character that at index lower (or upper); if upper is less than lower then the substring is empty (has
length zero). Examples of substrings are:
s2(2:5)
lastName(k:)
address(i-1:index(address,'-'))
account % name(i:j)
The result of a character expression may, among other uses, be assigned to a character
variable (including an array element) of the same kind or to a substring of such a variable.
In either event the expression has a length (number of characters it produces) and the
receiving variable has a length (number of characters it receives). If these lengths are the
same, then the expression result becomes the value of the receiving variable. If the expression length is less than the receiving length, the expression result is padded on the right
with the requisite number of blank characters so that the two lengths are the same and then
the assignment is made; if the expression length is greater than the receiving length, the
expression is truncated on the right to the receiving length, and then the assignment is
made. Examples of character assignment are:
s1 = s1(1:4) // s2(5:)
s2(2:5) = "."
firstName(k+1) = firstName(n)
16
implicit declaration
Unless implicit none is specified at the beginning of the program-unit (R205, R540), it is
possible to use variables in the program that have not been explicitly typed in type declaration statements. Such variables will have the types specified by the implicit type environment in effect and are said to be implicitly typed. Such variables may be given other
attributes with attribute-oriented statements (R519-539).
The implicit type environment associates a type/kind combination to each letter. A name
not explicitly typed is implicitly typed according to its first letter. The default implicit type
environment is that letter I-N are associated with type default integer and all others are
associated with type default real. implicit statements (R540-542) may be used to change
these associations for some or all of the letters, and this may include implicitly typing for
the nondefault kinds and for user-defined types. implicit none is a special form of implicit
statement that turns off all implicit typing and requires that each data object be explicitly
typed. implicit none is not the default implicit environment (unfortunately); unless implicit
none is explicitly specified in the program unit, each letter in that program unit has an
associated implicit type/kind combination.1
1. An exception to the rule that implicit none turns off all implicit typing is in internal and
module procedures having implicit none in their hosts; such procedures may have implicit
statements defining implicit typing for part of the letters, leaving implicit none (and hence
explicit typing required) for the other letters - see chapter 9.
17
The intrinsic types are the numeric types (integer, real, complex), the logical type, and the
character type. Each of these may be parameterized (type kinds), have intrinsicallydefined forms for constant values, and have intrinsically-defined operators and operations.
A number of intrinsic functions are defined for the intrinsic types, and user-defined functions may return values of intrinsic type. Fortran 90 has user-defined types as well, called
derived types because they are derived from the intrinsic types (and other derived types);
all aspects of an intrinsic type, except type kind parameterization, may be provided for a
derived type - name, constants, operators, and functions returning derived type values.
Derived types, once defined, essentially augment the intrinsic types as the data types
available for use in a program. Two other uses of derived types are common: record structures and dynamic structures. Record structures are convenient for organizing data into
logical groups (records) for input and output and corresponding processing. Dynamic
structures, such as linked lists and binary trees, are indispensable for certain application
areas.
derived-type definitions
Unlike intrinsic types, whose definitions are intrinsic (built into the language), a derived
type must be defined. This is done by specifying its components, which are objects of
intrinsic or derived type (R422). The simplest form for such a definition is:
type type-name
component-definition
[ component-definition ] ...
end type [ type-name ]
Each component definition is an ordinary type declaration statement, except that the only
attributes permitted are dimension and pointer. A component can be either a scalar or an
array, and derived types for recursive dynamic structures (e.g., linked lists, binary trees)
can have pointer components that have the same type as that being defined. More than one
component may be declared in the same component definition statement. Simple examples illustrating all of these possibilities:
type Point
real :: x, y
end type
type Student
character(30) :: ID
integer :: homework(15)
integer :: hour_exam(3)
integer :: final_exam
end type
18
type Tree
type (TreeData) :: node_data
type (Tree), pointer :: left, right
end type
type Pixel
type (Point) :: p
integer :: R, G, B
end type
The first (and last) of these four examples do indeed suggest new data types, and the
expectation would be that appropriate operations would be defined on objects of these
types. The second example suggests a typical record structure, with an expectation that
various computations would be made with individual fields (components) but not on a
student as a whole. The third example clearly is intended to be used as a dynamic structure, in this case a binary tree with left and right links to subtrees. The data for such a tree
can, of course, be of any nature, and in this case the details of that nature have been encapsulated in yet another derived type called TreeData.The fourth example also illustrates the
use of a previously-defined derived type as a type component. Though not having the
properties of true object-oriented inheritance, the Point component of Pixel does inherit
all of the properties (e.g., operations) defined for type Point. (In this manner, and through
use of type definitions packaged in modules, Fortran 90 provides much of the inheritance
and data abstraction benefits of object-oriented programming; typical O-O features not
accommodated are polymorphism and object invocation of procedures.)
The name of a derived type must not be the same as any intrinsic type name, nor the same
as any other derived type accessible in that scope; it also must not be the same as any variable or procedure name accessible in that scope. Derived-type definitions are local to the
scope in which they are defined, but may be accessible to other scopes via use and host
association.
Component names have a scope of their derived-type definition, though they are accessible outside the type definition when (and only when) selected with the % component
selection operator (see below). Within a given type definition, each component name must
be unique, but otherwise there is no restriction on component names; in particular, they
can be the same as the names of entities defined in or accessible to the surrounding scope
of the type definition.
derived-type objects
Derived-type definitions do not create data objects; a type definition only specifies the
name of the type (analogous to, say, the type name integer) and the component structure
for objects of that type. Actual objects must be created, again in analogy with intrinsic
types, in type declaration statements (R501); derived type objects are created with a typespec of
type ( type-name )
19
As with objects of intrinsic type, a derived type object, also called a structure or structured object, may be: declared as a constant (have the parameter attribute), an array (have
the dimension attribute and, optionally, be an allocatable or pointer array), a dummy argument (and, optionally, have the intent and/or the optional attributes), a module object (and,
optionally, have the private or public attribute), a pointer or a pointee (have the pointer or
target attribute), a saved local variable (have the save attribute). Function results may be
declared to be of derived type, in which case either the type ( type-name ) type specifier
may appear on the function statement or the function may be typed in the functions specification part.
Some example declarations of derived-type objects:
type (Point) :: p1, p2
type (Point), allocatable :: property_corner(:)
type (Student), intent(in) :: valedictorian
type (Student), private :: onProbation (100)
type (Tree) :: dictionary
type (Tree), pointer :: root
type (Pixel), save :: screen (480,640)
type (Pixel) function summit (topo_map)
A structure reference may appear in an expression, on the left hand side of an assignment
statement, and as an actual argument - as may a component reference. A component of a
structure may be referenced by using the component access operator, %, in the following
manner (R612):
structure-reference % component
Specific examples of component references (using the above example type definitions and
structure object declarations) are:
p1 % x
property_corner(i) % x
property_corner % y
valedictorian % ID
valedictorian % homework
onProbation(n) % hour_exam(m)
dictionary % node_data
dictionary % left
screen(i,j) % R
! a scalar object
20
screen % B
screen % p
screen(i,j) % p % x
The last of these examples illustrates that if a structure component is itself a structured
object, then its components may be accessed as well. Such a sequence of % operators may
be of any length, as long the entity on the left of each % is of derived type and the entity on
the right is a component of that derived type; the parsing of such a sequence is from left
to right. The very left one must be a structured object, and is either its declared name or (if
the structure is an array) an element or section of that array. Each entity on the right of a %
operator must be either a component name or (if the component is an array) an element or
section of that array. Any array name (whole array) or array section in a component reference makes the result of the reference array valued, with the same shape; there can be at
most one array-valued entity in a given component reference.
structure constructors
A structured object may be assigned a value by individually assigning a value to each of
its components. For example:
p2 % x = 112.2
p2 % y = 35.7
! completely define p2
The effect of this last assignment is the same as the preceding individual component
assignments; a structure value of a given type may be assigned to a derived-type variable
of that type. (But this intrinsically-defined assignment may be overridden by a defined
assignment - see chapter 20).
The structure value Point ( 112.2, 35.7 ) is a constant because all of the component values
are constants. Such a value may be used to establish a named constant of derived type:
type (Point), parameter :: origin = Point (0.0, 0.0)
In general, however, any expressions may be used for the component values in a structure
constructor, so long as the constructor contains an assignment-compatible value for each
component, in the order in which the components are declared in the type definition.
An associated structure constructor is available for any defined or accessible type, (except
for types with private components - see below). If a type has a pointer component (either
21
scalar or array) an allowable target object must appear in the corresponding position in a
constructor for that type. If a component is an explicit-shape array (the only type allowed
as a component other than a pointer array), an array value with that shape must appear in
the corresponding position in a structure constructor.
Additional examples of structure constructors are:
Point (z+1, w-2)
Point ( r*sin(phi), r*cos(phi) )
Point ( 2*p2%y, 0.0)
Student ( Joe, hw(i,:), (/e1,e2,e3/), fe )
In the last example hw must be a two-dimensional integer array with a size of 15 in its second dimension, and e1, e2, e3 and fe must all be scalar integer variables (or named constants). The first three of these examples illustrate the use of arbitrary expressions to
specify component values in a structure constructor.
Structure values may also be obtained from input. A structure variable name may appear
in the input list of a read statement, in which case a value is input for each component. In
list directed input the effect is the same as if the individual components had been placed
(with the % operator) in the input list instead. For formatted input, a format is specified for
each component, in component-declaration order, in exactly the same manner as for the
intrinsic type complex.
read *, p1
! read two real values, one for p1%x and one for p1%y
read (2F10.2), p1
read *, valedictorian
Similarly, structure values may be placed in the output list of a print or write statement,
and the component values are output in component-declaration order. Structures with
pointer components can be neither input nor output, though individual nonpointer components of such structures can appear in I/O lists.
derived-type operators
Since dummy arguments may be of derived type, and functions may return structure values, functions may be used to define virtually any operation on and among structured
objects. For example, the midpoint between two Point objects may be defined as follows:
type (Point) function midpoint(a,b); type (Point) :: a, b
midpoint = Point ( (a%x+b%x)/2, (a%y+b%y)/2) )
end function
22
Note that the midpoint is, of course, a Point value. An operator, say .mid., can be associated with this operation:
interface operator (.mid.)
module procedure midpoint
end interface
Then the midpoint of two points, say p1 and p2, can be computed with the expression
p1.mid.p2
Chapter 20 contains more details on defining operators. Chapter 19 illustrates how a module can be used to encapsulate a derived-type definition, its constants, and any operations,
so that the type could be used almost as naturally as an intrinsic type.
private types
Sometimes it is desirable to hide the internal structure of objects and access components
only via explicitly provided procedures. This is possible only for derived types defined in
modules. A derived-types components are accessible anywhere inside the module in
which the type is defined, but the internal structure of a private type can be hidden from
users of the module. This is accomplished with the derived-type private statement, an
example of which is:
type Point; private
real :: x, y
end type
In this case users of the module which contains this type definition can declare objects of
type Point, but cannot use the % operator to access either the x component or the y component of those objects, nor is the Point structure constructor accessible to the user of the
module. The module may contain functions to access x and y, but need not if the intended
use of Point does not involve the user accessing the components. In this latter case the
module presumably includes procedures that provide the intended computations on and
with Point objects.
The private statement, if used, immediately follows the type statement (R422, R423) and
hides all of the components from users of the module containing the derived-type definition. Note that
type type-name; private
is really two statements, and many programmers prefer to put them on separate lines,
whereas
type, private :: type-name
is a single statement that makes the entire type, name as well as the components, private to
the module and not accessible to users of the module.
23
sequence types
A derived-type actual argument must be exactly the same type as the associated dummy
argument or an equivalent type. Same type means that both a dummy and its associated
actual argument derive from the same type definition. For all practical purposes this
means that the derived type must be defined in a module that is used by, or host to, (a) any
procedure definition with arguments of that type and (b) any program unit making calls to
such procedures. (The only way the requisite conditions can be met without a module is if
all of the procedures having an argument of this type are internal procedures in a host procedure containing the type definition.)
Equivalent types are sequenced type definitions with the same type and the same number of components; corresponding components in each list must have the same name, the
same or equivalent type, the same attributes (dimension and/or pointer), and neither can be
private. An example of a sequence type is
type Student; sequence
character (30) :: ID
integer :: homework(15), hour_exam(3), final_exam
end type
This type definition need not be used from a module and can be repeated in any scope
which has actual or dummy arguments of type Student. The main problem with such
duplication is, of course, the maintenance one of needing to make a change in more than
one place. This problem can be circumvented by putting the sequenced type definition in
its own file and including that file wherever the type definition is needed; this, however, is
not much different from putting the type definition in a module and using the module
wherever the type definition is needed.
A derived type is made into a sequenced type by inserting a sequence statement between
the type statement and the list of component definitions (R422, 423). There is one use of
sequence types other than for equivalent type argument association. This is to allow
derived-type objects to be associated (e.g., in common blocks) with numeric or character
storage sequences. If all of the components of a sequence derived type have numeric storage units (i.e., they comprise only intrinsic kinds of integer, real, complex, and logical
components), the type is a numeric sequence type and can be storage associated with any
numeric storage sequence. Similarly, if all of the components of a sequence derived type
are of type default character, the derived type is a character sequence type and can be storage associated with any character storage sequence.
24
Arrays
25
Arrays
The array features of Fortran 90 represent one of the most significant aspects of the language. A computation can be specified on a whole array (or any portion of an array); such
a computation is performed on each element of the array, conceptually concurrently. The
corresponding potential for actual process parallelism is enormous - namely the number of
elements in the array. Roughly speaking, versions of Fortran prior to Fortran 90 allowed
the programmer to specify computations only on scalar entities, such as individual array
elements, with an entire array processed by sequencing (looping) through its elements.
array-valued expressions
Suppose that A, B, and C are two-dimensional real arrays, all dimensioned at 200x300 elements. Fortran 90 allows the following statement, involving the addition of two of these
arrays and the assignment of the result:
C=A+B
The meaning of this operation is C(i,j) = A(i,j) + B(i,j) for all 200 values of i and all 300 values of j, for a total of 60,000 individual (scalar) computations involving the array elements. The array computational model is concurrent element-by-corresponding-element
computation for all elements of the arrays.
In addition to extending all of Fortrans scalar operations to arrays in this manner, other
useful whole array operations are provided. These include reduction operations (e.g.,
product(A) returns the product of all the elements of array A), construction operations
(e.g., (/ (i, i=1,n) /) constructs the vector [ 1, 2, 3, ..., n ], and inquiry operations (e.g.,
shape(B) returns the shape of array B - a vector comprising the size of each dimension of
array B, or [ 200, 300 ] for the array B in the above example). All such operations can be
combined into more complex expressions; for example, product(shape(B)) has the value
60,000, the total number of elements in B (but Fortran 90s rich supply of array functions
also includes the size intrinsic function, which gives the same result more directly).
Generally speaking, except in a few contexts in which an expression is restricted to be scalar, any Fortran 90 expression may have array operands and the result is array valued.
(Scalar expressions are required in control contexts such as if construct control (scalar logical expressions required), do loop indexing expressions, and I/O specifiers such as unit
number, file names, open statement specifiers, etc.) In most cases the arrays in an arrayvalued expression must have the same shape (must be conformable) and the expression
value is an array of the same shape.
Note that in many cases, such as in the above example (C = A + B), array expressions
appear indistinquishable from scalar expressions and one needs to know from other contexts (e.g., the specifications) that the variables have been declared as arrays. However,
Fortran 90 allows such expressions to be written with explicit dimensionality, which
clearly identifies array operations. For example, the above assignment can be written as:
C(:,:) = A(:,:) + B(:,:)
26
Functions may be defined to return array values (array-valued functions) and calls to such
functions may be operands in array-valued expressions. Array-valued functions, including
both user-defined and intrinsic ones, make array-valued expressions a complete, natural
extension/generalization of scalar expressions, with arrays replacing scalars as operands
and results.
conformability and element-by-element computation
The principal requirement in forming an array expression is conformability of the operands. Each operand of an array operation must have the same rank and the same number of
elements along each dimension as the other operands - that is, conformable arrays are
arrays with exactly the same shape. The result of such an operation is, of course, conformable with the operands, and the value of each element of the array result is the scalar computation involving the corresponding elements of the array operands.
Thus if A and B are the following 2x3 arrays: A =
the result of A + B is
7 7 6
3 9 7
2 3 5
1 7 4
B=
5 4 1
2 2 3
10 12 5
2 14 12
If there is more than one operation in an expression, the (array-valued) result of the first
subexpression is an operand for the second operation, and so on, just as in scalar operations. For example, for A and B as given above, in the expression A + B * A, A is added to
the result of B * A; thus the result of A + B * A is
2 3 5
1 7 4
10 12 5
2 14 12
12 15 10
3 21 16
Note that, for example, a 3x2 array is not conformable with a 2x3 array - they have the
same rank and total number of elements, but corresponding dimensions dont have the
same size - and thus two such arrays cannot be the operands in the same array operation.
The only exception to this basic conformability rule is in the event that one of the operands
is a scalar. In this case the scalar is broadcast into an array conformable with the other
operand, the value of each element of this broadcast array being that of the scalar. For
example, B + 2 is a valid array operation and (assuming B is as given above)
the result of B+2 is
5 4 1
2 2 3
2 2 2
2 2 2
7 6 3
4 4 5
Common uses of (broadcast) scalars in array operations are to initialize and scale arrays:
A=0
B = (B + 1)/2
Arrays
27
This last example illustrates a key aspect of the Fortran array operations: in an array-valued assignment the effect is as if the right-hand side array value is fully evaluated before
any assignment takes place. Otherwise it is possible (though not in this simple example)
for the right-hand-side array value to be affected before its evaluation is complete. Thus
the conceptual model is that all elements of the right-hand-side array value are computed
concurrently (or in any order) before any assignment takes place, and any implementation
is allowed that guarantees this behavior.
An example where this rule is important is in the pivoting step in Gauss elimination (see
the last example in this chapter). There the pivot row is normalized with the array operation
G(P,:) = G(P,:)/G(P,K)
G(P,:) is the Pth row of the two-dimensional array G, and G(P,K) is the pivot element; the
normalization scales the row so that the pivot element value is 1.0. Note that if the value of
this element is changed to 1.0 before the evaluation of the right-hand side is complete,
then the row is not properly normalized (a typical error in sequential scalar code). Therefore, array operations should not be thought of as loops over the array elements, as a
loop implies a sequentially of the operations; in general, thinking of array operations as
loops gives incorrect results when assignment is involved. Array operations should be
thought of as integral/parallel computations.
The index-variable is a scalar integer variable serving as an iterative index in exactly the
same manner as in a do loop. The example above, (/ (i, i=1,n) /), employs an implied-do
construct in an array constructor. In general, a list of expressions can precede the indexing
in an implied-do construct; a simple example: 100 million alternating ones and zeros,
(/1,0,1,0,1,0,1,... /) can be constructed with the array constructor (/ (1,0, j=1,50000000) /).
The implied-do simply replicates the list the specified number of times, and if the indexvariable is an operand in an expression in the expression-list, each replication of that item
uses the corresponding value of the index-variable. The items in the implied-do expres-
28
sion-list may be any of the three forms allowed in the array constructor itself - scalar
expressions, implied-do constructs, and array expressions. The two examples above have
only simple scalar expressions in the implied-do lists.
An array expression of any dimension may appear in an array constructor. For example, if
A is a 1000*1000 array then (/ A+1.3 /) is an array constructor of one million elements,
each having a value of 1.3 more than the corresponding element value of A. The elements
of A+1.3 are placed in the array constructor in array element order; array element order is
obtained by varying the first dimension first, the second dimension next, and so on. Thus (/
A+1.3 /) is equivalent to (/ ((A(j,k)+1.3, j=1,1000), k=1,1000) /). Implied-do constructs may be
used to specify a different order of the array elements in the constructor. For example, if a
row by row vector of the elements of A+1.3 is desired, rather than the column by column of
array element order, (/ ((A(j,k)+1.3, k=1,1000), j=1,1000) /) would do the job.
Finally, a simple form of the reshape intrinsic function can be used to reshape the (onedimensional) result of an array constructor into the desired array shape:
reshape ( array-constructor , shape-vector )
where the shape-vector (which may itself be an array constructor) has one element for
each dimension of the desired array shape; the value of each shape-vector element is the
number of elements in that dimension in the target array. For example, a 1000*1000 identity matrix of can be created as the array constant named ident by the declaration
real, parameter :: ident(1000,1000) =
reshape ( (/ (1.0, (0.0, k=1,1000), j=1,999), 1.0 /), (/ 1000,1000 /) )
&
Thus the array constructor, coupled with the reshape intrinsic, is an extremely powerful
tool for constructing array values, including array constants.
masked array assignment
A mask is an array of type logical. A masked array operation is one in which a mask conformable to the result of the operation is used to specify that only a subset of the concurrent element operations are to be performed. This functionality is available in some of the
intrinsic functions, those with a mask argument, and for array assignment. An array
assignment is placed under mask control in a where statement (R738):
where ( mask ) array-assignment-statement
The where mask must be conformable with the array on the left of the assignment, which
must be conformable with the expression on the right of the assignment. For mask elements that have the value true the corresponding element assignments take place; where
the mask is false the assignment is not made. A example of masked array assignment is
where (C.gt.0) A = B/C
in which the assignment is made only for those elements of C that have a positive value.
Arrays
29
Arrays A, B, and C must all be conformable and the (array-valued) logical expression
C.gt.0 is therefore a mask conformable with these arrays.
Another simple example of the use of masked array assignment can be found in the picture
refinement program near the end of this chapter. In this case the elements of a character
array are set to # where all corresponding elements in another (conformable) array are 1:
where (picData.eq.1) picDisplay = "#"
Any number of array assignments that are conformable with the mask, can be placed
under the control of a single mask; in this case the where takes a block form (R739):
where ( mask )
array-assignment-1
array-assignment-2
...
end where
The forms of where described above leave unassigned some elements of the array on the
left hand side of the assignment statement. An extension of the block form of where, the
elsewhere option, specifies a value to be given to the left-hand-side array elements where
the mask is false. This takes the form (R739):
where ( mask )
array-assignment-1
array-assignment-2
...
elsewhere
array-assignment-n+1
...
end where
In this case those elements of picDisplay for which picData has a value other than one are
assigned a blank rather than the # character. This is an important form of where, because it
results in a fully defined array picDisplay that can be used in subsequent array operations.
Without the elsewhere option the array picDisplay might end up not being fully defined, in
which case it cannot be used in other array expressions.
30
In a call to calc3, any two-dimensional array expression (of type real) may be passed to U
and any one-dimensional array expression may be passed to V; conversely, a two-dimensional real array must be passed to U and a one-dimensional real array must be passed to V.
In effect the colons in the declarations for U and V instruct calc3 to accept the descriptor
information supplied by the calling program. U and V then exactly represent the corresponding array objects in the actual argument list and may be used in array operations in
the body of calc3.
Assumed-shape dummy arguments require explicit interfaces (see chapter 9). This
requirement is automatically met for internal and module procedures; an interface block
must be supplied for an external procedure, however. When the procedures interface is
explicit, the calling program knows when an assumed-shape dummy argument is the
receiver and can then pass an efficient descriptor; otherwise the calling program cannot
assume the dummy arguments are assumed-shape and must therefore provide a contiguous
actual argument, packing and unpacking the actual argument array(s) as necessary.
array elements and sections
A portion of an array containing more than one element is called an array section. Often
an operation is needed on an array section, not on the entire array. The earlier example of
normalizing the pivot row of a matrix is a case in point. In this example exactly one row of
the matrix was of interest in the computation, not the whole array, and the array section
was one row of a two-dimensional array. In general virtually any subset of an array can be
an array section. Array sections have array values and may be used in array-valued expressions; they may be assigned array values.
An array element is specified by the array name and a subscript value for each dimension:
array-name ( scalar-subscript-1 , scalar-subscript-2 , scalar-subscript-3 , ... )
Arrays
31
where the number of subscripts is the rank of the array and each subscript is a scalar integer expression (scalar subscript). An array section is specified by replacing at least one
scalar subscript by a vector subscript (R618). A vector subscript is a one-dimensional
array of scalar subscript values for that dimension; a vector subscript may be constructed
with an array constructor. If (only) one scalar subscript is replaced by a vector subscript
the resulting array section is a one-dimensional array; if two scalar subscripts are replaced
by vector subscripts the result is a two-dimensional array, and so on. An array section has
a rank equal to the number of vector subscripts used to specify it.
As an example, consider the following 5x6 array, Q. Three sections of Q are shown in
bold: the entire second column (a one-dimensional section), the 2x2 upper right hand corner of Q (a two-dimensional section), and the last half of the fifth row of Q (a one-dimensional section).
13
9
Q = 16
7
37
11
3
45
20
56
25
31
54
18
54
2
14
36
19
66
1
52
15
8
77
9
27
20
19
90
Q( :, 2 ) == (/11,3,45,20,56/)
Q( (/1,2/), (/5,6/) ) == reshape( (/1,52,9,27/), (/2,2/) )
Q( 5, (/4,5,6/) ) == (/66,77,90/)
Note that all of these vector subscripts could be written with implied-do constructs:
Q( (/(k, k=1,5)/), 2 )
Q( (/(k, k=1,2)/), (/(k, k=5,6)/) )
Q( 5, (/(k, k=4,6)/) )
The implied-do form is more extensible and, for large sections, considerably more compact than explicit lists. Implied-do constructs are also useful for regularly-spaced but noncontiguous vector subscripts. For example,
Q( (/(k, k=1,5,2)/), 2) == Q( (/1,3,5/), 2 ) == (/11,45,56/)
The implied-do form is common enough that a more readable shorthand notation, called a
triplet subscript (R619), is also provided for the indexed-do control triplet.
A triplet subscript is just the indexed-do control values, separated by colons rather than
commas, with the last one (the increment or stride value) optional. Thus using triplet notation the above four examples may be written (much more clearly!) as:
Q( 1:5, 2 )
Q( 1:2, 5:6 )
Q( 5, 4:6 )
Q( 1:5:2, 2 )
or
or
or
or
Q( :, 2 )
Q( :2, 5: )
Q( 5, 4: )
Q( : :2, 2 )
(The form Q(:,:) is a section that comprises the entire array Q. This form in a dummy argument declaration, rather than in an array expression, specifies an assumed shape dummy.)
32
Though the above examples employ array constructors, any one-dimensional integer array
expression is permitted as a vector subscript. The only requirement is that the value of
each element of the vector subscript be a valid subscript value for that dimension of the
array. A common form for vector subscripts is a one-dimensional integer array name (or
section), whose element values have been previously established. This form is useful for
indirect access, such as indexing into a table; e.g., table elements may be retrieved (or set)
by subscripting the table array with an array containing the desired table index values.
For the array Q defined above, for example, consider Q( (/2,5,3/), (/6,4/) )
Q
2, 6
5, 6
5, 4
3, 6
3, 4
2, 4
27 14
= 90 66
20 36
This section can be used in any array expression in which a 3x2 array object is valid. It
may also appear on the left hand side of an array assignment, in which case the (1,1) element of the right hand side expression value gets assigned to Q2,6, the (3,2) value of the
right hand side gets assigned to Q3,4, and so on.
A vector subscript may contain more elements than the size of that array dimension. In
this case there are duplicate values, since all of the values must be within the array dimension range. Indeed, subscript values may be duplicated in a vector subscript even if the
size of the vector is less than the array dimension (the only requirement is that the subscript values must be within range). Both of these cases are illustrated in the following
example, which specifies a 7x4 section from the elements of Q.
Q
Q
Q
4, 1
1, 1
2, 1
4, 1
2, 1
5, 1
4, 4
1, 4
2, 4
4, 4
2, 4
5, 4
4, 4
4, 3
1, 4
1, 3
2, 4
2, 3
4, 4
4, 3
2, 4
2, 3
5, 4
5, 3
Q ( ( /4,1,2,3,4,2,5/ ), ( /1,4,4,3 ) ) = Q 3, 1 Q 3, 4 Q 3, 4 Q 3, 3
Q
Q
Q
Note that rows one and five of this section are identical, as are rows three and six and columns two and three. Many elements of Q therefore appear twice in this array section and
two elements, Q2,4 and Q4,4, each appear four times. Array sections with multiple appearances of a given parent array element are perfectly legitimate array operands in array
expressions, but such sections must not appear on the left hand side of array assignments
(or be actual arguments associated with intent(out) dummy arguments - see chapter 9).
Arrays
33
dynamic arrays
Fortran 90 has three varieties of dynamic arrays. All three allow array creation at run time
with sizes determined by computed (or input) values. The three varieties are: automatic
arrays, allocatable arrays, and pointer arrays.
automatic arrays: Automatic arrays are local arrays whose sizes depend upon values associated with dummy arguments. Automatic arrays are automatically created (allocated)
upon entry to the procedure and automatically deallocated upon exit from the procedure.
The size of an automatic array typically is different in different calls to the procedure.
Examples of automatic arrays are:
function F18(A,N)
integer N
real A(:,:)
real F18(size(A,1))
complex Local_1(N,2*N+3)
real Local_2(size(A,1),size(A,2))
real Local_3(4*size(A,2))
...
end function
! a scalar
! an assumed shape array
! the function result itself is an automatic array
! Local_1 is an automatic array whose size
!
is based on N
! Local_2 is an automatic array
!
exactly the same size as A
! Local_3 is a one-dimensional array 4 times
!
the size of the second dimension of A
Note the importance of the intrinsic inquiry functions, such as size in declaring automatic
arrays; a number of inquiry functions are provided that are allowed to appear in declarations. Array bounds and sizes, character lengths, and type kinds may all be specified with
expressions involving these inquiry functions. Roughly, a specification expression, as such
expressions are called, is a scalar integer expression that has operands whose values are
determinable upon entry to the procedure. Such operands include constants, references to
certain intrinsic procedures, and variables accessible through dummy arguments, modules,
common, and (in the case of module and internal procedures) the host procedure.
allocatable arrays: Allocatable arrays are those explicitly declared allocatable. An allocatable array may be local to a procedure or may be placed in a module and effectively be
global to all procedures of the application. An allocatable array is explicitly allocated with
the allocate statement, and deallocated either explicitly with the deallocate statement or, if
it is a local array for which save has not been specified, automatically upon exit from the
procedure. (If save has been specified, local allocatable arrays can persist from one execution of the procedure to the next - they must be explicitly deallocated with a deallocate
statement.) A global allocatable array persists until it is explicitly deallocated, which may
occur in a procedure different from the one in which it was allocated. An allocatable (or
pointer) array is indicated if its size depends on a value to be computed after its declaration. The allocation status (allocated or not yet allocated) of an allocatable array may be
tested with the allocated intrinsic function. Examples of allocatable arrays are:
34
subroutine Peach
use Recipe
real, allocable :: Pie(:,:)
...
allocate ( Pie(N,2*N) )
! allocate a local allocatable array
if (.not.allocated(Jam)) allocate ( Jam(4*M) )
! allocate a global allocable array
...
! if it is not already allocated
deallocate ( Pie )
...
Note that the declared bounds for allocatable arrays are simply colons, indicating that
these will be provided later, at the time of allocation. This makes allocatable array declaration appear similar to assumed-shape dummy argument declaration, appropriate because
the deferred nature of the sizes of the dimensions is conceptually similar.
pointer arrays: Pointer arrays are similar to allocatable arrays in that they are explicitly
allocated with the allocate statement to have computed sizes and are explicitly deallocated
with the deallocate statement. Simple examples of pointer arrays result by replacing allocatable with pointer in the preceding examples of allocatable arrays.
In addition, pointer arrays can be used as aliases for (may point to) other arrays and array
sections; the pointer assignment statement is used to establish such aliases. The target for
pointer associations (as such aliasing is called) may be other explicitly allocated arrays, or
static or automatic arrays that have been explicitly identified as allowable targets for pointers. The association status of a pointer array may be tested with the associated intrinsic
function. Pointer arrays may be dummy arguments and structure components, neither of
which are allowed for allocatable arrays.
Given this apparent similarity between allocatable arrays and pointer arrays, what is the
fundamental distinction between these two forms of dynamic arrays, and when should
allocatable arrays be used rather than pointer arrays? Pointer arrays subsume all of the
functionality of allocatable arrays, and in this sense allocatable arrays are never needed pointer arrays could always suffice. The problem with pointer arrays is efficiency. Though
pointer arrays must always point to explicit targets, which makes some optimization practical that would otherwise be infeasible, pointer assignment makes optimization of pointer
arrays much more difficult than for allocatable arrays. Because of their more limited
nature and functionality, allocatable arrays are just simpler and can be expected to be
more efficient than pointer arrays.
Therefore, when all that is needed is simple dynamic allocation and deallocation of arrays,
and automatic arrays are not sufficient, use allocatable arrays. A common example of this
is if a work array is needed of a size dependent upon the results of a local computation.
If, on the other hand, the algorithm calls for a dynamic alias, of for example a moving
section of a host array, then a pointer array is probably indicated.
Arrays
35
array-valued functions
As noted above, functions can be defined that return array-valued results. In addition, most
intrinsic functions can return array values (and some always do). Array-valued functions
may be used as operands in array-valued expressions, allowing more forms of concurrent
computation expression.
An example using an array-valued intrinsic function is common in applications of finite
difference modeling. Here each element of a large two-dimensional array g is to be added
to the next element in the same row of a conformable array u, and subtracted from this is
the previous row element of u; this is to be done with all of the elements of g, resulting
in a conformable array r. The computation, for each element, is sketched as follows:
g
u
+
r
Using the cshift intrinsic function, which returns a given array shifted a specified
amount, this computation is nicely expressed as follows:
r = g + cshift(u,1, 2) - cshift(u,-1, 2)
This illustrates the power of array-valued functions, especially if g were replaced with an
array-valued function reference rather than an array variable reference.
The array-valued intrinsic functions are all summarized at the end of chapter 9 and
described in detail in chapter 10. Function F18 in the previous section and the functional
form of g in the preceding example are examples of user-defined array-valued functions.
The shape of the result returned by user-defined array-valued functions normally is determined (dynamically) from arguments, as illustrated in the F18 example (and see the Refine
and Solve examples below). Note that function results are declared to be array-valued with
ordinary declaration statements, as if the function name is an ordinary variable (as indeed
it is within the body of the function). Though automatic arrays may be the most useful
form for user-defined array-valued functions, any other form is also valid: explicit-shape
array, allocatable array, pointer array.
The main additional requirement for user-defined array-valued functions is that the array
value must be fully defined before completeion of execution of the function. On the caller
side, the interface of an array-valued function must be explicit so that the caller knows that
it is dealing with a function that is array-valued; otherwise the caller has to assume the
function returns a scalar value, which is then broadcast in the array-valued expression
from which the function is called.
36
! assumed-shape argument
! returned value same size
! use of array intrinsics
&! entire array refined
&! in one array operation
&
&! the sum of the 3x3
&! neighborhood is divided
&! by 5 to give the refined
&! one or zero for each
&! element in the interior
! of the array
Arrays
37
##
#
refined picture
#
#
############## ############# #############
######################### ############### ##
##
#####
#####
###
#
#
####
####
####
#
####
####
#
## #
# ## #
#
### ##
#####
#####
####
######
## #
####
#
#
#####
#### ##
# ##
#
#### #
# ##
#
#
####
####
###
###
####
#
####
###
#
#
# #
###
####
##### ########### ####
####
#
####
# ###### #########
## #
##
####
####
### #
#
#####
#
########### ##################### ##########
##################### #################### #
#
#
##
#########################################
############################################
#####
#####
####
####
###
###
###
####
####
####
#####
####
####
###
#####
####
####
####
####
####
####
####
####
#
#
####
####
####
###
####
####
#### ################
####
####
# ###############
####
####
####
#####
#####
############################################
##########################################
##
Program Refine defines two array-valued functions, both with assumed-shape dummy
arguments whose size determines the returned array size. Function display illustrates the
use of the where construct. Function refined illustrates (a) the use of an array intrinsic
(size) in the execution part as well as in the specification part, (b) assigning a value to an
array section, and (c) a nontrivial array-valued expression which exhibits considerable
conceptual concurrent computations.
38
do pn=1,n
! pn is next pivot number
not_pivot_rows_or_cols = .true.
not_pivot_rows_or_cols(p(1:pn-1,1),:) = .false.
! mask all pivot rows
not_pivot_rows_or_cols(:,p(1:pn-1,2)) = .false.
! mask all pivot columns
P(pn,:) = maxloc(abs(G(:,1:n)),mask=not_pivot_rows_or_cols)
! find next pivot
if (abs(G(p(pn,1),p(pn,2))).lt.1E-4) stop 'ill-conditioned matrix'
! check stability
G(p(pn,1),:) = G(p(pn,1),:)/G(p(pn,1),p(pn,2))
When executed with the simple data sets shown above, this program returns (1.0, -1.0, 2.0)
and (7.0, -2.0) for the respective solution vectors, demonstrating that function Gauss will
correctly solve any size linear system. The entire matrix is reduced for each pivot, rather
than just those columns needing reduction, so that about twice as many (scalar element)
operations are performed as are really necessary; further tailoring of the not_pivot_row
mask could decrease the number of (scalar) operations. Note that, in terms of the number
of array operations, more attention is devoted in Gauss to preparing the masks than to the
numerical computations themselves - in array algorithms logical masks take the place of
conditional statements in sequential scalar algorithms.
The Gauss code is pretty straightforward (though reading and writing such compact,
highly concurrent array operations code takes some getting used to); perhaps the least
obvious aspect of Gauss is its use if the spread intrinsic function. spread replicates
(spreads) a scalar into a one-dimensional array, or replicates an n-dimensional array into
an n+1-dimensional array. The scalar-to-one-dimensional array form is used in Gauss to
convert the scalar operation G(i,j)=G(i,k)*G(k,j), where k is a constant, into a whole-array
operation (over all i and j) on G. spread has three arguments: the first is the scalar or array
value to be spread, the second is the dimension over which the spreading occurs (and must
be one for spreading a scalar), and the third is the number of replications.
Function Gauss has, for any given system size n, of the order of: 7n array masking operations and 7n array numerical computations, corresponding to about n4 scalar logical operations and 7n3 scalar numerical operations. As the cost (execution time) of an array
operation, continues its inexorable march toward that of a scalar operation, array codes
such as Gauss become increasingly attractive in terms of performance.
Redundancy
39
Redundancy
Some of the newer features of Fortran, motivated by modern common programming practices, have made some of the earlier features redundant. The purpose of this chapter is to
identify and summarize these redundancies.
The current Fortran standard officially identifies two categories of outmoded features:
(1) those for which better methods existed in Fortran 77 and (2) those for which better
methods exist in Fortran 90. The standard goes on to say programmers should use these
better methods .... In this reference these two categories are called deprecated (out of
favor) features.
In addition to those officially deprecated, there are several features of Fortran 90 that are
redundant and for which many believe that better methods exist: common, equivalence,
and attribute specification statements.
common blocks
Before Fortran 90, the only practical way to provide for global objects (variables and constants) was via common blocks; because global objects are important to many Fortran
application areas, much practical pre-Fortran-90 code uses common. Common blocks are
contiguous blocks of storage, and an object may be associated with (occupy) certain storage units in a common block. Any program unit can access a given common block and
thereby access an object by virtue of its known location in the common block. Such
objects are said to be storage associated, and common blocks share objects among program units through storage association.
Common blocks are distinguished by (programmer-specified) names, and the common
statement (R548) allows the programmer to declare a common block having a given name.
The common statement also specifies a sequence of objects that are associated with the
successive storage units of that common block; the common block can contain any mix of
scalar and array variables (R549), but cannot contain an allocatable array, a dummy argument, a nonsequence structure, or a function result name; arrays dimensioned in common
block arrays must have constant bounds. In a given program unit, a object cannot be
assigned to two (or more) common blocks.
The common block names are themselves global, known to all program units. Two (or
more) program units accessing the same common block access the same sequence of storage units; the object names and mix may be different in the two program units - the association is by storage sequence. For example, suppose that two program units specify the
same common block as follows (where all the variables are of type default real):
common / Omega / x(100), y, z(200)
common / Omega / a(200), b(100), c
The common block name is Omega and it contains 301 storage numeric units. In one of
the program units the first 100 storage units of Omega are known as the array x, the 101st
40
is the scalar y, and the last 200 are the array z; in the second program the first 200 storage
units are known as the array a, the next 100 storage units are known as the array b, and the
last storage unit is know as the scalar variable c; y and a(101), for example, represent the
same storage location and hence are the same thing.
Objects of type default integer, default real, and default logical have numeric storage
units; objects of type default complex and double precision real each require two numeric
storage units and double precision real requires four numeric storage units. Objects of type
default character have character storage units. Every other type/kind combination (or
type/kind/rank combination for pointers) has a different, unique (but unspecified) storage
unit. Objects with different storage units maybe be placed in a given common block, but
each program unit in a program using that common block must specify exactly the same
sequence of storage units. If a sequenced structure appears in a common block, the effect
is as if the individual components, in order, had been placed in the common block.
Because of the strict requirement of the preceding paragraph, a popular use of include
lines (before the advent of modules in Fortran) was to make one copy of a common block,
place it in a file, and include that file in every program unit that used that common block.
With modules, the same effect can be achieved by placing the common block in a module
and using that module. Even better (and simpler), place the variable definitions directly in
the module, without putting them in common blocks; those variables are then global to all
programs units using that module (see chapter 8).
Two or more common statements naming the same common block can appear in the same
program unit; the effect of the second (and subsequent) statements is to extend the common block defined in the first such statement. A named common block must have the same
size in all program units. A common block name may appear in a save statement, in which
case the entire block is saved; individual variables in a common block must not have the
save attribute. Variables in a named common block may be initialized in a block data program unit.
The common block name may be omitted in a common statement, in which case the common block is known as blank common. There may be any number of named common
blocks, but there is only one blank common; multiple blank common statements in a program unit simply extend the one blank common. The rules for blank common are the same
as for named common, except that blank common is always saved, blank common variables cannot be initialized, and different program units can specify blank commons of different sizes (but storage units must still be associated with like storage units).
equivalence
To save space, two or more variables may share the same storage; the equivalence statement is how such sharing is specified. This was important when computing systems had
quite limited storage, but equivalence is largely redundant these days because there is not
normally now the overpowering need to save space.
Two (or more) variables are equivalence objects (share the same space) if they appear in
an equivalence-set of an equivalence statement (R545-547). An equivalence object may be
Redundancy
41
a variable name (scalar or array), an array element, or a substring; it may not be a named
constant, an allocatable array, a dummy argument, a nonsequence structure, a function
result name, a pointer (or structure containing a pointer), or any part thereof. There must
be at least two equivalence objects in an equivalence set and all equivalence objects in an
equivalence set must be of like storage unit. An example of an equivalence statement is:
equivalence ( x, b(10,20) ), ( first, name )
In this case the variable x is the same as the array element a(10,20), assuming that x is a
scalar real and b is and array of reals, and changing one changes the other; if first is a single-character variable and name is a longer character string, this equivalence statement
causes first to be the same character (share the same character storage unit) as the first
character of name.
Equivalence superimposes (makes the same) two or more storage unit sequences; thus
unlike storage units cannot be equivalenced. Moreover since arrays and array element may
be equivalence objects, and (whole) arrays occupy contiguous storage units, care must be
taken to not specify inconsistent pairings. For example, if x and y are both one-dimensional real arrays
equivalence ( x(10), y(20) )
specifies inconsistent offsetting and hence is illegal. As illustrated, any array elements or
substrings specified as equivalence objects must use constants as the subscripts or substring ranges. An unsubscripted array name (or a character variable name) as an equivalence object, storage associates the first element of the array (or first character of the
string) to the other equivalence objects in that equivalence set.
The objects in an equivalence set must be local to that program unit. An equivalence object
may be a variable in a common block, but equivalence must not cause two different common blocks to become storage associated, nor add storage units that precede the front of a
common block.
attribute statements
Prior to Fortran 90 Fortran did not have the attribute form of the type declaration statement
(see chapter 2); separate statements, now called attribute statements, were used to convey
attributes to objects; each such statement conveys exactly one such attribute. Though the
attribute form of the type declaration makes the attribute statements essentially redundant,
attribute statements are the only way attributes can be given to implicitly typed objects.
Constraints pertaining to attributes are summarized in chapter 2.
The typical (but not only) form for attribute statements is
attribute-name [ :: ] object-list
The effect is that the named attribute is given to each of the object listed in the object list.
42
real :: x, y
dimension :: x(100), y(200,200)
save :: y
In the first of these, which is not of the general form given above, MAX may be implicitly
typed; in the second, the (two) variables are explicitly typed, but the other attributes are
conveyed with separate attribute statements. The attribute statements having precisely the
form shown above are: the optional statement (R520), the dimension statement (R525), the
allocatable statement (R526), the pointer statement (R527), the target statement (R528),
the external statement (R1207), and the intrinsic statement (R1208).
The attribute statements having almost the form shown above are: the intent statement
(R519), the public and private statements (R521), and the save statement (R523). In the
intent statement, an intent-spec (R511) must follow the intent keyword. In the public, private, and save statements, the object-list is optional; if it is missing then the attribute
applies to all of the local objects with which it is compatible. Note that the save attribute
statement is the only mechanism for saving a named common block.
The form of the parameter statement is given in R538-539; such a statement can contain
any number of named constant value definitions, separated by commas and enclosed in
parentheses. Another example of a parameter statement is:
parameter ( MAX=100, DOUBLE=kind(1D0) ) )
The data statement (R529-537), which initializes variables, not constants, is the attribute
statement that differs the most from the general form; it also is the one that is almost not
redundant, as it can be used to initialize part of an array, a structure, or a substring (the initialization provision of the type declaration, when applied to an array, structured object, or
a character string, must initialize the entire array, structure, or string).
The simplest form of the data statement is:
data variable-list / value-list /
The variables in the variable list are paired, left to right, with the values in the value list;
each value has to be assignment-compatible with its associated variable. Any substring or
array section ranges, or array element subscripts, in the variable list must be constants, and
all values in the value list must be constants and any repeat factors must be positive integer
constants. An example of a data statement is:
data count, n, name(1:3), (x(i), i=4,19,3) / 0, 0, "Dru", 6*3.5 /
After the data keyword comes the list of variables to be initialized; between the slashes (/)
are the initial values. In this case the variables are scalar integers count and n, both initialized to zero, a substring (first three characters) of character variable name, initialized to
"Dru", and six elements (4,7,10,13,16,19) of real array x all initialized to the value 3.5.
The 6 in 6*3.5 is a repeat factor and 6*3.5 is equivalent to 3.5,3.5,3.5,3.5,3.5,3.5.
Redundancy
43
Recall that an object with the data attribute (i.e., has been initialized) also automatically
has the save attribute. The following objects must not appear in a data statement: a named
constant, an object in common (unless the data statement is in a block data program unit)
an allocatable array, a dummy argument, a function result name, a pointer (or structure
containing a pointer), or any variable imported by host or use association.
block data program unit
The sole purpose of the block data program unit (R1110) is to initialize objects in named
common blocks. A block data program unit has only a (limited) specification part and no
execution part or internal procedure part. It has common statements to specify the common
blocks it initializes, and any declaration and specification statements needed to fully specify the attributes of the common block variables to be initialized. Thus the only statements
that block data program units can have are: derived-type definitions, type declarations, and
use, common, equivalence, dimension, pointer, target, intrinsic, save, parameter, and data
statements; common statements must specify named common blocks. The role of use
statements in block data program units is quite limited; only named constants can be
imported in this manner.
Common block variables cannot be initialized in type declaration statements, and so data
statements must be used for this purpose; therefore, unlike in other program units, in block
data program units common block variables may appear in the variable lists of data statements.
A block data program unit can initialize more than one named common block, and only a
part of a common block need be initialized - it is not necessary to initialize the entire common block. Though a common block may be only partially initialized, it must be entirely
specified in that block data program unit. A program may contain any number of block
data program units (at most one of which can be unnamed), but a given common block
may be initialized in at most one of the block data program units.
deprecated features
The Fortran standard says that deprecated features may be removed from subsequent versions of the standard. Even should this happen, standard-conforming implementations are
still allowed to support these features (as extensions to the language); many will do so.
The five deprecated features for which the standard proclaims there are better methods in
Fortran 77 are:
1.1 real (and double precision) do control variables (R822)
This tends to be error-prone because of accumulated round-off error
associated with repeated arithmetical operations. The better method is to
use an integer control variable and to convert it to the requisite real value
prior to using it in the computations of the loop.
1.2 branching to an end if statement (from outside that if construct)
Better method - branch to the statement following the end if.
44
Redundancy
45
46
Input/Output
47
Input/Output
Just as Fortran has an entire sublanguage for array processing (see chapter 4), so too
does it have a comprehensive sublanguage for performing data input and data output.
The read statement performs data input. The sources for data input are the users keyboard
and/or one or more data files on the computing system; the input process transfers a copy
of the data from the external source(s) into specified variables of the program, replacing
the previous values of those variables. The write statement performs data output. The destinations for data output are the users screen and/or one or more data files; the output process transfers a copy of the values of specified variables and expressions to the external
destinations, either appending the data to previously written data or replacing existing data
on the external destination(s), depending on the nature of that particular output operation.
Fortran I/O is record oriented. A data file is a sequence of records, each record being a
sequence of values terminated by a special end-of-record (EOR) character (or character
combination). EOR is system-dependent but often is equivalent to end-of-line - when displayed on a screen, each line represents a record. A read statement normally consumes
an entire record (line), regardless of how much data is then actually used; a write statement normally produces an entire record (including the EOR). When reading from the
keyboard each typed line, ending with the return key, is an input record; when writing to
the screen each write operation produces one line of output. Fortran 90 introduced nonadvancing I/O, providing Fortran, for the first time, with partial-record I/O capability.
The basic read and write statements are quite simple. The bulk of the I/O sublanguage
involves the many data formats that the input/output processes must accommodate, as well
as tools for effectively utilizing the data file system. The first two sections of this chapter
illustrate basic reading and writing of data; though relatively simple, these illustrations
include a great many practical uses of the read and write statements. The remaining sections are devoted to the more specialized, or more subtle, aspects of formats and files.
inputting data (read)
A simplified general form of the read statement (R909) is:
read ( [ unit= ] unit [ , [ fmt= ] format ] [ , [ iostat= ios-variable ] ) [ input-list ]
The input-list specifies the variables into which the data is to be read; the items in parentheses specify the data source (unit), the data format, and a status variable (to detect input
errors, end of file, etc.) - these are called the input control specifiers (R912). Note that the
only control specifier required is the unit and that the only specifier keyword required,
when that specifier is used, is iostat=. If the input list is omitted, no values are input, but a
record is consumed nonetheless.
Actual uses of the read statement tend to appear quite a bit simpler than the above general
form:
read (dataFile, fmt=* ) x, y, z
48
An asterisk (*) for the unit specifies keyboard input rather from a file. An asterisk for the
format specifies default formatting (also called list-directed formatting); list-directed input
formatting assumes the individual values requested (by the input-list) are separated by
(any combination of) spaces, commas, and end-of-lines. The iostat option is used if and
only if the programmer wants to detect input errors or the end of the file.
If the input unit is to be a data file rather than the keyboard, the unit is an integer value
(this is a good place to use a named constant); this value must have been connected to a
specific file, with the open statement, prior to executing the read statement. For example:
open(inputData, file="lab/test-16.data")
After execution of this open statement the appearance of inputData as the unit in a read
statement will cause the input to be taken from the next record in the file identified as lab/
test-16.data, which on most systems is the file named test-16.data in the directory
named lab. The simplest form of the open statement is
open ( [ unit= ] unit , file= file-name )
where unit is as defined above for the read statement and file-name is any character expression; of course if the file specified by file-name does not exist, an I/O error occurs. See the
section below on opening files for other features of the open statement and how to prevent,
detect, and recover from I/O errors encountered while opening files.
The format specifier in the read statement may be: omitted (in which case this is a unformatted read), an asterisk (listed-directed formatting, see above and the relevant section
below), a character expression (whose value must be a valid format specification, R1002),
or a label (which must be the label of a format statement, R1001). (See chapter 5 for a deprecated option not listed here.) The format specifies how the input data is converted and
assigned as the values of the variables in the input list. An unformatted read must specify a
unit that is connected to a file previously created with unformatted write statements.
If an iostat variable is specified in a read statement, it must be an integer variable, and after
execution of the read statement it is defined as follows: with a negative value if end-of-file
is detected (in which case no data input occurs, and the variables in the input list are undefined), with a positive integer value if an I/O error occurs (also in which case the variables
are undefined), or zero (in which case no error or end-of-file occurred and the variables are
defined with the input values). The non-zero values for the iostat variable are implementation-dependent, but in principle can be used to determine the exact nature of the error.
Alternatives to the iostat= specifier are the end= specifier and the err= specifier (R912).
applies only to input and specifies the label to which the program branches if the
end-of-file is encountered during execution of the read statement in which the end=
end=
Input/Output
49
appears. err= can be used with both input and output and specifies a label to which the program branches if any I/O error occurs during execution of the read or write statement in
which the err= appears. In addition, the err= option is available in the other I/O contexts in
which iostat= can appear: the open and inquire statements. end=/err= can be used together
with iostat=, in the same statement, or they can be used separately.
The input list (R914) can contain any variables, in any order, that can appear on the lefthand side of an assignment statement, including scalar variable names, array variable
names, array elements, array sections, substrings, and structure components; in addition,
the input list can include io-implied-do constructs (R916).
outputting data (write)
A simplified general form of the write statement (R910) is similar to the read statement:
write ( [ unit= ] unit [ , [ fmt= ] format ] [ , [ iostat= ios-variable ] ) [ output-list ]
The output-list specifies the values to be copied to the output destination; the only difference between the input list and the output list is that, whereas the input list must specify
assignment-capable variables, the output list can comprise any set of expressions (including stand-alone variables and expressions formed in io-implied do constructs). If the output list is omitted, an empty record is written; on the screen this appears as a blank line.
The unit, format, and iostat specifiers in the write statement are the same as in the read
statement. The unit is an integer value that identifies the file that is to receive the output, or
it is an asterisk; if the latter, the output is displayed on the users screen. As for input, if the
output is to a file, the unit (integer value) must have been connected, by an open statement,
to the desired file before execution of the write statement. The simplest form of opening a
file for output appears exactly like that for input.
Also as in the read statement, the format specifier in the write statement may be: omitted
(in which case this is a unformatted write, and any subsequent reads on this file must be
unformatted), an asterisk (listed-directed, system-defined default output formats are used),
a character expression, or a label. The format specifies how the values of the output list are
to appear in the destination record. Unformatted output should not be sent to the users
screen.
The only role of the iostat variable in a write statement is to detect, and take corresponding
action, if an error occurs during the execution of the write statement. As in the read statement, if an error occurs the iostat variable is defined with an implementation-determined
positive value; if no error occurs the iostat value is zero.
Examples of the write statement are:
write (dataFile, fmt=* ) x, y, z
50
A redundant form of write(*, format ) ... is provided as the print statement (R911):
print format [ , output-list ]
Similarly, a redundant form of read(*, format ) ... is provided (R909, second alternative):
read format [ , input-list ]
Input/Output
51
Each intrinsic data type has a set of data edit descriptors. The I, B, O, and Z data edit
descriptors are for integer values. The F, D, G E, EN, and ES data edit descriptors are for
real values (and complex values - each complex values takes two real data edit descriptors
- one for the real part and one for the imaginary part). The L edit descriptor is for logical
values, and the A edit descriptor is for character values. A derived type (structure) value
requires a set of data edit descriptors corresponding to its components, an appropriate one
for each of its (intrinsic) components, similar to complex (thinking of a complex value as a
structure with two real components). The following table summarizes these 12 data edit
descriptors:
data edit
data type
descriptor
effect
more
examples
Iw [.m]
integer
optional followed by decimal digits; on output write a minimum of m digits and rightjustify value in field width w; on input value must be an integer constant (not necessarily
right-justified in the field); m has no effect on input; mw; default value of m is 1
I8
I4
I9.5
Bw [.m]
integer
same as I format, except binary digits (0,1) instead of decimal digits and no sign
B16
Ow [.m]
integer
Zw [.m]
integer
Z2.2
Fw.d
real,
complex
output has optional followed by decimal digits with d digits to right of decimal point,
right-justified in field width w; input may be integer, decimal digits with decimal point
anywhere, or either followed by followed by an integer exponent; d+1<w;
need two for complex values (and for the E, D, G, EN, and ES data edit descriptors)
F7.2
F12.8
F5.1
F6.0
Ew.d [Ee]
Dw.d
real,
complex
Gw.d [Ee]
O3
Ew.d output has optional and 0 preceding decimal point, d digits after decimal point,
followed by a base-10 exponent of the form Euu or uuu (u being a decimal digit);
Ew.dEe is the same but with e us in the exponent part; Dw.d is the same as Ew.d but with
a D instead of E in the exponent; d+6<w; same as Fw.d on input, except input value may
have an E or D exponent
E9.2
D9.2
E14.4E4
E30.6
real,
complex
same as Fw.d on input; a generalized edit descriptor that for output value v acts approximately as Fw.d for 0.1<v<10**d and approximately as Ew.d [Ee] otherwise
G10.3
G10.3E3
ENw.d
[Ee]
real,
complex
output is in engineering notation, which is like Ew.d [Ee] but with an exponent divisible
by 3 and 1-3 digits preceding the decimal point; same as Fw.d on input
EN15.5
ESw.d
[Ee]
real,
complex
output is in scientific notation, which is Ew.d [Ee] with the exponent one smaller so that
there is a single nonzero digit preceding the decimal point; same as Fw.d on input
ES15.5
Lw
logical
output consists of w-1 blanks followed by a T or an F; on input, in field width w, any number of blanks followed by an optional period followed by a T or F, followed by anything
L2
L14
A [w]
character
if w is omitted the field width is the length, n, of the character value/variable; on input, if
w>n then the n rightmost characters in the field are read and if w<n then the w characters
are character-assigned to the variable; on output, if w>n then the characters are left-justified in the field and if w<n then the leftmost w character of the value are output
A
A10
A40
52
In these data edit descriptors w, d, e, and m all must be unsigned integer constants (but not
named constants); in addition all may be optionally preceded by an unsigned integer constant (but not named constant) repeat factor; the letters I, B, O, Z, F, E, D, G EN, ES, L
and A must all be capital (cannot be lowercase). All involve a field width, w, which is the
total number of characters reserved for this value.
The control edit descriptors, which can be inserted among the data edit descriptors as
desired, and also comma delimited, are summarized in the following table:
control edit
descriptor
/
effect
at this point complete the current record and start a new one; need not be comma delimited
examples
/,/
Tn
tab to the character column n of the record (tabbing may be either forward or backward)
T40
TL n
TL2
TR n
TR12
nX
S
same as TR n
12X
processor choice as to whether or not to output the optional plus sign (this is the default)
SP
from this point, the optional plus sign must be output; no effect on input
SP
SS
from this point, the optional plus sign must not be output; no effect on input
SS
BN
from this point, nonleading blanks in numeric input fields treated as nulls; no effect on output
BN
BZ
from this point, nonleading blanks in numeric input fields treated as zeros; no effect on output
BZ
scales subsequent numerical values; on input, no effect if the input field has an exponent, and
otherwise divides the input value by 10**k during conversion; on output, no effect for the F, (F
part of) G, EN, and ES edit descriptors, and for the E and D (and E part of G) descriptors
reduces the exponent value by k and multiplies the nonexponent part by 10**k
3P
8P
kP
ch-ed
:
a character constant (but not a named constant) that is written to output; no effect on input
stops output format processing if the output list has been finished (suppresses subsequent ch-ed)
"x= "
:
In these control edit descriptors k and n must be unsigned integer constants (but not named
constants); the letters P, T, L, R, X, S, N, and Z must all be capital (cannot be lowercase).
Some examples of format-specifications containing both data edit descriptors and control
edit descriptors are:
(T5, I5, I5, 2F10.2, A42)
The discussion, tables, and examples in this section summarize most of the important concepts and techniques of I/O formatting. But there are many other combinations and subtlies: treatment of formatting takes an entire chapter and 21 large pages in the Fortran
standard, and 53 (smaller) pages in the exhaustive Fortran 90 Handbook. Consult the references listed in the preface for additional details regarding formatted I/O.
Input/Output
53
specifier
value
meaning
unit=
integer expr.
file=
character expr.
access=
"direct"
"sequential"
"read"
"write"
"readwrite"
"null"
ignore blanks in numeric input fields (can be overridden by BZ); the default
"zero"
action=
blank=
delim=
"apostrophe"
"quote"
"none"
err=
label
form=
"formatted"
the records in the file are formatted; the default for sequential access
"unformatted"
the records in the file are unformatted; the default for direct access
iostat=
integer variable
pad=
"yes"
use blank padding for character input, when needed; the default
54
specifier
value
meaning
"no"
dont pad - require that input data has the requested number of characters
"asis"
"rewind"
"append"
upon connection, insure that file is positioned after its last record
recl=
integer expr.
record length for direct files; number of characters for formatted files;
processor-dependent units for unformatted files, typically bytes or words
status=
"old"
"new"
the file must not exist prior to the connection - created by connection
"unknown"
"replace"
creates or replaces file; in either case, the exist= inquiry returns .true.
"scratch"
position=
For those open specifiers for which character values are listed in the above table (e.g.,
action= "read"), the value can be specified as a character expression, but such expressions
must evaluate to one of the listed options, either in uppercase or lowercase (all lowercase
shown above). For those specifiers having a specific default value, the default is identified;
in the other cases the default is processor dependent. Note the one case that is incompatible with the file= specifier: when status="scratch" is specified.
Some of the options in the above table involve concepts to be discussed in subsequent sections of this chapter; for example, access= "direct" specifies a random file rather than a
sequential file, and random files are described in section below entitled sequential and
random files.
The close statement (R907-908) disconnects the file currently connected to the specified
unit, allowing the unit to be reconnected later to another (or even the same) file. Any connections not explicitly terminated by close statements are automatically close at the termination of the program. As with the open statement, the close statement has a list of
specifiers, only one of which is required (the unit specifier, which is the same as in the
open statement). The close err= and iostat= specifiers play the same error-handling role in
the close statement as they do in the open statement. The only other close specifier is the
status= option, which has two possible values: "keep" specifies that the file remain on the
system after being closed, and "delete" specifies that the file be deleted from the system;
"delete" is the default for scratch files and "keep" is the default for all other files.
Input/Output
55
file inquiry
The Fortran I/O sublanguage has an extensive file inquiry mechanism, which allows information to be obtained about a file before opening it; such information can be used in subsequent connection specifiers. The form of the inquire statement (R923-924) is similar to
that of the open statement in that in has a statement name and a list of specifiers; each
specifier specifies a variable to hold the returned information (except err=, which specifies
a label). As in the open statement, the only specifier for which the keyword can be omitted
is the unit specifier, and then only if this is the first specifier in the list; any given specifier
can appear at most once in a given inquire statement.
Each inquire statement must have either a unit specifier or a file= specifier but, unlike the
open statement, not both. If it has a unit specifier then the inquiry is by unit, and the
information returned pertains to the unit and the file connected thereto (if any). If the
inquire statement has a file= specifier then the inquiry is by file and the information
returned pertains to the file on the system with the name specified in the file= specifier. In
inquiry by unit the specified unit may or may not be connected; in inquiry by file the file
may or may not exist and, if it exists, may or may not be connected to a unit. the various
inquiry specifiers are summarized in the following table.
specifier
unit=
not allowed
file=
not allowed
number=
named=
.true.
name=
file name
exist=
opened=
access=
sequential=
direct=
action=
read=
write=
readwrite=
form=
formatted=
unformatted=
56
specifier
blank=
delim=
err=
iostat=
pad=
position=
recl=
nextrec=
iolength=
recl= value for the output-item-list (a special form of the inquiry statement)
a. The value is undefined if the unit is not connected, or is connected to a scratch file.
b. If the connection is for direct access, all records have the same length;
if the connection is for sequential access, the maximum record length is returned.
Three of the inquire specifiers (unit=, file=, and err=) serve as input to the inquire statement; the others all return values to the program. Three of these specifiers (named=, exist=,
and opened=) return logical values, five (number=, iostat=, recl=, nextrec=, and iolength=)
return (default) integer values, and the rest return (default) character values. Note that in a
great many cases the value return is undefined if the file or unit in not currently connected,
which means that normally an opened= inquiry should be made first.
sequential and random files
Fortran data files come in two flavors, sequential and direct. The records of a sequential
file are processed in sequence, starting from the first record of the file. The read and write
statements illustrated above are sequential reads and writes. (Note that the keyboard is a
sequential input file and the screen is a sequential output file.) Opening a file for
sequential access positions the file at its first record; a sequential file may be repositioned
at its first record by closing the file and reopening it; it may also be repositioned at the first
record, without closing and reopening, by executing a rewind statement (R921-922) on the
unit connected to that file. A sequential file may also be backed up one record by issuing
a backspace (R919) on the unit; this is handy if there is a need to reread (or rewrite) the
previous record. The endfile statement (R920) causes an end-of-file marker to be written to
a sequential file opened for write or readwrite action; closing such a file also writes an
end-of-file marker.
A direct file is so called because a one can go directly to any record number in the file;
direct files are also called random files, because one can specify processing any record at
random. If there are n records in the file, they are numbered, 1, 2, 3, ..., n, and the read or
write statement can specify, with the rec= specifier, which record is to be involved:
Input/Output
57
read ( [ unit= ] unit [ , [ fmt= ] format ] , rec= record-number [ , iostat= ios-variable ] ) input-list
write ( [ unit= ] unit [ , [ fmt= ] format ] , rec= record-number [ , iostat= ios-variable ] ) output-list
Other than the addition of the rec= specifier, the read and write statements for direct files
are the same as for sequential files. The record-number is any (default) integer expression,
the value of which specifies the record to be processed.
All of the records of a direct file are the same length (this does not have to be the case for
sequential files). access="direct" and the recl= specifier must be included when opening
direct files; note that the default formatting for direct files is "unformatted", and thus
form="formatted" must also be specified if the direct file is to be formatted. The inquire
statement with the recl= and nextrec= specifiers can be used to, respectively, determine the
record length of a direct file and the record following the last record processed with a
direct file read or write statement.
partial-record (nonadvancing) I/O
As mentioned above, Fortran I/O is fundamentally record oriented, and explicit specification is needed for a read (write) statement to consume (produce) only part of a record. In
(the default) whole-record I/O, the position of the file is said to advance to the next record
after a read or a write statement. Thus partial-record I/O is called nonadvancing I/O, as the
file position is left where it is rather than advancing to the beginning of the next record.
In nonadvancing input the position of the file is left at the beginning of the next datum
within the record that has not yet been read, and the next read statement continues reading
from that point; in nonadvancing output an end-of-record is not written by the write statement, and the next write statement continues the same output record.
Nonadvancing I/O is specified with the advance="no" specifier (R912) in the read or write
statement; nonadvancing can be specified only for sequential, formatted I/O, so the general forms of the read and write statements for partial-record I/O are:
read ( [ unit= ] unit , [ fmt= ] format , advance="no" [ , iostat= ios-variable ] ) input-list
write ( [ unit= ] unit , [ fmt= ] format , advance="no" [ , iostat= ios-variable ] ) output-list
Note the (syntactic) similarity of nonadvancing I/O with direct I/O, the only differences
being that the format is not optional, and may not be an asterisk, and there is an advance=
specifier rather than a recl= specifier. The "no" can be any scalar (default) character
expression which evaluates to either no or yes (upper/lower case immaterial); yes
represents (the default) ordinary whole-record sequential formatted I/O. An extended
example of nonadvancing read and write statements is:
! read from a file the day-month-year, such as "24 September 1987"; year position unknown;
! write the results in a (slightly) different form to the screen, interleaving the writes with the reads
read (f, fmt="(I2), advance="no") day
! assume that i, j, day, year are integer
write (*, fmt="(I3,TR1), advance="no") day
! print day to screen, blanks on both sides
do i=1,10
read (f, fmt="(A1), advance="no") month(i:i)
! assume that month, m are character
if (i>1.and.month(i:i)==' ') exit
! read characters through second blank
end do
! (first character of month is a blank)
58
This example illustrates the advance="no" option, of course, but also illustrates that nonadvancing can be used with both file I/O and screen/keyboard I/O. If the interleaving of
the read and write statements had been important then, because of the unknown length of
the Month data, the partial-record I/O is exactly the tool needed. If the interleaving is not
important (which it probably isnt in the example as shown) then whole-record read and
writes could have been used, together with and internal read (see the next section). Generally speaking, nonadvancing I/O is indicated when some action must be taken after part of
a record (line) has been input or output and before it is completed.
In nonadvancing I/O the iostat= specifier can be used to detect end-of-record on input as
well as end-of-file. At end-of-file the iostat variable has a negative value and a different
negative value at end-of-record. Unfortunately, these values are implementation dependent, although some implementations provide a module with named constant definitions
that include the end-of-file (typically named EOF) and end-of-record (EOR) values. If the
implementation does not provide such definitions, at least the documentation should identify what these values are for that implementation; then the programmer can provide the
appropriate named constant definitions. If these values are not readily available then resort
must be made to the end= and eor= specifiers, which specify the branch point label if the
input encounters end-of-file or end-of-record, respectively. The eor= specifier is available
for use only with nonadvancing input.
internal data conversion (internal files)
The file unit in a whole-record formatted sequential read or write statement may be a character variable, rather than an integer expression or an asterisk. If the variable is an array
then the effect is as if the array represents a formatted sequential file, each element of the
array being one record of the file; if the variable is a scalar (a scalar character variable, a
substring, or an array element), the file is a one-record file. Such a file is called an
internal file, as the file (character variable), as well as the input or output list entities, is an
internal entity of the program. A read statement specifying an internal file is an internal
read and a write statement specifying and internal file is an internal write. The general
form of internal reads and writes are:
read ( [ unit= ] unit , [ fmt= ] format [ , iostat= ios-variable ] ) input-list
write ( [ unit= ] unit , [ fmt= ] format [ , iostat= ios-variable ] ) output-list
in which the unit in the read statement is a (default) character expression and the unit in
the write statement is a (default) character variable (R901, R903).
The purpose of an internal write is to convert a set of expression values (the output list) to
a (sequence of) character string(s), just as a formatted write to an external file; the purpose
Input/Output
59
of an internal read is to convert a (sequence of) formatted record(s) - any formatted record
is simply a string of characters - to the proper internal values for a set of variables (the
input list), exactly the role of a formatted read of an external file. Thus internal reads and
writes are exactly the same as external reads and writes, except that the records are internal character objects rather the same kind of thing in an external file.
An external read reads from the record, converts the character values as specified by the
format, and defines the variables in the input list; the record itself is not changed and therefore the internal file may in fact be any character expression - it is not limited to a variable.
On the other hand, an external write converts the values in the output list to characters,
according to the format, and writes the record; hence the internal file for an internal
write must be a character variable that can be assigned a value. Any character variable, or
element, section, or substring thereof, in an internal file must not appear in the format (if
specified as a character expression) or the input or output list.
Internal files are most often used to convert between numerical values and character string
(and vice versa). A common instance of this is when the format of an record is not known
until after it has been read (into a character string); after determining the format, an internal read can convert the values to the target variables. For example, consider the example of the preceding section. A whole-record read, coupled with internal reads, can
accomplish the same thing as the nonadvancing reads:
! read from a file the day-month-year, such as "24 September 1987"; year position unknown;
read (f, fmt="(A)) iFile
! assume that iFile isa character variable
i = index(iFile, ' '); i = index(iFile(i+1:), ' ')
! assume i, j , day, year are integer
! i is location of the second blank in IFile
read (iFile(:2)), fmt"(I2)) day
! internal read to convert
month = iFile(3:j)
! assume month, m are character
read (iFile(i:i+4)), fmt"(I5)) year
! internal read
m = "*** January February March April May June July "
//
&
August September October November December "
j = index(m, trim(month)//' ')
write (*, fmt="(I3,TR1,A3,I5)) day, m(j+1:j+3), year ! ordinary advancing write to the screen
! output is the same as in preceding section, but all with whole-record and internal I/O
Note in this example that the contents of the entire external record are read into an ordinary character variable (iFile). The index function is then used to identify the substrings on
which internal reads are used to convert the numeric data into the desired variables.
If the internal file cannot be an unallocated array or unassociated pointer; the file for an
internal read must be a valid character expression (that is, all parts must have defined values). Data transfer in internal file I/O is the same as in external file I/O. Internal file I/O
may be list directed (see next section), but may not be name directed (namelist), direct,
unformatted, or nonadvancing. The file connection (open and close statements), inquiry
(inquire statement), and positioning (backspace, rewind, and endfile) cannot be used with
internal files; the blank="null", delimit="none", and pad="yes" connection specifications are
assumed.
60
The format is an asterisk to indicate system-supplied formatting. The unit may be either an
internal or external file, or an asterisk (keyboard/screen); when the unit is an asterisk the
short form may be used: read * ... and print * ... .
In list-directed input, the first value is extracted from the record and converted for assignment to the first variable in the input list, the second value extracted, converted, and
assigned to the second variable, and so on until values have been read for all of the input
list variables, or until a slash (/)or end-of-file is encountered. If a slash (or end-of-file) is
encountered and some of the variables have not been assigned new values, those input list
variables retain their current values.
A value in the input file is separated from the next value by a blank or a comma; a comma
may optionally be preceded and/or followed by a blank. (Multiple consecutive blanks in
the input, but not in a character value, are equivalent to a single blank, and blanks are
never zeros.) Consecutive commas (possibly with intervening blanks) represent null input
values, and the corresponding input list variable values are not changed. The end of a
record is treated as a blank.
A numeric input value must be in the form of a numeric constant, assignment compatible
with the input list variable to which it is to be assigned, but binary, octal, and hexadecimal
constants must not be used in list-directed input and the separator characters (blank,
comma, and slash) cannot be part of a logical value (they would be treated as value separators). A character value may be a character constant, assignment compatible with the corresponding input list variable, or not delimited at all; in the last case the first appearance of
a separator character terminates the character value; a separator character appearing in a
character constant is part of the constant, however, and not treated as a separator.
A value may be repeated, much as in the data statement (R532), by preceding it with an
unsigned (default) integer constant followed by an asterisk; for example: 4*1.0 is equivalent to 1.0, 1.0, 1.0, 1.0. Such a repeated construct must contain no blanks (any blank
would serve as a value separator). The repeat without a constant specifies that many consecutive nulls; for example 6*, specifies six nulls and is equivalent to , , , , , , , .
Input/Output
61
The format for list-directed output is entirely implementation dependent, except that it
must be (almost) suitable for list-directed input of the same values in the same sequence.
An integer value is in I format, a real value is in F or E format, the real and imaginary parts
of a complex value are enclosed in parentheses and separated by a comma, a logical value
is T or F, and a character value is delimited by the character specified by the delim= specifier in the open statement (note that the delim= default is none); if a character value is
written with single (or double) quote delimiters, any single (or double) quote characters in
the character values are repeated once, as per the rules for character constants. The
almost in the first sentence of this paragraph refers to the situation where a character
value containing separator characters is written with delim="none"; in this case the listdirected output does not represent the same set of values for subsequent list-directed input.
A list-directed write statement may output any number of records, and the first character
of each such record is a blank.
Name-directed I/O is similar in many respects with list-directed I/O, except that the values
in the input or output list can be in any order. This is accomplished by making two syntax
changes in the read and write statements and keywording the input (and output) values.
The value keywords are modeled after the specifiers (e.g., iostat=...) of the various I/O
statements - the value is preceded by a variable= construct, where variable is the identification of the variable to receive that value (input) or whose value is to be written (output);
note that name-directed output works only with variables, not with arbitrary expressions.
The following forms for the name-list read and write statements illustrate the two syntax
changes:
read ( [ unit= ] unit , [ nml= ] group-name [ , iostat= ios-variable ] )
write ( [ unit= ] unit , [ nml= ] group-name [ , iostat= ios-variable ] )
The two changes are: (1) the fmt=* has been replaced by nml=group-name, and (2) there is
no input list or output list, which are also replaced by group-name. The group name is
defined by the namelist specification statement (R543-544), the simplest form of which is:
namelist / group-name / variable-name-list
The namelist statement associates a name (the group name) with a list of variable names;
some or all of these variables, or parts of them, are assigned input values by a namedirected read statement; similarly the values of some or all of these variables, or parts of
them, are output by a name-directed write statement. Each name in the variable name list
of a namelist statement must be a scalar or array variable name, but cannot be the name of
an array dummy argument with a nonconstant bound, an allocatable array, a variable with
a nonconstant character length, a pointer or an structure containing a pointer, or any other
nondummy argument local variable without the save attribute.
The variable part of a variable=value pair may specify one of the names in the variable name
list, or an element or section of an array having one of those names, a component of a
structure with one of those names, or a substring of a character variable with one of those
62
names. The value part of a variable=value pair may be empty (null value), a single scalar
value (if the variable is a scalar), or if the variable is an array (or array section) the value is
either a sequence of comma or blank separated scalar values or of the repeated * form
(as in list-directed I/O); as in list-directed I/O, if there is no value following the * then
that many null values are specified.
Name-directed input starts with an ampersand followed (immediately) by the group name,
followed by a set of variable=value pairs (in any order), and ending with a slash. Each variable=value must be preceded by a comma or a blank; there may be a blank between the =
and the value. If the variable and value are scalar, that value is assigned to the specified
variable; if the variable is array valued then the specified sequence of scalar values are
assigned to the corresponding elements of the array. Unlike list-directed input, a character
value in name-directed input must be a character constant; otherwise name-directed input
is pretty much the same as list-directed input. Name-directed output has an implementation-dependent form, but must be (almost) suitable for subsequent name-directed input for
the same variable values; the almost is the same as for list-directed I/O - if
delim="none" then character output is not delimited and thus likely would not represent
the same values for namelist input.
Examples of list-directed and name-directed I/O are:
read (labData, fmt=*) name, weight(1:4)
! #1 ! weight is an array
"white rats"
4.3, 5.1, 4.6, 4.3
print *, name, weight (3)
white rats 4.319683
Each of the above input statement reads data from a file (labData), and prints it on the
screen. Note that the print * statement may be used for list-directed screen output, but not
for name-directed output. Also note the subtle change in the input data between cases #1
and #3 - in the first case the name is two words separated by blanks, in the second the
blank is replaced with a hyphen; the output for #2 is not suitable for re-input with the #1
read statement, but the #4 output is suitable for re-input with the #3 read statement.
Control Structures
63
Control Structures
Control structures allow the programmer to (a) select which statements are executed next
(if and select), (b) specify repetitive execution of a group of statements (do), and (c)
branch to another part of the program (goto).
if construct
The if construct has the basic form:
if ( logical-expr ) then
executable-constructs
end if
If the logical-expr is true then the block of executable constructs is executed; if the logicalexpr is false then the block is skipped. Note that the executable constructs can be any mix
of action statements and other (nested) constructs, such as loops, other if constructs, etc.
The syntax of the if construct is more fully described in syntax rule R802 and the rules it
references.
Another useful form of the if construct is:
if ( logical-expr ) then
executable-constructs
else
executable-constructs
end if
In this form the first block of executable constructs (between the if and else), but not the
second (between the else and end if) is executed if the logical-expr is true, and just the
reverse if it is false. This form of the if construct has one logical expression and two blocks
of executable constructs. One can think of the logical expression as guarding the first
block; if the guard is true the first block is executed and the second one isnt; if the guard
is false the block it guards (the first one) is not executed and the second one is.
The most general form of the if construct involves n guards (logical expressions) and n+1
blocks of executable constructs (where n can be any integer value greater than zero):
if ( logical-expr ) then
executable-constructs
[ else if ( logical-expr ) then
executable-constructs ] ...
[ else
executable-constructs ]
end if
Each guard is associated with (guards) its own block of executable constructs. The executable construct associated with the first guard that is true is executed and the rest of the if
construct is skipped. If none of the guards are true then the unguarded block (the one
between else and end if) is executed. Note that the optionality brackets in the above gen-
64
eral form show that the other two forms described above (with just one guard, with and
without an unguarded block) are just special cases of this general form.
An example of an if construct with two guards is:
if ( temperature > BOILING ) then
...
else if ( temperature > FREEZING ) then
...
else
...
end if
! vapor phase
! liquid phase
! solid phase
Finally, Fortran has a single-line if statement, also called the logical if:
if ( logical-expr ) action-stmt
In this case the action statement is executed if (and only if) the logical expression is true.
The logical if is especially handy when you want to get out fast:
if ( code == "DONE" ) exit
if ( n > 20 ) return
The guards in an if construct need not be disjoint - that is any of them can be true at the
same time. But only one block of executable constructs is executed - that one guarded by
the first (top most) guard that is true. In the case (select) construct, however, at most one
guard can be true at any given time.
case construct
The case construct also involves n guards and n+1 blocks of executable constructs, only
one (or, more precisely, at most one) of which is executed. The order of the guards in a
case construct is immaterial (whereas the order of the guards in an if construct may well
be critical - witness the temperature example above).
The case construct syntax is described in detail in R808 and the syntax rules it references.
The general form is:
select case ( case-expr )
[ case ( case-value-list )
executable-constructs ] ...
[ case default
executable-constructs ]
end select
The case expression and case values may be of type integer, type character, or type logical;
all of the case values are constants, and all of the case-value lists are disjoint. The block of
executable constructs corresponding to (guarded by) the case-value list that contains the
value of the case expression (or the default block, if there is one and there is no value
Control Structures
65
match) is the block executed. Since the case-value lists are disjoint, the case expression
value can match at most one, and therefore the order of the case blocks, including case
default, is immaterial.
The case-value lists are comma-separated lists of constants or constant ranges, as
described by R813. Examples of the case construct are:
select case ( shape )
case ( CIRCLE );
case ( SQUARE );
case ( TRIANGLE );
case ( HEXAGON );
case default;
end select
area = d*d*PI/4
area = d*d
area = d*d*sqrt(3.)/2
area = 6*d*d*sqrt(3.)/8
area = f_area(shape,d)
...
...
...
! youth
! adult
! senior
do construct
Modern loop constructs do not involve statement labels. For compatibility with older Fortran code, which makes extensive use of the original labelled form of the do construct,
Fortran 90 has three categories of do construct:
(a) a modern construct (do - end do) without any labels
(b) the modern construct with labels
(c) the original style
Category (b) is the same as (a) with an optional label, and is provided for those who want
the modern structure but prefer to have loops with labels.
The syntax of all forms of the do construct is described in R816 and the syntax rules it references. The modern form, without labels (category (a)), itself comes in three flavors infinite, indexed, and while:
do
executable-constructs
end do
do while ( logical-expr )
executable-constructs
end do
66
Execution of the infinite do construct loops forever unless there is an exit statement
somewhere in the block of executable constructs (loop body).
The semantics of the indexed do is best described by making the first line more specific:
do i = e1, e2, e3
If e3 is omitted, a value of +1 is assumed; if e3 is negative then the test is i < e2 rather than
i > e2. Of course a value of zero must not be specified for e3. (See R817 and related syntax
rules for additional, but inconsequential, syntax details of the indexed do construct.)
The semantics of the while loop are:
do; if ( .not. logical-expr ) exit
executable-constructs
end do
The modern form with labels (category (b)) simply replaces do and end do with labelled
versions of these statements (same label on both); the label is described in R313; the unlabeled and labelled versions of these two statements are summarized as follows:
unlabeled
labelled
do
do label
end do
label end do
label continue
The original style DO-loop (category (c)) required labels and did not have end do. Though
it allowed terminating a loop on a labelled continue statement, it did not require it; the
(labelled) last statement could be the final action statement of the loop body (R827). (Note
that such an action statement could not, however, be a goto, return, or other branching
statement.) Moreover, two (or more) nested loops could share the same termination statement (and label) - see R830. For example, a two-dimensional array can be initialized with
the nested loops:
do 101, i=1,m
do 101, j=1,n
101 x(i,j) = 0
Control Structures
do i=1,m
do i=1,m
x(i,j) = 0
end do
end do
67
The execution of any loop may be explicitly and immediately terminated (with an exit
statement, R835) or advanced to the next iteration (with a cycle statement, R834) anywhere within the loop body. The most common use of these features is to exit a loop upon
the occurrence of some condition. A common pattern, for example, is the read-test-process
nature of processing file data:
do
...
if ( end-of-file ) exit
...
end do
If only part of the records are to be processed, then the loop could be:
do
...
if ( end-of-file ) exit
if ( not-of-interest ) cycle
...
end do
In the nested loop case these simple forms of exit and cycle apply only to the inner-most
loop in which they appear. To make them apply to an outer loop, that outer loop must be
named with a construct name (R818, R825) and the exit (or cycle) statement must specify
this name. For example:
outer_loop: do
...
do
...
if ( . . . ) cycle outer_loop
...
end do
...
end do outer_loop
goto statements
The if, case, and do constructs provide the disciplined, readable, and reliable way to control the execution sequence. The goto statement, and variations, are primitive, but powerful, branching statements that allow execution to be switched to (almost) any other place
in the current scope. The basic goto (which can also be spelled go to) has the form:
goto label
! see R836
68
Execution of a goto statement causes execution to resume with the statement having the
label specified in the goto statement. Any action statement may be labelled, as well as the
if, select, or do statement (that is, first statement) of a control construct.
A goto statement must not cause a branch into the body of an if, select, or do construct
from outside that construct, but the reverse (branch out from inside) is allowed.
Though a label may be placed on any action statement, plus a few others, many programmers prefer to use only the continue statement to identify a branch point:
! see R840; execution of continue does nothing
label continue
The computed-goto statement (deprecated - see chapter 5) specifies a list of labels and
causes a branch to one of them, depending on the value of an integer expression:
! see R837
For example:
goto ( 222, 333, 222 ) K/5
causes a branch to the statement labelled 222 if K is in the 5-9 range or 15-19 range, to the
statement labelled 333 if K is in the10-14 range, and has no effect otherwise.
The assigned-goto statement (also deprecated) uses an integer variable as a label:
! see R839
Prior to executing an assigned-goto statement, the integer variable must have been
assigned a label value with the assign-statement (also deprecated):
! see R838
If the optional label-list is included in the assigned-goto statement, the label value of the
integer variable must match one in the list.
The arithmetic-if (also deprecated) causes a branch to a specified label, based upon a
numeric value:
if ( numeric-expr ) label , label , label
! see R840
If the numeric value is less than zero the branch is to the first label, if the value is zero the
branch is to the second label, and if the value is greater than zero the branch is to the third
label.
Modules
69
Modules
The module is a new program unit in Fortran 90 that provides definitions for use in other
program units; modules may be placed in separate files and re-used with different programs.
A module is not executable; it contains definitions to be used by other program units; these
definitions include procedures, which are individually executable, but the module itself is
not executable.
Module entities are made available to other program units by the use statement:
program Seismic_Processing
use Seismic_Trace_Definitions
...
end program
Available modules entities are said to be use associated within the using program. A
module may contain private entities; such entities are not available to using program units
(private entities are available only within the module itself, including any procedure definitions within the module). In addition, the only form of the use statement limits the module entities that are available in the using program unit.
The principal contents of a module include: type definitions, interface definitions, procedure definitions, and shared data objects (including global constants). Typical uses of
modules include: procedure libraries (with explicit interfaces), encapsulated data abstractions, and shared-data units (alternative to COMMON).
module structure
The general structure of a module (R1104-1106) is as follows; additional syntax rules are
listed for specific items in the following description:
module module-name
use-statements
constant-definitions
variable-declarations
interface-blocks
type-definitions
contains
module-subprograms
end module
module use
Other program units (main programs, functions, subroutines, and other modules) may use
the definitions provided in a module by including a use statement (R1107-1109) immediately after the program unit heading, as in the Seismic_Processing example above:
70
Module entities are imported into the using program with the same name as they have in
the module, unless they are renamed in the use statement; this may be necessary to avoid
name conflicts, as an imported (use associated) name does not mask a local entity
with the same name. A rename (R1108) has the form:
local-name => use-name
where local-name is the new name (in the using program) and use-name is the name of the
entity in the module (the new name points to the module entity). An only (R1109) can be
either the name of the module entity being imported, or a rename:
[ local-name => ] use-name
A module for the above Seismic_Processing program might take the form:
module Seismic_Trace_Definitions
real, parameter :: PI=3.1415926
real, allocatable :: seismicWorkArray(:,:)
! a global constant
! a shared data work-space
interface FFT
subroutine FFT_C (...)
...
end subroutine
end interface
type SeismicTrace
real :: trace(1000)
end type
contains
!----------------------------------------function FFT (...)
...
end function FFT
!----------------------------------------subroutine FFT_C (...)
...
end subroutine
!----------------------------------------subroutine timeDomain (...)
...
end subroutine
!----------------------------------------end module
Modules
71
module applications
A module might contain just shared (global) constants and variables:
module Shared_Data
real, parameter :: PI=3.1415926
integer :: n_rho, n_vel
real, allocatable :: workArray(:,:)
end module
A module might be used to collect a set of procedure interfaces, for use by other program
units; these can include (1) explicit interfaces for external procedures, (2) generic (overloaded) names for specific procedures, and (3) operator symbol definitions:
module Procedure_Interfaces
!----------------------------------------interface
subroutine T_time (A)
real :: A(200,300)
end subroutine T_time
end interface
!----------------------------------------interface FFT
subroutine FFT_C (...)
...
end subroutine
module procedure FFT_R
end interface
!-----------------------------------------
72
interface operator(.inverse.)
module procedure inverse
end interface
!----------------------------------------interface operator(+)
function or(a, b)
logical :: or
logical, intent(in) :: a, b
end function
module procedure addCharDigits
end interface
!----------------------------------------contains
!----------------------------------------function inverse (matrix)
...
end function
!----------------------------------------function addCharDigits (d1, d2)
integer :: addCharDigits
character :: d1, d2
...
end function
!----------------------------------------end module
Modules
73
! etc....
74
Procedures
75
Procedures
Subroutines and functions are the two forms for Fortran 90 procedures; each may appear
in the following contexts: external (stand-alone, separately compiled), module (packaged
within a module definition), internal (packaged within another procedure or main program
definition). Fortran 90 has a large number of built-in intrinsic procedures; these are summarized here and described in detail in chapter 10. Both subroutines and functions are
used to encapsulate particular computations, and the principal difference between them is
the manner in which they are used (called, invoked). A subroutine does not return a value
(except possibly through its argument list) and is invoked by a separate subroutine call
statement; a function returns a value and is invoked by using its name (and arguments) in
an expression in which its returned value is used.
Procedures interact with each other (primarily) through argument lists, and these interfaces are either explicit (known) or implicit (unknown) to the calling procedure; only
external procedures have implicit interfaces; interface blocks can make even these interfaces explicit. Procedures can be generic (multiple procedures called by the same name),
and procedures may be used to define new operators.
subroutines
A subroutine is defined by a subroutine subprogram (R1219), which has the form
subroutine subroutine-name ( dummy-arg-list )! see R1221 for dummy arguments
specification-part
! see R204 for specification-part
execution-part
! see R208 for execution-part
internal-subprogram-part
! see R210 for internal-subprogram-part
end subroutine
Any of the three parts in a subroutine definition may be empty, but a subroutine will normally have a specification part (e.g., argument declarations) and do some computation
(execution part). If the subroutine is recursive, it definition starts with the keywords recursive subroutine rather than just the keyword subroutine. See R1219 for some minor syntax
options (such as allowing the subroutine name to be repeated on the end subroutine statement).
A subroutine definition may be placed in:
(1) the internal-subprogram-part of a module (R1104), in which case it is a module subroutine,
(2) the internal-subprogram-part (R210) of an external subroutine definition, an external
function definition, a main-program (R1101), or a module procedure definition, in
which case it is an internal subroutine,
(3) its own file, or a file with other stand-alone procedure definitions, in which case it
is an external subroutine.
76
An external subroutine has an implicit procedure interface (if no interface block is supplied for it) and, as it has no host, does not access a host data environment. (An external
subroutine is also the only kind of subroutine in which end is an acceptable abbreviation
of the end subroutine statement.)
A module subroutine has an explicit interface and accesses the data environment of its
host module; an internal subroutine has an explicit interface and accesses the data environment of its host procedure.
In all cases, a subroutine is invoked with a call statement (R1210):
call subroutine-name ( actual-arg-list )
If the subroutines interface is explicit the compiler can enforce consistency between the
actual-arg-list in the call statement and the dummy-arg-list in the subroutine definition;
otherwise interface consistency is not enforceable. (Interface inconsistency is the source of
difficult-to-find errors in programs with implicit interfaces.)
(Note: subroutine argument lists may include alternate returns (deprecated - see chapter
5), and this is the only way that subroutine argument lists differ from function argument
lists. An alternate return is an asterisk (*) in a dummy-arg-list; the corresponding actual argument must be a *label (e.g., *220) specifying the alternate return point.)
functions
A function is defined by a function subprogram (R1215), which has a form similar to that
of subroutines:
[ type-spec ] function function-name ( dummy-arg-name-list ) [ result ( result-name ) ]
specification-part
! same
execution-part
! as in
internal-subprogram-part
!
subroutines
end function
As with a subroutine, recursive must be added to a recursive function (R1217), and the
result clause is required for recursive functions (and optional for all other functions). See
R1215 for other (minor) syntax options. Functions may be internal, module, or external in
exactly the same way as subroutines, with the same implications in each case.
Each function returns a result value and therefore must have a result type; that type may be
specified on the function statement (type-spec) or in the specification part of the function.
Function results may be of any type, including derived type, and may be array valued; if
the function is array valued, the array (dimension) attributes must be specified in the specification part. The result clause, if present, specifies the name to which the result is
assigned in the execution part; otherwise the function name is also the result name.
A function is invoked as an operand in an expression, not as a stand-alone statement, and
its result value becomes the value of that operand; such a function call has the form
(R1209):
Procedures
77
function-name ( actual-arg-list )
Explicit interfaces and arguments work the same for functions as for subroutines, except
that alternate returns are not allowed in function arguments lists. The result clause is
required for recursive functions for the following reason. Consider:
recursive function rf(a,b) result(rf_result)
integer :: a, b
real :: rf_result(2,3)
...
... = rf(2,1)
...
end function rf
If the result clause had not been present, then rf would be used for the result value as well
as for recursive calls. Because rf has two integer arguments and returns a two-dimensional
array, the reference rf(2,1) could be either a recursive call or a reference to an element of
the result. Though only very few combinations of argument lists and arrayness cause such
ambiguity, nevertheless the Fortran 90 rule is recursive implies result.
host association
All procedures have the following four data access mechanisms: (1) local entities, (2)
argument association, (3) use association, and (4) common association. The second of
these (argument association) allows a procedure to access entities explicitly passed by
the procedures caller; the third (use association) refers to module entities accessed via use
statements in the procedures specification part; the fourth (common association) refers to
entities in the common blocks listed in the specification part. These are the only data
access mechanisms for external procedures.
Module procedure and internal procedures have a fifth mechanism - host association. Host
association refers to a procedures access to entities declared in the procedures host. The
host of a module procedure is the module that contains its definition; the host of an internal procedure is the procedure (or main program) that contains its definition. Any entity
declared in the host is automatically accessible by that declared name in the contained procedure - even private module entities (private affects only use association) - unless the contained procedure has an explicit declaration of that name. In the latter case the name refers
to an entity local to the procedure and not to the host entity with this name; the host entity
is then available to the procedure only through argument association. The following example illustrates these concepts:
program P
integer :: x
real :: y
...
call s1(x)
...
contains
78
In the execution part of subroutine s1, x is (always) the local real variable (not the hosts
integer x), y is (always) the hosts real variable, and z is the argument-associated entity; in
the shown call to s1, z becomes associated with the hosts x, and thus for this call z in the
procedures execution part refers to the hosts x.
In the preceding example the host-association rules are simple and obvious because all
entities are explicitly declared. Fortran 90 allows implicit declaration of variables, however, which can make host association less obvious. The above rules, as stated, still apply;
the one missing piece is this: a variable implicitly declared in the host is host associated as
if it were explicitly declared and a variable implicitly declared in a contained procedure
(possible only if it has not been explicitly or implicitly declared in the host) is local to the
procedure. Recall that a variable is implicitly declared if there is no type declaration for its
name in the specification part, but its name is referenced in the execution part. The following example illustrates the host-association rules involving implicit declarations:
program P
...
call s2(x)
...
contains
subroutine s2(z)
...
print *, x, y, z
...
end subroutine
end program
! no type declarations in s2
! x is host associated
! y is local to s2
! z is argument associated (with x in this case)
In this example subroutine s2 accesses three variables, x, y, and z, all implicitly declared. x
is implicitly declared in the host, by virtue of its reference in the call statement, and thus is
host associated in s2. y is not (explicitly or implicitly) declared in the host and so is
implicitly declared in s2, by virtue of its reference in s2, and is therefore local to s2. z is
argument associated.
The default implicit typing rules in a main program, module, or external procedure are: all
default real except variables starting with letters I-N, which are implicitly default integer.
Implicit typing can be turned off (with implicit none, which then requires that all variables
to be explicitly typed) or modified by implicit statements (R540) in the specification part of
the host. Whatever implicit typing is in effect in the host becomes the default implicit typing in the contained procedure. This can in turn be turned off (implicit none) or modified
by implicit statements in the specification part of the contained procedure. These are
straightforward, consistent rules, but by far the simplest host association scenario is
explicit declaration of all entities in both the host and the contained procedures.
Procedures
79
Note that actual arguments that are substrings work well with assumed-length dummy
arguments. Similarly, actual arguments that are array sections work well with assumedshape dummy arguments.
This simple set of argument association rules is all that is needed, and is the preferred way,
to develop new Fortran code and to update existing code. However, assumed-shape
dummy arguments require explicit procedure interfaces, and much existing code predates
Fortran 90, explicit interfaces, and assumed-shape dummy arguments. Fortran 90 allows
the array element sequence association mechanism for array arguments that Fortran provided prior to Fortran 90. In this case the dummy argument is declared as either an
explicit-shape array (R513) or an assumed-size array (R518); the principal difference
between the two is that the last dimension of an assumed-size array is declared as an asterisk. An actual argument array must have a size (total number of elements) at least as big as
an associated explicit-shape or assumed-size dummy array (a condition that will automatically be satisfied by an assumed-size array).
Array element sequence association treats the associated actual and dummy arrays each as
a linear sequence of array elements, with the corresponding elements of each sequence
being associated; thus the nth element of the actual array sequence is associated with the
nth element of the dummy array sequence. The order of such a sequence is Fortrans array
80
element order, which varies the first subscript first, the second subscript next, and so on.
Thus, for a two-dimensional array, array element order is the first column followed by the
second column, and so on; for the array declared as real :: x(3,2), array element order is
x(1,1), x(2,1), x(3,1), x(1,2), x(2,2), x(3,2).
Array element sequence association means, essentially, that the ranks of the actual and
dummy arguments are immaterial, and therefore the ranks are not required to match in this
form of argument association. If the actual argument is an array section (and the dummy
argument is not assumed shape) the processor must generate an array element sequence
for array element sequence association with the dummy argument; this may involve copying the array section into a contiguous area of memory before association with the dummy
array, and then refreshing the original array section from this copy after execution of the
procedure call is completed (copy-in, copy-out).
If character arrays are involved in array element sequence association there is one additional wrinkle - the sequences generated are character sequences, not array element
sequences, and the association is character by corresponding character. If the character
length of the actual and dummy array elements are the same (as they would be with
assumed length) then this character association is equivalent to array element association.
With array element sequence association both the array rank and character length can be
changed across procedure boundaries, with the indicated consequences for argument
association.
Array element sequence association is permitted in any procedure, by declaring the
dummy array as an explicit-shape or assumed-size array, and is the only option for procedures with implicit interfaces - that is external procedures without interface blocks. In
those cases where the interface is explicit (all module and internal procedures, and external procedures with interface blocks) both array element sequence association and
assumed-shape array association are permitted (and normally assumed-shape array association is preferred).
Structure (derived type) argument association follows the same rules as for other types namely, the actual and dummy arguments must be the same type. This means they must be
derived from the same type definition. Another form of structure association, called structure sequence association, involves sequence structures (R422-423). In this case the same
type rule for the actual and dummy arguments is relaxed in favor of equivalent types.
Equivalent structure types are sequence types with the same type name and with components that are all public and agree in order, name, and type (or equivalent type).
A caveat about procedure arguments, regardless of the association mechanism, is that if
the same entity becomes associated with two (or more) dummy arguments then, in order to
prevent nondeterminism in results, the procedure must treat both dummy arguments as
intent(in). There are two common instances of this situation. One is when an actual argument is an array section with at least one vector subscript; in this case two or more of the
actual array elements may be the same element of the sections parent array and will be
associated with different dummy array elements. The second case is when the same data
entity is used two (or more) times in an actual argument list: e.g., call s3(x,y,x).
Procedures
81
For procedures with explicit interfaces, the actual argument list may be keyworded
(R1211-1212). When the interface is explicit, the dummy argument names are known to
the procedures caller. This information allows the actual arguments to be placed in any
order, if the dummy argument names are used as argument keywords in the call. For example, in this call to subroutine s4 (which has dummy arguments d1, d2, and d3, in that order)
call s4(d2=x, d3=y, d1=z)
the actual arguments are not in the order of their associated dummy arguments, but
because the interface is explicit the processor can create the intended associations.
A dummy argument may be declared as optional (R503, R520). This effectively creates
overloaded (generic) versions of the procedure, and calls to such procedures are resolved
in accordance with the generic reference resolution rules (see below). The present intrinsic
function is available for use within the procedure to determine if in a given call to the procedure the optional dummy argument has an associated actual argument or not. Note that
either optional arguments must be the last ones in the dummy argument list or calls that
omit actual arguments must be keyworded. In any event, optional arguments require
explicit interfaces.
Dummy arguments are references to (aliases for) their associated actual arguments. One
consequence of this is that any change to a dummy argument is reflected in the actual
argument. The intent may be specified for a dummy argument to control such unbridled
access in some respects. The intent attribute (R503, R511, R519) may limit the use of the
dummy argument to in, out, or inout. Intent(in) arguments are intended for input to the
procedure; the actual argument must be defined upon entrance to the procedure - it may be
a variable or an expression - and the dummy argument must not be defined in the procedure. Intent(out) arguments are intended for procedure output - the dummy argument must
be defined at some point during execution of the procedure (thus the actual argument must
be a variable); the associated actual argument need not be defined upon entrance, so an
intent(out) dummy argument must not be referenced in the procedure before it is defined.
Intent(inout) specifies that the actual argument must be defined upon entrance and the
dummy argument may be defined in the procedure; the associated actual argument must be
a variable.
Procedures may be passed through argument lists. That is, a dummy argument may be
declared as a procedure name (in an external statement, intrinsic statement, or in an interface block) or used as a procedure name (in a call statement or in a function reference).
The associated actual argument must be the name (without an argument list) of a specific
procedure (generic procedures cannot be passed). If the dummy argument is declared or
used as a function name, the associated actual argument must be the name of a function; if
the dummy argument is declared or used as a subroutine name, the actual argument must
be the name of a subroutine. Except for internal procedures and statement functions,
which cannot be used as actual arguments, any specific procedure, including any specific
intrinsic function, may be used as an actual argument.
82
interface blocks
A procedure interface comprises the information needed to use that procedure correctly;
explicit interfaces make this information available to the calling environment. Interface
blocks are used to provide various explicit interfaces. Explicit interfaces include dummy
argument list characteristics, alternate names for a procedure (primarily used to define
procedure overloads - that is, generic procedures), and new operator and assignment definitions.
Interface blocks are not needed to make module and internal procedure interfaces explicit,
as these interfaces are automatically explicit wherever such procedures are accessible.
However, external procedure interfaces are not automatically explicit; interface blocks
(R1201) with one or more interface bodies (R1204) may be used to make them explicit:
interface
interface-body
[ interface-body ] ...
end interface
Each interface body specifies an external (or dummy) procedure name, its type (if it is a
function), and the order names, and types (and kinds) of all dummy arguments.
If a function has certain properties it may be given an operator interface, thereby creating
a defined operator, and called using operator notation; it must have one (unary operator) or
two (binary operator) intent(in) arguments. Such a function may be called with either the
normal function syntax or infix operation format; in the latter form the first actual argument appears as the first operation operand and the second actual argument is the second
operand (for unary operators the operand follows the operator). The operator form of the
interface block is used to define a new operator and associate it with one (or more) functions:
interface operator ( defined-operator ) ! suppose this defines an overload of +; then
[ interface-body ] ...
! sum_char_int(c,i) the function form
[ module-procedure-stmt ] ...
!c+i
the operator form
end interface
A defined operator can be either a user-defined dot operator or (an overload of) an intrinsic
operator (R311), as in the preceding example. If it is an intrinsic operator it must not redefine an intrinsic operation - for example, the + operator must not be given an operator
interface for a function with two integer arguments, as that would be an attempt to redefine
addition of two integer values. All operator definitions are considered to be generic proce-
Procedures
83
dure definitions and must be consistent with the generic reference resolution rules (see
below). The function(s) associated with a defined operator may be either external functions (in which case the interface contains the corresponding interface bodies, as in the
above example) or accessible module functions (in which case the interface contains the
corresponding module procedure statements).
If a subroutine has two arguments, the first being intent(out) or intent(inout) and the second being intent(in), then it may be given an assignment overload:
interface assignment ( = )
[ interface-body ]...
[ module-procedure-stmt ]...
end interface
An example is:
interface assignment ( = )
subroutine to_char_from_int(c, i)
character :: c
integer :: i
end subroutine
end interface
The purpose of such a subroutine is to convert the value of the second argument to an
appropriate value for the type of the first argument, and to assign this converted value to
the first actual argument; the subroutine defines the conversion that takes place in such an
assignment. The assignment interface makes it possible to use assignment syntax for this
operation, as an alternative to using normal subroutine calls. In analogy with operator
interfaces, assignment interfaces define assignment overloads and thus must be consistent
with the generic reference resolution rules. Intrinsic assignments cannot be redefined
except for intrinsic assignment of structures (that is, derived type intrinsic assignment). As
with operator functions, assignment subroutines may be either external subroutines or
module subroutines.
Interface blocks may be used to define overloaded (generic) procedure names. Any procedure name may be (further) overloaded, including an intrinsic procedure name:
interface generic-name
[ interface-body ] ...
[ module-procedure-stmt ] ...
end interface
A generic name may be associated with any number of external procedures and module
procedures. Such a procedure may be called using either its original (specific) name or the
generic name. A call to a procedure using the generic name is considered to be a generic
reference; any generic reference must be resolvable to a specific procedure, in accordance
with the generic reference resolution rules. Generally speaking, this means that each procedure sharing the same generic name must have a different argument signature (type
pattern). External and module procedures may be given generic interfaces.
84
generic procedures
A generic procedure is one that can be called in more than one way. These include procedures with generic as well as specific names, functions with operator interfaces (function
reference and operator form), and subroutines with assignment interfaces (subroutine call
and assignment syntax). The only restriction on the proliferation of generic procedures is
that each reference be resolvable to the appropriate underlying specific procedure.
There are two rules which allow generic procedure references to be resolved to a unique
specific procedure. the first of these rules (rule (a) below) derives from the positional significance of an argument when keyworded calls are not involved; the second (rule (b))
imposes a further restriction in order to disambiguate keyworded calls. If two procedures
may be called with the same generic name (or with the same operator or assignment syntax), one of the argument lists must have a nonoptional dummy argument that (a) has a
type/kind/rank pattern different from that of the dummy argument (if one) in the same position in the other argument list and (b) has a name/type/kind/rank pattern different from
that of all the dummy arguments in the other argument list. That is, there must be at least
one argument that disambiguates two generic references on the basis of it type/kind/rank
signature (and dummy argument name also, in the case of keyworded calls).
Most of Fortrans intrinsic procedures are generic, and references to these intrinsics are
resolved in the same manner as described above. Intrinsic functions have an additional
generic form: many of them are elemental. An elemental function is one defined with a
scalar dummy argument and a scalar result. It may, however, be called with an array actual
argument, and in this case delivers an array result with the same shape; the value of each
result element is the same as if the function had been called with the corresponding actual
argument array element.
return statement
The return statement (R1224) is a separate statement that causes return from a procedure,
in the same way as the procedures end statement. return can be used anywhere in the execution part, but is needed only in exceptional cases. See chapter 5 for alternate returns.
statement functions
A statement function is a one-liner function (R207, R1226), with scalar arguments and a
scalar result, for use only in the program unit in which it is defined. Statement functions
are not internal procedures, their interfaces are always implicit, they may not be used as
actual arguments, and they employ only intrinsic operations. Statement function calls have
the normal function call syntax and argument association rules. (See also chapter 5.)
entry statements
The entry statement (R1223) can be used to provide alternate entry points into a procedure; the entry statement has a name and an argument list, similar to the function or subroutine statement, and can be placed anywhere in a function or subroutine definition. The
original purpose of the entry statement was for data -sharing among different procedures,
a functionality now better provided by internal and module procedures.
Procedures
85
intrinsic procedures
The rest of this chapter is devoted to summarizing and categorizing Fortran 90s 113
intrinsic procedures (108 intrinsic functions and 5 intrinsic subroutines). This summary
has nine categories of procedure, each with certain similar characteristics, and ends with a
concise alphabetical listing of all 113 intrinsic procedures and their arguments. Each
intrinsic procedure is described more fully, in alphabetical order, in the next chapter.
numeric inquiry functions
digits
significant digits (e.g., bits) for a given integer or real kind
epsilon
a small value (small compared to 1) for a given real kind
exponent
the exponent value for a given real value
fraction
the fractional part of a given real value
huge
the largest value representable for a given real or integer kind
minexponent
the minimum exponent value for a given real kind
maxexponent
the maximum exponent value for a given real kind
nearest
the processor value nearest to a given real value, in a given direction
precision
the decimal precision of a given real or complex kind
radix
numeric base (typically binary) for a given real or integer kind
rrspacing
reciprocal of the relative spacing near a given real value
range
the decimal exponent range of a given numeric kind
scale
change the exponent of a given real value by a specified amount
set_exponent
set the exponent of a given real value to the specified amount
spacing
the absolute spacing near a given real value
tiny
the smallest positive value representable for a given real kind
array inquiry functions
allocated
true if the given array is currently allocated (false otherwise)
lbound
lower bound(s) of a given array or a given dimension of an array
shape
the number of elements in each dimension of a given array
size
the size (total number of elements) of a given array
ubound
upper bound(s) of a given array or a given dimension of an array
miscellaneous inquiry functions
associated
true if the given pointer is currently allocated (false otherwise)
bit_size
the number of bits (for bit computations) in a given integer kind
kind
the value of the kind type parameter of a given data entity
len
the number of characters in a given string value
present
true if there is an actual argument for a given optional dummy argument
selected_int_kind
the integer kind for a given integer decimal range
selected_real_kind the real kind for a given decimal precision and range
conversion functions
achar
aimag
aint
86
anint
char
cmplx
conjg
dble
iachar
ibits
ichar
int
logical
nint
real
transfer
a given real value rounded to the nearest integer (result is still real)
the character in the specified position of the processor character set
the complex value of a given single or pair of integer or real values
the complex conjugate of a given complex value
the double precision value of a given numeric value of any type
position of the specified character in the ASCII character set
the specified substring of bits of a given integer value
position of the specified character in the processor character set
the (truncated) integer value of a given numeric value of any type
the logical value of specified kind for a given logical value
the (rounded) integer value of a given real value
the real value of a given numeric value of any type and kind
conversion to a specified type without change in the bit pattern
adjustl
adjustr
index
Procedures
len_trim
lge
lgt
lle
llt
repeat
scan
trim
verify
87
all
any
count
cshift
eoshift
maxloc
maxval
merge
minloc
minval
pack
product
reshape
spread
sum
transpose
unpack
intrinsic subroutines
date_and_time
mvbits
random_number
random_seed
system_clock
88
optional
arguments
specific names,
arguments
specific
argument types
abs (a)
cabs (a)
dabs (a)
iabs (a)
default real
default complex
double precision real
default integer
acos (x)
dacos (x)
default real
double precision real
aimag (z)
default complex
aint (a)
dint (a)
default real
double precision real
anint (a)
dnint (a)
default real
double precision real
asin (x)
dsin (x)
default real
double precision real
atan (x)
atan (a)
dtan (a)
default real
double precision real
atan2 (y, x)
atan2 (a)
dtan2 (a)
default real
double precision real
conjg (z)
conjg (x)
default complex
cos (x)
cos (x)
ccos (x)
dcos (x)
default real
default complex
double precision real
cosh (x)
cosh (x)
dcosh (x)
default real
double precision real
dim (x,y)
idim (x,y)
default real
default integer
abs (a)
achar (i)
acos (x)
adjustl (string)
adjustr (string)
aimag (z)
aint (a, kind)
kind
dim
allocated (array)
anint (a, kind)
kind
dim
asin (x)
associated (pointer, target)
target
bit_size (i)
btest (i, pos)
ceiling (a, kind)
kind
kind
y, kind
dim
dim
date, time,
zone, values
dble (a)
digits (x)
dim (x, y)
dot_product (vector_a, vector_b)
dprod (x, y)
eoshift (array, shift, boundary, dim)
epsilon (x)
exp (x)
boundary,
dim
Procedures
89
optional
arguments
specific names,
arguments
specific
argument types
index (string,
substring)
default character
len (string)
default character
log (x)
alog (x)
clog (x)
dlog (x)
default real
default complex
double precision real
log10 (x)
alog10 (x)
dlog10 (x)
default real
double precision real
mod (a, p)
amod (a, p)
dmod (a, p)
default integer
default real
double precision real
nint (a)
idnint (a)
default real
double precision real
exponent (x)
floor (a, kind)
kind
fraction (x)
huge (x)
iachar (c)
iand (i, j)
ibclr (i, pos)
ibits (i, pos, len)
ibset (i, pos)
ichar (c)
ieor (i, j)
index (string, substring, back)
back
kind
ior (i, j)
ishft (i, shift)
ishftc (i, shift, size)
size
kind (x)
lbound (array, dim)
dim
len (string)
len_trim (string)
lge (string_a, string_b)
lgt (string_a, string_b)
lle (string_a, string_b)
llt (string_a, string_b)
kind
a3, ...
maxexponent (x)
maxloc (array, dim, mask)
dim, mask
dim, mask
a3, ...
minexponent (x)
minloc (array, dim, mask)
dim, mask
dim, mask
mod (a, p)
modulo (a, p)
mvbits (from, frompos, len, to, topos)
nearest (x, s)
nint (a, kind)
kind
90
optional
arguments
specific names,
arguments
specific
argument types
sign (a, b)
sign (a, b)
dsign (a, b)
isign (a, b)
default real
double precision real
default integer
sin (x)
sin (x)
csin (x)
dsin (x)
default real
default complex
double precision real
sinh (x)
sinh (x)
dsinh (x)
default real
double precision real
sqrt (x)
csqrt (x)
dsqrt (x)
default real
default complex
double precision real
tan (x)
tan (x)
dtanh (x)
default real
double precision real
tanh (x)
tanh (x)
dtanh (x)
default real
double precision real
not (i)
pack (array, mask, vector)
vector
precision (x)
present (a)
product (array, dim, mask)
dim, mask
radix (x)
random_number (harvest)
random_seed (size, put, get)
range (x)
real (x, kind)
kind
pad, order
rrspacing (x)
scale (x, i)
scan (string, set, back)
back
selected_int_kind (r)
selected_real_kind (p, r)
p, r
set_exponent (x, i)
shape (source)
dim
spacing (x)
spread (source, dim, ncopies)
sqrt (x)
dim, mask
system_clock
(count, count_rate, count_max)
count,
count_rate,
count_max
tiny (x)
transfer (source, mold, size)
size
transpose (matrix)
trim (string)
ubound (array, dim)
dim
back
Intrinsic Procedures
91
10
Intrinsic Procedures
The 113 intrinsic procedures are introduced and organized in the previous chapter, and each is
described in detail in this chapter. A pseudo interface block, without the interface ... end interface
bracketing keywords, describes the interface of each procedure; the semantics is described in comments in the interface, often augmented by text following the interface. Constraints and other relevant information are also included, either in the interface comments or in the following text.
Most of the intrinsic procedures are generic over the various kinds of the argument type - for example, sqrt is generic for both single and double precision real arguments, and any other real kinds the
implementation might supply. Unless explicitly mentioned otherwise, each single-argument intrinsic procedure is generic in this sense, with the result kind being the same as the argument kind.
Similarly, each intrinsic function with one argument plus a kind argument is generic in this sense,
but with the result kind as specified by the kind argument.
As described in the previous chapter, intrinsic procedures may be classified as either elemental or
transformational (most are elemental). If an intrinsic procedure is elemental the interface starts
with the keyword elemental; otherwise that procedure is tranformational. (In a call to an elemental
function with two or more arguments, the actual arguments must be conformable; but note that a
scalar is conformable with any array.) Similarly, some intrinsic functions are identified as inquiry
functions with the keyword inquiry; actual arguments to inquiry functions need not be defined.
All intrinsic function arguments are intent(in) and so the intent for these arguments is not explicitly
given in the interface; however, the argument intent is explicitly specified for each argument of the
five intrinsic subroutines. The argument names can be used as actual argument keywords.
Many of the intrinsic procedures take array arguments of any rank. These arguments are shown as
rank one (:) in the following interfaces, and the descriptions identify which arguments may be
generic over rank and the resulting meaning of the different ranks.
abs (a)
elemental function abs(a)
real :: abs
real :: a
end function
! the |a|
! or integer if a is of type integer
! or type integer or type complex
x2 + y2 .
achar (i)
elemental function achar(i)
character :: achar
integer :: i
end function
Note that achar(iachar(x)) is x for any character x of default kind represented by the processor.
acos (x)
elemental function acos(x)
real :: acos
real :: x
end function
92
adjustl (string)
elemental function adjustl(string)
character(len(string)) :: adjustl
character(*) :: string
end function
adjustr (string)
elemental function adjustr(string)
character(len(string)) :: adjustr
character(*) :: string
end function
aimag (z)
elemental function aimag(z)
real :: aimag
complex :: z
end function
! imaginary part of z
! if z = (x, y), aimag is y
! truncate a
! if kind is absent the result kind is kind(a)
! may be any kind
! if present, must be a scalar initialization expression
If |a|<1, aint (a) has the value 0; if a1, aint (a) has the sign of a and a value equal to the integer
whose magnitude is the largest integer that does not exceed the magnitude of a.
all (mask, dim)
function all(mask,dim)
logical :: all
logical :: mask(:)
integer, optional :: dim
The result is scalar if dim is absent or mask has rank one; otherwise, the result is an array of rank
n-1 and of shape (d1,d2,...,ddim-1,ddim+1,...,dn) where (d1,d2,...,dn) is the shape of mask.
allocated (array)
inquiry function allocated(array)
logical :: allocated
real :: array(:)
end function
The actual argument for array must be an allocatable array with defined allocation status.
anint (a, kind)
elemental function anint(a,kind)
real(kind) :: anint
real :: a
integer, optional :: kind
end function
Intrinsic Procedures
93
The result is scalar if dim is absent or mask has rank one; otherwise, the result is an array of rank
n-1 and of shape (d1,d2,...,ddim-1,ddim+1,...,dn) where (d1,d2,...,dn) is the shape of mask.
asin (x)
elemental function asin(x)
real :: asin
real :: x
end function
The actual argument for pointer must be a pointer with defined pointer association status. The
actual argument for target, if present, must be either a target or a pointer with defined pointer
association status. If target is absent, the result is true if pointer is currently associated with a
target and false otherwise. If target is present and is a target, the result is true if pointer is currently associated with target and false if it is not. If target is present and is a pointer, the result is
true if both pointer and target are currently associated with the same target, and false otherwise.
atan (x)
elemental function atan(x)
real :: atan
real :: x
end function
! 0pos<bit_size(i)
94
ceiling (a)
elemental function ceiling(a)
integer :: ceiling
real :: a
end function
If y is absent and x is not complex, then the imaginary part of the result is zero.
conjg (z)
elemental function conjg(z)
complex :: conjg
complex :: z
end function
cos (x)
elemental function cos(x)
real :: cos
real :: x
end function
! the cosine of x
! same type and kind as x
! may be complex
cosh (x)
elemental function cosh(x)
real :: cosh
real :: x
end function
If dim is present and n is greater than 1 then the result is an array of rank n-1. For example, if
mask is a 3x2 array and dim is 2, then the result is a one-dimensional array of size 3, with the
count taking place along each row of mask.
Intrinsic Procedures
95
Positive shift amounts are left shifts (e.g., cshift(i)=array(i+1)) and negative shifts are right;
values shifted off one end are routed into the other end. If dim is absent it is assumed to be 1.
If array has rank greater than 1 then n-1 one-dimensional shifts take place along the dimension specified by dim. For example, if array is a 3x2 array and dim=1, each of the two columns
of array are shifted an amount specified by shift. shift is allowed to be an array of rank n-1, specifying a different shift amount for each one-dimensional shift. In the preceding example, shift
could be a one-dimensional array of two elements, having values, say, of 2 and -1; in this case
the first column of the array will be circularly shifted up two and the second column will be
shifted down one.
date_and_time (date, time, zone, values)
subroutine date_and_time(date,time,zone,values)
character(*), optional, intent(out)) :: date
character(*), optional, intent(out)) :: time
character(*), optional, intent(out)) :: zone
integer, optional, intent(out)) :: values(:)
end subroutine
Returned results are compatible with the representations defined in ISO 8601:1988. CC is the
century, YY the year of the century, MO the month, DD the day of the month, HH the hour of
the day, MM the minutes of the hour , and SS.SSS the seconds/milliseconds. For zone, the result
is the hours and minutes from Coordinated Universal Time. For values, values(1) is the integer
form of CCYY - e.g., the year, values(2) is MO, values(3) is DD, values (4) is the zone, values(5)
is HH (range 0:23), values(6) is MM (range 0:59), values(7) is the seconds (range 0:60), and values(8) is the milliseconds.
dble (a)
elemental function dble(a)
real(DOUBLE) :: dble
real :: a
end function
If a is complex, then dble returns the real part of a in double precision form.
digits (x)
inquiry function digits(x)
integer :: digits
integer :: x
end function
dim (x, y)
elemental function dim(x,y)
integer :: din
integer :: x, y
end function
! returns max(0,x-y)
! same type and kind as x (and y)
! may also be real; y must have same type and kind as x
96
If the vectors are size zero, the result value is either zero or false; otherwise, if the vectors are of
type logical the result is type logical with value and kind of any(vector_a.and.vector_b), if
vector_a is of type integer or real the result value and kind are those of sum(vector_a*vector_b),
and else the result value and kind are are those of sum(conjg(vector_a)*vector_b).
dprod (x, y)
elemental function dprod(x,y)
real(DOUBLE) :: dprod
real :: x, y
end function
is exactly the same as cshift, except that values shifted off one end are not routed into
the vacated positions on the other end; the boundary value is placed in the vacated positions. If
boundary is omitted, the default value is 0, 0.0, (0.0,0.0), false, or blanks, depending on whether
array is type integer, real, complex, logical, or character, respectively. boundary is allowed to be
an array of rank n-1, specifying a different fill value amount for each vacated position. For
eoshift
A B C
D E F
GH I
, then eoshift(m,shift=1,boundary='*',dim=2) is
and eoshift(m,shift=(/1,1,0/),boundary=(/'*','/','!'/),dim=2) is
AB
E F /
GH I
epsilon (x)
inquiry function epsilon(x)
real :: epsilon
real :: x
end function
exp (x)
elemental function exp(x)
real :: exp
real :: x
end function
! an approximation to ex
! type and kind of x
! may be complex, in which case its imaginary part
!
is regarded as a value in radians
exponent (x)
elemental function exponent(x)
integer :: exponent
real :: x
end function
A B
D E
GH
Intrinsic Procedures
97
floor (a)
elemental function floor(a)
integer :: floor
real :: a
end function
fraction (x)
elemental function fraction(x)
real :: fraction
real :: x
end function
huge (x)
inquiry function huge(x)
real :: huge
real :: x
end function
iachar (c)
elemental function iachar(c)
integer :: iachar
character :: c
end function
iand (i, j)
elemental function iand(i,j)
integer :: iand
integer :: i, j
end function
The result is the bit-by-corresponding-bit and of the arguments; if both argument bits are 1 the
corresponding result bit is 1, otherwise the result bit is 0.
ibclr (i, pos)
elemental function ibclr(i,pos)
integer :: ibclr
integer :: i
integer :: pos
end function
The result has the sequence of len bits from i, beginning at bit pos; these bits are in the rightmost
bit positions of the result, with all other bits zero.
ibset (i, pos)
elemental function ibset(i,pos)
integer :: ibset
integer :: i
integer :: pos
end function
98
ichar (c)
elemental function ichar(c)
integer :: ichar
character :: c
end function
ieor (i, j)
elemental function ieor(i,j)
integer :: ieor
integer :: i, j
end function
The result is the bit-by-corresponding-bit exclusive-or of the arguments; if one of the argument
bits is 1 and the other is 0, the corresponding result bit is 1, otherwise the result bit is 0.
index (string, substring, back)
elemental function index(string,substring,back)
integer :: index
character(*) :: string
character(*) :: substring
logical, optional :: back
end function
If back is absent or present with the value false, the result is the minimum positive value of i
such that string(i:i+len(substring)1) == substring or zero if there is no such value; if back is
present with the value true, the result is the maximum value of i less than or equal to len(string)
len(substring)+1 such that string(i:i+len(substring)1)==substring or zero if there is no such value.
Zero is returned if len(string)<len(substring) and one is returned if len(substring)==0.
int (a, kind)
elemental function int(a,kind)
integer(kind) :: int
real :: a
integer, optional :: kind
end function
If a is of type integer, the result is this same value, but possibly of a different kind. If a is of type
real, the real value is truncated toward zero (e.g., int(3.7) is 3 and int(-3.7) is -3). If a is of type
complex, the result is int(real(a)).
ior (i, j)
elemental function ior(i,j)
integer :: ior
integer :: i, j
end function
The result is the bit-by-corresponding-bit inclusive-or of the arguments; if either one, or both,
of the argument bits is 1, the corresponding result bit is 1, otherwise the result bit is 0.
ishft (i, shift)
elemental function ishift(i,shift)
integer :: ishft
integer :: i
integer :: shift
end function
The result is the value obtained by shifting the bits of i by shift positions. If shift is positive, the
shift is to the left. Bits shifted out are lost; zeros are shifted in at the opposite end.
Intrinsic Procedures
99
The result has the value obtained by shifting the bits of i by shift positions. If shift is positive, the
shift is to the left. Bits shifted out are shifted into at vacated positions at the opposite end.
kind (x)
inquiry function kind(x)
integer :: kind
real :: x
end function
If dim is present the result is a scalar and is the lower bound of array along the dimension dim. If
dim is absent the result is a one-dimensional array whose size is the rank of array, and the value
of each element of the result is the lower bound of that dimension of array. If array is an array
expression other than an array name (e.g., an array section), the lower bound for each dimension
is 1.
len (string)
inquiry function len(string)
integer :: len
character(*) :: string
end function
len_trim (string)
elemental function len_trim(string)
integer :: len_trim
character(*) :: string
end function
! same as len(trim(string))
! the length of string with all trailing blanks removed
100
log (x)
elemental function log(x)
real :: log
real :: x
end function
log10 (x)
elemental function log10(x)
real :: log10
real :: x
end function
The two arguments must be both of type logical or of numeric (integer, real, complex) type. The
size of the first (or only) dimension of matrix_b must equal the size of the last (or only) dimension of matrix_a. There are three cases: (1) matrix_a has shape (n,k) and matrix_b has shape
(k,m), in which case the result has shape (n,m); (2) matrix_a has shape (k) and matrix_b has
shape (k,m), in which case the result has shape (m); (3) matrix_a has shape (n,k) and matrix_b
has shape (k), in which case the result has shape (n). For case (1) the (i,j) element of the result
has the value and kind of sum(matrix_a(i,:)*matrix_b(:,j)) if the arguments are of numeric type and
any(matrix_a(i,:).and.matrix_b(:,j)) otherwise. For case (2) the (i) element of the result has the
value and kind of sum(matrix_a(:)*matrix_b(:,i)) if the arguments are of numeric type and
any(matrix_a(:).and.matrix_b(:,j)) otherwise, and for case (3) the (i) element of the result has the
value and kind of sum(matrix_a(i,:)*matrix_b(:)) if the arguments are of numeric type and
any(matrix_a(i,:).and.matrix_b(:)) otherwise.
max (a1, a2, a3, ...)
elemental function max(a1,a2,a3,...)
real :: max
real :: a1, a2
real, optional :: a3, ...
end function
Intrinsic Procedures
101
maxexponent (x)
inquiry function maxexponent(x)
integer :: maxexponent
real :: x
end function
The size of the result is equal to the rank of array. The value of the kth element of the result is the
value of the kth subscript of the location of the element with the maximum value. If more than
one element of array has this maximum value, the location of the first, in array element order, is
returned. If mask is present, only those locations in array corresponding to the true values in
mask are searched for the maximum value.
maxval (array, dim, mask)
function maxval(array,dim,mask)
real :: maxval
real :: array(:)
integer, optional :: dim
logical, optional :: mask(size(array))
end function
The result is scalar if dim is omitted or array has rank 1 (as illustrated in the interface), in which
case the value returned is the maximum element value in array. If array has rank n greater than 1
and dim is present, 1dimn and dim specifies the dimension along which to determine the maximum values; in this case the result is an array of rank n-1 and shape (d1,d2,...,ddim-1,
ddim+1,...,dn) where (d1,d2,...,dn) is the shape of array and each value of the result is the maximum value along the dim dimension of array. If mask is present only those elements of array corresponding to the true values in mask are searched for the maximum value.
merge (tsource, fsource, mask)
elemental function merge(tsource,fsource,mask)
real :: merge
real :: tsource
real :: fsource
logical :: mask
end function
is an elemental function and is most often used to merge two arrays, based on the (conformable) mask.
merge
minexponent (x)
inquiry function minexponent(x)
integer :: minexponent
real :: x
end function
102
! same as maxloc,
!
but with minimum value rather than maximum value
! same as maxval,
!
but with minimum value rather than maximum value
mod (a, p)
elemental function mod(a,p)
integer :: mod
integer :: a
integer :: p
end function
modulo (a, p)
elemental function modulo(a,p)
integer :: modulo
integer :: a
integer :: p
end function
Copies len bits from object from, starting at bit position frompos in from, to object to, starting at
bit position topos in to.
nearest (x, s)
elemental function nearest(x,s)
real :: nearest
real :: x
real :: s
end function
! integer nearest to a
! value is int(a-sign(0.5,a))
! if present, must be a scalar initialization expression
! if kind is absent, the result kind is default integer
Intrinsic Procedures
103
not (i)
elemental function not(i)
integer :: not
integer :: i
end function
If
vector is
count(mask).
present the size of pack is the size of vector; otherwise the size of pack is
The elements of array that correspond to true values in mask are placed in pack,
starting with the first element of pack and in array element order from array.
precision (x)
inquiry function precision(x)
integer :: precision
real :: x
end function
present (a)
inquiry function present(a)
logical :: present
real :: a
end function
The result is scalar if dim is omitted or array has rank 1, in which case the value returned is the
product of the elements of array. If array has rank n greater than 1 and dim is present, dim specifies the dimension along which to compute the products; in this case the result is an array of
rank n-1 and shape (d1,d2,...,ddim-1, ddim+1,...,dn) where (d1,d2,...,dn) is the shape of array and
each value of the result is the product of the elements along the dim dimension of array. If mask
is present only those elements of array corresponding to the true values in mask are used in computing the product(s).
radix (x)
inquiry function radix(x)
integer :: radix
real :: x
end function
random_number (harvest)
subroutine randon_number(harvet)
real, intent(out) :: harvest
end subroutine
104
If harvest is a scalar, a single pseudorandom number from the uniform distribution between 0
and 1 is generated and assigned to harvest; if harvest is an array, size(harvest) such numbers are
generated and assigned to harvest.
random_seed (size, put, get)
subroutine random_seed(size,put,get)
integer, optional, intent(out) :: size
integer, optional, intent(in) :: put(:)
integer, optional, intent(out) :: get(:)
end subroutine
If a call to random_seed is made without any arguments, the seed is set to an implementationdetermined value. When the argument is put, the seed is reinitialized to this value; when the
argument is get, the current value of the seed is retrieved.
range (x)
inquiry function range(x)
integer :: range
real :: x
end function
If x is of type integer, huge(x) returns an integer, which is not legal for log10; the effect for range
is, however, as if the equivalent real value had been returned for huge. If x is of type real the
value actually returned by range is min(int(log10(huge(x))),-int(log10(tiny(x)))).
real (a, kind)
elemental function real(a,kind)
real(kind) :: real
real :: a
integer, optional :: kind
end function
If a is of type real, the result is this same value, but possibly of a different kind. If a is an integer,
the equivalent real value is returned. If a is complex, the result is the real part of a.
repeat (string, ncopies)
function repeat(string,ncopies)
character(len(string)*ncopies) :: repeat
character(*) :: string
integer :: ncopies
end function
Values are copied from source (and then, if needed, from pad) to reshape, in array element
order. If size(source) > product(shape), the extra values of source are ignored. If size(source) <
product(shape), pad must be supplied, with size(pad) product(shape)-size(source). If order is
present it specifies the the array element order of the reshape subscripts. For example,
reshape((/1,2,3,4, 5,6/),(/2,3/))
is
135
246
, and reshape((/1,2,3,4,5,6/),(/2,4/),(/0,0/),(/2,1/)) is
1234
5600
Intrinsic Procedures
105
rrspacing (x)
elemental function rrspacing(x)
real :: rrspacing
real :: x
end function
scale (x, i)
elemental function scale(x,i)
real :: scale
real :: x
integer :: i
end function
selected_int_kind (r)
function selected_int_kind(r)
integer :: selected_int_kind
integer :: r
end function
If more than one integer type meets the criteria, the kind value for the one with the smallest decimal exponent range is returned or, if there are several such, the smallest of these kind values.
selected_real_kind (p, r)
function selected_real_kind(p,r)
integer :: selected_real_kind
integer, optional :: p
integer, optional :: r
end function
The result is the kind type parameter of a real data type with decimal precision, as returned by
the precision function, of at least p digits and a decimal exponent range, as returned by the range
function, of at least r; if no such type is available on the processor, the result is 1 if the precision is not available, 2 if the exponent range is not available, and 3 if neither is available. If
more than one real type meets the criteria, the kind value for the one with the smallest decimal
precision is returned or, if there are several such, the smallest of these kind values.
set_exponent (x, i)
elemental function set_exponent(x,i)
real :: set_exponent
real :: x
integer :: i
end function
shape (source)
inquiry function shape(source)
integer :: shape(:)
real :: source(:)
end function
106
The value of the kth element of shape is the size of the kth dimension of source. size(shape) is n,
where n is the rank of source; if source is a scalar, n is zero. source must not be a dissassociated
pointer array, an unallocated allocatable array, or an assumed-size array.
sign (a, b)
elemental function sign(a,b)
real :: sign
real :: a
real :: b
end function
sin (x)
elemental function sin(x)
real :: sin
real :: x
end function
! the sine of x
! same type and kind as x
! may be complex
sinh (x)
elemental function sinh(x)
real :: sinh
real :: x
end function
spacing (x)
elemental function spacing(x)
real :: spacing
real :: x
end function
spread broadcasts several copies of source along a specified dimension (as in forming a book
from copies of a single page) and thus forms an array of rank one greater than source. If source
is a scalar then spread is an array of rank one and size max(0,ncopies) and all element have the
value of source. If source is an array with shape (d1,d2,...,dn), spread has shape (d1,d2,...,ddim-1,
234
234
234
Intrinsic Procedures
107
sqrt (x)
elemental function sqrt(x)
real :: sqrt
real :: x
end function
If x is complex, the real part of the result is nonnegative; if the real part is zero, the imaginary
part is nonnegative.
sum (array, dim, mask)
function sum(array,dim,mask)
real :: sum
real :: array(:)
integer, optional :: dim
logical, optional :: mask
end function
The result is scalar if dim is omitted or array has rank 1, in which case the value returned is the
sum of the elements of array. If array has rank n greater than 1 and dim is present, 1dimn and
dim specifies the dimension along which to compute the sums; in this case the result is an array
of rank n-1 and shape (d1,d2,...,ddim-1, ddim+1,...,dn) where (d1,d2,...,dn) is the shape of array and
each value of the result is the sum of the elements along the dim dimension of array. If mask is
present only those elements of array corresponding to the true values in mask are used in computing the sum(s).
system_clock (count, count_rate, count_max)
subroutine system_clock(count,count_rate,count_max)
integer, intent(out), optional :: count
integer, intent(out), optional :: count_rate
integer, intent(out), optional :: count_max
end subroutine
All values are processor dependent; count_rate indicates how many times count is incremented
each second; when it reaches count_max, it resets to zero. If there is no processor clock count
always returns -huge(0), count_rate returns zero, and count_max returns zero.
tan (x)
elemental function tan(x)
real :: tan
real :: x
end function
! the tangent of x
! value is assumed to be radians
tanh (x)
elemental function tanh(x)
real :: tanh
real :: x
end function
tiny (x)
inquiry function tiny(x)
real :: tiny
real :: x
end function
108
If mold is scalar and size is absent the result is scalar. If mold is an array and size is absent the
result is a rank 1 array; its size is the smallest possible to hold all of the bits of source. If size is
present, the result is a rank 1 array of this size; if this makes transfer longer than source, the
extra part of transfer is undefined and if it makes transfer shorter than source the extra bits of
source are not transferred.
transpose (matrix)
function transpose(matrix)
real :: transpose(size(matrix,2),size(matrix,1))
real :: matrix(:,:)
end function
! transpose matrix
! element (i,j) is matrix(j,i)
! may be any type and kind
trim (string)
function trim(string)
character(*) :: trim
character(*) :: string
end function
If dim is present the result is a scalar and is the upper bound of array along the dimension dim. If
dim is absent the result is a one-dimensional array whose size is the rank of array, and the value
of each element of the result is the upper bound of that dimension of array. If array is an array
expression other than an array name (e.g., an array section), the upper bound value is based on
the lower bound value being 1.
unpack (vector, mask, field)
function unpack(vector,mask,field)
real :: unpack(:)
real :: vector(:)
logical :: mask(:)
real :: field(size(mask))
end function
The element of the result that corresponds to the kth true element of mask, in array element
order, is vector(k), for all the true values in mask. Each other element of the result is the value of
the corresponding element of field.
verify (string, set, back)
elemental function verify(string,set,back)
integer :: verify
character(*) :: string
character(*) :: set
logical, optional :: back
end function
Syntax Rules
109
11
Syntax Rules
This chapter contains the complete syntax of Fortran 90. For reference purposes the syntax rules
are the same as in the Fortran 90 standard, with the same R (rule) numbers; however, the constraints are not included here.
Each syntax rule defines a term with the symbol is, optionally followed by alternative definitions
introduced by the symbol or. Optional parts of a definition are in closed in square brackets ( [ ] ),
and repeated parts are enclosed in square brackets followed by three dots ( [ ] ... ). Abbreviations
are used liberally (e.g., -stmt for statement) and any term ending with -list represents a comma-separated list (e.g., xyz-list is an abbreviation for xyz [ , xyz ] ...); a term ending with -name is a name
(R304). Syntactic classes (nonterminals) are in italicized-font and literals are in bold. Literal words,
such as function are lower case, but upper-case letters are allowed. Where a syntax rule specifies
more than one line (statement) of actual code syntax, the rule for each code line is on a separate
syntax rule line (e.g., the if-construct, R802, involves multiple lines of actual code). In those few
cases where a syntax rule is too long to fit on one line, the # is used to indicate its continuation on
the next line (e.g., the syntax rule for the function statement, R1216, is too long to fit on one line).
is
program-unit
[ program-unit ] ...
R202 program-unit
is
or
or
or
main-program
external-subprogram
module
block-data
R1101 main-program
is
[ program-stmt ]
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-program-stmt
R203 external-subprogram
is
or
function-subprogram
subroutine-subprogram
R1215 function-subprogram
is
function-stmt
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-function-stmt
R1219 subroutine-subprogram
is
subroutine-stmt
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-subroutine-stmt
R1104 module
is
module-stmt
[ specification-part ]
[ module-subprogram-part ]
end-module-stmt
110
R1110 block-data
is
block-data-stmt
[ specification-part ]
end-block-data-stmt
R204 specification-part
is
[ use-stmt ] ...
[ implicit-part ]
[ declaration-construct ] ...
R205 implicit-part
is
[ implicit-part-stmt ] ...
implicit-stmt
R206 implicit-part-stmt
is
or
or
or
implicit-stmt
parameter-stmt
format-stmt
entry-stmt
R207 declaration-construct
is
or
or
or
or
or
or
or
derived-type-def
interface-block
type-declaration-stmt
specification-stmt
parameter-stmt
format-stmt
entry-stmt
stmt-function-stmt
R208 execution-part
is
executable-construct
[ execution-part-construct ] ...
R209 execution-part-construct
is
or
or
or
executable-construct
format-stmt
data-stmt
entry-stmt
R210 internal-subprogram-part
is
contains-stmt
internal-subprogram
[ internal-subprogram ] ...
R211 internal-subprogram
is
or
function-subprogram
subroutine-subprogram
R212 module-subprogram-part
is
contains-stmt
module-subprogram
[ module-subprogram ] ...
R213 module-subprogram
is
or
function-subprogram
subroutine-subprogram
R214 specification-stmt
is
or
or
or
or
access-stmt
allocatable-stmt
common-stmt
data-stmt
dimension-stmt
Syntax Rules
111
or
or
or
or
or
or
or
or
or
equivalence-stmt
external-stmt
intent-stmt
intrinsic-stmt
namelist-stmt
optional-stmt
pointer-stmt
save-stmt
target-stmt
R215 executable-construct
is
or
or
or
or
action-stmt
case-construct
do-construct
if-construct
where-construct
R216 action-stmt
is
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
allocate-stmt
assignment-stmt
backspace-stmt
call-stmt
close-stmt
computed-goto-stmt
continue-stmt
cycle-stmt
deallocate-stmt
endfile-stmt
end-function-stmt
end-program-stmt
end-subroutine-stmt
exit-stmt
goto-stmt
if-stmt
inquire-stmt
nullify-stmt
open-stmt
pointer-assignment-stmt
print-stmt
read-stmt
return-stmt
rewind-stmt
stop-stmt
where-stmt
write-stmt
arithmetic-if-stmt
assign-stmt
assigned-goto-stmt
pause-stmt
112
is
or
alphanumeric-character
special-character
R302 alphanumeric-character
is
or
or
letter
digit
underscore
R303 underscore
is
R304 name
is
R305 constant
is
or
literal-constant
named-constant
R306 literal-constant
is
or
or
or
or
or
int-literal-constant
real-literal-constant
complex-literal-constant
logical-literal-constant
char-literal-constant
boz-literal-constant
R307 named-constant
is
name
R308 int-constant
is
constant
R309 char-constant
is
constant
R310 intrinsic-operator
is
or
or
or
or
or
or
or
or
power-op
mult-op
add-op
concat-op
rel-op
not-op
and-op
or-op
equiv-op
R708 power-op
is
**
R709 mult-op
is
or
*
/
R710 add-op
is
or
R712 concat-op
is
//
R714 rel-op
is
or
or
.eq.
.ne.
.lt.
Syntax Rules
113
or
or
or
or
or
or
or
or
or
.le.
.gt.
.ge.
==
/=
<
<=
>
>=
R719 not-op
is
.not.
R720 and-op
is
.and.
R721 or-op
is
.or.
R722 equiv-op
is
or
.eqv.
.neqv.
R311 defined-operator
is
or
or
defined-unary-op
defined-binary-op
extended-intrinsic-op
R704 defined-unary-op
is
R724 defined-binary-op
is
R312 extended-intrinsic-op
is
intrinsic-operator
R313 label
is
R401 signed-digit-string
is
[ sign ] digit-string
R402 digit-string
is
R403 signed-int-literal-constant
is
[ sign ] int-literal-constant
R404 int-literal-constant
is
digit-string [ _ kind-param ]
R405 kind-param
is
or
digit-string
scalar-int-constant-name
R406 sign
is
or
R407 boz-literal-constant
is
or
or
binary-constant
octal-constant
hex-constant
114
R408 binary-constant
is
or
R409 octal-constant
is
or
R410 hex-constant
is
or
R411 hex-digit
is
or
or
or
or
or
or
digit
A
B
C
D
E
F
R412 signed-real-literal-constant is
[ sign ] real-literal-constant
R413 real-literal-constant
is
or
R414 significand
is
or
digit-string . [ digit-string ]
. digit-string
R415 exponent-letter
is
or
E
D
R416 exponent
is
signed-digit-string
R417 complex-literal-constant
is
( real-part , imag-part )
R418 real-part
is
or
signed-int-literal-constant
signed-real-literal-constant
R419 imag-part
is
or
signed-int-literal-constant
signed-real-literal-constant
R420 char-literal-constant
is
or
R421 logical-literal-constant
is
or
.true. [ _ kind-param ]
.false. [ _ kind-param ]
R422 derived-type-def
is
derived-type-stmt
[ private-sequence-stmt ] ...
component-def-stmt
[ component-def-stmt ] ...
end-type-stmt
R423 private-sequence-stmt
is
or
private
sequence
Syntax Rules
115
R424 derived-type-stmt
is
R425 end-type-stmt
is
R426 component-def-stmt
is
R427 component-attr-spec
is
or
pointer
dimension ( component-array-spec )
R428 component-array-spec
is
or
explicit-shape-spec-list
deferred-shape-spec-list
R429 component-decl
is
R430 structure-constructor
is
type-name ( expr-list )
R431 array-constructor
is
(/ ac-value-list /)
R432 ac-value
is
or
expr
ac-implied-do
R433 ac-implied-do
is
( ac-value-list , ac-implied-do-control )
R434 ac-implied-do-control
is
R435 ac-do-variable
is
scalar-int-variable
is
R502 type-spec
is
or
or
or
or
or
or
integer [ kind-selector ]
real [ kind-selector ]
double precision
complex [ kind-selector ]
character [ char-selector ]
logical [ kind-selector ]
type ( type-name )
R503 attr-spec
is
or
or
or
or
or
or
or
or
or
or
parameter
access-spec
allocatable
dimension ( array-spec )
external
intent ( intent-spec )
intrinsic
optional
pointer
save
target
116
R504 entity-decl
is
or
R505 kind-selector
is
( [ kind = ] scalar-int-initialization-expr )
R506 char-selector
is
or
or
or
length-selector
( len = type-param-value , kind = scalar-int-initialization-expr )
( type-param-value , [ kind = ] scalar-int-initialization-expr )
( kind = scalar-int-initialization-expr [ , len = type-param-value ] )
R507 length-selector
is
or
( [ len = ] type-param-value )
* char-length [ , ]
R508 char-length
is
or
( type-param-value )
scalar-int-literal-constant
R509 type-param-value
is
or
specification-expr
*
R510 access-spec
is
or
public
private
R511 intent-spec
is
or
or
in
out
inout
R512 array-spec
is
or
or
or
explicit-shape-spec-list
assumed-shape-spec-list
deferred-shape-spec-list
assumed-size-spec
R513 explicit-shape-spec
is
[ lower-bound : ] upper-bound
R514 lower-bound
is
specification-expr
R515 upper-bound
is
specification-expr
R516 assumed-shape-spec
is
[ lower-bound ] :
R517 deferred-shape-spec
is
R518 assumed-size-spec
is
[ explicit-shape-spec-list , ] [ lower-bound : ] *
R519 intent-stmt
is
R520 optional-stmt
is
optional [ :: ] dummy-arg-name-list
R521 access-stmt
is
access-spec [ [ :: ] access-id-list ]
R522 access-id
is
or
use-name
generic-spec
Syntax Rules
117
R523 save-stmt
is
save [ [ :: ] saved-entity-list ]
R524 saved-entity
is
or
object-name
/ common-block-name /
R525 dimension-stmt
is
R526 allocatable-stmt
is
R527 pointer-stmt
is
R528 target-stmt
is
R529 data-stmt
is
R530 data-stmt-set
is
data-stmt-object-list / data-stmt-value-list /
R531 data-stmt-object
is
or
variable
data-implied-do
R532 data-stmt-value
is
[ data-stmt-repeat * ] data-stmt-constant
R533 data-stmt-constant
is
or
or
or
or
scalar-constant
signed-int-literal-constant
signed-real-literal-constant
structure-constructor
boz-literal-constant
R534 data-stmt-repeat
is
scalar-int-constant
R535 data-implied-do
is
( data-i-do-object-list , data-i-do-variable =
scalar-int-expr , scalar-int-expr [ , scalar-int-expr ] )
R536 data-i-do-object
is
or
or
array-element
scalar-structure-component
data-implied-do
R537 data-i-do-variable
is
scalar-int-variable
R538 parameter-stmt
is
parameter ( named-constant-def-list )
R539 named-constant-def
is
named-constant = initialization-expr
R540 implicit-stmt
is
or
implicit implicit-spec-list
implicit none
R541 implicit-spec
is
type-spec ( letter-spec-list )
R542 letter-spec
is
letter [ letter ]
118
R543 namelist-stmt
is
R544 namelist-group-object
is
variable-name
R545 equivalence-stmt
is
equivalence equivalence-set-list
R546 equivalence-set
is
( equivalence-object , equivalence-object-list )
R547 equivalence-object
is
or
or
variable-name
array-element
substring
R548 common-stmt
is
R549 common-block-object
is
variable-name [ ( explicit-shape-spec-list ) ]
R601 variable
is
or
or
scalar-variable-name
array-variable-name
subobject
R602 subobject
is
or
or
or
array-element
array-section
structure-component
substring
R603 logical-variable
is
variable
R604 default-logical-variable
is
variable
R605 char-variable
is
variable
R606 default-char-variable
is
variable
R607 int-variable
is
variable
R608 default-int-variable
is
variable
R609 substring
is
parent-string ( substring-range )
R610 parent-string
is
or
or
or
scalar-variable-name
array-element
scalar-structure-component
scalar-constant
R611 substring-range
is
[ scalar-int-expr ] : [ scalar-int-expr ]
R612 data-ref
is
variables (R601-631)
Syntax Rules
119
R613 part-ref
is
part-name [ ( section-subscript-list ) ]
R614 structure-component
is
data-ref
R615 array-element
is
data-ref
R616 array-section
is
data-ref [ ( substring-range ) ]
R617 subscript
is
scalar-int-expr
R618 section-subscript
is
or
or
subscript
subscript-triplet
vector-subscript
R619 subscript-triplet
is
R620 stride
is
scalar-int-expr
R621 vector-subscript
is
int-expr
R622 allocate-stmt
is
R623 stat-variable
is
scalar-int-variable
R624 allocation
is
allocate-object [ ( allocate-shape-spec-list ) ]
R625 allocate-object
is
or
variable-name
structure-component
R626 allocate-shape-spec
is
[ allocate-lower-bound : ] allocate-upper-bound
R627 allocate-lower-bound
is
scalar-int-expr
R628 allocate-upper-bound
is
scalar-int-expr
R629 nullify-stmt
is
nullify ( pointer-object-list )
R630 pointer-object
is
or
variable-name
structure-component
R631 deallocate-stmt
is
is
or
or
or
or
or
or
constant
constant-subobject
variable
array-constructor
structure-constructor
function-reference
( expr )
expressions (R701-743)
R701 primary
120
R702 constant-subobject
is
subobject
R703 level-1-expr
is
[ defined-unary-op ] primary
R704 defined-unary-op
is
R705 mult-operand
is
R706 add-operand
is
R707 level-2-expr
is
R708 power-op
is
**
R709 mult-op
is
or
*
/
R710 add-op
is
or
R711 level-3-expr
is
R712 concat-op
is
//
R713 level-4-expr
is
R714 rel-op
is
or
or
or
or
or
or
or
or
or
or
or
.eq.
.ne.
.lt.
.le.
.gt.
.ge.
==
/=
<
<=
>
>=
R715 and-operand
is
[ not-op ] level-4-expr
R716 or-operand
is
R717 equiv-operand
is
R718 level-5-expr
is
R719 not-op
is
.not.
R720 and-op
is
.and.
R721 or-op
is
.or.
Syntax Rules
121
R722 equiv-op
is
or
.eqv.
.neqv.
R723 expr
is
R724 defined-binary-op
is
R725 logical-expr
is
expr
R726 char-expr
is
expr
R727 default-char-expr
is
expr
R728 int-expr
is
expr
R729 numeric-expr
is
expr
R730 initialization-expr
is
expr
R731 char-initialization-expr
is
char-expr
R732 int-initialization-expr
is
int-expr
R733 logical-initialization-expr
is
logical-expr
R734 specification-expr
is
scalar-int-expr
R735 assignment-stmt
is
variable = expr
R736 pointer-assignment-stmt
is
R737 target
is
or
variable
expr
R738 where-stmt
is
R739 where-construct
is
where-construct-stmt
[ assignment-stmt ] ...
[ elsewhere-stmt
[ assignment-stmt ] ... ]
end-where-stmt
R740 where-construct-stmt
is
where ( mask-expr )
R741 mask-expr
is
logical-expr
R742 elsewhere-stmt
is
elsewhere
R743 end-where-stmt
is
end where
122
is
[ execution-part-construct ] ...
R802 if-construct
is
if-then-stmt
block
[ else-if-stmt
block ] ...
[ else-stmt
block ]
end-if-stmt
R803 if-then-stmt
is
R804 else-if-stmt
is
R805 else-stmt
is
else [ if-construct-name ]
R806 end-if-stmt
is
end if [ if-construct-name ]
R807 if-stmt
is
if ( scalar-logical-expr ) action-stmt
R808 case-construct
is
select-case-stmt
[ case-stmt
block ] ...
end-select-stmt
R809 select-case-stmt
is
R810 case-stmt
is
R811 end-select-stmt
is
R812 case-expr
is
or
or
scalar-int-expr
scalar-char-expr
scalar-logical-expr
R813 case-selector
is
or
( case-value-range-list )
default
R814 case-value-range
is
or
or
or
case-value
case-value :
: case-value
case-value : case-value
R815 case-value
is
or
or
scalar-int-initialization-expr
scalar-char-initialization-expr
scalar-logical-initialization-expr
R816 do-construct
is
or
block-do-construct
nonblock-do-construct
Syntax Rules
123
R817 block-do-construct
is
do-stmt
do-block
end-do
R818 do-stmt
is
or
label-do-stmt
nonlabel-do-stmt
R819 label-do-stmt
is
R820 nonlabel-do-stmt
is
[ do-construct-name : ] do [ loop-control ]
R821 loop-control
is
or
R822 do-variable
is
scalar-variable
R823 do-block
is
block
R824 end-do
is
or
end-do-stmt
continue-stmt
R825 end-do-stmt
is
end do [ do-construct-name ]
R826 nonblock-do-construct
is
or
action-term-do-construct
outer-shared-do-construct
R827 action-term-do-construct
is
label-do-stmt
do-body
do-term-action-stmt
R828 do-body
is
[ execution-part-construct ] ...
R829 do-term-action-stmt
is
action-stmt
R830 outer-shared-do-construct is
label-do-stmt
do-body
shared-term-do-construct
R831 shared-term-do-construct
outer-shared-do-construct
inner-shared-do-construct
is
or
R832 inner-shared-do-construct is
label-do-stmt
do-body
do-term-shared-stmt
R833 do-term-shared-stmt
is
action-stmt
R834 cycle-stmt
is
cycle [ do-construct-name ]
R835 exit-stmt
is
exit [ do-construct-name ]
R836 goto-stmt
is
go to label
124
R837 computed-goto-stmt
is
go to ( label-list ) [ , ] scalar-int-expr
R838 assign-stmt
is
R839 assigned-goto-stmt
is
go to scalar-int-variable [ [ , ] ( label-list ) ]
R840 arithmetic-if-stmt
is
R841 continue-stmt
is
continue
R842 stop-stmt
is
stop [ stop-code ]
R843 stop-code
is
or
scalar-char-constant
digit [ digit [ digit [ digit [ digit ] ] ] ]
R844 pause-stmt
is
pause [ stop-code ]
R901 io-unit
is
or
or
external-file-unit
*
internal-file-unit
R902 external-file-unit
is
scalar-int-expr
R903 internal-file-unit
is
default-char-variable
R904 open-stmt
is
open ( connect-spec-list )
R905 connect-spec
is
or
or
or
or
or
or
or
or
or
or
or
or
[ unit = ] external-file-unit
iostat = scalar-default-int-variable
err = label
file = file-name-expr
status = scalar-default-char-expr
access = scalar-default-char-expr
form = scalar-default-char-expr
recl = scalar-int-expr
blank = scalar-default-char-expr
position = scalar-default-char-expr
action = scalar-default-char-expr
delim = scalar-default-char-expr
pad = scalar-default-char-expr
R906 file-name-expr
is
scalar-default-char-expr
R907 close-stmt
is
close ( close-spec-list )
R908 close-spec
is
or
or
or
[ unit = ] external-file-unit
iostat = scalar-default-int-variable
err = label
status = scalar-default-char-expr
Syntax Rules
125
R909 read-stmt
is
or
R910 write-stmt
is
R911 print-stmt
is
R912 io-control-spec
is
or
or
or
or
or
or
or
or
or
[ unit = ] io-unit
[ fmt = ] format
[ nml = ] namelist-group-name
rec = scalar-int-expr
iostat = scalar-default-int-variable
err = label
end = label
advance = scalar-default-char-expr
size = scalar-default-int-variable
eor = label
R913 format
is
or
or
or
default-char-expr
label
*
scalar-default-int-variable
R914 input-item
is
or
variable
io-implied-do
R915 output-item
is
or
expr
io-implied-do
R916 io-implied-do
is
( io-implied-do-object-list , io-implied-do-control )
R917 io-implied-do-object
is
or
input-item
output-item
R918 io-implied-do-control
is
R919 backspace-stmt
is
or
backspace external-file-unit
backspace ( position-spec-list )
R920 endfile-stmt
is
or
endfile external-file-unit
endfile ( position-spec-list )
R921 rewind-stmt
is
or
rewind external-file-unit
rewind ( position-spec-list )
R922 position-spec
is
or
or
[ unit = ] external-file-unit
iostat = scalar-default-int-variable
err = label
R923 inquire-stmt
is
or
inquire ( inquire-spec-list )
inquire ( iolength = scalar-default-int-variable ) output-item-list
126
R924 inquire-spec
is
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
or
[ unit = ] external-file-unit
file = file-name-expr
iostat = scalar-default-int-variable
err = label
exist = scalar-default-logical-variable
opened = scalar-default-logical-variable
number = scalar-default-int-variable
named = scalar-default-logical-variable
name = scalar-default-char-variable
access = scalar-default-char-variable
sequential = scalar-default-char-variable
direct = scalar-default-char-variable
form = scalar-default-char-variable
formatted = scalar-default-char-variable
unformatted = scalar-default-char-variable
recl = scalar-default-int-variable
nextrec = scalar-default-int-variable
blank = scalar-default-char-variable
position = scalar-default-char-variable
action = scalar-default-char-variable
read = scalar-default-char-variable
write = scalar-default-char-variable
readwrite = scalar-default-char-variable
delim = scalar-default-char-variable
pad = scalar-default-char-variable
is
format format-specification
R1002 format-specification
is
( [ format-item-list ] )
R1003 format-item
is
or
or
or
[ r ] data-edit-desc
control-edit-desc
char-string-edit-desc
[ r ] ( format-item-list )
R1004 r
is
int-literal-constant
R1005 data-edit-desc
is
or
or
or
or
or
or
or
or
or
or
or
Iw[.m]
Bw[.m]
Ow[.m]
Zw[.m]
Fw.d
Ew.d[Ee]
EN w . d [ E e ]
ES w . d [ E e ]
Gw.d[Ee]
Lw
A[w]
Dw.d
Syntax Rules
127
R1006 w
is
int-literal-constant
R1007 m
is
int-literal-constant
R1008 d
is
int-literal-constant
R1009 e
is
int-literal-constant
R1010 control-edit-desc
is
or
or
or
or
or
position-edit-desc
[r]/
:
sign-edit-desc
kP
blank-interp-edit-desc
R1011 k
is
signed-int-literal-constant
R1012 position-edit-desc
is
or
or
or
Tn
TL n
TR n
nX
R1013 n
is
int-literal-constant
R1014 sign-edit-desc
is
or
or
S
SP
SS
R1015 blank-interp-edit-desc
is
or
BN
BZ
R1016 char-string-edit-desc
is
or
char-literal-constant
c H rep-char [ rep-char ] ...
R1017 c
is
int-literal-constant
is
[ program-stmt ]
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-program-stmt
R1102 program-stmt
is
program program-name
R1103 end-program-stmt
is
R1104 module
is
module-stmt
[ specification-part ]
[ module-subprogram-part ]
end-module-stmt
128
R1105 module-stmt
is
module module-name
R1106 end-module-stmt
is
R1107 use-stmt
is
or
R1108 rename
is
R1109 only
is
or
access-id
[ local-name => ] use-name
R1110 block-data
is
block-data-stmt
[ specification-part ]
end-block-data-stmt
R1111 block-data-stmt
is
R1112 end-block-data-stmt
is
R1201 interface-block
is
interface-stmt
[ interface-body ] ...
[ module-procedure-stmt ] ...
end-interface-stmt
R1202 interface-stmt
is
interface [ generic-spec ]
R1203 end-interface-stmt
is
end interface
R1204 interface-body
is
function-stmt
[ specification-part ]
end-function-stmt
subroutine-stmt
[ specification-part ]
end-subroutine-stmt
procedures (R1201-1226)
or
R1205 module-procedure-stmt
is
R1206 generic-spec
is
or
or
generic-name
operator ( defined-operator )
assignment ( = )
R1207 external-stmt
is
external [ :: ] external-name-list
R1208 intrinsic-stmt
is
intrinsic [ :: ] intrinsic-procedure-name-list
R1209 function-reference
is
function-name ( [ actual-arg-spec-list ] )
R1210 call-stmt
is
R1211 actual-arg-spec
is
[ keyword = ] actual-arg
Syntax Rules
129
R1212 keyword
is
dummy-arg-name
R1213 actual-arg
is
or
or
or
expr
variable
procedure-name
alt-return-spec
R1214 alt-return-spec
is
* label
R1215 function-subprogram
is
function-stmt
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-function-stmt
R1216 function-stmt
is
R1217 prefix
is
or
type-spec [ recursive ]
recursive [ type-spec ]
R1218 end-function-stmt
is
R1219 subroutine-subprogram
is
subroutine-stmt
[ specification-part ]
[ execution-part ]
[ internal-subprogram-part ]
end-subroutine-stmt
R1220 subroutine-stmt
is
R1221 dummy-arg
is
or
dummy-arg-name
*
R1222 end-subroutine-stmt
is
R1223 entry-stmt
is
R1224 return-stmt
is
return [ scalar-int-expr ]
R1225 contains-stmt
is
contains
R1226 stmt-function-stmt
is
130
A Fortran 90 Implementation
131
12
A Fortran 90 Implementation
This chapter describes vendor-specific features of the Absoft Pro Fortran implementation of Fortran 90, including implementation-dependent values (kind values, I/O error values, etc.), language extensions, compiler directives, and command-line compiler options.
The implementation-dependent values will vary, but many of these extensions, directives,
and command-line options are typical of many commercial implementations.
implementation-dependent values
kind values for all intrinsic data types
default integer
default logical
2-byte logical
1-byte logical
default character
a. Only four of these constants are really needed, one for each kind value.
iostat value
I/O condition
-1
-2
iostat= variable values for various i/o error conditions (trigger err=, if present)
value
error condition
value
error condition
132
value
error condition
value
error condition
13 permission denied
17 file exists
19 no such device
20 not a directory
21 is a directory
22 invalid parameter
29 illegal seek
A Fortran 90 Implementation
133
language extensions
dec-style structures. A structure type is a data type extension that is similar to a sequence
derived type, but components of objects of structure types are guaranteed to be physically
stored in the order defined. Note that the terms structure and structured object refer to
an object of derived-type; the terms structure type and structure definition will be
used to refer to this extended type, and the terms record and record object will refer to
objects of this extended type. A structure definition has the form:
structure [/ structure-name / ] [record-list ]
abx-component-def
[ abx-component-def ]...
end structure
A union defines a data area which is shared by two or more groups of fields and has form
union
map-definition
map-definition
[ map-definition ]...
end union
where a map-definition is
map
field-declaration
[ field-declaration ]...
end map
134
where pointer-name is the name of the pointer variable being declared and target may be
any Fortran object, including a structure component, or an external function name. When
such a pointer is used as a dummy argument, the intent attribute applies to the pointer
value, not the value of the pointed-to object (if any).
The intrinsic functions loc and pointer are added (see below), each of which returns the
address (pointer value) of its argument.
An example serves to illustrate the use of this pointer type; note that strict type-checking
of pointer arguments may be relaxed in unambiguous cases:
A Fortran 90 Implementation
135
module Mytypes
type Rect; sequence
integer(2) :: top
end type
type Picture; sequence
integer(2) :: picSize
end type
end module
module Mod
interface
subroutine drawPicture(h_myPicture, dstRect)
use mytypes
type(Picture) :: myPicture
pointer(p_myPicture, myPicture)
! pointer to a derived-type object
pointer(h_myPicture, p_myPicture)
! pointer to a pointer
value :: h_myPicture
! pass the pointer by value
type(Rect) :: dstRect
end subroutine
end interface
end module
subroutine foobar
use Mod
type(Rect) :: dstRect
pointer (p,i)
call drawPicture(p,dstRect)
call drawPicture(loc(j),dstRect)
call drawPicture(708089,dstRect)
end
! legal - p is a pointer
! legal - type of loc is pointer
! error - an integer constant is not a pointer
!
(but may compile with a warning)
Pointer type matching is utilized, however, when resolving references to generic interfaces; for example:
interface bogus
subroutine point_bogus(p)
pointer (p,i)
end subroutine
subroutine real_bogus(z)
real z
end subroutine
subroutine int_bogus(i)
integer i
end subroutine
end interface
call bogus(0)
call bogus(loc(z))
call bogus(1.0)
end
! reference to int_bogus
! reference to point_bogus
! reference to real_bogus
136
Record statements in a structure definition may specify targets of the type of the structure
being defined. For example, the following is legal:
structure /outer/
record /outer/ pointee
pointer (next, pointee)
...
end structure
All of the records of such record statements (that specify the name of the structure being
defined) must appear as targets in pointer declarations in that structure, and forward references to subsequent structure definitions are illegal. For example:
structure /outer/
structure /inone/
structure /intwo/
record /outer/ junk
pointer (p_outer, junk)
end structure
record /spaced/ nogood
end structure
record /outer/ circle
end structure
structure /spaced/
integer out
end structure
Attribute Extensions. Several attributes are added to the standard set of attributes:
attribute
effect
automatic
variable s are allocated on the stack; incompatible with static, save, and common
static
value
volatile
assignments and references occur, even if optimizations have eliminated these objects
stdcall
dll_import
dll_export
a. The stdcall attribute keyword can, alternatively, be specified on the function or subroutine
statement, in the same manner as the recursive keyword; stdcall and recursive are mutually
exclusive - either one or the other, or neither, appears. If stdcall appears on a subroutine statement,
the parentheses for the optional dummy argument list must also appear (otherwise the statement
looks like, and is interpreted as, a stdcall attribute statement rather than a subroutine statement).
A Fortran 90 Implementation
137
These attributes can be specified either in type declarations statements, in the normal way,
or in attribute statements, with syntax similar to that for the standard attributes:
automatic [ [ :: ] sym-name-list ]
static [ :: ] sym-name-list
value [ :: ] sym-name-list
volatile [ [ :: ] sym-common-name-list ]
stdcall [ :: ] procedure-name-list
dll_import [ :: ] procedure-name-list
dll_export [ :: ] procedure-name-list
The name list is not required for the automatic and volatile statements, and if omitted that
attribute is applied to all of the local objects in the scope. A sym-name is an object name
and an sym-common-name in the volatile statement can be either an object name or / common-name /. The stdcall attribute can be specified only for external procedure names.
Module objects are inherently static/save, and automatic (or the stack directive) cannot be
specified within the scope of a module. Otherwise automatic and static take precedence
over save without a sym-name-list, the stack directive, and the -ev command-line option.
(Automatic is the same as the stack directive, and the -ev option is the same as save without a sym-name-list.)
The value attribute is incompatible (must not be used) with these other attributes: external,
intent, intrinsic, optional, parameter, pointer, private, public, save and stdcall. If the interface of a procedure having a value dummy argument is explicit, all associated actual arguments will be passed by value.
The stdcall attribute is incompatible with these other attributes: allocatable, intent, parameter, pointer, target, save, and value. Stdcall functions cannot be: assumed-length (len=*),
variable length (len=n) character functions, array-valued functions, derived-type functions, or storage associated in any way. The stdcall attribute can be applied only to external procedure names, but not to: a function name specified in a result clause, a procedure
name specified by an entry statement, or a generic name specified in an interface block.
Because stdcall applies only to external functions, it is incompatible with: data initialization, namelist, statement functions, labels, block data, dll_import, and dll_export.
Stdcall is a platform-dependent extension specifically provided for direct communication
with the Windows Win32 API; dll_import and dll_export are intended to interface with
DLLs that are not part of the Windows API. See also the compiler options -YIL, YDLL_STDCALL, and -YDDL_NAMES for compiler settings regarding these attributes.
138
Eb
acosd, dacosdc
asind, dasindc
atand, datandc
atand, datan2dc
cosd, dcosdc
cotan, dcotanc
function
purpose
bit_size(ref)
bitest, bjtest
carg(expr)
clock
equivalent to date_and_time
cpu_time([time=] real-variable)
date, jdate
equivalent to date_and_time
eof([unit=] int-expr)
x
x
i2sign,iisign, jisign
ibchng([inta=] int-expr, [intb=] int-expr) returns value of inta with bit intb reversed
iiand, jiand
iandd
iibclr, jibclr
iibits, jibits
iibset, jibset
iieor, jieor
iior, jior
iishft, jishft
iishftc, jishftc
A Fortran 90 Implementation
139
function
purpose
imag([z=] complex-expr)
inot, jnot
notd
Pa
Eb
irtc, rtc
equivalent to system_clock
shift inta the amount specified by intb (positive intb shifts left)
loc, log10
passedd
pointer(ref )
secnds([x=] real-variable)
sind, dsindc
tand, dtandc
zext(int-expr)
%loc(expr)
%val(expr)
The bit_size function is extended from the standard version, which allows only integer
objects as actual arguments; the extended version allows derived-type and structure-type
names (not objects) as actual arguments as well. In the case of derived-type and structuretype names, the result is the number of bits any object of that type will occupy in memory
at runtime. For example:
type point
integer(kind=2) :: x, y, z
integer(kind=1) :: alpha, r, g, b
end type
...
print *, bit_size(Point)
140
Miscellaneous Extensions.
new open statement specifiers (last two are for the inquire statement)
specifier
effect
form="binary"
can be used only with sequential unformatted files - for stream I/O
action={"publish"|"subscribe"}
for MacOS/MRWE
access="window[,*]"
access="transparent"
blocksize=default-integer-expr
in bytes
carriagecontrol={"Fortran"|"list"}
filetype=character-expr
creator=character-expr
convert={"big_endian"|"little_endian"}
access=character-variable
flen=default-integer-variable
If a character constant is appended with a C, as in "now is the time"C, then (a) a backslash
character (\) in the string is interpreted as an escape character that converts the subsequent character(s) in accordance with the following table and (b) appends a null character
(ascii 0) to the end of the string. The intent is to simulate C-style strings.
\a
\t
\b
\v
\f
\xh[h]
\n
\r
hexadecimal digit(s), up to 2
backslash
Any such escape sequence, including the backslash character, is replaced with the indicated character. If a backslash precedes any other character it is ignored (and removed).
The -YCSLASH command-line compiler option allows these escape sequences to be used
in any character constant (i.e., not just C-strings).
Subsequent use of the len intrinsic with a C-string value reflects the addition of the null;
for example, len("now\tis\nthe\ttime"C) has the value 16. Octal and hex values must fall in
the 0-255 (decimal) range, '\'C is illegal, C-strings may not appear in format statements,
and the character constant must be default kind.
A Fortran 90 Implementation
141
The keyword recursive may be omitted from a directly recursive procedure definition.
The byte type specifier is added and can be used anywhere the integer type specifier can be
used; it cannot have a kind value, and is equivalent to integer(1).
For Absoft compilers running on systems other than Apple MacOS, symbol names may
start with a leading dollar sign ($); for example: subroutine $foo(); end
Implicit typing of $ is default real, and in the implicit statement, $ is ordered after z; e.g.:
implicit integer (a-$) makes everything in the program type default integer, including, for
example, $foobar. (But note that names with leading dollar signs may not be the names of
variables associated with a namelist group.)
142
compiler directives
Compiler directives are placed on (separate) lines in the Fortran source code and provide
the compiler with additional information over that in the Fortran code itself. Directive
lines are identified by an initial token, !dir$, not shown in the following table, and appear
as comment lines. In fixed-form source Cdir$ also identifies a directive line, if the C is in
column 1. All directives, including the directive-identifying token, are case insensitive,
and ms$ and dec$ are acceptable alternatives to dir$ in all cases; in addition, if (and only
if) the -YMS7D compiler option is specified, the initial token may be simply $ in the first
column for the free[form], fixed[formlinesize], nofreeform, and pack directives, but this
form ($ in column 1) should be considered deprecated.
directive
effect
free[form]
nofreeform
fixed
same as nofreeform
fixedformlinesize: {72|80|132}
name (name="external-name")
pack[on] [ = {1|2|4|mac68K} ]
pack[on] and packoff specify that sequenced structure fields be aligned on byte,
packoff
stack
a. The name directive can be applied to external procedure definitions as well as to external procedure names
(to put Fortran procedures into other language namespaces)..
b. The mac68k packing is for 68K-Pascal structures, which is character, integer(1), and logical(1) aligned on
byte boundaries; all other objects aligned on even-byte boundaries.
The packing directives affect the current program unit being compiled (if there is one), or
the next program unit (when there is no current program unit). The packing directive is
reset to the default (packoff) after the end of each program unit. A packing directive
affects only derived-types found below the directive in the source code.
The alignment of any derived-type object (i.e. not its components) is dependent on the
highest alignment bound of any component. This holds true for packed structs, unions,
and maps. A union embedded in a derived type will start on a boundary based on the most
restrictive member of the union (i.e. padding may be inserted before the base of a union
and all maps will start at the padded boundary).
A component with the pointer attribute has an alignment which is the same as the alignment the most restrictive of either a natural-word-sized integer or a machine address on
the target machine, regardless of the object type. For example, in type foo; character,
pointer :: p_c; end type foo has a 32-bit alignment on Pentium Pro and PowerPC 601.
A Fortran 90 Implementation
143
effect
-c [<name>]
-d {a|j|n|p|q|v|B|R}
-e {a|j|n|p|q|v|B|R}
enable options (multiple options can be specified at once); same note as for -d
-f <form>
-g
-I <search-path>
identify search path for include files; multiple search paths require multiple -I options
-o <name>
-O
-p <file>
-s
-v
verbose compilation - echo all process commands used to create the output file(s)
-V
output version number; can be used without file(s) or other options, for example: f90 -V
-w
-W <line-length>
line length for fixed form source; must be from the set {72,80,132}
-x <directive>
disable specified source code directive; possible values are free, fixed, integer, name, stack
-YCHARV=ICHAR
-YCOM_NAMES= {UCS|LCS}
-YCOM_PFX [=prefix-string]
-YCOM_SFX [=suffix-string]
specifies suffix (including null) for external common-block names; default is null
-YCSLASH={0|1}
if 1, any character constant can contain C-string backslash escapes sequences; default is 0
-YEXT_NAMES={ASIS|UCS|LCS}
-YEXT_PFX [=prefix-string]
-YEXT_SFX [=suffix-string]
-YMS7D
recognize Microsoft form of source code directive, which is $<directive> with the $ in column 1
-YNDFP=1
disallow use of period for component selection; default is that period can be used in place of %
-YPEI={0|1}
1 (the default) makes the pointer type equivalent to integer; 0 turns this off
144
option
effect
\/---------------- MacOS/MPW-specific options ----------------\/
-launch
-link <arg>
-mrwe
-N9
forces generated code to make very frequent checks for command period
-plainappl
-ppc
-share
use shared versions of intrinsic libraries and I/O libraries; default is to use static linkage
-tool
-z <msg-level>
suppress output message by level control (errors, warnings, cautions, notes, comments)b
-Z <msg-number-list> suppress the output of the specified messages (useful for turning off long warning lists)
\/---------------- Windows/PC-specific options ----------------\/
-YDLL_NAMES={ASIS|UCS|LCS}
-YDLL_STDCALL={0|1}
0 means callee does not pop the argument frame; 1 means the frame is popped
-YIL={AC90,ACC,AC77,MSVC,MSVB,BC,BD,WINAPI}
-L <path>
-m <msg-level>
-M<msg-number-list>
-r
-S
-u <sym>
-YCFRL={0|1}
location of character length in argument list; 0 (default) at end of list, 1 after character value
A Fortran 90 Implementation
145
The -YIL= Windows option controls the calling mechanism and name mangling used in
the machine code when creating LIB and DLL files. The following table summarizes the
effect of the various -YIL= option values:
call mechanism name manglea
value
AC90b
default
uppercase
ACC
default
asis
AC77
default
asis
MSVC
MSVB
stdcall
asis
BC
stdcall
asis
BD
stdcall
asis
WINAPI
stdcall
a.
Trademark acknowledgments:
Pro Fortran is a trademark of Absoft Corporation
MacOS, MRWE, and MPW are trademarks of Apple Computer
CF90 is a trademark of Cray Research
VAX/VMS are trademarks of Digital Equipment
PowerPC is a trademark of IBM Corp used under license
Pentium is a trademark of Intel Corporation
Windows and Win32 are trademarks of Microsoft Corporation
Unix is a trademark of Santa Cruz Organization
146
A-1
Appendix A
Fortran 95 Features
The Fortran 95 language features of Absoft ProFortran are described in this appendix.
Fortran 95 extends the Fortran 90 language with extensions to existing language features
and the addition of certain new features. These extensions and additions include the WHERE
statement and construct; the FORALL statement and construct; and a number of intrinsic
functions including NULL, CPU_TIME, CEILING, FLOOR, MAXLOC, and MINLOC.
WHERE
The WHERE keyword can be used both as a statement and a construct, similar to the IF
keyword. WHERE is used to perform masked array assignments, applying a logical test to
each element of an array. The syntax of the WHERE statement is:
WHERE ( mask_expr )assign_stmt
assign_stmt
mask_expr
In the following example, the arcsine function will only be evaluated if the absolute value
of the element of the array a is less than or equal to 1.0.
REAL a(100), b(100)
.
.
.
WHERE (ABS(a) <= 1.0) b = ASIN(a)
A-2
Fortran 95 Features
where_body_construct is an array assignment statement or a
WHERE statement or construct. The shape of all arrays must be the
same as the shape of the array used in the mask_expr
FORALL
The FORALL keyword can be used both as a statement and a structure. It is similar to the
masked array assignment WHERE, but is more general, allowing more array shapes to be
assigned. It is used to perform array assignments, possibly masked, on an element by
element basis. The syntax of the FORALL statement is:
FORALL (triplet_spec [,triplet_spec] [,mask_expr] )assign_stmt
mask_expr
assign_stmt
statement.
In the following example, every element of the array a is assigned the value 1.0.
REAL a(100, 100)
.
.
.
FORALL (i=1:100, j=1,100) a(i,j) = 1.0
Fortran 95 Features
A-3
mask_expr
CPU_TIME
CPU_TIME is subroutine that returns the processor time. The calling sequence is:
CALL CPU_TIME(time)
A-4
Fortran 95 Features
NULL
Null is a transformational intrinsic function that returns a disassociated pointer. The
referencing sequence is:
NULL ([mold])
FLOOR
FLOOR is an elemental intrinsic function that returns
MAXLOC
is a transformational intrinsic function that returns the maximum value of the
elements in an array, a set of the array elements, or along a specified array dimension. The
referencing sequence is:
MAXLOC
Fortran 95 Features
A-5
of
the array
mask is a logical array and must be conformable with array
MINLOC
is a transformational intrinsic function that returns the value of the elements in an
array, a set of the array elements, or along a specified array dimension. The referencing
sequence is:
MINLOC
the array
mask is a logical array and must be conformable with array
of
Index
147
Index
A
Absoft, miscellaneous extensions 140
allocatable array 33
argument association 77, 79
actual argument 79
argument intent 81
argument keyword 79, 81
array element order 80
array element sequence association 79
assumed-length dummy argument 79
assumed-shape dummy argument 79
assumed-size dummy argument 79
dummy argument 79
dummy procedure 81
explicit-shape dummy argument 79
for derived types 80
for equivalent types 80
preventing nondeterminism 80
type/kind match 79
array 25
allocatable arrays 33
allocation status 33
array-valued expressions 25
array-valued functions 26, 35
assignment 25, 27
assumed size (deprecated) 45
assumed-shape dummy arguments 30
automatic arrays 33
broadcast, of scalars 26
computation functions 87
conformable, conformability 25, 26
constant 27
constructor 25
constructors 27
dimensions 11
element 30
element order 80
element-by-element operations 25, 26
example, Gauss elimination 37
example, picture refinement 36
implied-do, in constructors 27
inquiry functions 25, 85
lower bound 11
mask 28
masked array assignment (where) 28
pointer arrays 33, 34
rank 26
reduction operations 25
reshape, of a constructor 28
scalar subscript 31
section 30
shape 25
subscript 31
triplet subscript 31
upper bound 11
vector subscript 31, 32
whole array operations 25
assignment
array 27
character 15
masked array 28
numeric 14
assignment statement 4
assumed-shape dummy arguments 30
attribute extensions 136
attribute statements 3, 41
attributes
allocatable 12, 33
compatiblity between 12
dimension 12
external 12
intent 12
intrinsic 12
of data objects 12
optional 12
parameter 12, 13, 27
pointer 12, 34
private 12
public 12
save 12, 13, 33
target 12, 34
B
bit
computation functions 87
intrinsic functions 6
pseudo data type 6
role of logical 9
block data 2, 40, 43
BNF, syntax rules 1
C
character data type 9
148
assignment 15
computation functions 86
computations 15
concatenation 15
constant 9
expression 15
intrinsic functions 10
kind 9
length 9
operator 9
strings 9
substring 15
character storage unit 23, 40
comment initiation 4, 45
common blocks 39
common, blank 40
common, named 40
compilation unit 2
compiler directives, Absoft 142
compiler options, Absoft 143
complex data type 8
comparison of values 8
constant 8
imaginary part 8
kind 8
numeric computation functions 86
operators 8
real part 8
components, of derived data types 17
computation
character 15
complex 8
integer 6
logical 9
real 7
concatenation, character 15
constant
array 27
character 9
complex 8
double precision 8
integer 5
logical 8
named 13
real 7
constraints, on syntax 1
constructs
case (select) 63, 64
case default 65
do - end do, with labels 65
do - end do, without labels 65
Index
149
H
host association 77
I
IEEE floating point 7
imaginary part, of a complex value 8
implicit
declaration 16
none 16
statement 16
type environment 3, 16
typing 16
implicit procedure interface 75
include line 3
initial value specification 11
initialization expression 11
input/output
control edit descriptors 50, 52
data edit descriptors 50, 51
data input 47
data output 47
direct (random) files 54, 56
end of file (EOF) 48
end of record (EOR) 47
end= and eor= 58
end= and err= 48
end-of-record (EOR) 58
file (unit) connection - open 48, 53
file (unit) disconnection - close 54
file (unit) reconnection 54
file close 53
file connection properties 53
file inquiry 55
file inquiry options 55
file open 53
file position 56
format 47, 50
format specification 50
input control specifiers 47
input list 47
internal files (data conversion) 58
io-control-list 50
keyboard input 48
list-directed 48
list-directed I/O 60
name-directed (namelist) 61
namelist 61
namelist group name 61
nonadvancing 47
partial-record (nonadvancing) 47
partial-record (nonadvancing) I/O 57
random (direct) files 54, 56
150
records 47
repeat factor, for edit descriptors 52
repeat factor, for input values 60
scratch files 54
sequential files 54, 56
status variable (iostat=) 47
unformatted 48, 50
unit 47, 53
value separators 60
int 8
integer
operators 6
integer data type 5
constant 5
expressions 6
kind 5
numeric computation functions 86
integer division 6
intent specifier 42
interface block 75, 82
interfaces, procedure 75
internal procedure (see procedures) 75
intrinsic data types 5
intrinsic functions
abs 91
achar 91
acos 91
adjustl 92
adjustr 92
aimag 92
aint 92
all 92
allocated 33, 92
alphabetical listing 88
anint 92
any 92
array inquiry functions 85
asin 93
associated 34, 93
atan 93
atan2 93
bit computation functions 6, 87
bit_size 93, 139
btest 93
ceiling 94
char 94
character computation functions 10, 86
cmplx 8, 14, 94
conjg 8, 94
conversion functions 85
cos 94
cosh 94
count 94
cshift 35, 95
date_and_time subroutine 95
dble 95
digits 7, 95
dim 95
dot_product 96
dprod 96
eoshift 96
epsilon 96
exp 96
exponent 96
extensions 138
floor 97
fraction 97
huge 5, 97
iachar 97
iand 97
ibclr 97
ibits 97
ibset 97
ichar 98
ieor 98
index 98
int 8, 14, 98
ior 98
ishft 98
ishftc 99
kind 5, 7, 8, 11, 14, 99
lbound 99
len 99
len_trim 99
lge 99
lgt 99
lle 100
llt 100
log 100
log10 100
logical 100
matmul 100
max 100
maxexponent 101
maxloc 101
maxval 101
merge 101
min 101
minexponent 101
minloc 102
minval 102
miscellaneous inquiry functions 85
mod 102
modulo 102
mvbits subroutine 102
nearest 102
Index
nint 102
not 103
numeric computation functions 86
numeric environmental 7
numeric inquiry functions 85
pack 103
precision 103
present 81, 103
product 25, 103
radix 7, 103
random_number subroutine 103
random_seed subroutine 104
range 5, 104
real 8, 14, 104
repeat 104
reshape 11, 27, 28, 104
rrspacing 105
scale 105
scan 105
selected_int_kind 105
selected_real_kind 105
selected-int-kind 5
selected-real-kind 7
set_exponent 105
shape 25, 105
sign 106
sin 106
sinh 106
size 25, 33, 106
spacing 106
spread 38, 106
sqrt 107
sum 107
system_clock subroutine 107
tan 107
tanh 107
tiny 5, 107
transfer 11, 108
transpose 108
trim 108
ubound 108
unpack 108
verify 108
intrinsic procedure 75
intrinsic procedure extensions 138
intrinsic subroutine 85
iostat values for EOF and EOR 131
iostat values for error conditions 131
K
kind 8, 11
specification 10
151
type parameter 5
kind values (for Absoft implementation) 131
L
length specification, character 10
logical data type 8
constant 8
default kind 8
expressions 9
operators 9
loop construct (see constructs) 65
M
main program 2, 3, 75
mixed-mode numeric computations 14
module 2, 3, 69
alternative to common blocks 40
applications, data abstraction 73
applications, global entities 71
applications, procedure interfaces 71
applications, procedure libraries 71
applications, user-defined types 72
general structure of 69
module procedures 75
rename of entities 70
use association 77
using a module 69
using selective parts of (use...only) 69
module procedure (see procedures) 75
N
named constants, parameter attribute 13
name-directed I/O (namelist) 60
numeric storage unit 8, 23, 40
O
operator precedence 6
output (see input/output) 47
P
parameter attribute, named constants 13
parent string 15
pass by value 137
pointer array 33
pointer data type (Absoft extension) 134
procedures 75
argument association 77, 79
arguments (see argument association) 79
array computation functions 87
array inquiry functions 85
152
assignment interface 83
bit computation functions 87
call, call statement 75
character computation functions 86
common association in 77
conversion functions 85
defined assignment 83
defined operator 82
dummy procedure 81
elemental 84
entry statement 84
explicit interface 75
external 75
function 75, 76
function result value 76
generic procedure 83, 84
generic resolution rules 84
host association 77
host association, implicit typing in 78
implicit interface 75
interface 75
interface block 75, 82
internal 75
internal subprogram part 75
intrinsic (see intrinsic functions) 75
intrinsic procedures (listing) 88
intrinsic subroutines 87
invocation 75
miscellaneous inquiry functions 85
module 75
new operators defined by 75
numeric computation functions 86
numeric inquiry functions 85
optional argument 81
recursive 75, 76
statement function 84
subroutine 75
subroutine call 76
use association in 77
program units 2
R
real 8
real data type 7
constant 7
expressions 7
kind 7
numeric computation functions 86
numeric inquiry functions 85
operators 7
real part, of a complex value 8
record structure 17
Index
parameter 42, 43
V
pointer 42, 43
value, pass by 137
private 42
variable 4
public 42
read 44, 47
return 84
rewind 56
save 40, 42, 43
statement function 84
stop 68
target 42, 43
use 43, 69
write 47, 49
statements (see also constructs) 4
storage association 39
storage unit
character 23, 40
numeric 8, 23, 40
unspecified 40
structure constructor 20
structure type (Absoft extension) 133
style, in examples 1
subroutine (see procedures) 75
subscript (see array) 31
substring (see character data type) 15
syntax rules 1, 109
control structures (R801-844) 122
data types (R401-435) 113
declarations and attributes (R501-549) 115
expressions (R701-743) 119
general structure (R201-216) 109
I/O formatting (R1001-1017) 126
input and output (R901-924) 124
procedures (R1201-1226) 128
program units (R1101-1112) 127
tokens (names, operators, etc.) R301-313
112
variables (R601-631) 118
T
type declaration 10
type specifier 10
U
use association 77
user-defined
operators 75
operators for derived types 22
types 17
153
154
syntax terms
access-id 116
access-spec 116
access-stmt 116
ac-do-variable 115
ac-implied-do 115
ac-implied-do-control 115
action-stmt 111
action-term-do-construct 123
actual-arg 129
actual-arg-spec 128
ac-value 115
add-op 112, 120
add-operand 120
allocatable-stmt 117
allocate-lower-bound 119
allocate-object 119
allocate-shape-spec 119
allocate-stmt 119
allocate-upper-bound 119
allocation 119
alphanumeric-character 112
alt-return-spec 129
and-op 113, 120
and-operand 120
arithmetic-if-stmt 124
array-constructor 115
array-element 119
array-section 119
array-spec 116
assigned-goto-stmt 124
assignment-stmt 121
assign-stmt 124
assumed-shape-spec 116
assumed-size-spec 116
attr-spec 115
backspace-stmt 125
binary-constant 114
blank-interp-edit-desc 127
block 122
block-data 110, 128
block-data-stmt 128
block-do-construct 123
boz-literal-constant 113
c 127
call-stmt 128
case-construct 122
case-expr 122
case-selector 122
case-stmt 122
case-value 122
case-value-range 122
character 112
char-constant 112
char-expr 121
char-initialization-expr 121
char-length 116
char-literal-constant 114
char-selector 116
char-string-edit-desc 127
char-variable 118
close-spec 124
close-stmt 124
common-block-object 118
common-stmt 118
complex-literal-constant 114
component-array-spec 115
component-attr-spec 115
component-decl 115
component-def-stmt 115
computed-goto-stmt 124
concat-op 112, 120
connect-spec 124
constant 112
constant-subobject 120
contains-stmt 129
continue-stmt 124
control-edit-desc 127
cycle-stmt 123
d 127
data-edit-desc 126
data-i-do-object 117
data-i-do-variable 117
data-implied-do 117
data-ref 118
data-stmt 117
data-stmt-constant 117
data-stmt-object 117
data-stmt-repeat 117
data-stmt-set 117
data-stmt-value 117
deallocate-stmt 119
declaration-construct 110
default-char-expr 121
default-char-variable 118
default-int-variable 118
default-logical-variable 118
deferred-shape-spec 116
defined-binary-op 113, 121
defined-operator 113
defined-unary-op 113, 120
derived-type-def 114
derived-type-stmt 115
digit-string 113
dimension-stmt 117
do-block 123
do-body 123
do-construct 122
do-stmt 123
do-term-action-stmt 123
do-term-shared-stmt 123
do-variable 123
dummy-arg 129
e 127
else-if-stmt 122
else-stmt 122
elsewhere-stmt 121
end-block-data-stmt 128
end-do 123
end-do-stmt 123
endfile-stmt 125
end-function-stmt 129
end-if-stmt 122
end-interface-stmt 128
end-module-stmt 128
end-program-stmt 127
end-select-stmt 122
end-subroutine-stmt 129
end-type-stmt 115
end-where-stmt 121
entity-decl 116
entry-stmt 129
equivalence-object 118
equivalence-set 118
equivalence-stmt 118
equiv-op 113, 121
equiv-operand 120
executable-construct 111
executable-program 109
execution-part 110
execution-part-construct 110
exit-stmt 123
explicit-shape-spec 116
exponent 114
exponent-letter 114
expr 121
extended-intrinsic-op 113
external-file-unit 124
external-stmt 128
external-subprogram 109
file-name-expr 124
format 125
format-item 126
format-specification 126
format-stmt 126
function-reference 128
function-stmt 129
function-subprogram 109, 129
generic-spec 128
goto-stmt 123
hex-constant 114
Index
hex-digit 114
if-construct 122
if-stmt 122
if-then-stmt 122
imag-part 114
implicit-part 110
implicit-part-stmt 110
implicit-spec 117
implicit-stmt 117
initialization-expr 121
inner-shared-do-construct 123
input-item 125
inquire-spec 126
inquire-stmt 125
int-constant 112
intent-spec 116
intent-stmt 116
interface-block 128
interface-body 128
interface-stmt 128
internal-file-unit 124
internal-subprogram 110
internal-subprogram-part 110
int-expr 121
int-initialization-expr 121
int-literal-constant 113
intrinsic-operator 112
intrinsic-stmt 128
int-variable 118
io-control-spec 125
io-implied-do 125
io-implied-do-control 125
io-implied-do-object 125
io-unit 124
k 127
keyword 129
kind-param 113
kind-selector 116
label 113
label-do-stmt 123
length-selector 116
letter-spec 117
level-1-expr 120
level-2-expr 120
level-3-expr 120
level-4-expr 120
level-5-expr 120
literal-constant 112
logical-expr 121
logical-initialization-expr 121
logical-literal-constant 114
logical-variable 118
loop-control 123
lower-bound 116
155
m 127
main-program 109, 127
mask-expr 121
module 109, 127
module-procedure-stmt 128
module-stmt 128
module-subprogram 110
module-subprogram-part 110
mult-op 112, 120
mult-operand 120
n 127
name 112
named-constant 112
named-constant-def 117
namelist-group-object 118
namelist-stmt 118
nonblock-do-construct 123
nonlabel-do-stmt 123
not-op 113, 120
nullify-stmt 119
numeric-expr 121
octal-constant 114
only 128
open-stmt 124
optional-stmt 116
or-op 113, 120
or-operand 120
outer-shared-do-construct 123
output-item 125
parameter-stmt 117
parent-string 118
part-ref 119
pause-stmt 124
pointer-assignment-stmt 121
pointer-object 119
pointer-stmt 117
position-edit-desc 127
position-spec 125
power-op 112, 120
prefix 129
primary 119
print-stmt 125
private-sequence-stmt 114
program-stmt 127
program-unit 109
r 126
read-stmt 125
real-literal-constant 114
real-part 114
rel-op 112, 120
rename 128
return-stmt 129
rewind-stmt 125
saved-entity 117
save-stmt 117
section-subscript 119
select-case-stmt 122
shared-term-do-construct 123
sign 113
signed-digit-string 113
signed-int-literal-constant 113
sign-edit-desc 127
signed-real-literal-constant 114
significand 114
specification-expr 121
specification-part 110
specification-stmt 110
stat-variable 119
stmt-function-stmt 129
stop-code 124
stop-stmt 124
stride 119
structure-component 119
structure-constructor 115
subobject 118
subroutine-stmt 129
subroutine-subprogram 109, 129
subscript 119
subscript-triplet 119
substring 118
substring-range 118
target 121
target-stmt 117
type-declaration-stmt 115
type-param-value 116
type-spec 115
underscore 112
upper-bound 116
use-stmt 128
variable 118
vector-subscript 119
w 127
where-construct 121
where-construct-stmt 121
where-stmt 121
write-stmt 125
156