You are on page 1of 215

CAMBRIDGE FACULTY OF MATHEMATICS FORTRAN PROGRAMMING COURSE

***********************************************************
Outline
=======
This basic course focuses on the aspects of the language essential to
understanding existing code and the writing of new Programs. No previous
experience is needed. As an introduction, a short history traces the
origins and development of the various versions of Fortran up to the most
recent (2003) standard. However, the course deals mainly with the 1977
Standard ("Fortran 77"), but considers those features of the 1990 and
later standards ("Fortran 90") most likely to be encountered in and of
most value to scientific and mathematical programming.
The course comprises 6 one Hour Lectures. The first 2 cover Program
structure, data representation and basic flow control constructs, aimed
at entry level Fortran programmers. Then Array handling, Files and I/O
(Input and Output) and Program Units, are visited, and a full Program is
walked through in the last session. A seminar on High Performance (HPC)
programming should follow the course.

Contents - Part 1
==================
Introduction : Fortran, a Brief History
Fortran Program and Code Structure :
1/
2/
3/
4/

General
Fortran
Fortran
Fortran

Fortran Program Structure


Statements
Fixed Form Code Example (clpent.for)
Free Form Code Example (clpent.f90)

Fortran Data Representation :


1/
2/
3/
4/
5/
6/
7/
8/
9/
10/
11/

Introduction
Basic Declaration Form
Entity (Variable) Names
Basic (Intrinsic) Types
Implicit and Explicit Data Types
Basic (Intrinsic) Type Constants
Declared (Named) Constants
Variable Initialisations
Common Blocks
Overlays (Equivalences)
Common Block Data Initialisations

Fortran Assignments and Operations :


1/
2/
3/
4/
5/
6/
7/
8/
9/

Introduction
Basic Assignment Form
Basic Assignment with COMPLEX Variables
Basic Assignment of LOGICAL Variables
Basic Assignment aspects for CHARACTER Variables
Fortran Expressions
Fortran Numeric (Arithmetic) Expressions
Fortran Character (String, or Text) Expressions
Fortran Logical Expressions

Contents - Part 2
==================
Fortran Flow Control and Logic :
1/
2/
3/
4/
5/
6/
7/
8/
9/
10/
11/
12/
13/

Introduction
Relational (Conditional) Expressions
Relational Expressions with Arithmetic Operands
Relational Expressions with COMPLEX Type Operands
Relational Expressions with CHARACTER Operands
Composite Relational Expressions
Fortran Logical IF Statement
Fortran Block IF Statements
Arithmetic IF Statement
Loops (Iterative constructs) in Fortran
Branches in Fortran
Use if INTEGER Variables for Labels in Fortran
Exiting Fortran Programs

Fortran Array Processing :


1/
2/
3/
4/
5/
6/
7/
8/
9/
10/
11/
12/
13/
14/
15/
16/
17/

Introduction
Array Declarations
Array Subscript Range Declarations
Array Declaration Examples
Arrays in Common Blocks
Array Storage Rules
Array Initialisations
Array Initialisations with Implied DO Loops
Array Element Access and Assignment
Array Access and Assignment with DO Loops
Multidimensional Array Access and Assignment
Additional Array Processing Features in Fortran 90
Whole Array or Section Processing in Fortran 90
Array Section Processing in Fortran 90
Array Section Processing with Vectors in Fortran 90
Array Intrinsic Functions in Fortran 90
WHERE Statements to Process Arrays in Fortran 90

Contents - Part 3
==================
Fortran Files And I/O (Input/Output) :
1/
2/
3/
4/
5/
6/
7/
8/
9/
10/
11/
12/
13/
14/
15/
16/
17/

Introduction
External File handling and I/O Units
General Form of Input/Output Statements
External File Connection, OPEN Statement
External File Connection, OPEN Statement Examples
External File Release, CLOSE Statement
External File Enquiries, INQUIRE Statement
Input from Files, READ Statement
Formatted READ Statement Examples
Unformatted READ Statement Examples
List Directed READ Statement
List Directed READ Statement examples
Input from Internal Files
Output to Files, WRITE Statement
External File Repositioning Statements
Formatted Record Layout, FORMAT Statements
Formatted Record Layout, FORMAT Statements examples

Fortran Program Units :


1/
2/
3/
4/
5/
6/
7/
8/
9/
10/
11/
12/
13/

Introduction
Invoking Subprograms
Subprogram Structure and Variables
Subprogram Execution and Termination
Function Subprograms
Subroutine Subprograms
Assumed Size Arrays and CHARACTER Variables
Function Subprogram example
Subroutine Subprogram example
Intrinsic Functions
Selected Intrinsic Functions
Selected Intrinsic Functions New in Fortran 90
Subprograms as Call Arguments

Contents - Part 4
==================
Fortran Program Example :
1/
2/
3/
4/
5/
6/
7/

Introduction
Example Program Source Code
Example Program Control Parameters File
Example Program Input Data File
Example Program Output Data File and Run Report
Observations from Example Program
General Guidelines

Appendix 1, Fortran Resources :


1/
2/
3/
4/
5/
6/
7/
8/
9/
10/

Overview
General Programming and Specialist Resources
ANSI (and ISO) Fortran Standards
Compiler and Implementation Manuals
Fortran Resources on the World Wide Web
Selected Fortran 77 Literature
Selected Fortran 90, 95 and 2003 Literature
Numerical Applications Literature
General Programming Literature
Hardware Design and Performance Literature

Appendix 2 : Downloading and Running the Examples :


1/ Downloading the Example Routines and Data Files
2/ Compiling and Running the Example Routines

Fortran, a Brief History - Part 1


==================================
Fortran stands for "Formula Translation". It was the first High Level
or Third Generation programming language. Before it, all Programs were
written in Assembler, where one Program Instruction corresponded to a
single machine operation, and each model of computer featured its own
Instruction Set.
Coding in Assembler or Machine Code (where the Mnemonics naming data
entities or Instructions were replaced by the raw numeric Values and
Addresses understood by the hardware) was tedious. In 1953, John Backus,
an IBM researcher proposed the idea of Fortran to ease coding numerical
and engineering calculations. IBM took up the idea. A first manual was
ready by October 1956. The Fortran Code, where each Statement could
replace several Assembler Instructions was transformed to Machine Code
by a special Program called the Compiler. IBM was worried that Fortran
would not prove successful if the performance of compiled Binaries did
not come close to that of hand crafted Assembler Programs, so a lot of
effort went into optimisation right from the first Fortran Compiler.
Released in 1957 on the IBM 704 Mainframe, it turned into an instant
success. The compiled code still delivered good speed compared to the
Assembler equivalent, but complicated algorithms could be coded in a
fraction of the time needed before. Fortran II followed in 1958, adding
Subroutines. Fortran IV, released in 1962 became the de facto standard,
before it was adopted by the American National Standards Institute in
1966 as the first (ANSI) standard programming language. By then, several
other languages had emerged, like ALGOL (Algorithmic Language, 1958),
COBOL (Common Business Oriented Language, 1960), BASIC (Beginners All
Purpose Symbolic Instruction Code) and PL/1 (Programming Language 1,
1964). The latter, from IBM, represented the first universal language
attempt. It never really left the realm of IBM Mainframes.
Other computer manufacturers had by the time also produced their own
Fortran Compilers (as well as offerings for COBOL and Algol). With the
System 360 Mainframes of 1964, IBM created the first family of genuine
Plug Compatible computers, which became widespread and emulated by the
other manufacturers (Britains indigenous manufacturer, I.C.T. offered
the 1900 series for instance). Much as COBOL became the language of
choice for commercial applications, Fortran remained predominant in
scientific programming.

Fortran, a Brief History - Part 2


==================================
The 1966 ANSI Standard always represented a minimum specification of
what the different compilers supported. By the late 1970s, the need
for a new standard was felt, so the more widespread extensions could be
included. The 1977 Standard (published in 1978) added CHARACTER Type
Variables, Block IF constructs, and much enhanced File handling.
Over the 1980s, the need emerged to incorporate more extensions, but
also keep the language in tune with programming practice. However, the
discussions over a new standard, labelled "Fortran8x" proved conflictual
between those after a minimal expansion and retained compatibility with
previous versions, and those seeking a more radical redesign. For lack
of features such as User defined types, or block structured constructs,
Fortran was being replaced by C, C++ and other languages in a lot
of applications. It remained very prominent in the sciences though, if
only because of the vast body of existing Code still in use.
Also, the tightly defined features and fixed memory model of Fortran
programs allowed good optimisation of the code. Fortran was the choice
language on high performance hardware. Its only recently that C++
Compilers managed producing executables of comparable efficiency to
their Fortran equivalents.
Fortan8x finally emerged as Fortran 90 in 1992. Full compatibility
was preserved, but a lot was added. Free form Source Code, long Names
and in line Comments eased coding style constraints. New DO WHILE
and SELECT CASE constructs appeared as did Modules and interfacing
specifications. A lot of new Intrinsic Functions were included. But,
the most important development from the scientific viewpoint was that
Arrays, or parts of them could be manipulated or operated upon (with
arithmetic or Intrinsic Functions) as single objects.
Fortran 90 introduced the idea of more regular revisions to the latest
standard as well as of it charting a way forward for the language. It
effectively entered constant review. Starting with Fortran 90, items for
eventual removal are marked as "Obsolete". A few lesser used features
(PAUSE, ASSIGN and Arithmetic IF Statements for example) were the first.
These were removed in the next Standard, Fortran 95. Others, including
Fixed Form Source coding were in then marked for deletion. The important
scientific aspect of Fortran 95 lies in it now including High Performance
Fortran elements. The 95 Standard was adopted in 1997.

Fortran, a Brief History - Part 3


==================================
Fortran 2003 followed as the next standard, released in 2004. It brought
interoperability with other languages (mainly C and C++), more object
oriented programming features, and formalised Exception handling. Items
obsoleted in 1995 were in fact not removed. With most compilers still
offering features deleted in the 95 standard, the original 1950 Programs
should still Compile and run !
Fortran thus retains a lot of its original concepts and qualities, but
has again become a modern language, now perfectly suitable for tasks or
programming methods not yet imagined in the mid 1950s.
It took a long time for Fortran 90 and later compilers to write Binaries
getting near the performance of 77 Binaries. So, Fortran 77, if not "the"
recommended language on supercomputers remains in widespread use on such
systems. It also forms a much simpler and smaller language than the later
versions, so forms a good starting point.
This course focuses on Fortran 77, but will mention Fortran 90 additions
commonly seen or useful in scientific programming, like Array handling.
For a more detailed history of the language, see the Fortran Wikipedia
Page (see http://en.wikipedia.org/wiki/Fortran) or chapter 1, "Whence
Fortran" from "Fortran 95/2003 Explained" (M. Metcalf, J. Reid, M. Cohen,
Oxford University Press, 2004, ISBN 0-19-852692-X). The first chapter in
Volume II of "Handbook of Programming Languages" (P.H. Salus, Macmillan
Technical Publishing, 1998, ISBN 1-57870-009-4) also begins with a short
history, emphasising the role of the standards.

Fortran Program and Code Structure - Part 1


============================================
-

1/ General Fortran Program Structure :


Fortran constitutes an Imperative High Level programming language,
in that the Source Code in Programs is not directly understood, let
alone executed by the hardware. Instead, the Code is submitted to a
Compiler which writes out a Binary or Executable Module, containing
(Machine Code) Instructions appropriate (and often peculiar to) the
Hardware being used.
All Fortran Programs begin with a "Non Executable" Part, where
Variables, Arrays, and Constants may be declared and initialised.
The "Executable" Part follows, in which all computations, logic,
and File handling take place.
Diagrammatic form of a Fortran Program :
Program : PROGRAM Statement

: Optional to Name Program

Non Executable Part : Non Executable Statements


Executable Part

: Executable Statements

END

: Completes Executable Part

The two small example Programs at the end of the chapter both
use Comments to indicate the Non Executable and Executable Parts.
The PROGRAM Statement at the top Names the Program and marks it
as a Main Program, as opposed to a Subprogram or Subroutine. The
PROGRAM Statement is not required, in which case a (unnamed) Main
Program is assumed. Providing a name can help in tracing Errors,
or just which Routine is executing at any time.
Other Statements than PROGRAM would be used (FUNCTION, SUBROUTINE
or BLOCK DATA) for Subprograms. A (Main) Program makes up a stand
alone Execution Unit, which can be invoked and run by the (computer)
system, while Subprograms may not. They need to be invoked (or, in
programming terminology, "called") from a Main Program. Subprograms
will be covered in a later chapter of these notes. Subprograms can
themselves call other Subprograms.
An END Statement must be present to terminates all Routines.

Fortran Program and Code Structure - Part 2


============================================
-

2/ Fortran Statements :
In Fortran Programs, the Source Code, or simply Code, is written
as Statements, the equivalent of phrases in English. Except from
Comments and Blank Lines which may appear anywhere in Programs,
Statements are either "Non Executable", in which case they may only
show in the Non Executable Part, or "Executable", only to be used
in the Executable Part.
Blank Lines may be placed anywhere in any Source File, and Comment
Statements ditto, even part way through other Statements. Comments
are indicated by a C (Upper or Lower Case) or Asterisk (*) in
the leftmost Position (Column 1) of every Line deemed a Comment :
*
c
CCCC

Various ways to indicate Comment Statements (Lines)

Statements by default take one Line. No terminators are required.

10

Fortran Program and Code Structure - Part 3


============================================
-

2/ Fortran Statements (continued) :


Columns 1 to 5 are either left blank, or may contain a Numeric Label
of up to 5 Digits. Labels act as Addresses in Programs. Executable
Statements can be referred to by their Labels, or (logical) flow
transferred to them from elsewhere in Routines. Every Label must be
unique in the Routine it appears in, but no particular ordering of
Label Values is imposed.
Labels may sit with any number of blanks before or after, but not
within, and must not spill over beyond Column 5. Leading Zeros in
Labels are ignored so 0020 and 20 both refer to Label 20, but
at least one Digit must be non Zero.
Column 6 is always reserved for a Continuation Mark, when the Line
becomes a Continuation of that above. Any non Blank Character apart
from Zero may be used for that purpose. In Fortran 77, up to 19
Continuation Lines are allowed. Excluding Comments or blank Lines,
this means any Statement may occupy up to 20 Lines.
Columns 7 to 72 inclusive should contain the Code, which need not
start at Column 7. Columns 73 onwards are ignored. The limitation
originates from the early years of the language, when many Programs
were submitted via Punched (Hollerith) Cards, on which Columns 73 to
80 were left aside for a Card Number in the Deck. Most Terminal or
Editor Windows will offer 80 Character wide Lines but can be set
to 72, or Marker Comment Lines of that length slotted in the Code.
Compilers by default will not flag the presence of Code beyond
Column 72. However, options exist in most to either generate errors
in such cases, or allow Lines of a greater length to be used. This
became part of the Fortran 90 Standard where up to 132 Characters
are allowed per Line.

11

Fortran Program and Code Structure - Part 4


============================================
-

2/ Fortran Statements (continued) :


Diagrammatic form of Fortran (77) Statements :
Cols 1-5
-------Numeric
Label

Col 6
----Cont.
Mark

Col 7-72
---------------------Fortran Statement Text

Col 73 onwards
-------------Ignored

Example Fortran 77 Statements, second one with a Continuation :


CHARACTER * 32 CLNE1, CLNE2
1000 WRITE ( *, 10000 ) CLNE1,
1
CLNE2
10000 FORMAT ( A, A )
Fortran 90 extended the permitted Length of Lines to 132 Characters
with up to 31 Continuation Lines per Statement. Comments could be
initiated with an Exclamation Mark (!). That can appear at any
point along the Line, with or without Code preceding it, and will
turn the rest of the Line into a Comment, for example :
CHARACTER ( 32 ) CLNE1, CLNE2 ! Two Lines for Results.
10000 FORMAT ( A, A )

! Two Character Strings.

Additionally, multiple Statements could appear on one Line, with


Semi Colons separating them. In that case, the Column following
a Semi Colon took the role of Column 1 if that Statement had been
on the following Line, and so on. This breaks the model of "One
Statement, one or more Lines and no Terminators" of early versions
of the language and can be confusing. Semi Colons are used in many
other languages as Terminators (C, Pascal, or PL/1 for instance),
and the lack of them makes Fortran Code easy to detect.

12

Fortran Program and Code Structure - Part 5


============================================
-

2/ Fortran Statements (continued) :


Strictly Standard conforming Fortran 77 Statements should be
written using only the "Fortran Character Set", as follows :
A to Z
0 to 9
Blank
=
+ and *
/
( and )
.
,
:

(Upper Case Letters),


(Digits 0 to 9),
(not Tab, Null or other non Display Chars),
(Equal Sign),
(Plus and Minus Signs),
(Asterisk, used in various roles),
(Slash, Divide and Line Feed Operator),
(Left (Open) and Right (Close) Parentheses),
(Dot, Condition Delimiter and Decimal Point),
(Comma, Separator for any Lists),
(Colon, used in various separation roles),
(Single Quote (Apostrophe), Text Delimiter),
(Dollar, Currency Sign).

The Currency Sign need not be Dollar but must be present and
distinct from the other Characters. It plays no special role.
Fortran 90 extended the Fortran Character Set to include :
_
%
"
< and >
!
&
;
?

(Underscore, may be used in Names),


(Per Cent, Derived Types component Delimiter),
(Double Quote, alternative Character Delimiter),
(Less and Greater than, Relational Operators),
(Exclamation Mark, begins a Comment),
(Ampersand, Line Continued symbol (at end)),
(Semi Colon, Statement Separator on Line),
(Question Mark, no special role (like $)).

Note no requirement exists for the presence of Lower Case Letters.


These notes present all code examples and passages in Upper Case
to distinguish them from the rest of the text, using Single Quotes
to delimit Names and Expressions when used inside paragraphs.

13

Fortran Program and Code Structure - Part 6


============================================
-

2/ Fortran Statements (continued) :


Spaces may be inserted anywhere in Statements, as long as Column
restrictions are not infringed, and all Keywords, Names and Labels
remain atomic, so, for example :
CHARACTER*12 CC
CHARACTER * 12
CC
CHARACTER
* 12

CC

will all be equivalent, as will :


IF(II.EQ.3)YY=XX+5*ZZ**2
IF ( II.EQ.3 ) YY = XX+5*ZZ**2
IF ( II .EQ. 3 ) YY = XX + 5 * ZZ ** 2
but this Code would be invalid :
CHAR ACTER * 12
CHARACTER * 12
CHARACTER * 1 2

CC
C C
CC

I F(II.EQ.3)YY=XX+5*ZZ**2
IF ( II.EQ.3 ) Y Y = XX+5*ZZ**2
IF ( II .E Q. 3 ) YY = XX+5*ZZ**2
As will be seen when Variables and Constants are described, Spaces
inside the Single Quote delimited Value of a CHARACTER Variable or
Constant are significant unless no non Blank Characters follow them.
Such Spaces in effect become part of that Strings Value.
On most modern implementations, Fortran Statements may be written
in any mixture of Upper and Lower case Letters, which are treated
the same, Lower case being equivalent to Upper. For example :
CHARACTER * 12 CC
Character * 12 CC
character * 12 cc
would all declare a 12 Byte (Positions) Character Type Variable.
Originally capitals only were used to simplify parsing by Compilers,
and some of the Character sets did not include Lower Case letters.

14

Fortran Program and Code Structure - Part 7


============================================
-

2/ Fortran Statements (continued) :


The Fortran (77 or 90) Character Set should not be confused with
that available to assign CHARACTER Variables, or Constants, or Text
Strings in Output Statements, which on most systems includes Lower
Case Letters, and several additional Punctuation Characters.
This is called the Collating Sequence. PC and Unix systems use the
A.S.C.I.I. (American Standard Code for Information Interchange),
but Mainframes operate under E.B.C.D.I.C. which was arranged for
easy handling of punched cards.
Fortran places no constraints on Collating Sequences other than :
Upper Case Letters must come in alphabetical order,
though not forcibly in contiguous places in the sequence),
Digits must come in Numerical order,
and as a set, before or after the Upper Case Letters,
the Blank (Space) must precede both the Letters and Digits.
So overall, either :
< 0 < 1 < ... < 9 < A < B < ... < Z,
or
< A < B < ... < Z < 0 < 1 < ... < 9.
When included, the Lower Case Letters must also sit in Alphabetical
order, and as a set, after the Blank (Space), and before or after
the Digits. The Standards do not specify any relationships between
Upper and Lower Case Letters.
Fortran contains special operators for lexicographical comparisons
of Character Strings, so these remain possible irrespective of the
relationship of between Letters and other symbols in the Collating
Sequence of any given system. See the later notes on Operators.

15

Fortran Program and Code Structure - Part 8


============================================
-

2/ Fortran Statements (continued) :


Fortran 90 also introduced "Free Source Form", which was in effect
made the standard in Fortran 2003. The format of 77 and earlier
Source Code was then called "Fixed Source Form".
Under Free Form coding, the Label, when present, and Statement may
show anywhere along the Line, as long as at least a Space separates
the eventual Label and the Statement. Only the Exclamation Mark
Character remains valid to prefix a Comment, but may be typed any
Column along the Line. In Free Form, Continuations are marked by
an Ampersand (&) as the last non Blank or Comment Character in
the Line. Up to 31 Continuations are permitted, excluding Blank
and whole Comment Lines. Conversely, several Statements may share
a Line, separated by Semi Colons.
Fixed and Free Form coding may not coexist in the same Program.
Examples of Fixed Form and Free Form Code Programs are given in
the following pages. Note the minimal changes between the two forms.
The alterations consist of using Exclamation Marks to initiate the
Comments, appending Ampersands at the end of continued Lines, and
removing the Continuation Marks in Column 6 of the Fortran 77 Code.
The effects of the Various Statements will be explained in later
pages, but the Comments should give an idea of the processing.
Notice the use of spacing, between and within Statements, and the
alignment of the Labels. In the (77) Fixed Form coding Example,
the Comments all use a CCCC Prefix to better stand out.
These notes will use "Traditional", Capitalised, Fixed Form coding
for all examples and passages of Code, unless otherwise indicated.
If desired, most well laid Fixed Form Source Files should be easy to
convert to Free Form, while remaining easy to read. Utilities exist
to automate part of the task.

16

Fortran Program and Code Structure - Part 9


============================================
-

3/ Fortran Fixed Form Code Example (clpent.for) :


PROGRAM CLPENT
CCCC
CCCC
CCCC
CCCC

PROGRAM COMPUTES PENTAGONAL NUMBER FOR INDEX ENTERED BY USER,


AND NEXT 3 (PENTAGONAL FOR N = ( ( 3 N ** 2 - N ) / 2 ).
PROGRAM CONFORMS TO A.N.S.I. 1978 FORTRAN 77 STANDARD.

CCCC

NON EXECUTABLE PART (DATA DECLARATIONS).

CCCC

INDEX, INPUT STATUS AND FOUR PENTAGONAL NUMBERS.


INTEGER NPINDX, NPSTAT,
1
NPENT1, NPENT2, NPENT3, NPENT4

CCCC

EXECUTABLE PART, REQUEST STARTING INDEX ENTRY.

100 WRITE
1000 FORMAT

( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )

READ
1001 FORMAT

( *, 1001, ERR = 101, IOSTAT = NPSTAT ) NPINDX


( I80
)

IF

1002

( NPSTAT

.NE.

WRITE
FORMAT

( *,
( /,

GOTO

100

0 ) THEN
1002 )
Not an Integer. Try again )

ENDIF
CCCC

COMPUTE PENTAGONAL NUMBERS FROM INDEX AND SHOW THEM.

200 NPENT1
NPENT2
NPENT3
NPENT4
WRITE
1
2000 FORMAT
1

= ( ( 3 * NPINDX ** 2 - NPINDX ) / 2 )
= ( NPENT1
= ( NPENT2
= ( NPENT3

+ ( 3 * ( NPINDX
) ) + 1 )
+ ( 3 * ( NPINDX + 1 ) ) + 1 )
+ ( 3 * ( NPINDX + 2 ) ) + 1 )

( *, 2000 ) NPINDX,
NPENT1, NPENT2, NPENT3, NPENT4
( /, Pentagonal Numbers from Index , I6, :, /,
/, 4 ( I8, 1X )
)

END

17

Fortran Program and Code Structure - Part 10


============================================
-

4/ Fortran Free Form Code Example (clpent.f90) :


PROGRAM CLPENT
!
!
!
!

Program computes Pentagonal Number for Index given by User,


and next 3 (Pentagonal for N = ( ( 3 N ** 2 - N ) / 2 ).
Program conforms to A.N.S.I. (I.S.O.) Fortran 90 Standard.

Non Executable Part (Data declarations).

Index, Input Status and 4 Pentagonal Numbers.


INTEGER NPINDX, NPSTAT,
&
NPENT1, NPENT2, NPENT3, NPENT4

Executable Part, request starting Index entry.

100 WRITE
1000 FORMAT

( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )

READ
1001 FORMAT

( *, 1001, IOSTAT = NPSTAT ) NPINDX


( I80
)

IF

1002

( NPSTAT

.NE.

WRITE
FORMAT

( *,
( /,

GOTO

100

0 ) THEN ! Test for Input Error.


1002 )
Not an Integer. Try again )
! Branch back for Index retry.

ENDIF
!

Compute Pentagonal Numbers from Index and show them.


200 NPENT1

= ( ( 3 * NPINDX ** 2 - NPINDX ) / 2 )

NPENT2
NPENT3
NPENT4

= ( NPENT1
= ( NPENT2
= ( NPENT3

WRITE

( *, 2000 ) NPINDX,
&
NPENT1, NPENT2, NPENT3, NPENT4

2000 FORMAT

+ ( 3 * ( NPINDX
) ) + 1 )
+ ( 3 * ( NPINDX + 1 ) ) + 1 )
+ ( 3 * ( NPINDX + 2 ) ) + 1 )

( /, Pentagonal Numbers from Index , I6, :, /, &


/, 4 ( I8, 1X )
)

END

18

Fortran Data Representation - Part 1


=====================================
-

1/ Introduction :
This Chapter covers how data, numeric or otherwise, are represented
in Fortran. The general form of declarations is explained, followed
by a description of the Types available. Constants and allocation
of Values are described, then Data initialisations. Finally, The
mechanism to make data visible to multiple Program Units and share
storage are explained. Data declaration and associated statements
constitute the "Non Executable" part of a Fortran Program unit, and
must come before all Executable Statements in the Source Code.
Whatever their nature, all referenced, aka Named, data in a Fortran
Program or Subprogram are explicitly or implicitly declared. They
must also feature a Type, for which defaults exist for implicitly
declared Variables. These may be amended if desired. Declaration
Statements are also called "Type" Statements for they always provide
a Type for all Variables they introduce.
Fortran 77 includes 6 (Intrinsic) Types : CHARACTER for text data,
INTEGER, REAL, DOUBLE PRECISION and COMPLEX for Integer, Floating
Point (Single and extended Precision) and Complex Numbers, and
LOGICAL for On-Off (True or False) Switches.
Constants may appear in some Fortran Statements, and be named via
a special form of declaration, the PARAMETER Statement. Variables
may be given initial Values with DATA Statements, which allow this
to be carried out in bulk.
Groups of Variables, explicitly of implicitly declared, may be
mapped in a (single) region of storage (Memory) made available to
multiple Program Units (main Program and any number of Subprograms)
in COMMON Blocks, defined in COMMON Statements. For initialisation,
Variables in Common Blocks require BLOCK DATA Subprograms.
Variables can share the same storage (Memory) area. The EQUIVALENCE
statement facilitate this, with some restrictions as the the Types
and other attributes of the Variables so related.
In Fortran 90 Data Structures and Pointers are also supported.
These are not covered in these notes which focus on Fortran 77.
Fortran 90 also lifts some restrictions affecting PARAMETER, DATA,
COMMON and EQUIVALENCE Statements in Fortran 77.

19

Fortran Data Representation - Part 2


=====================================
-

2/ Basic Declaration Form :


Type Keyword followed by one or more comma separated entity Names.
So, for each intrinsic Type offered in Fortran, with leading Spaces,
the Statements below show typical declarations :
CHARACTER *14
CHARACTER

CHS1,
CHS2,
CHS3
CHVAR1, CHVAR2, CHVAR3

INTEGER

INVAR1, INVAR2, INVAR3

LOGICAL

LGVAR1

REAL

REVAR1, REVAR2, REVAR3

COMPLEX

PXVAR1, PXVAR2

DOUBLE PRECISION

DPVAR1, DPVAR2

Note placing a comma as the last non blank character in a line does
not alone mean the following Line is considered a continuation. For
that, a Character will be needed in Column 6 of the next Line :
CHARACTER CEXMP1,
1
CEXMP2
As an alternative, in Fortran 90 Free Form coding,
an Ampersand should follow the comma at the end of the top Line :
CHARACTER CEXMP1, &
CEXMP2
See more examples below where the Intrinsic Types are described.
In Fortran 90, a ( KIND = ... ) qualifier, or ( ... ) Kind Value
and comma separated list of Attributes can follow the Type Keyword.
KIND allows several Sizes, in terms of Memory Bytes for entities,
or some other features, like Character Sets, or numeric ranges.
Also in Fortran 90 a double colon (::) may split a Type Keyword
and Attributes from the following list of Variable Names :
CHARACTER :: CEXMP1, &
CEXMP2

20

Fortran Data Representation - Part 3


=====================================
-

3/ Entity (Variable) Names :


Fortran 77

- At most 6 alphabetical or numeric Characters,


beginning with a letter.
Upper and Lower Case letters same in Names,
so for example, Vrnm01 and VRNM01 both
refer to the same Variable.
Many implementations will allow "Long Names",
for example up to 31 Characters as in Fortran 90.
- Note Variables need not be explicitly declared,
so Names may first show in Executable Statements.
See notes about implicit Variable Types below.
Implicitly declared Variables allowed fewer
Statements in Programs, so less Punched Cards,
or smaller Source Code Files for Compilers,
but made detection of (typing) errors harder.
All Variables should now be explicitly declared.
- Avoid single letter Variable Names,
as they can make Variable instances hard to find,
for example in Editors, and typing errors could
more easily slip through undetected.
- Also avoid Names which clash with Keywords,
Intrinsic Functions or other Fortran attributes.

Fortran 90

- Same as Fortran 77 apart :


- Entity Names up to 31 Characters allowed,
which can also include digits and Underscores.
Many Fortran 77 compilers allowed "Long Names",
though not necessarily limited at 31 Characters.
- Implicit Types match those found in Fortran 77,
but can be invalidated with IMPLICIT NONE,
then with no other IMPLICIT Statements allowed.

21

Fortran Data Representation - Part 4


=====================================
-

4/ Basic (Intrinsic) Types :


CHARACTER

- Character String, from 1 to 32,767 Characters,


containing any of the Characters present in the
Collating Sequence, the full set of possible
Characters known to the computer system.
- By default, single Byte length (one character),
but eventually given an Integer Length, say NN,
with a * NN or * ( NN ) default Prefix, or,
for each Variable, Suffix. For example :
CHARACTER*12

C1, C2, C3

CHARACTER * 12 C1, C2, C3


CHARACTER

C1*12,
C2*12,
C3*12

CHARACTER

C1 * 12,
C2 * 12,
C3 * 12

1
1

1
1

all Define three 12 Byte Character Strings,


named C1, C2, C3. Overrides allowed
for a defaulted Length like :
CHARACTER * 12 C1, C2, C3 * 10
CHARACTER

C1 * 12,
C2 * 12,
C3 * 10

1
1

CHARACTER *(4) CA, CB*1, CC, CD*2


define 12 Byte Character Strings by default,
with an override to Length 10 for the last, C3,
then 4 Byte Variables apart from CB and CD.
- Lengths cannot be Zero or Negative and any
such Lengths should cause compilation failure.

22

Fortran Data Representation - Part 5


=====================================
-

4/ Basic (Intrinsic) Types (continued) :


CHARACTER (Cont.) - When Variable a Dummy Variable in a Subprogram,
or a Named Constant set in a PARAMETER Statement,
Length Value may be "assumed" from actual Data.
This is indicated with an Asterisk :
CHARACTER * (*) CHARG1, CHARG2, CHARG3
CHARACTER * (*) CHPARM
For Subprograms, this means length of actual
passed Variable. See later notes on Subprograms.
For Named Constants, aka Parameters, this means
length of actual String assigned to Parameter.
See later notes on (Named) Constants.
- In Fortran 90, ( LEN = NN ) or just ( NN )
may be used to specify Default Lengths. Then,
first example above could be any of :
CHARACTER

( 12 )

C1, C2, C3

CHARACTER ( LEN = 12 )

C1, C2, C3

CHARACTER ( LEN = 12 ) :: C1, C2, C3


CHARACTER ( LEN = 12 ) :: C1, &
C2, &
C3
but next example above requires two Statements :
CHARACTER ( LEN = 12 )

C1, C2

CHARACTER ( LEN = 10 )

C3

23

Fortran Data Representation - Part 6


=====================================
-

4/ Basic (Intrinsic) Types (continued) :


INTEGER

- Integer entity.
- Example : to declare Integers I1, I2, I3,
INTEGER

I1, I2, I3

- Usually 4 Bytes (32 Binary Bits),


so Max. Absolute Value ( 2 to Power 31 ) - 1,
thus Range -2,147,483,647 to +2,147,483,647.
- In some implementations, INTEGER*2 and INTEGER*4
allowed to specify 2 or 4 Byte Integers.
Two Byte Integers limit absolute Value to 32,767.
LOGICAL

- On or Off Switch,
with Value .TRUE. or .FALSE..
- Example : to declare Variables LG1, LG2,
LOGICAL

XC1, XC2

- May be used as Conditional on its own,


without Conditional Operator (see later).
- Note despite their On-Off nature,
LOGICAL Variables usually occupy full Bytes,
Bytes being the lowest level (amount of) Memory
addressable in machine (Assembler) Instructions.
So the benefit of LOGICAL Variables lies in them
being a Condition in their own right, and not
in economy of storage compared to other Types.
Length 1 CHARACTER Variables also take one Byte.

24

Fortran Data Representation - Part 7


=====================================
-

4/ Basic (Intrinsic) Types (continued) :


REAL

- "Single Precision" Floating Point entity.


- Usually 4 Bytes (32 Binary Bits) in IEEE format,
with Sign, 8 Bit Exponent and 23 Bit Mantissa.
Thus Binary Exponent Ranges from -127 to +128,
corresponding to a Base 10 Range of about 10-38
to 10+38. The 23 Bit Mantissa equates to decimal
accuracy of 7 to 8 Digits.
- Fortran 90 implementations must support at least
2 Real Kinds, so extended entities may act as an
alternative to the DOUBLE PRECISION Type.

DOUBLE PRECISION

- Extended Floating Point entity,


allocated twice as much Memory as a REAL entity.
- Usually 8 Bytes (64 Binary Bits) in IEEE format,
with Sign, 11 Bit Exponent and 52 Bit Mantissa.
Thus Binary Exponent Ranges from -1021 to +1024,
corresponding to a Base 10 Range of about 10-308
to 10+308. The 52 Bit Mantissa equates to decimal
accuracy of 15 to 16 Digits.
- Example : to declare Variables D1, D2, D3,
DOUBLE PRECISION

D1, D2, D3

- In modern applications, all real arithmetic


should be carried out in DOUBLE PRECISION,
to reduce numerical drift and other errors.
- In Fortran 90, an equivalent to DOUBLE PRECISION
Variables may be implemented via the second Kind
of REAL Variable a system should offer.

25

Fortran Data Representation - Part 8


=====================================
-

4/ Basic (Intrinsic) Types (continued) :


COMPLEX

- Twin REAL entity, with Real and Imaginary Parts,


each a REAL, obeying laws of Complex arithmetic,
that is, Real Part behaves like such a number,
while squared Imaginary Unit become minus one.
- Example : to declare Variables XC1, XC2,
COMPLEX

XC1, XC2

- Fortran 90 implementations must support at least


2 Kinds, to allow DOUBLE PRECISION sized entities,
for both (Real and Imaginary) Parts.

26

Fortran Data Representation - Part 9


=====================================
-

5/ Implicit and Explicit Data Types :


By default, declaring Variable in Type Statements not required
before using them in other Statements, including Executable ones.
Implicit Types are used for such undeclared Variables.
By default, Variables not explicitly declared are Integers,
for Names beginning with any of the Letters from I to N,
and (Single Precision) Real numbers for all others.
Implicit typing my be overridden with IMPLICIT Statements,
to associate one or more starting letter ranges with a Type.
Each IMPLICIT Statement may cover one or more Types :
IMPLICIT COMPLEX
IMPLICIT CHARACTER
1
LOGICAL
IMPLICIT INTEGER

( A-B )
( C
( L

),
)

( I-K )

IMPLICIT DOUBLE PRECISION ( D,E, P-Z )


Many Fortran 77 implementations and compilers allow NONE,
as an Attribute to IMPLICIT, forcing all Variables to be declared.
When IMPLICIT NONE used, no other IMPLICIT Statements permitted.
This became a Standard feature in Fortran 90.
For strictly conforming 77 Code, use IMPLICIT CHARACTER ( A-Z ),
to force declaring all entities found in assignments or arithmetic,
as CHARACTER Values need enclosing Quotes, which will not be valid
in any form of numerical Expression or Assignment.
In Fortran 90 Implicit Types match those found in Fortran 77,
but can be invalidated with an IMPLICIT NONE, in which case no
other IMPLICIT Statements are allowed.
When available, use of IMPLICIT NONE is recommended.

27

Fortran Data Representation - Part 10


=====================================
-

6/ Basic (Intrinsic) Type Constants :


Data Values may be used as Constants, to assign Variables,
either directly, or in Expressions involving several entities.
Constants may also show in Expressions used in Conditionals.
For each Intrinsic Data Type, constants are written as follows :
CHARACTER

- Enclose actual text String in Single Quotes,


and for every Quote to form part of String,
code 2 Quotes, distinct from end quotes.
Effectively, delimiters not part of Data.
- CHARACTER Constants cannot be Zero Length,
so illegal, and Data over 32,767 Characters
truncated to that length.
- Examples :
Data_String
01234567
OBrien

for
for
for
for

Data_String,
the Digits 0 to 7,
OBrien,
one Single Quote.

- In Fortran 90, Double Quotes delimiters allowed,


Single Quotes then being ordinary characters,
and vice versa when Single Quotes delimit data.
Above Examples would alternatively become :
"Data_String"
"01234567"
"OBrien"
""

for
for
for
for

Data_String,
the Digits 0 to 7,
OBrien,
one Single Quote.

28

Fortran Data Representation - Part 11


=====================================
-

6/ Basic (Intrinsic) Type Constants (continued) :


INTEGER

- Digits in Value with optional Arithmetic Sign,


always showing at left and without separation.
- Leading Zeros may show without effect, but
Decimal Points, commas and Exponents illegal.
- Constants are assumed positive when not signed.
Signs ignored when Constant Value Zero,
- Constants over maximum allowed Absolute Value
illegal and should cause compilation to fail.
- Examples :
-345
+32767
0034
- illegal Examples :
-345.0
+32,767

(Decimal Point)
(comma in Field)

-214748648
LOGICAL

(exceeds Max. Absolute Value)

- May only take Values "True" and "False",


written between full stops (as all other
Logical Operators must be in Fortran 77) :
.TRUE.
.FALSE.

29

Fortran Data Representation - Part 12


=====================================
-

6/ Basic (Intrinsic) Type Constants (continued) :


REAL

- Digits in Value with optional Arithmetic Sign,


Decimal Point, Decimals (following Point),
and (Base 10) Exponent, with optional Sign.
- When present, Arithmetic Sign must show at left,
and without separation, while Exponent Coded
to right, with E Prefix, and following Sign,
then Exponent Absolute Value, without spaces.
- Leading Zeros may show without effect,
including in Exponent, unless that makes Field
longer than allowed (2 Digits).
- Constants and Exponents assumed positive
when not signed. Signs ignored with Zero Values.
- When more Digits than can be represented,
(in 4 Bytes) right side truncated and rounded.
- Constants over maximum allowed Absolute Value,
that is, with Exponent Absolute Value too large,
illegal and should cause compilation to fail.
For REAL Type Constants, Max. Exponent 38.
- Examples :
-345
+32767
0034.0
0.0

(effectively
345.0)
(
"
32,767.0)

12E2
(1200.0, like other writings below)
12.E2
12E+02
+12.0E+02
1.20E3
+0.120E+4

30

Fortran Data Representation - Part 13


=====================================
-

6/ Basic (Intrinsic) Type Constants (continued) :


DOUBLE PRECISION

- Same as for REAL Constants above,


except that Exponent must be written as D,
rather than E, assumed when no Exponent.
- For DOUBLE PRECISION Type Constants,
Maximum Exponent Absolute Value 308.
- Examples, matching above REAL cases :
-345D0
(effectively
345.0)
+32767D0 (
"
32,767.0)
3.4D1
0.0D0

COMPLEX

- COMPLEX Constants consist of Real and Imaginary


(Single Precision) REAL Values, in parentheses,
and with a comma Separator.
- Examples :
(3.0,2.1)
( 3.0E0, 2.1E0 )

(note same as above)

( -0.31E-3, +7.50E+2 )

31

Fortran Data Representation - Part 14


=====================================
-

7/ Declared (Named) Constants :


Variables of any Type may be used to hold Constant Values,
specified via PARAMETER Statements, effectively naming Constants.
Each PARAMETER Statement presents a bracketed list of Name = Value
(Constant) Parameter assignments, separated by commas, for example :
CHARACTER * 12

CFILE1

INTEGER

IFILE1

PARAMETER

( CFILE1 = ProgInpt.dat, IFILE1 = 8 )

Assumed Length CHARACTER Constants allowed, for example :


CHARACTER

CFILE1 * (*)

would be valid for the above PARAMETER Statement, with the Length
of the Constant CFILE1 then defined by the count of Characters in
the String assigned to it, here 12 Characters.
Arithmetic Expressions are allowed as long as all Values known,
and exponentiation (** Operator) limited to Integer powers, so :
INTEGER
DOUBLE PRECISION
1
1

IEX1

PARAMETER
1
1

XARG01,
XARG02,
XARG03
( IEX1 = 3, XARG01 =
3.14159D0,
XARG02 =
3.14159D0 ** 3,
XARG03 = ( XARG01 + XARG02 ) )

Assignments being left to right, in the example above,


all Values available at time each Parameter Value assigned.
Intrinsic Functions CHAR, ICHAR, and LEN are likewise allowed,
when associated with already declared CHARACTER Variables.

32

Fortran Data Representation - Part 15


=====================================
-

7/ Declared (Named) Constants (continued) :


When Values provided in Parameter assignments disagree with
corresponding Variable Types, either forced conversion happens,
as would between INTEGER, REAL and DOUBLE PRECISION Types,
or the Statement becomes illegal. So, these are allowed :
INTEGER
PARAMETER

IPR1
( IPR1 = 10.5 )

REAL

RPR2

DOUBLE PRECISION

DPR3

PARAMETER

( RPR2 = 12, DPR3 = 11.2 )

In the first case above, IPR1 takes the Integer Value 10,
In the second case, RPR2 becomes 12.0, and DPR3 11.2D0.
When CHARACTER Parameters are assigned Strings of different
Length to that declared, shorter Strings get Blank padded,
while longer Strings get truncated, so for example :
CHARACTER * 12
PARAMETER

CHP1, CHP2
( CHP1 = Test, CHP2 = Test long String )

result in CHP1 being assigned Test


(8 trailing Blanks),
and CHP2 being truncated to Test long St (so ring cut off).
Note Implicit naming conventions apply to Parameters, and also,
later IMPLICIT Statements cannot contradict Types for Parameters.
PARAMETER
IMPLICIT

( ICHL = 12 )
CHARACTER *7 ( I-J )

would be invalid because later IMPLICIT would imply Type CHARACTER


for the undeclared ICHL, by default, at that time, an Integer.

33

Fortran Data Representation - Part 16


=====================================
-

8/ Variable Initialisations :
Variables may be given initial Values via DATA Statements.
These take effect once, before Execution begins, so for Subprograms,
will not apply beyond the first occasion the Subprogram is called.
DATA Statements contain a List of comma separated Variable Names,
and then, in between slashes, a list of Values for those Variables :
CHARACTER * 6

CHD1, CHD2

DATA

CHD1, CHD2 / Test01, Test02 /

INTEGER
1

IDT1, IDT2, IDT3,


IDT4, IDT5, IDT6

DATA
DATA

IDT1, IDT2, IDT3 / 10, 10, 10 /


IDT4, IDT5, IDT6 / 10, 11, 12 /

REAL
DOUBLE PRECISION

RDT1
DDT2

DATA

RDT1, DDT2 / 20.0, 24.0D0 /

When the Values given disagree with the appropriate Variable Types,
conversion happens between INTEGER, REAL and DOUBLE PRECISION Types,
or the Statement becomes illegal. For example :
INTEGER

IPR1

REAL

RPR2

DOUBLE PRECISION

DPR3

DATA

IPR1

DATA

RPR2, DPR3 / 12,

/ 10.5 /
11.2 /

In the first case above, IPR1 takes the Integer Value 10,
In the second case, RPR2 becomes 12.0, and DPR3 11.2D0.

34

Fortran Data Representation - Part 17


=====================================
-

8/ Variable Initialisations (continued) :


When CHARACTER Variables are assigned Strings of different Length
to that declared, as is the case for Parameters (see above),
shorter Strings get Blank padded and longer ones truncated, so :
CHARACTER * 12

CHS1, CHS2

DATA

CHS1, CHS2 / Test, Test long String /

result in CHS1 being assigned Test


(8 trailing Blanks),
and CHS2 being truncated to Test long St (so ring cut off).
Note that unlike CHARACTER Parameters, ordinary CHARACTER Variables
cannot be declared with unspecified Length (CHARACTER * ( * ),
assigned a Value in a DATA Statement, and take their Length off it.
CHARACTER entities may be partially initialised by adding a Range,
in parentheses after their Names, giving ( FROM : TO ) Substrings,
both FROM and TO being Integers.
For any CHARACTER Substring, the "From" Byte must equal or exceed 1,
and "To" may at most equal the base Variable Length. Either or both
may be defaulted, in which case 1 or the Variable Length are used.
Positions following a Substring will be set to Blank, so in effect
only the the "From" value matters. So ( : ) or ( 1 : ) as Ranges
equate to the whole Variable.
Examples of CHARACTER Substring DATA Statements :
CHARACTER * 12
DATA
1

CHS1, CHS2
CHS1 ( 5 : 7 ), CHS1 ( 3 : )
/ xx
, 123456789 /

initialise Bytes 5 and 6 of CHS1 to x, with Bytes 7 to 12 Blank,


and Bytes 3 to 11 of CHS2 to the String given, and Byte 12 Blank.
In both cases leading Bytes before the Substring remain unassigned.

35

Fortran Data Representation - Part 18


=====================================
-

8/ Variable Initialisations (continued) :


Successive sets of Variable Names and Values may be merged,
or DATA Statements with comma separators in one DATA Statement,
so the initial DATA example above could be written as :
DATA
1
1
1

IDT1,
/ 10 ,
IDT5,
/ 11 ,

IDT2,
10 ,
IDT6,
12 ,

IDT3,
10 ,
RDT1,
20.0,

IDT4
10
/
DDT2
24.0D0 /

Repeated Values may be replaced by a Multiplier and a single Value,


with the Asterisk (*) symbol between them. The top 2 Lines above
could for example be written as :
DATA

IDT1, IDT2, IDT3, IDT4

/ 4 * 10 /

or, with CHARACTER Type Variables :


DATA

CHS1, CHS2 / 2 * Test /

For arrays, a special form of DO Loop called "Implied DO Loop"


may also be used in DATA Statements. See later coverage of Arrays.
In Fortran 90, as an alternative to using DATA Statements,
Variables can be initialised in their Type declaration Statement,
with Values following the corresponding Names after an Equal Sign :
CHARACTER ( 6 )

CHD1 = Test01, CHD2 = Test02

INTEGER
INTEGER

IDT1 = 10, IDT2 = 10, IDT3 = 10, IDT4 = 10


IDT5 = 11, IDT6 = 12

REAL
DOUBLE PRECISION

RDT1 = 20.0
DDT2 = 24.0D0

could replace the first set of DATA examples above.

36

Fortran Data Representation - Part 19


=====================================
-

9/ Common Blocks :
Blocks of storage (Memory) may be accessed by several Program Units,
be they a Program and some of its Subprograms, or just the latter.
Such structures are called Common Blocks.
The Variables in a Common Block are listed in one or more COMMON
Statements. Common Blocks may be Blank or Named. For the latter, a
Name, surrounded by Slashes, precedes the comma separated Variables.
Several Blocks may be declared per COMMON Statement, optionally
separated by commas, for example :
INTEGER
1

IDC1, IDC2, IDC3,


IDC4, IDC5, IDC6

DOUBLE PRECISION
1

DDC1, DDC2, DDC3,


DDC4, DDC5, DDC6

COMMON
1

IDC1, IDC2, IDC3,


DDC1, DDC2, DDC3

COMMON
1

/ COM1 / IDC4, IDC5, IDC6,


/ COM2 / DDC4, DDC5, DDC6

declare a Blank Common, then the Named Common Blocks COM1, COM2
in a Single Statement, with the optional comma Separator in between.
Two consecutive Slashes may also specify Blank Common. Common Names
must not clash with Program Unit or Intrinsic Function Names, but if
one (Common) Name appears in multiple COMMON Statements, the second
and later Statements merely add to the earlier set of Variables. The
Blank Common above could have been coded :
COMMON

/ / IDC1, IDC2, IDC3

...
COMMON

/ / DDC1, DDC2, DDC3

Mismatched Numeric data Types as well as Arrays and lone entities


may be involved, but CHARACTER or LOGICAL Variables may not be mixed
with other Types. Also, any Variable may appear in only one COMMON
Statement, or Block, in any Program Unit.

37

Fortran Data Representation - Part 20


=====================================
-

9/ Common Blocks (continued) :


When Blank Common is used in multiple Program Units, the list of
Variables need not include the whole set of Variables in the Block,
and as long as any Type mismatches remain valid, that list may vary.
For example, one CHARACTER Variable could become two :
Program Unit A :
CHARACTER * 24
COMMON

CHCO
/ / CHCO

Program Unit B :
CHARACTER * 12
COMMON

CHC1, CHC2
/ / CHC1, CHC2

For Named Common Blocks, all Variables must be listed in all Program
Units where the Block features (in effect implying the same length is
kept at all times).
Variables used as
not belong to any
be initialised in
See 11/ below for

(passed or received) Arguments in Subprograms may


Common Blocks. Also, Common Block Variables cannot
DATA Statements, but need BLOCK DATA Subprograms.
BLOCK DATA Subprograms.

38

Fortran Data Representation - Part 21


=====================================
-

9/ Common Blocks (continued) :


Common Blocks allow sets of Variables to remain in proximity to each
other in Memory, and can save overheads when Subprograms are called.
This can facilitate efficient Memory access.
It is advisable to list all the Variables in Common Blocks in one
COMMON Statement, and the sequence of Names should be the same in all
Program Units where the Block features. For Blank Common, Variables
should all be listed.
Fortran 90 relaxes the restriction that Numeric and Non Numeric
Variables cannot be entered in the same Common Blocks, but still
imposes that 32 Bit Numeric Variables must occupy a full Memory
Word, starting on a multiple of 4 Address, and 64 Bit Variables
(DOUBLE PRECISION and COMPLEX) must take a Double Word, with an
Address on a multiple of 8 Bytes.

39

Fortran Data Representation - Part 22


=====================================
- 10/ Overlays (Equivalences) :
Variables can be forced to share the same storage space (Memory),
with EQUIVALENCE Statements, in effect a superimposition of Memory
mappings with joint reference points given by the Statements.
Mismatched Numeric data Types as well as Arrays and lone entities
may be involved, but CHARACTER or LOGICAL Variables may not be
mixed with other Types. Association of single CHARACTER Variables
and Arrays are allowed. See later coverage regarding Arrays.
Each Equivalence encompasses 2
separated Names listed between
can include several lists each
featuring various Numeric data
INTEGER
COMPLEX
REAL
DOUBLE PRECISION

or more Variables, with their comma


parentheses. An EQUIVALENCE Statement
separated by a comma. For example,
Types :

IEA1, IEA2, IEA3, IEA4


XEQ1
REQ1, REQ2
DPE1, DPE2, DPE3

EQUIVALENCE

( IEA1, IEA2 )

EQUIVALENCE

( IEA3, REQ1, DPE1 )

EQUIVALENCE

( XEQ1, DPE2 ), ( DPE3, REQ2 )

In terms of Memory Mappings, using = to mark jointly used storage


and | at 4 Byte (Memory Word) boundaries, these examples produce :
|====|
|====|

4 Bytes for IEA1


4
"
" IEA2 at the same location as IEA2

|====|
|====|
|====|----|

4 Bytes for IEA3


4
"
" REQ1, first 4 Shared with IEA3, DPE1
8
"
" DPE1,
"
4
"
"
IEA3, REQ1

|====|====|
|====|====|

8 Bytes for XEQ1 (4 for each Part of Complex)


8
"
" DPE2, shared with XEQ1 Complex Number

|====|----|
|====|

8 Bytes for DPE3


4
"
" REQ2, shared with first 4 of DPE3

40

Fortran Data Representation - Part 23


=====================================
- 10/ Overlays (Equivalences) (continued) :
Note much as Variables are often mapped in Memory in the order they
are declared, this is not required. So, it must not be assumed that
any Variables not explicitly mentioned in EQUIVALENCE lists overlap.
In the last example above, the Integer IEA4 will not lay over the
trailing 4 Bytes of DPE1. The one exception to this happens with
Arrays as these, for Equivalence purposes become single objects. See
the later notes explaining Arrays.
Also, as no conversion whatsoever takes place when mismatched Types
appear in EQUIVALENCE Lists, any assignments to one entity in a List
will not produce the same Value in the others, apart from the one
case of REAL and COMPLEX as each Part of the COMPLEX constitutes a
REAL Variable. Using the List ( IEA3, REQ1, DPE1 ) above, with the
Decimal Value 49,153 in the Integer IEA3 yields the Bit Map :
00000000 00000000 11000000 00000001

= 49153

With either the Sign, 8 Exponent and 23 Mantissa Bits of a REAL, or


the Sign, 11 Exponent and 52 Mantissa Bits of a DOUBLE PRECISION,
the Bits making the Integer Value at that Memory location (Address)
produce very small, but different, Floating Point Values.
With CHARACTER Variables, Equivalence (storage overlap) may be set
against Substrings of the Variables, but the whole storage mappings
will thus become partly of fully overlapped, beyond any Substrings
in the actual EQUIVALENCE Statement. For example :
CHARACTER * 20

CEQ1, CEQ2, CEQ3 * 10, CEQ4

EQUIVALENCE

( CEQ1 ( 4 : 6 ), CEQ2 )

EQUIVALENCE

( CEQ3, CEQ4 ( 9 : )

would give actual storage (Memory) mappings :


|---=================|
CEQ1 Memory
|=================---| CEQ2
"
|==========|
|--------==========--|

CEQ3 Memory
CEQ4
"

41

Fortran Data Representation - Part 24


=====================================
- 10/ Overlays (Equivalences) (continued) :
One but not both of the pair of Variables in an Equivalence may
belong to a COMMON Block, and at least one must remain outside any
COMMON Blocks. For example :
Fortran 90 relaxes the restriction that Numeric and Non Numeric
Variables cannot be entered in EQUIVALENCE Statements, but still
imposes that 32 Bit Numeric Variables must occupy a full Memory
Word, starting on a multiple of 4 Address, and 64 Bit Variables
(DOUBLE PRECISION and COMPLEX) must take a Double Word, with an
Address on a multiple of 8 Bytes.
Equivalence was useful on hardware with limited Memory, in that
it allowed Programs to invoke more Variables without consuming
additional Memory to hold them, or (see later coverage) overlay
Arrays of different structure on the same Memory space. Later
computer systems usually contain enough Memory, so EQUIVALENCE
looses its main justification, while Fortran 90 offers obvious
ways to rearrange Arrays (see later notes).

42

Fortran Data Representation - Part 25


=====================================
- 11/ Common Block Data Initialisations :
Any Variable listed in a Common Block may only be initialised in a
BLOCK DATA Subprogram, and not elsewhere. One Blank BLOCK DATA
Subprogram is allowed, and any number of Named ones, of which the
Names cannot clash with other Subprogram or COMMON Names.
BLOCK DATA Subprograms begin with a BLOCK DATA Statement, possibly
giving the Subprogram a Name, and finish with an END Statement. In
between them, any Common Blocks may appear, at they would in other
Program Units, with the same constraint that all Variables in Named
Common Blocks must be listed.
However, DATA Statements to initialise part or all of the (Common)
Variables are allowed, while not permitted in other sorts of Program
Unit. BLOCK DATA Subprograms may not declare or use Variables not in
a Common Block, and cannot contain Executable Statements.
Example Blank BLOCK DATA Subprogram :
BLOCK DATA
INTEGER
COMMON

IDT1, IDT2, IDT3, IDT4


/ / IDT1, IDT2, IDT3, IDT4

DATA

IDT1, IDT2, IDT3, IDT4 / 4 * 10 /

END
Example Named BLOCK DATA Subprogram :
BLOCK DATA BKDT01
DOUBLE PRECISION
DOUBLE PRECISION
COMMON
COMMON
DATA
DATA

DDA1, DDA2, DDA3, DDA4


DDT1, DDB2, DDB3, DDB4

/ CDT1 / DDA1, DDA2, DDA3, DDA4


/ CDT2 / DDB1, DDB2, DDB3, DDB4
DDA1, DDA2 / 2 * 10.5D0 /
DDB1, DDB2 / 2 * 12.5D0 /

END

43

Fortran Assignments and Operations - Part 1


============================================
-

1/ Introduction :
Assignments represent the mechanism, via the Equal Sign Operator,
to give a (Target) Variable a new Value which may arise from some
other Variable, a Constant, or an expression.
In Expressions, one or more Values, called Operands,
eventual Operators or Function Calls. The Values may
Variables (including the Targets initial contents),
either implemented in PARAMETER Statements, or given
of the Expression itself.

are merged via


be those of any
or Constants,
in line as part

Functions represent a sort of Subprogram returning a single Value


from any number of passed Arguments. Functions may be Intrinsic,
built into Fortran and available to any Program, or specific. The
latter can be provided as additional Source Code at compilation, or
in Binary form via Libraries made known to the Compiler. Functions
will be treated in a following part of these notes.
Items involved in Expressions, must be of consistent Type, though
some Type mismatches are tolerated with Numerical data, which will
be converted to the appropriate Type. Operations take place left to
right, but in a hierarchical manner. This can be overridden with
Parentheses. The Operators available differ for Numeric, LOGICAL
and CHARACTER data. LOGICAL Expressions may serve as Conditionals
in Flow Control Statements. This is covered later in these notes.
In Fortran 90, whole Arrays or parts of them may be treated as a
single entity in assignments or Expressions. See the later chapter
on Arrays. Also, Fortran 90 introduces a new form of Assignment for
Pointer Variables. This will not be covered in these notes. Last,
many new Intrinsic Functions were added in Fortran 90.

44

Fortran Assignments and Operations - Part 2


============================================
-

2/ Basic Assignment Form :


Fortran Assignments obey the syntax "Target = Value". The Target
must be a Variable, explicitly declared in the Non Executable Part,
or implicitly declared by appearing in Executable Part Statements.
The initial content of the Target may form part of the Value. They
are lost with no possibility of retrieval after the assignment. In
effect the area in Memory where the Target resides is overwritten.
The Equal (Sign) Operator (=) is required to effect assignments,
with the Target always the Left Hand Side. The assigned Value may be
that of a Constant, another Variable, or an expression. In Fortran,
no data on the Right hand side of an assignment can change.
The Value may be absolute, or an Expression, involving one or more
Operands and Operators such that a single Value is produced by the
evaluation of the Expression. See the rules affecting Expressions
in the following pages.
Also, the Value in an assignment must be of the same Type as the
Target. In line Constants must obey the rules for their Type. When
not, conversions are eventually forced for Numeric Types, which
can entail loss of accuracy, or compilation errors arise. Data in
CHARACTER Variables can be assigned to Numeric Fields but only via
READ Input Statements. Likewise, WRITE Output Statements are needed
to send Numeric Values to CHARACTER strings. These are not taken as
Conversions, and are treated in a later chapter of these notes.
So, in effect only mismatches between Numeric Types are tolerated
in assignments and can be resolved at compilation time. For good
practice, all conversions should be made explicit in the Code.

45

Fortran Assignments and Operations - Part 3


============================================
-

2/ Basic Assignment Form (continued) :


Basic assignment examples (not involving composite Expressions) :
CHARACTER * 12

CVR1, CVR2, CVR3, CVR4

INTEGER

INV1, INV2

REAL

RLV1, RLV2, RLV3

DOUBLE PRECISION

DPV1, DPV2, DPV3

CVR1
CVR2
CVR3

= Data_String
= 01234567
=

INV1
INV1

= 10
= -8

RLV1
RLV2
RLV3

= 10.0
= 0.8E-02
= RLV2

DPV1
DPV2
DPV3

= 120.0D0
= 1200.0D0
= DPV2

all these assignments feature matched data Types (in most cases
involving an in line Constant as the Value) across the Equal Sign.

46

Fortran Assignments and Operations - Part 4


============================================
-

2/ Basic Assignment Form (continued) :


Using the same Variables as in the previous examples, all these :
DPV1
DPV2
DPV3

= 120
= 1200.0
= RLV3

RLV1
RLV2
RLV3

= 10
= 8E-03
= DPV1

INV1
INV2

= 10.5
= RLV2

exhibit Constants improperly written for the Target Type, or force


Type Conversions. In the Floating Point to Integer cases, Decimals
are dropped, so INV1 would become 10, and INV2 Zero. The top
two REAL and DOUBLE PRECISION assignments will be rearranged as if
written with one digit left of the Decimal Point and an exponent.
Note the first pair of DOUBLE PRECISION assignments risks loss of
accuracy. The Constants might be saved as REAL, and then converted.
Good compilers should avoid this, but the last DOUBLE PRECISION and
REAL assignments imply Type Conversions. The Code could explicitly
show such Conversions, at no computational cost, for clarity :
DPV3
RLV3

= DBLE ( RLV3 )
= REAL ( DPV3 )

and for the INV2 = RLV2 Integer case :


INV2

= INT

( RLV2 )

As shown above, the INT, REAL and DBLE Functions carry out
conversion of their (Numeric) Argument to Integer, REAL and DOUBLE
PRECISION. They should be used whenever that actually happens.
When a Numeric Variable receives a Value in excess of the Maximum
allowed, either a compilation error should arise or, if this cannot
be seen then, an "Execution Time" (or "Run Time") error should halt
execution. This may happen with Floating Point to Integer, or DOUBLE
PRECISION to REAL or COMPLEX, for the latter, because of the fewer
Exponent Bytes provided in REAL or COMPLEX Fields.

47

Fortran Assignments and Operations - Part 5


============================================
-

3/ Basic Assignment with COMPLEX Variables :


Unless assigned from another COMPLEX Variable, Values for COMPLEX
Variables should be a comma separated pair of REAL Variables or in
Line Constants. Each item in the pair should meet the criteria for
REAL assignments above. For example :
COMPLEX
1

CXV1, CXV2,
CXV3, CXV4

REAL

RLV1, RLV2, RLV3

RLV1
RLV1

= -2.2E-2
= +0.05

CXV1
CXV2

= ( 12.4, 28.6 )
= ( RLV1, RLV2 )

CXV3
CXV4

=
CXV1
= ( RLV1, -3.0 )

make up valid COMPLEX Variable assignments, where either another


COMPLEX or two REAL Variables are involved. With one or both Parts
of a Value INTEGER or DOUBLE PRECISION, the above rules for INTEGER
or DOUBLE PRECISION to REAL assignments apply. The examples below
both imply conversion to REAL or the DOUBLE PRECISION Real Part
and INTEGER Imaginary Part :
COMPLEX

CXV1, CXV2

DOUBLE PRECISION
INTEGER

DPV1
INV1, INV2

DPV1
INV1

= 120.0D0
= -300

CXV1
CXV2

= ( DPV1
, INV1 )
= ( 120.0D0, -300 )

The examples would be more clearly coded as :


CXV1
CXV2

= ( REAL ( DPV1 ), REAL ( INV1 ) )


= (
120.0,
-300.0 )

48

Fortran Assignments and Operations - Part 6


============================================
-

3/ Basic Assignment with COMPLEX Variables (continued) :


Non COMPLEX Numerical Variables can be assigned COMPLEX Values. If
no conversion is explicitly specified, the Imaginary Part is lost
and the Real Part possibly converted to INTEGER or DOUBLE PRECISION.
Conversely, COMPLEX Variables may actually be assigned atomic
Values of other Numeric Types, in which case the Imaginary Part is
set to Zero (0.0). In both instances of COMPLEX and other Numeric
Type mismatches across the Equal Sign, coding conversion Functions
can make the Code easier to follow :
CXV1
CXV2

= DPV1
= INV1

RLV2
INV2

= CXV3
= CXV4

would be more clearly coded as :


CXV1
CXV2

= ( DPV1, 0.0 )
= ( INV1, 0.0 )

RLV2
INV2

=
= INT

REAL ( CXV3 )
( REAL ( CXV4 ) )

For completeness, and clarity, the CMPLX conversion Function could


be coded. It accepts one or two Arguments, standing for the Real and
Imaginary Parts of the resulting COMPLEX Value respectively. for
example, the first pair of assignments above could be written :
CXV1
CXV2

= CMPLX ( DPV1 )
= CMPLX ( INV1 )

or more clearly :
CXV1
CXV2

= CMPLX ( REAL ( DPV1 ), 0.0 )


= CMPLX ( REAL ( INV1 ), 0.0 )

Non Numeric Types cannot be mixed with COMPLEX Variables.

49

Fortran Assignments and Operations - Part 7


============================================
-

3/ Basic Assignment with COMPLEX Variables (continued) :


Were the Imaginary Part of a COMPLEX Variable to be assigned to an
atomic Numerical Variable, the AIMAG Function would be required.
The above RLV2 and INV2 assignments would become :
RLV2
INV2

=
AIMAG ( CXV3 )
= INT ( AIMAG ( CXV4 ) )

Likewise, to place a unitary Numerical Values into the Imaginary


Part of a COMPLEX Variable, the Real Part should be entered as Zero
with or without explicit inclusion of the CMPLX Function :
CXV1
CXV2

=
=

( 0.0, REAL ( DPV1 ) )


( 0.0, REAL ( INV1 ) )

CXV1
CXV2

= CMPLX ( 0.0, REAL ( DPV1 ) )


= CMPLX ( 0.0, REAL ( INV1 ) )

In Fortran 90, COMPLEX Type entities may use either REAL or DOUBLE
PRECISION for their component Parts. So, assignments involving only
COMPLEX Values can still require conversions, when the Types for
the COMPLEX Parts are mismatched.

50

Fortran Assignments and Operations - Part 8


============================================
-

4/ Basic Assignment of LOGICAL Variables :


Only LOGICAL Type Values or Variables may be involved in assigning
LOGICAL Variables, which can only take Values .TRUE. or .FALSE..
When presented as in Line Constants, these must be written with the
surrounding Dots (.), but without any other form of quoting :
LOGICAL

LGV1, LGV2, LGV3

LGV1
LGV2

= .FALSE.
= .TRUE.

LGV3

= LGV1

In Fortran 77, Variables or Constants of other Types cannot directly


be converted to LOGICAL, and vice versa. Assignments mismatching
LOGICAL entities with other Types should cause compilation failures.

51

Fortran Assignments and Operations - Part 9


============================================
-

5/ Basic Assignment aspects for CHARACTER Variables :


Like LOGICAL data, CHARACTER assignments need a Right Hand side of
that Type. Using the earlier 12 Byte CHARACTER Variables, these will
all generate errors. The first two lack delimiting Single Quotes,
while the third assigns an empty String which is not permitted :
CVR1
CVR2
CVR3

= Data_String
= 01234567
=

For CHARACTER Type Variables, when the Value proves longer than the
Variable, the Bytes beyond the Length of the Variable are truncated.
Again with the earlier 12 Byte CHARACTER Variables :
CVR1
CVR2
CVR3

= Data String too long


=
Long Tail

result in :
CVR1
CVR2
CVR3

= Data_String
=
Long Tail
=

Conversely, with CHARACTER Targets longer than the assigned Values,


the tail of the Target is filled with Spaces. So, over the complete
Variables, these earlier CHARACTER assignments
CVR1
CVR2
CVR3

= Data_String
= Some Text
=

equate to :
CVR1
CVR2
CVR3

= Data_String
= Some Text

Thus trailing Blanks are ignored when dealing with CHARACTER data.
For instance, may be used to blank a whole Variable, or to test
whether it contains any non Blank data anywhere along its Length.

52

Fortran Assignments and Operations - Part 10


============================================
-

6/ Fortran Expressions :
Expressions combine any number of Variables Values and Constants
with Operators to form a single Value. That may be assigned to a
Variable, or used in a Relational Expression (used as Conditional
in an IF Statement). Thus, the right hand sides of the assignment
examples above form simple Expressions. Operators available in
Expressions depend on the Data Types involved. Rules govern the way
Expressions are evaluated to yield a single result.
All the data entities in an expression should be of the same Type.
However, when mismatched Numeric Types are present, conversions do
take place, by implicit or explicit use of the appropriate Function
as detailed above for basic assignments.
This means Expressions split into three major sorts :
Numeric Expressions, also called Arithmetic,
CHARACTER Expressions, also described as Text Expressions,
LOGICAL Expressions.
Numeric Expressions themselves subdivide into :
INTEGER (Type) Expressions,
REAL (Type) Expressions,
DOUBLE (Type) PRECISION Expressions,
COMPLEX (Type) Expressions.
So, three categories of Operators exist, applicable to Numeric,
CHARACTER and LOGICAL Expressions respectively. As they rely on
differing Symbols, risks of confusion or misuse are minimal.

53

Fortran Assignments and Operations - Part 11


============================================
-

7/ Fortran Numeric (Arithmetic) Expressions :


When evaluating Numeric Expressions with entities of dissimilar
Types, these are levelled by internal Conversions, to the higher
Type in the following atomic entity Type classification :
Lowest : INTEGER
REAL
Top
: DOUBLE PRECISION
This means Expressions mixing REAL and INTEGER entities will be
resolved after conversion to the REAL Type. Similarly, Expressions
with any DOUBLE PRECISION entities will call for their conversion
to that Type. An exception exists for Exponentiation. See the notes
about Operators below.
Example of Expressions and Assignments with mixed Type entities :
INTEGER

INV1

REAL

RLV1, RLV2

DOUBLE PRECISION

DPV1, DPV2

INV1
DPV2

= RLV1 + 52 * DPV1
= RLV2
* 12.6D2

The first case leads to 52 being converted to DOUBLE PRECISION


and multiplied by DPV1, then a similar conversion of RLV1 being
added to it, before the result gets turned to INTEGER (loosing the
decimals). In the second example, a prior conversion of RLV2 to
DOUBLE PRECISION is multiplied before assignment to DPV2.
Expressions featuring COMPLEX entities will call for conversion
to that Type. That can entail "down" typing of DOUBLE PRECISION
entities when they become Parts of a COMPLEX one.

54

Fortran Assignments and Operations - Part 12


============================================
-

7/ Fortran Numeric (Arithmetic) Expressions (continued) :


Fortran Numeric Expressions may use 5 Arithmetic Operators :
**
*
/
+
-

(Exponentiation),
(Multiplication),
(Division),
(Addition),
(Subtraction).

Also, an Arithmetic or "Unary" Sign can be placed without spacing


immediately to the left of a Value or Variable Name. A Unary Minus
effectively flips the Sign of the entity, a Plus being redundant.
For example -INV1 means ( -1 * INV1 ) for an INTEGER entity.
Operations fall into 4 levels, regarding order of evaluation :
Unary Sign
**
* and /
+ and -

applied when present,


evaluated first,
"
after all **
"
last, after all ** and * or /.

Sets of adjacent operations of the same category are processed left


to right, except Exponentiation (**), carried out right to left.
This order may be altered by placing portions to be evaluated first
inside parentheses. Also, any Function calls in an Expression will
be resolved before other evaluations. For example :
IVAR = 3
* INT ( DVR1 ) + 3
DVR2 = 80.0D0 *
( DVR1
+ 12.4D0 )
means the INT conversion in the top Statement happens first, then
the multiplication and last the addition. In the second case, that
takes place first, due to the Parentheses.

55

Fortran Assignments and Operations - Part 13


============================================
-

7/ Fortran Numeric (Arithmetic) Expressions (continued) :


Exponentiation Operator (**) :
Unless Parentheses are used to alter this natural order, and taking
entity Types as already equalised, Exponentiation takes priority over
other Operations in the evaluation of Numeric Expressions.
Unlike other Operations, Exponentiation proceeds right to left :
DPVR ** 3.2D0 ** 4.4D0
first raises 3.2 to the power 4.4, to then exponentiate DPVR.
Integer Exponents may be processed more efficiently by the system,
so they should be coded as such to facilitate that gain. These
operations to exponentiate a DOUBLE PRECISION Variable :
DPV1 ** 3.0D0
DPV2 ** 2.8D-1 ** 3.0D0 ** -4.8D0
would be better (and more clearly) coded as :
DPV1 ** 3
DPV2 ** 2.8D-1 ** 3 ** -4.8D0
or, to avoid any ambiguities in the second case :
DPV2 ** ( 2.8D-1 ** ( 3 ** -4.8D0 ) )
or, to also isolate the Unary Minus :
DPV2 ** ( 2.8D-1 ** ( 3 ** ( -4.8D0 ) ) )
In a lot of Code, squaring (Exponentiation by 2) is replaced by self
multiplication (so DPV1 * DPV1 substitutes for DPV1 ** 2). No
computational cost is incurred, while poor compilers would not always
implement this special case in an optimal manner.

56

Fortran Assignments and Operations - Part 14


============================================
-

7/ Fortran Numeric (Arithmetic) Expressions (continued) :


Multiplication and Division Operators (* and /) :
Again assuming entities of have been brought to a single Type,
Multiplications and Divisions follow any Exponentiations, but
precede all Additions and Subtractions in computing Expressions.
Use of Parentheses may of course alter this natural order.
In the standard fashion, Multiplications and Divisions proceed
left to right, taking operations of either sort indiscriminately :
DPV1 * 3.2D0 / DPV2 * 4.8D0 / DPV3
multiplies DPV1 by 3.2, divides the result by DPV2, that result
times 4.8 and, last, divided by DPV3 giving the Expression Value.
As with the last Exponentiation example on the previous page,
including Parentheses or positioning all operations of a same sort
in succession can make the Code clearer :
( DPV1 * 3.2D0 * 4.5D0 ) / ( DPV3 * DPV2 )
also, a good Compiler should reduce 3.2D0 * 4.8D0 to 15.36D0
so as to save one Multiplication when running the compiled Binary.
Integer Division removes any Decimals which would have been in the
quotient of an equivalent Floating Point Division. For example :
INV1 = 244
INV2 = INV1 / 5
assigns the result 48 to INV2.
The remainder from an Integer Division, aka the Numerator Modulo
the Divisor may be obtained via the MOD Intrinsic Function, like :
INV3 = MOD ( INV1, INV2 )
which, with INV1 and INV2 as above, produces the Value 4.

57

Fortran Assignments and Operations - Part 15


============================================
-

7/ Fortran Numeric (Arithmetic) Expressions (continued) :


Addition and Subtraction Operators (+ and -) :
Again assuming entities of of a consistent Type in the Expression,
Additions and Subtractions are performed last (that is following
all Exponentiations, and Multiplications or Divisions). As usual,
Parentheses can force changes to this natural order.
In the standard fashion, Additions and Subtractions are worked
left to right, taking operations of either sort indiscriminately :
DPV1 + 8.6D0 + DPV2 - 4.8D0 + DPV3
adds 8.6 to DPV1, then DPV2 to the result, before subtracting
4.8 and finally adding DPV3 to yield the final Expression Value.
No special criteria apply to INTEGER entities, and apart from making
the Code clearer, no computational benefits, or gains in accuracy
accrue from grouping additions and subtractions in an Expressions.
However, in the example above, the + 8.6D0 and - 4.8D0 could
be turned into + 3.8D0 to economise one Subtraction. The Code
would then become the neater :
DPV1 + DPV2 + DPV3 + 3.8D0

58

Fortran Assignments and Operations - Part 16


============================================
-

8/ Fortran Character (String, or Text) Expressions :


In terms of Data, CHARACTER Type Expressions can only include
Variables and Named or in Line Constants of that Type. However
Variables or Named Constants (set in PARAMETER Statements)
may be presented in the form of Substrings.
Concatenation forms the only Operator for CHARACTER Expressions.
When CHARACTER entities are concatenated, their non Blank portions,
if any, are merged in left to right order. As usual with CHARACTER
assignments, any remaining Bytes are filled with Spaces.
Example of CHARACTER Expressions and Concatenation :
CHARACTER * 16

CHV1, CHV2, CHV3

CHV1
CHV2
CHV3

= 01 // 234567
= CHV1 // 89
= CHV1 // 89 // ABCDEF

The first Concatenation merges 01 and 234567 into CHV1, and


fills the rest of CHV1 with Spaces. In the second case, 89 is
tacked straight after the 7 in CHV1, leaving 6 trailing Spaces.
The third example in effect takes these tail Blanks with ABCDEF.
So, CHV1 contains 01234567
, CHV2 0123456789
,
and CHV3 01234567890ABCDEF.
Exactly the same could be achieved with Substrings :
CHV1 ( 1 : 8 )
CHV2 ( 1 : 10 )
CHV3

= 01
// 234567
= CHV1 ( 1 : 8 ) // 89
= CHV2 ( 1 : 10 ) // ABCDEF

However, Substrings would have made these examples different :


CHV1 ( 1 : 12 )
CHV2 ( 1 : 10 )
CHV3

= 01234567xx
// ab
= CHV1 ( 1 : 8 ) // 89
= CHV2 ( 1 : 10 ) // ABCDEF

with CHV2 and CHV3 ending as before, despite a changed CHV1.

59

Fortran Assignments and Operations - Part 17


============================================
-

8/ Fortran Character (String, or Text) Expressions (continued) :


As with Numeric Data Additions or Subtractions, no computational
gain accrues from reordering Concatenations. However, benefit is
obtained by eliminating redundant operations. So :
CHV3
CHV3

= CHV1 // 89ABCDEF
= CHV2 // ABCDEF

would have proved more efficient for the last two examples above.
Parentheses may, just as in Arithmetic Expressions, force a given
order of evaluation, much as this will not change the final Value.
As usual with CHARACTER assignments, placing a String in a Variable
whose Length is less than that of the data causes truncation of the
excess text. For example :
CHARACTER
1
CHV1
CHV2
CHV3
CHV4

CHV1 *
CHV3 *
=
=
=
=

01
CHV1
CHV1
CHV1

4, CHV2 * 4,
6, CHV4 * 10
//
//
//
//

234567
89
89
89 // ABCDEF

result in 01234567 being assigned to CHV1, which becomes 0123.


The 89 Concatenation to CHV2 makes no difference. CHV1 fills
that Variable already. But 89 gets placed after CHV1 into CHV3
as the Expression 012389 is formed by the Concatenation, despite
the full state of CHV1.
In the last case, 89 first gets appended to 0123, then ABCDEF,
but EF is lost when the Expression is assigned to a Variable too
short to hold it.

60

Fortran Assignments and Operations - Part 18


============================================
-

9/ Fortran Logical Expressions :


Regarding Data, LOGICAL Type Expressions can only contain entities
of that Type. Type specific Operators must be used in Expressions,
as listed below.
Fortran Logical Operators (Delimiting Dots always required) :
.NOT.

(Negation, True when following entity False


and False when following entity True),

.AND.
.OR.

(Conjunction, True when both Sides True),


(Inclusive Disjunction, True when either Side True),

.EQV.
.NEQV.

(Equivalence, True when both Sides same),


(Non Equivalence, True when both Sides dissimilar).

Apart from .NOT. which relates to the entity to its Right hand
Side only, the Logical Operators require entities on both Sides when
showing in Expressions, or when assigning Expressions to Variables.
Operations fall into 4 levels, regarding order of evaluation :
.NOT.
.AND.
.OR.
.EQV. and .NEQV.

evaluated first,
"
after all .NOT.,
"
"
" .NOT. and .AND.,
"
last, after other Operators.

Example of LOGICAL Expressions and Operators :


LOGICAL
1

LGV1, LGV2, LGV3,


LGV4, LGV5, LGV6

LGV1
LGV2
LGV3

= .TRUE.
=
.NOT.
= LGV1 .AND.

LGV4
LGV5
LGV6

=
=
=

LGV2
LGV1
LGV2

.OR.
.EQV.
.NEQV.

LGV1
.TRUE.
LGV1
LGV3
LGV3

.AND. .FALSE.

Except in the second and fourth cases the Target will be .TRUE..

61

Fortran Assignments and Operations - Part 19


============================================
-

9/ Fortran Logical Expressions (continued) :


Evaluation of same level Operators proceeds left to right in an
Expression, unless Parentheses force their contents to be computed
first. The LGV4 example above, when written :
LGV4

= ( LGV2 .OR. LGV1 ) .AND. LGV3

would have yielded .TRUE. as both Sides of the .AND. are so.
It may help readability anyway to include (redundant) Parentheses,
and will entail no computational cost. Reordering operations in an
Expression, unless some can thus be eliminated will not bring any
efficiency gains either.
However, in this example Expression :
LGV4

= .NOT. ( LGV1 .OR. LGV2 ) .AND. LGV3

the Parentheses insure the .NOT. affects the result of the .OR.
between LGV1 and LGV2, and not merely LGV1 alone, but they
also force evaluation of that negated .OR. before the .AND..
Without the Parentheses, the .NOT. would be effected first, then
the .AND. between LGV2 and LGV3 and last a .OR. between
the outcome of the .AND. and the negated LGV1 from earlier.

62

Fortran Flow Control and Logic - Part 1


========================================
-

1/ Introduction :
Flow control Statements, or merely Control Statements direct the
sequencing of Statements in the Executable Part of Fortran Programs.
This may depend on some Data Values, or allow repeated execution of
some portions of the Program.
Conditional Statements, under the various forms of the IF Statement
evaluate Relational, Logical, or Arithmetic Expressions, and this
results in one or more Statements being executed or not, depending
on the True or False nature of the Expression or its Value. Logical
and Block IF Statements use Relational and Logical Expressions. The
obsolete Arithmetic IF uses Arithmetic Expressions.
Multiple execution of a passage of Code is facilitated by Loops.
The one available sort of Fortran Loop construct is called DO. A
Counter limits the number of runs, or Iterations, through Loops.
Branch Statements may also evaluate a Variable, but will always
result in transferring execution to a labelled Statement, wherever
that sits in the Executable Part of the Program. Branch Statements
in Fortran are all called GOTO.
Additional Control Statement permit temporary or permanent halts
to the execution of Programs, and mark the completion of Routines.
The STOP Statement terminates execution anywhere it appears. An END
is required as the last (Executable) Statement in all Routines.
Fortran 90 introduced additional Loop constructs, where iterations
may be handled on a conditional rather than just on a Count basis.
New Statements were also designed to deal with Loop exits.

63

Fortran Flow Control and Logic - Part 2


========================================
-

2/ Relational (Conditional) Expressions :


Relational (sometimes called Conditional) Expressions are commonly
used with the two main forms of IF Statement in Fortran (the Logical
IF and the Block IF and associated Statements).
Relational Expressions compare Arithmetic or CHARACTER Expressions
by use of Relational Operators. Evaluation of Relational Expressions
yields a LOGICAL Type .TRUE. or .FALSE. Result. That may then
form part of a more elaborate LOGICAL Expression of which the True
or False Value will determine the effect of the IF Statement.
Fortran Relational Expressions are written as either :
Arithmetic
Expression A (Left)

Relational
Operator

Arithmetic
Expression B (Right)

or (with CHARACTER Expressions either side of the Operator) :


CHARACTER
Expression A (Left)

Relational
Operator

CHARACTER
Expression B (Right)

The Expressions, or Operands, must be of the same Type, that is,


both Arithmetic or CHARACTER for the Expression to be valid.

64

Fortran Flow Control and Logic - Part 3


========================================
-

2/ Relational (Conditional) Expressions (continued) :


Fortran Relational Operators (Delimiting Dots always required) :
.EQ.
.NE.

(Equal, giving .TRUE. when both Expressions same),


(Not Equal, so .TRUE. when Expressions dissimilar),

.GE.

(Greater or Equal, so .TRUE. if Left Hand Expression


greater or equal to Right Hand Side),
(Less or Equal, so .TRUE. when Left Hand Expression
less than or equal to Right Hand Side),

.LE.

.GT.
.LT.

(Greater than, so only .TRUE. if Left Hand Expression


strictly greater than Right Hand Side),
(Less than, so .TRUE. only when Left Hand Expression
strictly less than Right Hand Side).

No Spaces may separate the Delimiting Dots from the pair of letters
in between, but no Blanks need separating the Operator itself from
the Expressions (Operands) either side of it.
Additionally, Relational Expressions with CHARACTER Type Operands
may use .LGE., .LLE., .LGT., and .LLT., which compare like
the standard .GE., .LE., .GT., and .LT. above, but on a
Lexicographical rather than Collating Sequence basis. See the later
notes explaining Relational Expressions with CHARACTER Operands.
Fortran 90 introduced alternative symbols for Relational Operators :
==
/=

for
for

.EQ.
.NE.

(Equal, note = alone invalid)


(Not Equal)

>=
<=

for
for

.GE.
.LE.

(Greater than or Equal)


(Less than or Equal)

>
<

for
for

.GT.
.LT.

(Strictly Greater than)


(Strictly Less than)

The same rules apply for spacing as with the older style Operators.

65

Fortran Flow Control and Logic - Part 4


========================================
-

3/ Relational Expressions with Arithmetic Operands :


When Relational Expressions involve Arithmetic Operands, these must
be of consistent Type. Otherwise, the same (Type) Conversion rules
as enforced for Arithmetic Expression evaluation and Assignments
apply for Relational Expressions. COMPLEX comparisons also limit
what Operators can be used. See the notes on the following page.
So, when compared to REAL or DOUBLE PRECISION Expressions, INTEGER
expressions get converted to those Types. Likewise, REAL Expressions
get converted to DOUBLE PRECISION when matched with that Type.
For Floating Point Expression comparisons, only the .GT and .LT.
Strict Operators should be used in Programs. The actual Value of the
Binary pattern written in REAL or DOUBLE PRECISION Fields rarely
achieves an exact match with the assigned Value. A lot of Fractions,
like ( 1.0 / 3.0 ), but also other Values will exhibit this. Exact
comparisons can then give the reverse of the result they should.
For example were 7.0 to be represented in Memory by 7.000001, as the
Value of a Floating Point Variable, equality tests against 7.0 would
fail, and so would "Less than or Equal" comparisons.
Relational Expression examples with Arithmetic Operands :
INTEGER

INV1, INV2

REAL
DOUBLE PRECISION

RLV1, RLV2
DPV1, DPV2

INV1 .NE. 0
INV2 .GE. INV1 ** 2 + 5
RLV2 .GT. ( 10.0 * RLV1 + 2.0 )
DPV1 .LT. ( DPV2 + 4.0D0 )
Note in the third INTEGER case, despite lacking Parentheses around
it, the (composite) Arithmetic Expression on the Right Hand Side is
still computed before comparison against INV2 is attempted. Note
also that Both Floating Point examples use Strict comparisons, as
should be done with REAL and DOUBLE PRECISION entities.

66

Fortran Flow Control and Logic - Part 5


========================================
-

4/ Relational Expressions with COMPLEX Type Operands :


When Relational Expressions involve COMPLEX Operands any non COMPLEX
entities in them must first be evaluated, then converted to COMPLEX,
as explained in the earlier notes on COMPLEX assignments.
So, INTEGER, REAL or DOUBLE PRECISION Operands will be turned into
COMPLEX, namely by creating a COMPLEX entity with a Zero Imaginary
Part, and the Operand eventually converted to REAL as the Real Part.
Relational Expressions with COMPLEX Type Operands can only use
the .EQ. and .NE. Operators. For comparison of COMPLEX numbers
by Complex Norm (Square rooted Sum of squared Part Absolute Values),
the ABS (more precisely CABS) Function may be used to produce a
REAL or DOUBLE PRECISION atomic Value, then allowing use of the full
range of Relational Operators.
COMPLEX comparisons with .GE., .LE., .GT., or .LT. should
cause compilation failures (unlike using .EQ., .NE., .GE.,
or .LE. with Floating Point entities which passes compilation).
Complex Comparison Examples :
COMPLEX
DOUBLE PRECISION

CPV1, CPV2, CPV3


DPV1, DPV2

CPV1 .NE. ( 0.0, 0.0 ) )


CPV2 .EQ. ( CPV1 ** 2 + ( 3.4, 5.6 ) )
CPV3 .NE. ( REAL ( DPV1 ), REAL ( DPV2 ) )
Note any COMPLEX entities represented by Value must be written in
the form ( Real Part, Imaginary Part ), both Parts being REAL.

67

Fortran Flow Control and Logic - Part 6


========================================
-

5/ Relational Expressions with CHARACTER Operands :


Relational Expressions cannot mix CHARACTER Operands with other
Types. Comparison of CHARACTER Operands is allowed with any of the
Relational Operators listed above. It does take place Byte by Byte
along the Operand, starting from the left.
Comparison using .EQ., .NE., .GE., .LE., .GT., or .LT.,
aka standard Relational Operators is based on the relative Positions
of the successive Bytes in the (host) Computers Collating Sequence.
Basic CHARACTER Relational Expression examples :
CHARACTER * 12

CVR1, CVR2

CVR1
CVR2

= Data_String
= 01234567

CVR1 .EQ. Data_String


CVR1 .GT.
CVR2 ( 10 : ) .NE.
CVR2
.GE. 0
The second CVR1 case above checks for non Blank Data. It can be
better implemented via the .NE. Operator as in the next case. The
last case return .TRUE. as Bytes after the first in CVR2 contain
non Blank Data, and Space comes before in the Collating Sequence.

68

Fortran Flow Control and Logic - Part 7


========================================
-

5/ Relational Expressions with CHARACTER Operands (continued) :


As explained earlier, the Collating Sequence represents the ordering
of the Characters known to the Computer system. Any Character in the
Sequence can be assigned to a CHARACTER Type entity. However, few
restrictions constrain the positions of the Letters, so Alphabetical
comparisons will not always yield the expected outcome.
Special "Lexical" or "Lexicographical" Relational Operators permit
matching CHARACTER entities on a Lexicographical basis. In effect
they correspond to the usual Operators with an L Prefix :
.LGE.
.LLE.

(Lexicographical Greater or Equal),


(
"
Less than or Equal),

.LGT.
.LLT.

(Lexicographical Strictly Greater than),


(
"
Strictly Less than).

For example, using the 12 Byte Variables on the previous page,


these comparisons should be coded with Lexical Operators :
CVR1
CVR1

.LGT. Data_String
.LLT. Some Text

CVR2 (
: 7 ) .LLT. Charles
CVR2 ( 8 : 10 ) .LGE. Tab
Were the ordinary Operators used, some text could come before
rather than after Data_String because of the leading Capital,
and all the other cases could end up likewise.
Trailing spaces are (as usual) ignored, so all CHARACTER entity
comparisons apply to the non Blank portion of those entities. That
they may be of different Lengths in storage (Memory) is irrelevant.

69

Fortran Flow Control and Logic - Part 8


========================================
-

6/ Composite Relational Expressions :


Once evaluated, a Relational Expression becomes a LOGICAL entity,
with only .TRUE. or .FALSE. as the possible Values. This may be
combined with any other LOGICAL entities and any Logical Operators.
A repeat of their list is given below. Logical entities will often
be other evaluated Relational Expressions, but could also be LOGICAL
Variables or Expressions.
Fortran Logical Operators (Delimiting Dots always required) :
.NOT.

(Negation, True when following entity False


and False when following entity True),

.AND.
.OR.

(Conjunction, True when both Sides True),


(Inclusive Disjunction, True when either Side True),

.EQV.
.NEQV.

(Equivalence, True when both Sides same),


(Non Equivalence, True when both Sides dissimilar).

Composite Relational Expressions examples :


CHARACTER * 12
LOGICAL

CVR1, CVR2
LVL1

INTEGER

INV1, INV2

REAL
DOUBLE PRECISION

RLV1, RLV2
DPV1, DPV2

CVR1 .EQ. Data_String


.NOT. LVL1

.NEQV.

INV1 .NE. 0

.EQV.

RLV1 .GT. 1.0


1
1

.AND.
.AND.
.OR.

.OR.

CVR2 .GE. 0

CVR2 .LLE. Data


INV2 .GE. INV1 ** 2 + 5
DPV1 .GT. 0.0
RLV2 .GT. RLV1 * REAL ( DPV1 )
DPV2 .GT. 10.0 * REAL ( RLV2 )

70

Fortran Flow Control and Logic - Part 9


========================================
-

6/ Composite Relational Expressions (continued) :


Evaluation of Composite Relational Expressions takes place exactly
like that of LOGICAL Expressions, with the same Operator hierarchy
and consequent order of resolutions :
.NOT.
.AND.
.OR.
.EQV. and .NEQV.

evaluated first,
"
after all .NOT.,
"
"
" .NOT. and .AND.,
"
last, after other Operators.

Within each class of Operator, (sub)Expressions are evaluated


left to right. This sequence may be changed by use of Parentheses
which force the Expression they enclose to be solved first. They
can be included anyway at no computational cost for clarity. The
examples above could be written :
( CVR1 .EQ. Data_String ) .OR. ( CVR2 .GE. 0 )
(

.NOT. LVL1 ) .NEQV. ( CVR2 .LLE. Data )

( INV1 .NE. 0

) .EQV.

( RLV1 .GT. 1.0 ) .AND.


1
.AND.
1
.OR.

( INV2 .GE.

INV1 ** 2 + 5 )

( DPV1 .GT. 0.0


)
( RLV2 .GT. RLV1 * REAL ( DPV1 ) )
( DPV2 .GT. 10.0 * REAL ( RLV2 ) )

71

Fortran Flow Control and Logic - Part 10


========================================
-

7/ Fortran Logical IF Statement :


The Logical IF facilitates execution of a single Statement attached
to the IF, when the associated Condition is True. The conditionally
executed Statement cannot not be another IF. The equivalent result
can be achieved by combining the Conditions of two (or more) such
would be IF Statements with .AND. Operators.
A Logical IF is laid out with the controlling Relational or Logical
Expression inside Parentheses followed by the conditionally executed
Statement. The latter must be atomic, which rules out Loops or Block
IF Constructs, but may be a Function or Subroutine Call. From the
point of view of the Routine containing the Logical IF, a Call to a
Subprogram represents an atomic single Statement.
The END Statement is not permitted in a Logical IF, but the same
effect (termination of the Program Unit) can be obtained with STOP.
Example Logical IF Statements :
IF
IF
IF
1
IF

( INV1 .NE.
0
( INV2 .GE. ( INV1 ** 2 + 5

)
) )

INV1 = INV1 + 2
GOTO 200

( RLV2 .GT. ( 10.0 * RLV1 + 2.0 ) )


RLV2
= ( RLV1 ** 2 + 24.0 )
( DPV1 .LT. ( DPV2 + 4.0D0

) STOP

IF
1

( ( CVR1 .EQ. Data_String ) .OR.


( CVR2 .GE. 0
) )
CSTR = Numbers

IF
1

( ( .NOT. LVL1 ) .NEQV. ( CVR2 .LLE. Data ) )


LVL1 = .TRUE.

Note presenting the conditional Statement on a continuation Line


below the IF Keyword and controlling Expressions is allowed and
can make for easier distinction of the Statements components.
Alignment of the Parentheses and Names can also improve clarity.
Before the Block IF (see below) was introduced in the 77 Standard,
constructs of the "If, then, Else If, then, Else" type were often
coded via Logical IF Statements with GOTO Branch Statements as
shown in one example above, so they can be common in old Code.

72

Fortran Flow Control and Logic - Part 11


========================================
-

8/ Fortran Block IF Statements :


The Block IF, came with the 1977 Standard. It works like the Logical
IF except it controls the execution of all the Statements following
it until an ELSE or END IF Line is encountered. At least one, but
any number of Statements may be included. The optional ELSE Clause
likewise controls one or more Statements until an END IF Statement
terminates the conditional Block.
The Statements after an ELSE can contain other Block IF Statements.
This enables the implementation of "If, then, Else If, then, Else"
constructs. The ELSE IF can be written as ELSEIF for clarity.
The Block IF is presented with the controlling Relational or Logical
Expression inside Parentheses and a following THEN, but without other
Code. The Statement after the THEN represents the first of the set
executed when the IF Condition proves True.
When no ELSE is present and the IF Condition ends up False, Program
execution proceeds with the Statement immediately after the END IF
Statement which closes the IF Block. Note END IF can be written as
ENDIF, used in these notes to avoid clashing with END and IF.
When an ELSE is included, the Statements between it and the ENDIF
will be executed when the controlling Condition is False. The ENDIF
is always required to mark the end of the Block. When the Condition
with a Block IF comes out True and an ELSE is present, execution
continues with the Statements following the IF till the ELSE, at
which point execution jumps to the Statement after the ENDIF.
The Logical IF equates to a basic (no ELSE Clause provided) Block
IF with only one Statement between the IF and associated ENDIF.

73

Fortran Flow Control and Logic - Part 12


========================================
-

8/ Fortran Block IF Statements (continued) :


Basic Block IF examples :
IF

( INV1 .NE.

) THEN

INV1 = INV1 + 2
ENDIF
IF

( INV2 .GE. ( INV1 ** 2 + 5 ) ) THEN


INV1 = 3
INV2 = 32

ENDIF
Were these two Block IF sets of Statement found in a Routine, and
the Relational Expression for the top one to be False, execution
would jump to the second IF, bypassing initial INV1 assignment.
Basic Block IF example with ELSE Clause :
IF

( CHV1 .EQ. 01234567 ) THEN


CHV1 (
CBSE

9 :

9 ) = 8
= 9

ELSE
CHV1
CBSE

= 01234567
= 8

ENDIF
In this case, one or the other pair of CHARACTER assignments would
be performed before execution of the Statement following the ENDIF.

74

Fortran Flow Control and Logic - Part 13


========================================
-

8/ Fortran Block IF Statements (continued) :


Block IF example with successive ELSEIF Clauses :
IF

( CHV1 .EQ. 01234567


CHV1 (
CBSE

ELSEIF

9 :

) THEN

9 ) = 8
= 9

( CHV1 .EQ. 012345678

) THEN

CHV1 ( 10 : 10 ) = 9
CBSE
= A
ELSEIF

( CHV1 .EQ. 0123456789 ) THEN


CHV1 ( 11 : 11 ) = A
CBSE
= B

ELSE
CHV1
CBSE

= 01234567
= 8

ENDIF
Any number of ELSEIF Clauses may be coded, and the controlling
Expressions need not involve the same entities. As soon as a
Condition tests True, the set of Statements after is is executed,
and then flow proceeds to the Statement below the ENDIF, even when
Conditions attached to other ELSEIF Clauses also prove True. That
is, only one Block of Statements is ever executed. In other words,
regardless of how many Conditions evaluate to .TRUE., only the
first one to be so matters.
Only one plain ELSE Statement is allowed but not compulsory.
In Fortran 90, the SELECT CASE ( Expression ) and CASE ( Value )
Clauses with conditionally executed Statements after them, with an
eventual CASE DEFAULT and END CASE terminator can emulate IF,
ELSEIF, ELSE, ENDIF Block constructs, but would be unlikely to show
any efficiency gains. It is not be covered further in these notes.

75

Fortran Flow Control and Logic - Part 14


========================================
-

8/ Fortran Block IF Statements (continued) :


Block IF constructs may be nested into each other, or included
in Loops, but straddling is not permitted. Also, a Block IF group
of Statements should only be entered via the initial IF. This means
Statements inside the construct cannot be the Targets of Branches
(GOTO or Arithmetic IF Statements) from outside it. Also, Branches
cannot jump across ELSEIF or ELSE Lines. For example, in :
IF

( CHV1 .EQ. 01234567


CHV1 (
GOTO

ELSEIF
300

9 :

) THEN

9 ) = 8
300

( CHV1 .EQ. 012345678

) THEN

CHV1 ( 10 : 10 ) = 9
GOTO
500
ELSE

400

INV1
IBSE
IF

= INV1 + 2
= IBSE + 1
( IBSE .LE. 20 )

GOTO 400

ENDIF
500 IF

( NTST .EQ. 0 ) GOTO 300

the GOTO 300 in the first Block, depending on the IF Condition,


and that forming part of the Logical IF after the ENDIF Statement
would both be rejected at compilation.
The GOTO 400 with the Logical IF inside the ELSE
as the GOTO 500 inside the ELSEIF Block would be
former jumps to within the same set of conditional
the GOTO 500 jumps out (not in) of a whole Block

76

Block, as well
valid as the
Statements, and
IF.

Fortran Flow Control and Logic - Part 15


========================================
-

8/ Fortran Block IF Statements (continued) :


Nested Block If example :
IF

( CHV1 .EQ. 01234567

) THEN

IF

) THEN

( CHV2 .GT.
CHV1 (

9 : 10 ) = 89

ENDIF
ELSEIF

( CHV1 .EQ. 0123456789 ) THEN


CHV1 ( 11 : 11 ) = A
CBSE
= B

ENDIF
Were the first ENDIF not showing above the ELSEIF, that ELSEIF would
then refer to the second IF rather than the first. The only place
the first ENDIF could then show would be just above the second ENDIF
as otherwise a straddle of IF Blocks would arise.
For the same reason ELSEIF and ELSE, in any order, and pairs of ELSE
or ELSEIF can never appear without other Statements separating them.
In the example above, combining the two IF Conditions into one with
a .AND. Operator would not give the same behaviour, as the case
with CHV1 containing 0123456789 would be tested when CHV2 is
Blank and CHV1 ( 1 : 8 ) holds 01234567, while it is not as
coded above. Nested Block IF constructs need care to unravel !

77

Fortran Flow Control and Logic - Part 16


========================================
-

9/ Arithmetic IF Statement :
In the Arithmetic IF, an Arithmetic Expression is evaluated, and
depending on the result being Negative, Zero or Positive, one of
three Labelled Statements is next executed. The same Statement
may be chosen for any pair of, or all outcomes from the evaluation.
The Statement is written with the Expression between Parentheses
and followed by the comma separated three Labels. For example :
INTEGER
DOUBLE PRECISION

INV1, INV2
DPV1, DPV2

DATA
DATA

INV1, INV2 / -10


, 3
/
DPV1, DPV2 /
8.2D2, 12D-2 /

IF

( INV1 + INV2 ) 100, 110, 120

IF

( DPV2 * DPV1 ) 100, 110, 120

would both result in execution continuing with the Statement


labelled 100, 110 and 120 respectively when the Expression
was Negative, Zero and Positive. Labels can be repeated, so any
of those examples would be valid :
IF

( INV1 + INV2 ) 100, 100, 110

IF

( INV1 + INV2 ) 100, 110, 110

IF

( INV1 + INV2 ) 100, 110, 100

The Arithmetic IF dates from the initial version of Fortran (1957)


where it constituted the sole IF construct. It was marked obsolete
in Fortran 90 and duly deleted in Fortran 95. It will likely only be
found in 1960s or earlier Code and should really be avoided. Modern
compilers, for compatibility purposes still permit is use.

78

Fortran Flow Control and Logic - Part 17


========================================
- 10/ Loops (Iterative constructs) in Fortran :
Fortran facilitates repeated execution (Iterations) of groups of
Statements, controlled by incrementing a Counter with DO Loops.
The DO Statement stipulates a Label, which marks the last Statement
in the Loop, the name of a Counter Variable, Equal Sign, and comma
separated Start and End Values for it, plus an optional Increment
Value. Any of those may be Constants or Arithmetic Expressions.
When the DO Statement is first reached, the Counter is assigned the
Start Value. That gets tested against the End Value, and when below
or equal to it, the Loop Statements are executed. After the last
Statement has been executed, the specified Increment is added to the
Counter, or by default, one, and the test of the Counter falling in
Range is repeated. When the Counter drops out of Range, Execution
goes to the first Statement following the end of the Loop.
The Labelled Statement thus marked as the last of the Loop may be
any atomic Executable Statement apart from an END Statement, but
will traditionally be the Null CONTINUE Statement. This became
a requirement in Fortran 90.
The Counter may be any atomic Numerical Variable, but an INTEGER
is advised. This has become obligatory in Fortran 90. The Increment
may be any non Zero Value, including a Negative one. In Fortran 90,
Loop Increments must be INTEGER.
The Counter retains the last Value assigned to it after the Loop
Iterations have run their course, so it will equate the End Value
plus one Increment Value. The Counter Value cannot be changed in
the Body of the Loop, but may be accessed and tested.
In Fortran 66 and before, DO Loops had to be executed once, whatever
the End Value for the Counter. In Fortran 77 and 90, if the Counter
Start Value exceeds the End Value, the Loop will not be run through.
In Fortran 90, DO Statements may be coded without the End Label, in
which case the Loop is (and must be) terminated by an END DO Line.

79

Fortran Flow Control and Logic - Part 18


========================================
- 10/ Loops (Iterative constructs) in Fortran (continued) :
Example DO Loops :
DO

100 ICNT = 1, 100


DPV1 = ( DPV1 + 3.2D0 )
DPV2 = ( DPV2 * DPV1 )

100 CONTINUE
DO

200 ICNT = 2, 200, 2


DPV3 = ( DPV3 / DBLE ( ICNT ) )
DPV4 = ( DPV4 - DPV3
)

200 CONTINUE
In the first Loop, ICNT is assigned 1, found to be less than
100, so the assignments of DPV1 and DPV2 take place, CONTINUE
is reached and found labelled as the end of the Loop. ICNT is
then incremented by the default single Unit, and checked against
100 another time, and so on. When ICNT becomes 101, the Loop
Iterations are finished and execution proceeds to the Statement
following the Labelled End Statement, here the DO 200 Loop. The
Counter is left as last assigned, which means with the first Value
which caused it to drop outside the Range in the DO Statement.
The second DO Loop would progress much like the first, except for
the Increment to the Counter being explicitly specified as 2, which
also makes up the initial Value. So that loop would run 100 times,
leaving the Value 202 in ICNT after all Iterations are completed.
In Fortran 90 (and a lot of 77 implementations),
the first example above could be written with ENDDO and no Label :
DO

ICNT = 1, 100
DPV1 = ( DPV1 + 3.2D0 )
DPV2 = ( DPV2 * DPV1 )

ENDDO

80

Fortran Flow Control and Logic - Part 19


========================================
- 10/ Loops (Iterative constructs) in Fortran (continued) :
Just like Block IF constructs, DO Loops may be nested inside each
other, but not straddled. So the example below would be rejected :
DO

100 ICNT = 1, 100


DPV1 = ( DPV1 + 3.2D0 )
DPV2 = ( DPV2 * DPV1 )

DO

200 JCNT = 2, 200, 2


DPV3 = ( DPV3 / DBLE ( ICNT ) )

100

CONTINUE
DPV5 = ( DPV6 - DBLE ( ICNT ) )

200 CONTINUE
This two Level DO Loop Nest would be valid :
DO

100 ICNT = 1, 100


DPV1 = ( DPV1 + 3.2D0 )
DPV2 = ( DPV2 * DPV1 )
DO

200 JCNT = 2, 200, 2


DPV3 = ( DPV3 / DBLE ( ICNT ) )

200

CONTINUE

100 CONTINUE
Note how the use of indentation makes it relatively clear to see
the first example was incorrect, even without trying a Compilation.
The same Counter may be used with successive loops, but not in the
cases of nested Loops on this page, as incrementing in the Inner
Loop would mean the Outer Loop counter is altered inside the Loop.

81

Fortran Flow Control and Logic - Part 20


========================================
- 10/ Loops (Iterative constructs) in Fortran (continued) :
Like Block IF constructs, DO Loops can only be entered at the top,
via the DO Statement, so cannot be branched into from outside their
Body. They may be exited with GOTO Statements.
So, for example :
DO

200 ICNT = 2, 200, 2


DPV3 = ( DPV3 / DBLE ( ICNT ) )
DPV4 = ( DPV4 - DPV3
)

100

IF

( DPV4 .GT. 2000D0 )

GOTO 300

200 CONTINUE
300 IF

( ITST .GT. 200 ) GOTO 100

The GOTO 300 with the Logical IF in the 200 Label Loop would
jump out of (and finish there and then) the Loop, but the GOTO 100
attached to the Logical IF at Label 300 would produce a Compilation
error as it attempts entry into a Loop away from its DO Statement.
Fortran 90 introduced DO WHILE Loops, where a Condition, similar
to that for a Logical or Block IF follows the DO WHILE Keywords
and the Loop Body runs till and END DO is reached. For example :
DO WHILE ( ICNT .LE. 100

DPV1
DPV2

= ( DPV1 + 3.2D0 )
= ( DPV2 * DPV1 )

ICNT

= ( ICNT + 1

ENDDO
This example emulates a DO ICNT = 1, 100 Loop, but the essential
programming aspect with DO WHILE Loops lies in avoiding lock ups
where the Loop Condition never gets broken and the Program enters
an infinite loop.

82

Fortran Flow Control and Logic - Part 21


========================================
- 11/ Branches in Fortran :
Branch Statements transfer control to any Executable Statement
with a Label by reference to that Label. They consist of GO TO,
written GOTO in these notes, an unconditional Branch, and the
Computed GOTO which branches to one of a list of Labels as per
the Value of an Arithmetic Expression.
The plain or unconditional GOTO just provides a Label for the
Target Statement, before or after it in the sequence of the Code :
GOTO 300
would transfer execution to the Statement labelled 300. The Label
in a GOTO Statement must exist. Compilation will fail otherwise.
GOTO is commonly frowned upon but disciplined and limited use can
be useful. Older programs relied extensively on GOTO as the Language
then lacked the Block IF constructs which allow GOTO to be avoided.
The Computed GOTO presents a list of Labels in Parentheses, an
optional comma, and an Arithmetic Expression. That may be of any
Type, but gets converted to INTEGER when the Statement is executed.
When the Value obtained comes to less than 1 or more than the
number of Labels, execution continues with the Statement following
the (Computed) GOTO. If the Value ranges from 1 to the Number of
Labels, it serves as the Index of the Label to use for the Branch.
In this Computed GOTO example :
GOTO ( 100, 110, 120, 130 ) ICNT
the Statements labelled 100, 110, 120, and 130 would be
next executed depending on the Variable ICNT containing 1 to 4
respectively. Were ICNT less than 1 or over 4 no Branch would
taken place and the next Statement would be that after the GOTO.
The Computed GOTO was marked obsolete in Fortran 95, but ended
up not being removed in Fortran 2003. It is advised to use Block
IF constructs instead. They will be more flexible and clearer.

83

Fortran Flow Control and Logic - Part 22


========================================
- 12/ Use if INTEGER Variables for Labels in Fortran :
The ASSIGN Statement permits a Label Value to be assigned to an
INTEGER Variable, such that the Variable may be used instead of a
Numeric Label in an unconditional GOTO Statement. For example :
ASSIGN 300 TO ILAB
then allows this Code :
GOTO ILAB
as if GOTO 300 had been Coded.
ASSIGN and the associated form of GOTO, usually called "Assigned
GOTO", have fallen into disuse, and both were marked as obsolete
in Fortran 90. Still, most compilers still permit them, if only to
enable continued compilation of old Programs.
Label assignments with ASSIGN may also be used to refer to Input
or Output FORMAT Statements, in exactly the same way, via INTEGER
Variables. This old practice is no longer recommended and will not
be treated in these notes.

84

Fortran Flow Control and Logic - Part 23


========================================
- 13/ Exiting Fortran Programs :
Fortran Programs must be exited via one of two mechanisms :
END Statements

: An END Statement must finish all Fortran Routines,


and so come as the last Line, apart from Blanks or
Comments. That applies even if prior Statements
(like a STOP) cause termination elsewhere and END
is never reached from the Statement above it.
END Statements can be labelled, implying they can
be Targets of GOTO Statements. However, they may
not be (Line) continued, nor complete DO Loops.

STOP Statements : A STOP Statement terminates execution of the whole


Program immediately, wherever it appears in any
Routine, whether Subprogram or main Program.
STOP Statements cannot be the last in DO Loop.
A STOP was required in Fortran 66, even if it came
as the last Statement before END. This limitation
was removed in Fortran 77, but old Programs will
possibly exhibit that now redundant coding.
STOP may be followed by an Integer Constant of up
to 5 Digits or Text String of up to 72 Characters
inside Single Quotes. These cannot be Expressions
or include Variables.
When either an Integer or Text String is provided,
it will be echoed on the Standard Output Channel
when the STOP is hit and Program execution halts.
For example this Statement :
STOP Expression Negative
leads to a test showing "STOP Expression Negative"
on the terminal screen. The Standard only tells
the Integer or Text String should be shown, so
other systems may do just that, or provide extra
comments as feedback.

85

Fortran Array Processing - Part 1


==================================
-

1/ Introduction :
Fortran Arrays represent ordered collections of atomic Elements,
with the same Type and properties. The total count of Elements is
called the Size. That subdivides into one or more Dimensions, their
Extent being the Number of Elements in the individual Dimensions.
Fortran can handle Arrays of up to 7 Dimensions in any of its 6
Intrinsic Data Types. Arrays are generally processed Element by
Element in Fortran 77. However, Array initialisation, Input and
Output may be handled in bulk. Fortran 90 allows whole Arrays, or
sets of Array Elements to be treated as if a single entity.
Fortran Arrays can be declared by providing optional Subscript
Ranges in Type Statements. This defines the Extents for for each
Dimension. Alternatively, this may be carried out with the special
DIMENSION Statement (even without explicit Type Statements).
Arrays may form part of COMMON Blocks, or BLOCK DATA Subprograms,
where they obey rules similar to those regarding atomic entities.
In Multidimensional Arrays, the (Data) Elements are stored (in the
computers Memory) in "Column Major Order". This constraint on the
implementation of the language facilitates efficient processing of
Arrays in DO Loops, on any computer system offering Fortran.
Implied DO Loops facilitate bulk initialisation of Arrays in DATA
Statements, or Input from and writing to Files in READ and WRITE
Statements. Only DATA Statement Implied DO Loops are covered in this
chapter, but the very same syntax extends to READ and WRITE, which
are treated in the Input and Output chapter of these notes.
All the rules governing assignments, Expressions and Conditionals
involving atomic entities also apply when Array Elements are used.
DO Loops facilitate bulk Array operations, but should be written
such than an efficient pattern of Element handling results.
Beside allowing Arrays to be viewed as if an atomic entity in a lot
of processing, like assignments, Fortran 90 introduced several new
Intrinsic Functions which also treat whole Arrays as single objects.

86

Fortran Array Processing - Part 2


==================================
-

2/ Array Declarations :
Arrays must be declared in the Non Executable Part of all Routines
where any of their Elements are used. Arrays are established by the
(joint) specification of their Extents, as a set of Numeric Ranges
for the Element Subscripts in each Dimension. An Arrays Size is
imputed from the product of its Extents.
The set of an Arrays Extents (Size in each Dimension) forms its
Shape. This may be accessed and manipulated dynamically in Fortran
90, but not under the 77 Standard.
Fortran 77 and 90 both support up to 7 Dimensions for Arrays. By
taking multiple Byte CHARACTER Variables as Arrays of single Bytes,
an additional Dimension becomes available for single Characters. A
few compilers will permit up to 20 Dimensions for Arrays.
Four ways exist to do declare Arrays :
With Type Statements where Array Variable Names are followed
by sets of comma separated Subscript Ranges, for all the
Dimensions, the whole set of Ranges in between Parentheses,
With Type Statements as if for atomic Variables, but then
DIMENSION Statements to define the Arrays, with each Array
Variable Name followed by its comma separated Subscript
Ranges for the Dimensions, the whole set in Parentheses,
Relying on the Implicit Naming facility for Variables, but
using DIMENSION Statements to define Arrays as above, with
each Array Name followed by its comma separated Subscript
Ranges for the Dimensions, and the set between Parentheses.
As for the precious two methods, but using COMMON rather than
DIMENSION Statements. This obviously puts Arrays in Common
Blocks (where they can be mixed with non Array entities).
Apart from the initial Keyword in a Type Statement, and the fact
only Array Names can follow DIMENSION, the same syntax of the Array
Names followed by their Dimensions applies to all four forms above.

87

Fortran Array Processing - Part 3


==================================
-

2/ Array Declarations (continued) :


The one imposition with Array declarations is that the Subscript
Ranges for all Dimension must only be specified once, be that in
a Type, DIMENSION or COMMON Statement.
In older Programs which rely on Implicit Declarations, DIMENSION
Statements must be used to establish Arrays. In Code with declared
Variables, it can be clearer to place the Subscript Ranges with the
Type Statements rather than in separate DIMENSION Statements, as it
will always be obvious the Name refers to an Array.
In Fortran 90 Free Form Source Code, DIMENSION Attributes may go
with Type Statements, after the Type Keyword and a comma, and
before the double Colon Separator with the list of Variables.

88

Fortran Array Processing - Part 4


==================================
-

3/ Array Subscript Range Declarations :


By default, Subscripts in any Dimension begin at 1 and finish at
the given End of the Range or Upper Limit, which must be provided.
If other Lower Limits (Start of Range) for Subscripts are desired,
they are set before the corresponding Upper Limits (End of Range)
and separated from them by Colons. Upper Limits are always required,
and be greater then or equal to the corresponding Lower Limits. If a
Lower Limit is not given, the Upper Limit must be 1 or greater. Of
course an Extent of 1 corresponds to an atomic Element, and makes
little sense, but is allowed.
When both Range Limits are given, a Colon must separate them. When
only the compulsory Upper Bound is given, a Colon must not appear.
Each (Lower or Upper) Range Limit must be an INTEGER Expression with
in Line or declared (in prior PARAMETER Statements) Constants, but
excluding any (Constant) Array Elements. All declared Constants must
be assigned in earlier PARAMETER Statements. In effect this means
all (Subscript Range) Limits must be known when defining an Array.
As long as the Limits represent valid INTEGER entities, they are
not otherwise constrained in Value. Both may be negative or one or
both Zero for example.
An exception exists for this when Arrays are passed as Arguments to
Subprograms. For such Arrays, Upper Limits for the last Dimension
(Right hand side in the list of Ranges) may be "assumed" by showing
either as the Name of a passed Argument INTEGER Variable, or an
Asterisk (*) Marker. Then, the Upper Limit will be obtained off
the calling Routine, where it must be known at Compile time. This
will be covered in detail in the later chapter on Subprograms.

89

Fortran Array Processing - Part 5


==================================
-

3/ Array Subscript Range Declarations (continued) :


Array Subscript Range examples with simple in Line Constants :
( 20 )
( 20, 10, 6 )
( 0 : 19, 10, 0 : 5 )
( ( -9 : -1 ), ( -9 : -1 ), ( -9 : -1 ), ( -9 : -1 ) )
The top example sets a Range of 1 to 20, defaulting the Lower Limit,
for a single Dimensional Array, and the second case sets a three
Dimensional Array, again defaulting the Lower Limits to 1. That
Array would have Shape and Extents ( 20, 10, 6 ) and Size 1,200.
The top two cases could, for completeness, be coded ( 1 : 20 ),
and ( 1 : 20, 1 : 10, 1 : 6 ), though omitting the default 1
for the Lower Bounds usually simplifies reading the Code.
The third example defines an Array of the same Size and Shape as the
second case, but with Dimension 1 starting at 0 and ending at 19
and Dimension 3 ranging from 0 to 5. This example also shows that
the Lower Limits are optional for any of the Subscript Ranges.
The method of indexing from Zero rather than 1 in the third example
is sometimes called "offsetting", where the Index tells of how many
Elements after the First an Element comes. So Offset Zero means the
First Element in the Array.
The fourth example presents a 4 Dimension Array, with all Subscripts
ranging from -9 to -1, so Extents of 9 in each Dimension, for a
total 9 ** 4 or 6,561 total Elements and Size. Note the Subscript
Ranges can be individually enclosed in Parentheses for clarity.

90

Fortran Array Processing - Part 6


==================================
-

3/ Array Subscript Range Declarations (continued) :


Array Subscript Range examples with in declared Constants :
( ISZE )
( ISZE, ISZE * 2, ISZE / 4 )
( 0 : ISZE - 1, 0 : ISZE / 2 - 1, 0 : ISZE / 4 - 1 )
( ( 0 : ( ISZE - 1 ) ), ( 0 : ( ISZE * 2 - 1 ) ),
( 0 : ( ISZE / 4 - 1 ) ) )
( ( ISZE - 3, ISZE + 8 ), 20, ( ISZE * JSZE ) )
In all the above cases, ISZE and JSZE would have been declared
and assigned in a PARAMETER Statement before the Statement(s) with
those Subscript Ranges appear in the sequence in the Non Executable
Part of the Routine.
When expressions involving Divisions set Range Limits, the usual
rules for Integer Division remain in force, such that the results
would cut off the decimals from the would be exact Division.
The third example represents the same Extents as the second case,
but with Offset subscripting. This is laid in a manner to make the
three Dimensions stand out more clearly in the fourth example.
The last example displays a case of more than one Parameter being
involved in Subscript Range specifications. Note arithmetic could
be presented even with only in Line Constants, as it can clarify
the structure of some Multidimensional Arrays. For instance :
( ( 1 * 200 ), ( 2 * 200 ), ( 3 * 200 ) )
in this situation, the seemingly redundant arithmetic helps in
highlighting the relative scales of the Extents. As the processing
of Array Bounds happens at Compile time, not run time, it incurs
no computational cost in the usual sense of execution time.

91

Fortran Array Processing - Part 7


==================================
-

4/ Array Declaration Examples :


With Type Statements only :
CHARACTER * 12
CHARACTER

CAR1 ( 200 ),
CAR2 ( 100 )
CAR3 ( 200 ) * 8, CAR4 ( 100 ) * 2

INTEGER
DOUBLE PRECISION

IAR1 ( 300),
DAR1 ( 0 : 24 ),

IAR2 ( 300 )
DAR2 ( 0 : 24 )

With Type and DIMENSION Statements :


CHARACTER * 12
CHARACTER

CAR1,
CAR2
CAR3 * 8, CAR4 * 2

INTEGER
DOUBLE PRECISION

IAR1, IAR2
DAR1, DAR2

DIMENSION
DIMENSION

CAR1 ( 200 ), CAR2 ( 100 )


CAR3 ( 200 ), CAR4 ( 100 )

DIMENSION
DIMENSION

IAR1 ( 300 ),
IAR2 ( 300 )
DAR1 ( 0 : 24 ), DAR2 ( 0 : 24 )

The Type Statement only method of Array definition calls for fewer
Statements. It means the Name shows as an Array in all instances in
the Non Executable Part. However, Arrays can be mixed with isolated
(Scalar) Variables in Type Statements, so poorly laid Code could
make it harder to notice them. See for example :
DOUBLE PRECISION

DAR1,DAR2(100),ARY2(20),ARTT(20),XX,YY,ZZ

DIMENSION Statements, when used for all Array declarations, allow to


easily identify Arrays, though with potential loss of information as
their Type. In large Programs, many Lines could separate IMPLICIT or
Type and DIMENSION Statements, so Array Types become less obvious.

92

Fortran Array Processing - Part 8


==================================
-

4/ Array Declaration Examples (continued) :


Array declaration examples with DIMENSION Statements only :
IMPLICIT

CHARACTER*12 (C)

IMPLICIT

DOUBLE PRECISION (D,E)

CHARACTER

CAR3*8, CAR4*2

DIMENSION
DIMENSION

CAR1(200), CAR2(100)
CAR3(200), CAR4(100)

DIMENSION
DIMENSION

IAR1(300), IAR2(300)
DAR1(0:24), DAR2(0:24)

The Code above replicates the Arrays in the examples using Type
Statements for all Variables. Despite the use of IMPLICIT to alter
the default Naming rules, a Type Statement remains needed for the
two CHARACTER Names where the Length differs from the default.
The inconsistency in the last examples suggests all entities should
appear in Type Statements, whether or not DIMENSION Statements get
used to set up Arrays.
In Fortran 90 Free Form source coding, DIMENSION can be used as an
Attribute with Type Statements, in addition to the other methods, to
the left of the Double Colon before the entity Names. For example :
INTEGER,
DIMENSION (
300 ) :: IAR1, IAR2
DOUBLE PRECISION, DIMENSION ( 0 : 24 ) :: DAR1, DAR2
would declare the Numeric Arrays in the earlier examples. However,
the CHARACTER Arrays would each need their own Statement because of
the differing Element and Array Sizes.

93

Fortran Array Processing - Part 9


==================================
-

4/ Array Declaration Examples (continued) :


Array declaration Type Statement with Parameters for the Extents :
INTEGER
PARAMETER

ISZ1, ISZ2
( ISZ1 = 100, ISZ2 = 24 )

CHARACTER * 12
CHARACTER

CAR1 ( 2 * ISZ1 ),
CAR2 ( ISZ1 )
CAR3 ( 2 * ISZ1 ) * 8, CAR4 ( ISZ1 ) * 2

INTEGER
DOUBLE PRECISION

IAR1 ( 3 * ISZ1 ),
DAR1 ( 0 : ISZ2 ),

IAR2 ( 3 * ISZ1 )
DAR2 ( 0 : ISZ2 )

Much as the Sizes of the Arrays no longer show directly where they
are declared, all Sizes can be amended by simply altering the Values
in the PARAMETER Statement. This technique reduces risks of errors,
and speeds up development of large Programs.
The arithmetic in the Bound settings is allowed as long as all the
items are known by the time the Statement is reached. The items must
additionally be INTEGER. Exponentiation is permitted.

94

Fortran Array Processing - Part 10


==================================
-

5/ Arrays in Common Blocks :


Arrays may be part of Common Blocks, but as a whole, not in part.
When Arrays are declared via the use of DIMENSION Statements,
or the Subscript Ranges are given in Type Statements, the COMMON
Statements must just specify the Name, without Subscript Ranges.
For example, these declarations would be valid :
CHARACTER * 12
CHARACTER

CAR1 ( 200 ),
CAR2 ( 100 )
CAR3 ( 200 ) * 8, CAR4 ( 100 ) * 2

INTEGER
DOUBLE PRECISION

IAR1 ( 300 ), IAR2 ( 300 )


DAR1,
DAR2

DIMENSION

DAR1 ( 0 : 24 ), DAR2 ( 0 : 24 )

COMMON
COMMON

/ CCBK / CAR1, CAR2, CAR3, CAR4


/ CNBK / IAR1, IAR2, DAR1, DAR2

However replicating the Subscript Ranges in the COMMON Statement(s)


will cause compilation failure as is shown below for this example :
COMMON
1

/ CNLK / IAR1 ( 300 ),


IAR2 ( 300 ),
DAR1 ( 0 : 24 ), DAR2 ( 0 : 24 )

The complete Code above could correctly be replaced by :


CHARACTER * 12
CHARACTER

CAR1,
CAR2
CAR3 * 8, CAR4 * 2

INTEGER
DOUBLE PRECISION

IAR1, IAR2
DAR1, DAR2

COMMON
1

/ CCBK / CAR1 ( 200 ), CAR2 ( 100 ),


CAR3 ( 200 ), CAR4 ( 100 )

COMMON
1

/ CNLK / IAR1 ( 300 ),


IAR2 ( 300 ),
DAR1 ( 0 : 24 ), DAR2 ( 0 : 24 )

where Array declarations happen when the Common Block are specified.
Note the CHARACTER and Numeric entities necessitate distinct Blocks.

95

Fortran Array Processing - Part 11


==================================
-

6/ Array Storage Rules :


Arrays are stored in a single zone of Memory, with no gaps (unused
space) between the Elements. Additionally, the beginning of Numeric
Arrays must be aligned on a Word (4 Byte) or Double Word (8 Byte)
multiple, as would an individual Variable of the same Type.
For single Dimension Arrays, only one way exists to construct linear
sequences in Memory, from the lowest to the highest Indexed Element.
For example the 8 Element INTEGER Array :
INTEGER

IARR ( 8 )

would be aligned on a 4 Byte Boundary (| below) and take up an


area or 32 consecutive Bytes, with Elements indexed as shown :
|__1_|__2_|__3_|__4_|__5_|__6_|__7_|__8_|
Fortran requires that Multidimensional Arrays be arranged in Memory
in "Colum Major Order". This means the Subscript to the left of the
set for each element represents consecutive locations in Memory.
For two Dimensional Arrays, the Elements in each Column
successive Memory locations, and each whole Column then
adjacent to those (if any) immediately before and After
6 Row and 4 Column INTEGER Array (24 Elements in total)
INTEGER

thus fill
gets stored
it. So, the
:

IARR ( 6, 4 )

would be mapped at the top Level by its 6 Element Columns, giving


a diagrammatic representation, where ^ to indicates the sequence :

Row
Row
Row
Row
Row
Row

1
2
3
4
5
6

Col. 1

Col. 2

Col. 3

Clo. 4

IV
IV
IV
IV
IV
IV

IV
IV
IV
IV
IV
IV

IV
IV
IV
IV
IV
IV

IV
IV
IV
IV
IV
IV

1,1 +2,1 ^
3,1 ^
4,1 ^
5,1 ^
6,1 -+

1,2 +2,2 ^
3,2 ^
4,2 ^
5,2 ^
6,2 -+

1,3 +2,3 ^
3,3 ^
4,3 ^
5,3 ^
6,3 -+

1,4
2,4
3,4
4,4
5,4
6,4

Thus, in Memory, the Elements making up each 6 Element Column fill


physically adjacent Memory Words. Going through the (whole) Array
as a linear sequence, the Row Index varies fastest.

96

Fortran Array Processing - Part 12


==================================
-

6/ Array Storage Rules (continued) :


The last examples two Dimensional 6 Row and 4 Column Array would
be stored with Elements indexed in the arrangement shown below :
1,1 2,1 3,1 4,1 5,1 6,1

1,2 2,2 3,2 4,2 5,2 6,2 -+


|
+-----------------------------------------------------+
|
+- 1,3 2,3 3,3 4,3 5,3 6,1
1,4 2,4 3,4 4,4 5,4 6,4 -+
|
+-----------------------------------------------------+
|
+- 1,5 2,5 3,5 4,5 5,5 6,5
1,6 2,6 3,6 4,6 5,6 6,6
For Arrays of more than two Dimensions, the Subscript to the right
in the set for each Element will vary slowest. For three Dimensions,
this equates to two Dimensional Arrays being stored next to each
other, each set up as shown above. for example :
INTEGER

IARR ( 6, 3, 4 )

would lead to this Memory layout :


1,1,1 ... 6,1,1

1,2,1 ... 6,2,1

1,3,1 ... 6,3,1 -+


|
+-------------------------------------------------------+
|
+- 1,1,2 ... 6,1,2
1,2,2 ... 6,2,2
1,3,2 ... 6,3,2 -+
|
+-------------------------------------------------------+
|
+- 1,1,3 ... 6,1,3
1,2,3 ... 6,2,3
1,3,3 ... 6,3,3 -+
|
+-------------------------------------------------------+
|
+- 1,1,4 ... 6,1,4
1,2,4 ... 6,2,4
1,3,4 ... 6,3,4
This enforced Memory arrangement means Loops proceeding through all
Elements in an Array should do so with the first (left) Subscript
varying quickest, in the innermost Loop of a nested set. When only
portions of an Array are to be accessed at a time, it should be
designed, if possible so those portions get stored in consecutive
locations in Memory.

97

Fortran Array Processing - Part 13


==================================
-

7/ Array Initialisations :
Once Arrays are declared, their Elements may be assigned initial
Values just like Scalar (individual, atomic Variables), with DATA
Statements. Any number of an Arrays Elements can be given initial
Values. Array references in DATA Statements always need Subscripts.
This means, in the forms of the DATA Statement considered so far,
that each Array Element is seen as an individual (Scalar) Variable.
When several Elements are initialised, no restrictions exist as to
them forming any pattern in the Array, or being listed in any order.
Element assignments can be split between multiple DATA Statements.
The same restriction apply as with individual Variables regarding
Common Blocks, namely that entities present in Common Blocks must
be initialised in (and only in) BLOCK DATA Subprograms.
By using the * repetition Operator of DATA Statements, the same
Value may be applied to a number of Array Elements, possibly mixed
with Scalar Variables, or the Elements of several Arrays.
Examples of basic Array Initialisations with DATA Statements :
CHARACTER * 12
CHARACTER

CAR1 ( 200 ),
CAR2 ( 100 )
CAR3 ( 200 ) * 8, CAR4 ( 100 ) * 2

INTEGER

IAR1 ( 300 ),

DOUBLE PRECISION

DVR1, DVR2

DATA
1
1

IAR2 ( 300 )

CAR1 ( 1 ), CAR1 ( 2 ) / , /,
CAR2 ( 1 ), CAR2 ( 2 ),
CAR2 ( 3 ), CAR2 ( 4 ) / 4 * x /

DATA
1

IAR1 ( 300 ), IAR1 ( 299 ), IAR1 ( 298 )


/ 3000,
2999,
2998 /

DATA
1

IAR2 (
/ 3000,

DATA
1

24 ), IAR2 ( 240 ), DVR1, DVR2


2999,
, 2 * 0.8D0 /

IAR1 ( 124 ), IAR2 (


IAR1 ( 148 ), IAR2 (

98

48 ) / 2 * 112 /,
96 ) / 2 * 124 /

Fortran Array Processing - Part 14


==================================
-

8/ Array Initialisations with Implied DO Loops :


Where series of Array Elements are to be initialised, a special form
of DO Loop exists, called an "Implied" DO Loop. For this, Elements
must all be separated in the Array by the same Stride (or Step) in
at least one Dimension. For instance in the Array :
DOUBLE PRECISION

XAR1 ( 20, 20, 0:9 )

these subsets of Elements :


XAR1 ( 1, 1, 0 ), XAR1 ( 2, 1, 0 ), XAR1 ( 3, 1, 0 ), ...
XAR1 ( 1, 2, 0 ), XAR1 ( 1, 4, 0 ), XAR1 ( 1, 6, 0 ), ...
XAR1 ( 1, 1, 9 ), XAR1 ( 1, 1, 8 ), XAR1 ( 1, 1, 7 ), ...
all constitute sequences with regular Strides, respectively 1, 2
and -1 in the first, second and third Dimension in turn. In some
recent literature, such Array subsets are called "Constructors".
When the
Elements
previous
make the

same initial Value is to be assigned to such sequences, the


can of course be listed in DATA Statements like those on
pages, but an Implied DO Loop can replace the list, and
Stride more obvious. For the Array and subsets above :

INTEGER

IX

DATA
1

( XAR1 ( IX,

1,

0 ), IX = 1, 10
)
/ 10 * 0.0D0 /

DATA
1

( XAR1 (

1, IX,

0 ), IX = 1, 10, 2 )
/ 10 * 2.0D0 /

DATA
1

( XAR1 (

1,

1, IX ), IX = 9, 0, -1 )
/ 10 * 2.0D0 /

As can be seen, an INTEGER Counter Variable replaces the regularly


incremented (or decremented) Subscript, with the Array entry being
followed by the Index specification. This replicates that of an
ordinary DO Loop, with comma separated Start and End Values and an
optional Increment which is otherwise defaulted to 1. The Array
subset and following Index settings must sit between Parentheses.

99

Fortran Array Processing - Part 15


==================================
-

8/ Array Initialisations with Implied DO Loops (continued) :


The Limits and Increment for the Loop Index obey the same rules as
for ordinary DO Loops, with some additional limitations. They must
be INTEGER Expressions, as for DO Loops, but every entity found in
the Expressions must be known, when the DATA Statement appears. This
effectively means they can only be in Line Constants or Parameters,
assigned in prior PARAMETER Statements.
Implied DO Loops may be nested, similarly to ordinary DO Loops. That
means Indexes for the Levels of nesting must be different Variables.
Also, each Implied DO Loop (Level) then necessitates its own set of
Parentheses. These examples would be valid :
INTEGER

I1, I2, I3

DATA
1

( ( DAR1 ( I1,I2 ), I1 = 1,32 ) I2 = 1,32 )


/ 1024 * 12.4D0 /

DATA
1
1
1

( ( ( XAR1 ( I1, I2, I3 ), I1 =


I2 =
I3 =
/ 1000

1, 10 )
1, 10 )
0, 9 )
* 0.0D0 /

But this would fail at compilation time :


DATA

( ( ( XAR1 ( IX, IX, IX ), IX = 1, 10 ) ...

Note the Sequence of Elements defined by the Implied DO Loop need


not be the sole item in the DATA Variables list. Also, the fact an
Implied DO Loop is present does not alter the way the list of Values
may be given. For example, the above DATA could become part of :
DATA
1
1
1
1
1

( ( ( XAR1 ( I1, I2, I3 ), I1 = 1, 10 )


I2 = 1, 10 )
I3 = 0, 9 ),
YVR1, YVR2, YVR3, YVR4
/ 500 * 0.0D0, 99 * 1.0D0, 2.0D0, 2.0D0,
403 * 3.0D0 /

However, whatever the way the lists of Variables and Values appear,
the number of Values must always match the number of Variables.

100

Fortran Array Processing - Part 16


==================================
-

9/ Array Element Access and Assignment :


All the rules governing the evaluation of Expressions and assignment
of Values apply indifferently to individual (Scalar) Variables or to
Array Elements or any mix of them. Array Elements simply appear with
the Name immediately followed by the Subscript in Parentheses. For
CHARACTER Variables, this means eventual Substring details come
after the Array Subscripts.
Examples of expressions and Assignments involving Array Elements :
CHARACTER * 12

CARY ( 12 ), CSTR

INTEGER

IAR1 ( 12 ), IAR2 ( 24 ), INVR

DATA
1

( IAR1 ( INVR ), INVR = 1, 12 ) / 12 * 2 /,


( IAR2 ( INVR ), INVR = 13, 24 ) / 12 * 2 /

CARY ( 12 )
= 012345
CARY ( 11 )( 7: ) = xxxxxx
CSTR
IAR2 (
IAR2 (
INVR

= CARY ( 11 )( 7:12 ) // CARY ( 12 )


2 )
3 )

= IAR1 ( 11 ) ** 2
= IAR2 ( 21 ) ** 2
= IAR2 ( 3 ) * IAR1 ( 1 ) - 2

Note INTEGER arithmetic is permitted with Subscripts. For example :


IAR1 ( INVR + 1 ) = 1
IAR2 ( INVR + 2 ) = IAR1 ( IAR1 ( 1 ) )
** 2
IAR2 ( INVR + 3 ) = IAR2 ( IAR1 ( 1 ) + 12 ) ** 2
would be valid, as long as the Expressions did not then take the
Subscript outside the specified Range, here 1 to 12 inclusive
for IAR1 and 1 to 24 inclusive for IAR2.

101

Fortran Array Processing - Part 17


==================================
- 10/ Array Access and Assignment with DO Loops :
When regular patterns of references or assignments to Array Elements
can be found, DO Loops can usually be designed to implement them :
INTEGER

IAR2 ( 120 ), IIAR3 ( 120 ), INDX

DO 100

INDX

= 1, 120

IAR2 ( INDX ) = INDX + 3


100 CONTINUE
DO 200

INDX

= 5, 110, 15

IAR3 ( INDX ) = IAR2 ( INDX - 3 )


200 CONTINUE
In the first case the whole Array is assigned. Note use of the Loop
Index in Subscripts or Expressions is allowed. In the second case,
Every 15th Element from the fifth on is assigned.
Note Fortran does not permit attempts to access Array Elements out
of the declared Subscript Ranges. This may not always be detected
at compile time, so successful compilation does not on its own
signify this has been avoided.
The first Loop in the pair above would fail with Iterations starting
at Zero (INDX = 0, 120), or ending above 120. The other Loop
needs a minimum Index of 4 to pass because of the INDX - 3 on the
Array IAR2. Because of its Increment of 15, an end Value of 111
up to 124 would be accepted as after the run with INDX at 110,
the next Loop Index be tested would be 125. Anything below that
will cause termination after 110 is incremented (to 125).

102

Fortran Array Processing - Part 18


==================================
- 11/ Multidimensional Array Access and Assignment :
With Multidimensional Arrays, large efficiency gains may be made by
designing Loops so that successive Array Elements processed in the
Loops sit closest together in Memory. In other words, that implies
Arrays should be progressed through with the left hand Subscript
varying fastest. In the case of two Dimensional Arrays, this Column
Major ordering tells Arrays should be handled Column by Column, with
the Row Subscript changing most often. For example :
DOUBLE PRECISION
INTEGER
DO 120

XAR1 ( 20, 20, 10 )


I1, I2, I3

I3

= 1, 20

I2

= 1, 20

DO 100 I1

= 1, 20

DO 110

XAR1 ( I1, I2, I3 ) = 2.0D0 * DBLE ( I1 * I2 * I3 )


100
110

CONTINUE
CONTINUE

120 CONTINUE
will run though the three Dimension Array with all successive
assignments to contiguous locations in Memory. A slight improvement
in efficiency could be achieved by saving the I2 * I3 product in
the 110 Loop, before the DO 100 Statement :
INTEGER
...

IS
IS

DO 100 I1

= I2 * I3
= 1, 20

XAR1 ( I1, I2, I3 ) = 2.0D0 * DBLE ( I1 * IS )


Note the use of regular indentation of the Code to distinguish the
nested Loops. Of course the Labels must remain in Columns 1 to 5 of
the Statement and Comment Statements start with a C in Column 1.

103

Fortran Array Processing - Part 19


==================================
- 11/ Multidimensional Array Access and Assignment (continued) :
With a Multidimensional Array, like that in the previous example,
access or assignment patterns implying jumps in Memory should be
avoided, possibly by storing the Array differently.
Were the XAR1 assignment above to be arranged as :
DOUBLE PRECISION
INTEGER
DO 120

XAR1 ( 20, 20, 10 )


I1, I2, I3

I3

= 1, 20

I2

= 1, 20

DO 100 I1

= 1, 20

DO 110

XAR1 ( I3, I2, I1 ) = 2.0D0 * DBLE ( I1 * I2 * I3 )


100
110

CONTINUE
CONTINUE

120 CONTINUE
jumps of 20 (Rows) * 20 (Columns), equating to 400 DOUBLE PRECISION
entities, or 3,200 Bytes would result. Even with this modest Size
Array, a lot of Memory management would be forced that was avoided
in the original I1, I2, I3 Subscript pattern.
In this respect, note how the earlier DATA Statement and Implied DO
Loops were coded. Much as DATA Statements are resolved when the Code
is compiled (a once off) rather than executed, it is advisable to
present Array accesses consistently and in the most efficient way.
As the implementation of Array storage under Column Major Order
form part of the 77 Standard, Programs coded to optimally process
Arrays will not loose that benefit by being run on other hardware.

104

Fortran Array Processing - Part 20


==================================
- 12/ Additional Array Processing Features in Fortran 90 :
Fortran 90 brought many new aspects to Array processing :
Arrays can be manipulated in Code as if a single Entity.
That extends to regular (say whole Rows) Sections of an
array as well as to lists of any Array Elements.
New Intrinsic Functions may for instance reshape Arrays,
invert two Dimensional Matrices, or pick extreme Valued
(Maximum and Minimum) Elements.
Arrays need no longer be completely defined at compile
time, and instead be ALLOCATABLE such that Memory gets
reserved for them only when asked during Execution. This
will not be covered further in these notes.
In Fortran 90 Array references can consist of :
The Array Name alone, to imply the whole Array,
The Array Name followed by a set of Subscript Ranges
rather than single Values, to define a regular Section,
The Array Name as Argument to the RESHAPE Intrinsic,
allowing any set of Elements to form a subset Array,
The Array Name and a set of exact Subscripts,
to pick an individual Element, as above for Fortran 77.

105

Fortran Array Processing - Part 21


==================================
- 13/ Whole Array or Section Processing in Fortran 90 :
Array Names without any Subscripts may appear in Expressions,
in which case the operations which would have affected a single
Element (or other Scalar quantity) will be carried out on every
Element of the Array. For example :
CHARACTER * 12

CAR1 ( 8 ), CAR2 ( 8 )

CAR1
CAR2

= xxx
= CAR1 // kkk

With the above Code, Every Element of CAR1 gets assigned xxx,
while every Element in CAR2 receives the corresponding Element
of CAR1 concatenated with kkk.
When two or more whole Arrays get involved in an Expression, the
Operators apply element by Element in the Arrays. For example :
DAR3

= DAR1 * DAR2

will multiply DAR1 ( 1 ) by DAR2 ( 1 ) to make DAR3 ( 1 ),


then multiply DAR1 ( 2 ) by DAR2 ( 2 ) for DAR3 ( 2 ) etc.
In this case the Arrays of course must be of a Numeric Type.
Handling Arrays as single entities can cut the need for DO Loops to
process the Elements, and leave arranging optimal access patterns to
implementations, via Compilers. Arrays remain stored in Column Major
Order, but Sections (see below) or the RESHAPE Function allow the
Elements to be dynamically rearranged if needs be.
Array may also get their Elements assigned dynamically like is done
in DATA Statements. There, the Array Name appears as the Left Hand
Side (Target) of an assignment where the Right Hand Side presents
the comma separated list of Values inside Slashes and Parentheses.
For example, the first case above could be :
CAR1
1

= ( / xxx, xxx, xxx, xxx,


xxx, xxx, xxx, xxx / )

But different Values could then have been assigned as in :


CAR1
1

= ( / abc, def, ghi, jkl,


mno, pqr, stu, vwx / )

106

Fortran Array Processing - Part 22


==================================
- 14/ Array Section Processing in Fortran 90 :
Alternatively to whole Array processing, regular cuts or patterns
of Elements in an Array can be accessed as if a single entity. In
so called Sections, Subscripts are specified as subset of the full
Range established at declaration, much like Substrings are set for
CHARACTER Type Variables. For example :
INTEGER

IAR1 ( 20, 10, 10 )

IAR1 ( 11:20, 1 , 1
) = 12
IAR1 (
: , 2:4, 2
) = 12
IAR1 (
: , 5:8, 3:4 ) = 12
The first assignment sets Elements ( 11, 1, 1 ) to ( 20, 1, 1 )
the second covers all Elements in Columns 2 to 4 of Plane 2,
and the third assigns Column 5 to 8 in Planes 3 and 4.
The part Subscript Ranges are specified, for each Dimension as a
triplet "Start : End : Increment". The Increment can be negative
and defaults to 1. The Start or End may be omitted in which case
the Limit at the Array Declaration will stand in. The Declared
Subscript Ranges form hard limits and attempts to access Elements
or of that Range will cause compile or execution time failure.
The combination of Start, End and Increment can however specify
a Zero sized Section, equivalent to a DO Loop which would not be
Executed when the Start Index already exceeds the End Value :
IAR1 ( 20:10: 2, 2:4, 2
) = 12
IAR1 ( 10:20:-2, 5:8, 3:4 ) = 12
would be Zero sized Sections and result in no assignments. In Line
Subscript ranges like this could be weeded out of the Code, but when
the subscript Ranges are computed from (INTEGER) Variables, a Zero
Section means execution of the Routine can still continue, and avoid
for instance the need to use some IF Statements to check the Size of
a Section before making reference to it.

107

Fortran Array Processing - Part 23


==================================
- 15/ Array Section Processing with Vectors in Fortran 90 :
As opposed to the "Start : End : Increment" specification for
an Array Sections Subscript Range, the Name of a one Dimensional
INTEGER Array may be given, which contains any allowed individual
Values for the Subscript. As in mathematical practice, this is
called a Vector. An an irregular shape Array Section can thus be
constructed. For example :
INTEGER
INTEGER
INTEGER

IAR1 (
8 )
IAR2 ( 100, 100 )
IAR3 (
8 )

IAR1

= ( / 1, 5, 7, 12, 20, 80, 85, 90 / )

IAR3

= IAR2 ( IAR1, 1 )

would pick Elements 1, 5, 7, 12, 20, 80, 85, 90 of


the first Column in IAR2 to assign IAR3. This can extend to more
than one Dimension. For example, reusing the above Code and :
INTEGER
INTEGER

IAR4 ( 6 )
IAR5 ( 8, 6 )

IAR4

= ( / 3, 15, 24, 30, 36, 42 / )

IAR5

= IAR2 ( IAR1, IAR4 )

would assign the elements 1,3, 5,3 ... 90,3, 1,15, 5,15
and so one from IAR2 to the reshaped 6 times 8 Array IAR5,
via the two Vector Sections IAR1 and IAR4.

108

Fortran Array Processing - Part 24


==================================
- 16/ Array Intrinsic Functions in Fortran 90 :
Several new Intrinsic Functions can extract Array characteristics
or apply operations on whole Arrays which would otherwise require
DO Loops to achieve. Some of the Functions presented below can
involve optional extra Arguments following those given, which have
been left out for brevity.
Functions to obtain Array Characteristics :
SIZE

Coded as SIZE ( ARRY ) gives the number of Elements


in Array ARRY or as SIZE ( ARRY, DM ), and DM a
Dimension Index, the Size for that Dimension.

LBOUND
UBOUND

Coded as SIZE with a Dimension Index, give the


Lowest or Highest Bound for that Dimension.

SHAPE

Coded as SHAPE ( ARRY ), gives a vector of the


Sizes in each Dimension of the Array ARRY.

Functions for Numeric Type Arrays :


SUM

Coded as SUM ( ARRY ) gives the Sum of the Elements


in Array ARRY or as SUM ( ARRY, DM ), and DM a
Dimension Index, the Sum for that Dimension.

PRODUCT

Coded the same way as SUM,


gives the Product of the Elements in an Array.

MAXVAL
MINVAL
MAXLOC
MINLOC

Coded as SUM, give the Lowest or Highest Element.


Coded as SUM, MAXVAL and MINVAL,
provide a one Dimensional Array of the Coordinates
of the Max. or Min. Values in its Argument Array.

For example, with the previous INTEGER Array IAR5 :


IAMX
DAMX

=
MAXVAL ( IAR5, 3 )
= DBLE ( SUM
( IAR5 ) ) / DBLE ( SIZE ( IAR5 ) )

would place the largest Element in Column 3 of IAR5 in IAMX,


and the (exact) Average Value of the Matrix Elements in DAMX.

109

Fortran Array Processing - Part 25


==================================
- 16/ Array Intrinsic Functions in Fortran 90 (continued) :
Functions to reconstruct Arrays :
RESHAPE

Coded as RESHAPE ( ARRY, SHPE ), gives


the Shape in the one Dimensional INTEGER
The new Shape must hold the same Size as
two Dimensional Arrays, TRANSPOSE also
transposition of Arrays.

Array ARRY
Array SHPE.
the old. For
allows the

CSHIFT

Coded as CSHIFT ( ARRY, SHFT ), shifts all Elements


in Array ARRY by the (INTEGER) Step SHFT, which
may be negative. The end Element is rotated.
When coded as CSHIFT ( ARRY, SHFT, DM ), the Shift
operation is restricted to the Dimension in DM,
which must be an INTEGER Scalar.

EOSHIFT

Works like CSHIFT above, but dropping off the last


Element, and placing a Zero in the lead Element when
Numeric, a Blank when CHARACTER and .FALSE. when
of LOGICAL Type.

110

Fortran Array Processing - Part 26


==================================
- 17/ WHERE Statements to Process Arrays in Fortran 90 :
Fortran 90 introduced the WHERE and associated ELSEWHERE and
closing END WHERE (thereafter written ENDWHERE) to process Arrays
Element by Element on a conditional Basis, obviating the need to
code a DO Loop merely containing a Block IF in its Iterations.
The Syntax of WHERE matches that of the Block IF, except that the
conditional Expression controlling entry must involve an Array as
a whole. An ENDWHERE is required, and one or more ELSEWHERE might
precede the ENDWHERE. No equivalent to the plain ELSE of the
Block If exists. For example :
INTEGER

IAR1 ( 100 ), IAR2 ( 100 )

WHERE

( IAR1 .LT. 0 )
IAR2 = IAR1 - 1

ELSEWHERE

( IAR1 .GT. 0 )
IAR2 = IAR1 + 2
IAR1 = IAR2 - 1

ENDWHERE
In this code, for each Element of IAR1 in succession, the test
against Zero is Carried out. When the Element is Negative, the
Statement following the WHERE executes. Otherwise, when the Element
of IAR1 is above Zero, the assignments after ELSEWHERE get done.
When the IAR1 Element matches Zero, nothing happens and the next
Element of IAR1 is tested.

111

Fortran Files And I/O (Input/Output) - Part 1


==============================================
-

1/ Introduction :
Input and Output (commonly abbreviated I/O) is the task by which
Programs respectively import or export Data. Usually this will be
with resources on the Computer system, like Disks, User Terminals,
or Printers. These resources are all deemed "External Files".
However, I/O may be used between internal entities, so that Data may
be placed in Variables when this would not be permitted in straight
assignments. In this case, CHARACTER Type Variables replace external
Files. For this purpose they are called "Internal Files". This way,
Numeric Values can be written to CHARACTER Variables or vice versa.
When involving external Files or facilities, I/O takes place via
Logical (I/O) Units (sometimes called Channels). Before being used,
the Units must be connected to actual resources. This can be done
before Programs are run, but will normally be via OPEN Statements.
The status of Files can be queried with the INQUIRE Statement.
When using CHARACTER Variables as Internal Files, their Name is
entered in the I/O Statement where a Logical I/O Unit would appear.
All Input is carried out with the READ Statement. Output may be by
WRITE or PRINT Statements, the latter being a simplified form of the
former. Data transfers can be Formatted, where the Program specifies
the Data layout in the File, or Unformatted, where the system takes
care of arranging the information. FORMAT Statements frequently
serve to detail Formatted Record layouts.
The Data in a single I/O transfer represents a Record. Formatted
Output requires Format specifiers, which may be the Labels of FORMAT
Statements. In any case, a string of "Edit Descriptors" indicate the
Record layout for every Transfer to or from a (Formatted) File.
External Files may be processed from start to end, in "Sequential
Access" mode, or randomly, in "Direct Access" mode, where Records
are picked in any order via Record Numbers.
BACKSPACE and REWIND Statements let Programs go back up Sequential
Access Files one Record at a time or the whole File Respectively.
The Close Statement releases Files, and the attached I/O Units.

112

Fortran Files And I/O (Input/Output) - Part 2


==============================================
-

2/ External File handling and I/O Units :


In Fortran, all Input and Output (I/O) transfers Data with Files.
External Files form resources outside the Program on the Computer.
They may be Disk Files, known to the Computers Operating System,
Display Terminals, their Keyboards, or Printers. All Files must be
connected to Logical I/O Units before I/O can take place.
The ANSI Standard (even 66) requires systems to offer a preconnected
Default Input and a Default Output File. Also called Default Units
or Default Channels, they must always be available so Data can be
received from the Default Input or sent to the Default Output.
Generally Default Input will come from the Keyboard of the Terminal
from which the Program is submitted for execution. Default Output
(and Error if connected) will go to the Screen of that Terminal. In
both cases, some Operating Systems, like Unix allow Redirection, so
Disk Files, or Printers (for Output) may be used instead. This will
however not be known and be immaterial to Fortran Programs.
All other external Files need an explicit connection to their Units.
This can be done by the Computer before the Program is executed, but
in most Code written since the 77 Standard, takes place via an OPEN
Statement. Externally attached Files may still need a basic OPEN
Statement (not naming the File) before I/O can take place.
Units must be INTEGER Constants, in Line or Parameters, or Variables
with a Value between 1 and a system dependent limit. At least 30
will normally be available, sometimes up to 32,767.
In most implementations, Standard Input will be via Unit 5, and
Output via Unit 6. Some systems will additionally offer a Default
Error on Unit 7. Programs should thus avoid picking these numbers
when connecting Units to Files in OPEN Statements.
Units are detached from Files and released for eventual reuse with
other Files by the CLOSE Statement. Programs should not attempt to
close the Standard Units. Files not closed at the normal termination
of a Program, get closed by the Operating system of the Computer. If
the Program terminates with an error, this may entail loss of Data
when Output transfers are batched and the Buffers are deleted.

113

Fortran Files And I/O (Input/Output) - Part 3


==============================================
-

3/ General Form of Input/Output Statements :


With External Files, all I/O Statements apart from OPEN and INQUIRE
operate with an I/O Unit connected to the File, and not via the File
Name. The latter may only appear in OPEN or INQUIRE Statements. All
External File I/O Statements apart from INQUIRE, a form of READ from
Default Input and PRINT actually require a Unit Number.
For Internal Files, the Name of the CHARACTER Variable serving in
that capacity replaces the Unit Number in the I/O Statements, which
reduce to (Formatted) READ and WRITE.
For External Files, the Unit may be given as an in Line INTEGER
Value or the Name of an INTEGER Variable, assigned the Unit Number.
Input/Output Statements take the form of a set of I/O Specifiers,
in Parentheses, eventually followed by a List of Variables. All the
Specifiers can be used with a Tag in the form "Tag = Value", and in
that case, the Specifiers can show in any order. Merely the Value of
some Specifiers can be given, but in that situation, the tag-less
Value must show in a set position in the List of Specifiers.
For clarity, it is advisable to prepend the Tags to all but the most
common Specifiers. In a lot of Code (including some of the following
examples), only the Unit (UNIT = and Format (FMT =) Tags are
omitted. Then the Unit (Number or Variable Name) must always come
first in the List, and for Data Transfer Statements where applicable
the Format second with the Unit before it.
File queries with the INQUIRE Statement may be by Unit or by Name,
but not jointly. Queries by Name must provide a FILE = Tag and
File Name and no I/O Unit. This forms one of three cases a Unit is
not needed (in fact it must not appear). For Queries by Unit, the
above rules for Unit Numbers apply, namely that if entered without
a UNIT = Tag, they must come first in the Specifier List. INQUIRE
cannot be used for Internal Files.
In two of the other instances of I/O Statement requiring no Unit,
Data transfer takes place with the Default Units and a simplified
Syntax is used where only a Format Specifier present. The third case
of Statement needing no Unit lies in FORMAT Statements used to tell
the Record layout of Data in Formatted File I/O.

114

Fortran Files And I/O (Input/Output) - Part 4


==============================================
-

3/ General Form of Input/Output Statements (continued) :


All Input and Output Statements apart from the List Directed READ
and PRINT permit the use of ERR and IOSTAT Error Specifiers.
The ERR Specifier provides the Label for a Statement to
control will pass when an error is detected. The IOSTAT
represents an INTEGER Variable which will receive a Value
on the outcome of the Statement. When an error occurs and
is present, execution should terminate.

which
Specifier
depending
neither

The nature of Error conditions will depend on what was attempted


by the I/O Statements. For example opening non existent Files, or
Data transfers to or from Variable Types mismatched with the Format
specifiers should cause errors.
The IOSTAT Variable must be an INTEGER. It is set to Zero when
the I/O operation concludes successfully, and to a positive Value
when an error arose. It can be set to Negative Values to indicate
some special conditions not genuinely deemed to be errors. The non
Zero Values will be implementation dependent.
The existence, status and Attributes of an External File can be
assessed via the INQUIRE Statement, before attempting to open it.
This does not need a Unit to have been attached to the File. A lot
of Errors pertaining to the presence of certain Files, how they can
(if allowed) be read or written to can be avoided by using INQUIRE.
List Directed I/O constitutes Formatted operations where the Format
Descriptors managing the Record layout are provided by the system
instead of being coded in FORMAT Statements or in Line details.

115

Fortran Files And I/O (Input/Output) - Part 5


==============================================
-

4/ External File Connection, OPEN Statement :


The OPEN Statement serves to connect an External File to a Logical
I/O Unit and eventually indicate its properties. This includes its
Status in terms of it being an existing or a new File, its Access
Mode (Sequential or Direct), and if Records are Formatted or not.
Only one File can be opened in an OPEN Statement.
The Specifiers can be listed in any order, but when the Unit lacks
its UNIT = Tag, it must come first. The Unit must be at least 1
and can (as in all other I/O Statements) be either an in Line Value
or the Name of an INTEGER Variable assigned the Unit Number.
OPEN Statement Syntax and I/O Specifiers :
OPEN
1
1
1
1
1
1
1
1

( UNIT
FILE
STATUS
ACCESS
FORM
RECL
BLANK
IOSTAT
ERR

=
=
=
=
=
=
=
=
=

nnnn,
____,
____,
____,
____,
iiii,
____,
iiii,
llll )

The Specifiers where ____ follows the Tag can be either given
as in Line Text Strings, inside (the usual) Single Quotes, or as the
Name of CHARACTER Variables to which an appropriate Character String
was assigned beforehand.
The iiii Specifier for RECL must be an Integer Constant or the
Name of an INTEGER Variable containing the Record Length. The iiii
Specifier for IOSTAT must give the Name of an INTEGER Variable,
which will receive an outcome related Value afterwards.
The llll Specifier must be the Label of another Executable Part
Statement, at which execution will continue when an Error occurs.
The IOSTAT Variable would then receive a Positive Value.

116

Fortran Files And I/O (Input/Output) - Part 6


==============================================
-

4/ External File Connection, OPEN Statement (continued) :


OPEN Statement I/O Specifiers (apart UNIT, IOSTAT, ERR ) :
For all these I/O Specifiers the Tags are necessary. Values
can either be given as in Line Constants or Variable Names.
FILE

Names the (External) File. The Name can be as known


to the Operating System, or a Script controlling
execution of the Program.

STATUS

One of : OLD

ACCESS

Access Mode : SEQUENTIAL for Files


to bottom
DIRECT
for Files
set order

FORM

Record Format : FORMATTED

RECL

Record Length : Maximum for Sequential Access Files,


For all Records in Direct Access Mode,

BLANK

Interpretation of Spaces in Records,


either NULL or ZERO.

for existing Files,


which must be present,
NEW
for new Files,
which must not exist,
SCRATCH for run time Temporary Files,
deleted at Program completion,
UNKNOWN For Files either NEW or OLD.
processed in top
Record sequence,
processed in no
by Record Number,

for Program controlled


layout of the Records,
UNFORMATTED where the system
arranges the Records,

The FILE Specifier is compulsory for STATUS NEW or OLD, but


optional for Status SCRATCH or UNKNOWN. SEQUENTIAL will be
taken as ACCESS when not provided. FORM defaults to FORMATTED
for Sequential Access Files, and UNFORMATTED for Direct Access.
The RECL Specifier is only required for Direct Access Files. It
must be 1 or more in Value. The BLANK Specifier only applies to
Formatted Files. It defaults to Space, the Null for CHARACTER Data.

117

Fortran Files And I/O (Input/Output) - Part 7


==============================================
-

5/ External File Connection, OPEN Statement Examples :


Example OPEN Statements (1) :
CHARACTER * 12
INTEGER

CCFN
NUCD

DATA
DATA

CCFN / ContVals.dat /
NUCD / 8
/

OPEN
1
1
1
1
1
1

( UNIT
FILE
STATUS
ACCESS
FORM
BLANK
ERR

=
=
=
=
=
=
=

NUCD
,
CCFN
,
OLD
,
SEQUENTIAL,
FORMATTED ,
NULL
,
910
)

This attempts to open an existing File called ContVals.dat,


on Unit 8, for Sequential Access, with Formatted Records of no
set Maximum Length (no RECL Specifier). The BLANK Value means
in effect that Blanks in Numeric Fields will not change the Value.
Were an error to arise, execution would carry on at Statement 910.
Were the Blank handling option to be changed, another OPEN may be
coded without the need for a CLOSE Statement beforehand. The File
Name (FILE) becomes optional, and in effect the existing position
in the File is maintained as the connection actually is not broken.
This Statement would be typical for ordinary plain Text Files. For
Files created by the Program, NEW should be used in STATUS, but
when a possibly existing File is reused, UNKNOWN would be best.
For anything other than very large Files, Plain text, and with it,
Formatted I/O will be advisable. It allows easy visual inspection of
the Files outside the Program, using Editors for instance.

118

Fortran Files And I/O (Input/Output) - Part 8


==============================================
-

5/ External File Connection, OPEN Statement Examples (continued) :


Example OPEN Statements (2) :
OPEN
1
1
1
1

( UNIT
STATUS
ACCESS
FORM
ERR

=
=
=
=
=

1
,
SCRATCH
,
SEQUENTIAL ,
UNFORMATTED,
920
)

This sets up a Scratch File, on Unit 1, for Sequential Access,


with Unformatted Records of no set Maximum Length (no RECL given).
The BLANK must not be present with Unformatted Files, and a Name
should not usually be provided either.
This File could serve as a store of transient Numeric Data. While
Text Data remains stored in the same way whatever the File Format,
Numeric Fields get stored in Internal Binary form in Unformatted
Files, at a considerable saving in Space and also efficiency as no
conversion to Text form will be necessary. For instance, INTEGER or
REAL Values of more than 4 Digits occupy only 4 Bytes in internal
representation. However, Internal representation of Data is decided
by the Operating System and can be inconsistent between systems, or
change with time. Therefore, when space considerations allow, non
Scratch Files should preferably use Formatted Records.
The Scratch File above will be lost at Program completion. Were it
to have been saved on Disk (which is not obligatory, even when a
File Name is given and a non Scratch Status selected), the OPEN
could be coded with STATUS as NEW and a FILE Specifier :
INTEGER
OPEN
1
1
1
1
1
1

IOST
( UNIT
FILE
STATUS
ACCESS
FORM
IOSTAT
ERR

=
=
=
=
=
=
=

9
,
NumrData.out,
NEW
,
SEQUENTIAL ,
UNFORMATTED ,
IOST
,
920
)

Note the same Label can appear in the ERR Specifier of more than
one OPEN (and some other I/O Statement), and likewise the IOSTAT.

119

Fortran Files And I/O (Input/Output) - Part 9


==============================================
-

6/ External File Release, CLOSE Statement :


Once no more transfers take place with an External File opened in
an earlier OPEN Statement, a CLOSE Statement should be coded for
it. This makes the I/O Logical Unit available again for eventual
attachment to other Files, via later OPEN Statements.
CLOSE also, and more importantly releases Files for access by other
Programs, and does so ensuring all Output transfers are completed.
When a Program completes (reaches a STOP or END Statement) with
Files still open, these should be closed by the Operating System.
However, sometimes output is buffered and the last few transactions
could be lost if the Buffers are simply discarded after an error.
A CLOSE Statement forces a write out of all Buffers to the File.
A Close should only relate to a previously opened File. So the
Default Units are excluded and so are Internal Files. Beside the
compulsory Unit Specifier and optional ERR and IOSTAT, CLOSE
may include a STATUS Specifier.
The CLOSE STATUS may only be KEEP or DELETE. In the former
situation, the File should remain after the closing operation, but
in the latter case, it will be discarded. Note that the Operating
System might override these actions. It should prevent deletion of
a File the session running the Program had no right to erase, and
ditto, stop the creation of a File by a session lacking that right.
Example CLOSE Statements :
INTEGER

IOST

CLOSE
1
1

( UNIT
= 1
,
STATUS = DELETE,
ERR
= 930
)

CLOSE
1
1
1

( UNIT
STATUS
IOSTAT
ERR

=
=
=
=

9
KEEP
IOST
940

,
,
,
)

The first example would be suitable for a Scratch File (see earlier
OPEN example), and the second example for a File to save to Disk.

120

Fortran Files And I/O (Input/Output) - Part 10


==============================================
-

7/ External File Enquiries, INQUIRE Statement :


The existence, Status and Attributes of External Files may be
queried by Programs with INQUIRE Statements, irrespective of the
Files already having been connected or not with OPEN Statements.
INQUIRE may be by Unit, in which case a Unit Specifier is required,
as the first I/O Specifier if not preceded by its UNIT = Tag, or
by Name, where a FILE Name Specifier is instead needed and a Unit
Specifier must not be present. The Name needs a FILE = Tag. The
error ERR and IOSTAT Specifiers can be given as with other I/O
Statements. All the other Qualifiers tell about the enquired File
either in returning a setting, or a Logical .TRUE. or .FALSE.
Value when a set property is enquired.
INQUIRE Specifiers with their Values :
Specifier
----------ACCESS

Values
----------SEQUENTIAL
DIRECT

Type
--------CHARACTER

Description
-----------------------Access Mode for the File

BLANK

NULL
ZERO

CHARACTER

Handling of Spaces

DIRECT

YES
NO

CHARACTER

Set to YES
for Direct Access Files

EXIST

.TRUE.
.FALSE.

LOGICAL

Set to .TRUE.
when File exists

FORM

FORMATTED
UNFORMATTED

CHARACTER

Record Format in File

FORMATTED

YES
NO

CHARACTER

Set to YES
for Formatted Files

NAME

ffff

CHARACTER

File Name (if present)


in queries by Unit

NAMED

.TRUE.
.FALSE.

LOGICAL

Set to .TRUE.
when File bears a Name
(continued on next page)

121

Fortran Files And I/O (Input/Output) - Part 11


==============================================
-

7/ External File Enquiries, INQUIRE Statement (continued) :


INQUIRE Specifiers with their Values (continued) :
Specifier
----------NEXTREC

Values
----------nnnn

Type
--------INTEGER

Description
-----------------------Number of Next Record,
or 1 when at beginning

NUMBER

nnnn

INTEGER

Unit Number when opened


and query by Name

OPENED

.TRUE.
.FALSE.

LOGICAL

Set to .TRUE.
when File opened

RECL

nnnn

INTEGER

Record Length
for Direct Access Files

SEQUENTIAL

YES
NO

CHARACTER

Set to YES
for Sequential Access

UNFORMATTED

YES
NO

CHARACTER

Set to YES
for Unformatted Files

Example File Query with INQUIRE Statements :


LOGICAL
CHARACTER * 12

LFEX
CFAC, CFFT

INQUIRE ( FILE
1
EXIST
1
ACCESS
1
FORMATTED

=
=
=
=

TestData.inp,
LFEX
,
CFAC
,
CFFT
)

will set LFEX to .TRUE if the File is Present, and then CFAC
to SEQUENTIAL or DIRECT and CFFT to YES or NO for a
Formatted or Unformatted File respectively. Both CFAC and CFFT
will be left undetermined when the File does not exist. So, an
initial test would check for LFEX to be .TRUE. with a Logical
or Block IF like IF ( LFEX ), before the other two results are
themselves tested to find the File characteristics.

122

Fortran Files And I/O (Input/Output) - Part 12


==============================================
-

8/ Input from Files, READ Statement :


All Input, that is reception of Data from either External Files or
Internal ones, is carried out via the READ Statement. Input will
be of Formatted, List Directed or Unformatted Nature. List Directed
Input corresponds to the use of default Format Specifiers. It is
common when picking up Data on the Standard (Input) Unit.
External Files subjected to READ Statements must have been connected
to a Logical I/O Unit beforehand, apart from the Default Input Unit.
Input from External Sequential Access Files apart from the Default
Unit causes the current position to advance one Record. When that
implies an attempt to go past the last Record, an End of File case
arises. If the READ Statement features an END Specifier, this
tells (by the Label) where execution will continue. Otherwise, when
neither the ERR nor the IOSTAT Specifiers appear, Program
execution should terminate.
The combination of I/O Specifiers in READ Statements determines the
nature of the transfers (Formatted, Unformatted or List Directed),
and the sort of Files (External, Default Input or External).
After the I/O Specifiers, the Statement lists the Variables which
will receive the Data from the File. The Data must be of suitable
layout to get assigned to the Type of the corresponding Variables
in the List. For instance non Numeric Data cannot be sent into
Numeric Variables with Formatted Input.
When no List of Variables follows the I/O Specifiers, a Record is
simply skipped in Sequential Files, or the operation has no effect
with Direct Access Files.

123

Fortran Files And I/O (Input/Output) - Part 13


==============================================
-

8/ Input from Files, READ Statement (continued) :


READ Statement I/O Specifiers (apart UNIT, IOSTAT, ERR ) :
For all these I/O Specifiers apart the Format, the Tags are
necessary. Values can either be given as in Line Constants
or Variable Names. When the Unit (UNIT) and Format (FMT)
tags are omitted, they must show in first and second place.
FMT

Label of a FORMAT Statement for Formatted Input,


or Character String with the Format information,
or Name of a CHARACTER Variable with this information,
or an Asterisk (*) for List Directed Input.
Must not be present for Unformatted Files.

END

Label of a Statement where execution continues when


trying to read past the last Record in a Sequential File.
Must not be present for Direct Access Files.

REC

Record Number for Direct Access Files,


which may be an in Line Integer Constant,
or an INTEGER Variable assigned the Record Number.
Must be provided for Direct Access Files,
but must not be present for Sequential Files.

When reading from the Standard Input, the Unit may be given as an
asterisk (*). This dispenses from the need to know what Unit is
used for this on any given system, and ensures the proper Unit will
be used on any system the Program is run on.
Alternatively, the Unit and all but the FMT Specifiers can be cut
out and the simplified READ ffff, Syntax used where ffff stands
for a FORMAT Statement Label or an Asterisk (*) for List Input.
Data transfer then happens from the Default Input Unit.
When present, the List of (Target) Variables following the I/O
Specifiers must consist of comma separated Scalar Variables, except
for Arrays which my be entered with Implied DO Loops in the form
as previously seen for DATA Statements, or just their Name, which
will bring the construction of an Implied DO Loop at compilation.

124

Fortran Files And I/O (Input/Output) - Part 14


==============================================
-

9/ Formatted READ Statement Examples :


READ

(8,1000,END=200,ERR=800) DVR1,DVR2,DVR3

READ
1

( 8, 1000, END = 200,


ERR = 800 ) DVR1, DVR2, DVR3

READ
1
1
1
1

( UNIT
FMT
END
ERR
IOSTAT

=
=
=
=
=

8
,
1000,
200 ,
800 ,
IOST ) DVR1, DVR2, DVR3

Disregarding the extra IOSTAT Specifier in the last case, these


READ Statements all assign the Variables DVR1, DVR2 and DVR3
from the File connected at Unit 8, with the Format information in
the FORMAT Statement at Label 1000.
READ
1

( NUIN, 2000, END = 210,


ERR = 810 ) CSTR ( 1 : 200 )

Input into Substrings is allowed with CHARACTER Variables. As will


be seen with FORMAT Statements, the A Descriptor for CHARACTER
Data allows an unspecified Length, in which case the Length of the
listed Variable determines the amount of Data transferred.
When fewer entities are listed than are present on the Record,
only those listed are input and the tail end of the Record ignored.
In the Statement above, the INTEGER NUIN would have been assigned
the appropriate Unit Number in advance. No FMT = Tag is used for
the Format, which is permitted as the Unit appears in first position
and the Format in second place.
READ
1

( NUDA, 2100, REC = 24,


ERR = 810 ) DADK, DADT1, DADT2

The READ above picks the 24th Record of the Direct Access File at
the Unit assigned to NUDA. Note with Direct Access Files, the same
Record (Number) may be read more than once, by different Statements,
with different Specifiers for the Format and ERR or IOSTAT. Were
this to be needed for Sequential Access Files, one or more BACKSPACE
Statements would be needed to return the current Position in the
File se the desired Record was again next in sequence.

125

Fortran Files And I/O (Input/Output) - Part 15


==============================================
-

9/ Formatted READ Statement Examples (continued) :


READ
1
1
1

( 9, (A12,2X,I6,2X,2(G12.4,2X),G12.4,A8),
END=200,ERR=800, IOSTAT=IOST )
CFLG, IFLG,
DVR1, DVR2, DVR3, CTAG

READ
1
1

( 8, ( 1X, F12.4, 1X, F12.4, 1X, F12.4 ),


END = 200, ERR = 800 )
DVR1, DVR2, DVR3

This example presents the Format Specifier as an in Line CHARACTER


Constant containing the Descriptors which would be held in a FORMAT
Statement if a Label had instead been entered in this position.
This keeps the formatting details with the List of Variables at all
times. In old Code, this way of presenting Format information saved
the need for separate FORMAT Statements and reduced the number of
Statements in the Program. However, this can make I/O Statements
hard to follow. Also, any FORMAT Statement can be referred to by
multiple READ (or WRITE) Statements. No computational cost incurs.
This method will not be covered further in these notes. for details
of the Descriptor String see the later notes on FORMAT Statements.
These example all pick Data from the Standard Input Unit :
READ
1
READ

( *, 1000, END = 200,


ERR = 800 ) DVR1, DVR2, DVR3
1000, DVR1, DVR2, DVR3

In the top case, just the Unit Number is replaced by the Asterisk
default Marker, while in the second case, the simplified Syntax is
shown where only the FMT Specifier, without FMT = Tag remains.

126

Fortran Files And I/O (Input/Output) - Part 16


==============================================
-

9/ Formatted READ Statement Examples (continued) :


As in assignments or Expressions, Array entities may show as
individual Elements with Subscripts for all Dimensions, like :
READ
1
1
1
1
1
1

( 9
,
1300,
END = 230 ,
ERR = 830 ) DVA1
DVA1
DVA1
DVA1

(
(
(
(

12
14
16
18

),
),
),
),

DVA1
DVA1
DVA1
DVA1

(
(
(
(

13
15
17
19

),
),
),
)

Implied DO Loops as in DATA Statements may be used, written in


the very same way, so the example above could be recoded as :
INTEGER
READ
1
1
1

IVAL
( 9
,
1300,
END = 230,
ERR = 830 ) ( DVA1 ( IVAL ), IVAL = 12, 19 )

Minimal computational cost might be incurred for the few entities in


this Statement, and a benefit would likely accrue when more than a
few tens of items are transferred.

127

Fortran Files And I/O (Input/Output) - Part 17


==============================================
-

9/ Formatted READ Statement Examples (continued) :


However, in this example featuring a large Floating Point Array :
DOUBLE PRECISION
INTEGER
READ
1
1
1
1
1
1

DVAR ( 124, 124, 124 )


IA1, IA2, IA3
( 10 ,
1400,
END = 240,
ERR = 840 ) ( ( ( DVAR ( IA1,
IA1
IA2
IA3

IA2,
= 1,
= 1,
= 1,

IV3 ),
124
)
124
)
124
)

the DOUBLE PRECISION Array in this Statement numbers 1,906,624


Elements, occupying around 15 Megabytes of Memory, and likely even
more on Disk. The Values must be read in the order they show in the
File, but with large Arrays like this, computational gains can be
achieved if the set up of the Dimensions allows the Arrays filling
in Column Major Order. This should be balanced against computations
carried out with the Data, especially as Input remains a once off
process, while several passes may be needed through the Array in
order to conclude the desired processing.
Also, as the whole Array DVAR is covered by the READ Statement,
the Implied DO Loop would have been imputed by merely coding :
READ
1
1
1

( 10 ,
1400,
END = 240,
ERR = 840 ) DVAR

Whole Arrays or Array Elements can be mixed up with Scalars in


an I/O Statement Variable List, so the example above could become :
READ
1
1
1

( 10 ,
1400,
END = 240,
ERR = 840 ) DVAR, DSA1, DSA2, DSA3

The explicit coding of the Implied DO Loop for the Array DVAR
would make it easier to distinguish it from the following Scalars.

128

Fortran Files And I/O (Input/Output) - Part 18


==============================================
- 10/ Unformatted READ Statement Examples :
If the data in the examples on the previous page was stored in an
Unformatted File, conversion from Text (Formatted) to Binary Form
would be avoided, and less actual Data moved from the Disk File.
Simply leaving the FMT Specifier out of the I/O Specifiers
implies Unformatted Input. The File must have been opened with
the ACCESS Specifier as UNFORMATTED though. For example :
DOUBLE PRECISION
INTEGER
READ
1
1
1
1
1

DVBR ( 100, 100, 100 )


IB1, IB2, IB3
( 10 ,
END = 240,
ERR = 840 ) ( ( ( DVAR ( IA1,
IA1
IA2
IA3

IA2,
= 1,
= 1,
= 1,

IV3 ),
100
)
100
)
100
)

This Statement pick a one million item DOUBLE PRECISION Array, so


8 Megabytes in total. It will prove a lot faster than the Formatted
version in the previous example. However, errors in the Data will
prove harder to detect, as most Binary Bit patterns would form a
valid DOUBLE PRECISION Value.
Data transmission will stop when either all items in the List are
filled, or the End of the File has been reached and an END was
present to provide a Label for the next Statement to execute.

129

Fortran Files And I/O (Input/Output) - Part 19


==============================================
- 11/ List Directed READ Statement :
In List Directed Input, the Format is defaulted with an Asterisk
(*). This is distinct from Unformatted Input. Files where List
Directed operations are intended should be opened as Formatted.
In List Directed I/O, the Data is expected to be Blank or comma
separated Values written as if Constants of the appropriate Type
in Source Code, apart from Logical Data, as enumerated below :
CHARACTER Data must show between Single Quotes,
and every internal Single Quote in the String as two
consecutive Single Quotes.
INTEGER Data must show as Digits and an optional Sign,
with any number of leading or trailing Blanks allowed.
Floating Point Data can consist of Digits, a Sign,
a Decimal Point, and an Exponent eventually Signed.
A Decimal Point is optional. If present, there need be
no Digits on both sides of the Decimal Point, but there
must be some on at least one side.
Complex Numbers must include two comma separated Floating
Point Numbers written as above, enclosed in Parentheses.
Logical Data can be any String of Characters as long as it
begins with a T for .TRUE. or F for a .FALSE. Value.
When the List Directed READ is from the Default Input, the List of
Variables may simply be preceded by READ *,. This equates to
writing READ ( *, * ). The Latter maintains consistency, and also
allows using the END and ERR Specifiers.
When fewer items than present on the Record are listed, the rest
of the Line in the Input File is skipped and the next Input will
take place at the beginning of the next Line in the File. Lines
are separated by Carriage Return Characters.

130

Fortran Files And I/O (Input/Output) - Part 20


==============================================
- 12/ List Directed READ Statement examples :
With the following Variables as Targets :
CHARACTER * 12
1

CHS1, CHS2,
CHS3, CHS4

DOUBLE PRECISION
INTEGER

DX01, DX02
INC1, INC2

COMPLEX

CNC1, CNC2

These List Directed READ Statements :


READ

( 10, *, ERR = 300 ) CHS1, CHS2

READ

*, DX01, INC1, DX02, INC2

READ

( *, * ) CHS3, CNC1, CHS4, CNC2

would be valid for File Records containing :


Text Data 1, Text Data 2 truncated
20.0D0 -300 .32D-3 +800
Complex 1 : ( 20.0 -30.0 ), Complex 2 : ( 1.2, 3.2 )
Note Spaces (in any number) or comma act indifferently as item
separators. Also, the usual CHARACTER assignment rules remain in
force. The second String in the first Record gets truncated to a
Length of 12 Bytes when assigned to the Variable CHS2. All the
other CHARACTER Variables get padded with Blanks.
Lacking and ERR Specifier, the last two Statements would cause a
run time error if they encountered and End of File, or Data like :
20,000 -300 .32D-3 +800 abc
Complex 1 : ( 20.0 -30.0 ), Complex 2 : ( , 3.2 )
where the first case contains a comma in a Numeric Field (the abc
being ignored as only 4 Values are input), and the second case is
missing a Single Quote and a Real Part in the second COMPLEX item.

131

Fortran Files And I/O (Input/Output) - Part 21


==============================================
- 13/ Input from Internal Files :
Internal File Input corresponds to picking the Data Values off a
CHARACTER Variable rather than from an External File. Internal
Files need not and should not be opened or closed, and cannot be
queried by INQUIRE Statements.
To implement Internal File Input, the Unit Number in the READ
Statement is replaced by the Name of a CHARACTER Variable or
Array Element, or an in Line CHARACTER Constant. For example :
CHARACTER * 80

CHR1, CHR2

DOUBLE PRECISION
INTEGER

DX01, DX02
INC1, INC2

READ
READ

( CHR1, 2400, ERR = 850 ) DX01, DX02


( CHR2, 2400, ERR = 860 ) INC1, INC1

will pick the two pairs of Numeric Variables from the CHARACTER
ones, as if those were the Records of some External File. Of course
no advance to the next Record will take place, but in the process
the numbers in Text form are converted to the Binary representation
suitable for any arithmetic (which would fail on CHARACTER Data,
even when containing only Numeric Characters). Data conversion to
or from Numeric (internal) representation to CHARACTER forms the
main use of Internal (File) I/O.
Except for a CHARACTER entity standing for the Unit Specifier, READ
Statements from Internal Files operate and are coded in exactly the
same manner as those for External Files.

132

Fortran Files And I/O (Input/Output) - Part 22


==============================================
- 14/ Output to Files, WRITE Statement :
All Output, that is sending Data from Variables to either External
or Internal Files, is carried out via the WRITE Statement. Like
input (see READ Statement above), Output may be of Formatted, List
Directed or Unformatted Nature.
As on Input, List Directed Output equates to using default Format
Specifiers. The dedicated PRINT Statement plays a role equivalent
to READ *,. It commonly serves in debugging, when inspection of
Variable Values is sought.
External Files subjected to WRITE Statements must be connected to
a Logical I/O Unit beforehand, apart from the Default Output Unit.
Output to External Sequential Access Files writes the new Record at
the End of the File. This means if an existing File was partly read
and gets written to, the end (unread) part gets deleted. The same
applies to Files which are rewound (with REWIND Statements) or when
a Record is sent out and the Position in the File stepped back (via
BACKSPACE) Statements. Such events do not constitute errors. They
will thus not set the IOSTAT Target, or connect to an ERR Label.
Write Statements can fail because of incorrect Data being sent to
a File under Formatted Output, or because of external circumstances.
For instance the Session running the Program may not enjoy write
access to the File as far as the Operating System is concerned, or
the Device the File is stored on might have become full. When errors
arise in WRITE Statements lacking both ERR and IOSTAT Specifiers
Program execution should terminate.

133

Fortran Files And I/O (Input/Output) - Part 23


==============================================
- 14/ Output from File, WRITE Statement (continued) :
Like for READ Statements, the combination of I/O Specifiers in a
WRITE Statement determines the nature of the transfer (Formatted,
Unformatted or List Directed). For Sequential Access Files, each
WRITE Statement produces a new Record. Direct Access File Records
may be written many times in the course of Program execution.
After the I/O Specifiers, the Statement lists the Variables from
which the Values will be sent to the File. The Data must be of
appropriate Type for the Field layout of the corresponding Record.
For instance non Numeric Data cannot be sent into Fields marked as
Numeric in Formatted Output.
When no List of Variables follows the I/O Specifiers, an empty
Record, basically a Line skip, is simply written in Sequential
Files, or the existing Data is cleared off Direct Access Records.
Apart from PRINT ffff, (with ffff a FORMAT Statement Label),
and PRINT *, being used for Default Output as the equivalents to
the simplified Syntax READ ffff, and READ *, respectively, and
the END Specifier not being applicable, the WRITE Statement Syntax
matches that of the READ Statement explained above.
The same similarity with READ Statements extends to Internal File
Output, where in effect Numeric Fields can be converted to Text
Form (and mixed with other CHARACTER Values or Constants). When
the CHARACTER Variable acting as the Internal File turns out too
short for the full Length of the transfer, the tail gets cut off.

134

Fortran Files And I/O (Input/Output) - Part 24


==============================================
- 14/ Output from File, WRITE Statement (continued) :
Examples of External File WRITE and PRINT (WRITE to Default Unit) :
WRITE
1
1
WRITE

( UNIT
FMT
ERR

= 11 ,
= 4000,
= 900 ) DVR1, DVR2, DVR3

( NUOU, 4100, ERR = 910 ) CSTR ( 1 : 200 )

WRITE
1
1
1
1

( 10 ,
ERR = 840 ) ( ( ( DVAR ( IA1,
IA1
IA2
IA3

WRITE

( 10, *, ERR = 420 ) CHS1, CHS2

WRITE

( *, * ) CHS3, CNC1, CHS4, CNC2

PRINT

4100, CSTR ( 1 : 200 )

PRINT

*, DX01, INC1, DX02, INC2

IA2,
= 1,
= 1,
= 1,

IV3 ),
100
)
100
)
100
)

The first two cases use Formatted Output to Sequential Files. The
third example shows Output to an Unformatted File with an Implied
DO Loop. The last two WRITE examples use List Directed Output, as
does the second PRINT Statement.
To implement Internal File Output, the Unit in the WRITE Statement
is replaced by the Name of a CHARACTER Variable or Array Element :
CHARACTER * 80

CHR1, CHR2

DOUBLE PRECISION
INTEGER

DX01, DX02
INC1, INC2

WRITE
WRITE

( CHR1, 2400, ERR = 950 ) DX01, DX02


( CHR2, 2400, ERR = 960 ) INC1, INC1

will send the two pairs of Numeric Variables to the CHARACTER ones,
as if those were the Records of some External File. If the CHARACTER
Variable is later Output to some External File(s), the conversion
overheads will be avoided.

135

Fortran Files And I/O (Input/Output) - Part 25


==============================================
- 15/ External File Repositioning Statements :
For External Files opened for Sequential Access, the current
Position can be adjusted via the BACKSPACE, REWIND and ENDFILE
Statements. In all cases the Statement can be coded in full form
with a Unit, and optional ERR and IOSTAT Specifiers between
Parentheses, or in short form with the Unit Number alone.
BACKSPACE moves the File back one Record. This means a previously
input Record can be read again (possibly with a different FORMAT
Statement and thus layout). An Output Record would be overwritten.
Any Number of BACKSPACE Statements can be executed to move back
more than one Line in the File. Note if this is done and a Record
written, all following Records are lost.
REWIND allows a File to be returned to its initial Position, as
when it was initially opened (with an OPEN Statement). There are
no limits as to how many times a File may be rewound. The Syntax
resembles that of the BACKSPACE Statement.
ENDFILE writes an End of File Marker to the File. When the File
contained Records beyond the current Position, these are lost.
The Syntax resembles that of the BACKSPACE or REWIND Statements.
Example File repositioning Statements :
BACKSPACE
BACKSPACE
BACKSPACE
REWIND
REWIND
REWIND
ENDFILE
ENDFILE
ENDFILE

( UNIT = NUIN, ERR = 970, IOSTAT = IOST )


NUIN
9
( UNIT = NUIN, ERR = 980, IOSTAT = IOST )
NUIN
9
( UNIT = NUIN, ERR = 990, IOSTAT = IOST )
NUIN
9

The first example of each triplet shows the full Syntax, while the
second and third examples show the short form Syntax with Unit only.

136

Fortran Files And I/O (Input/Output) - Part 26


==============================================
- 16/ Formatted Record Layout, FORMAT Statements :
In Formatted I/O, the layout of Records is controlled by the Format
Specifier in READ, WRITE and PRINT Statements. This will either be
an in Line CHARACTER Constant, the Name of a CHARACTER Variable, or
the Label of a FORMAT Statement.
When an in Line Constant is coded, it contains all the Format
Descriptors. If a CHARACTER Variable reference shows instead, that
Variable must contain the Descriptors. Finally when a Label shows,
that should correspond to a FORMAT Statement with the Descriptors
contained therein. The latter will be used in these notes, but the
String of Format Descriptors remains the same under all forms.
The format Descriptor String represents a sequence of Descriptors
detailing all Fields in the Records. When Fields are transferred to
Program Variables or written from them, the Descriptors are called
Data Edit Descriptors. Normally the same number of Edit Descriptors
would be provided as that of Variables transferred.
Data Edit Descriptors tell the Type of Data transferred, Length of
the Field and style convention for Numeric information. The other
Descriptors may send Text or padding Constants or bypass Fields of
no interest, or set the position of the next transfer in the Record.
Apart from verbatim CHARACTER String Descriptors, they may be called
Control Descriptors. Some Descriptors let a transfer to span several
Lines (Records) in the File, or bypass whole Records on Input.
Data Edit Descriptors allow a Field Width to be selected, and for
Floating Point Data, a number of Decimal Digits and sometimes of
Exponent Digits too.
Descriptors of any kind can be bundled in Parentheses and Repetition
factor applied. With early Printers, the First Character of Output
Records served to control Line advance on the Printer. This is no
longer the case as modern Programs are unlikely to send Output
directly to a Printer.
When Values too large to fit in the reserved Space are sent to
Numeric Fields, they will appear filled with Asterisks. Note the
Negative Arithmetic Sign will occupy one Position in the Field.

137

Fortran Files And I/O (Input/Output) - Part 27


==============================================
- 16/ Formatted Record Layout, FORMAT Statements (continued) :
Main Format Edit Descriptors :
Descr.
-----A

Data Type
--------CHARACTER

Description
----------------------------------------Plain A or Aw where w Width.
When no w, Length of Variable used.
When Variable Length over w, Output
cut off after w Chars. but on Input,
last w Chars. to right used. Blank
padding to right when destination
Longer than Source Data.

LOGICAL

Plain L or Lw where w Width.


Internal .TRUE. becomes T,
and .FALSE. becomes F on Output,
with rest of Field Blanked out,
and reverse for Input.

INTEGER

Normally Iw where w Width,


including Arithmetic Sign. Optional
form Iw.d where d minimum Digits,
resulting in eventual Leading Zeros.

Floating
Point

Usually Fw.d, where w Width,


including Sign and d Decimals Digits.
Always written without Exponent,
that is, Fixed Point Notation.

Floating
Point

Usually Dw.d, where w Width,


including Sign and d Decimal Digits,
but in Scientific Notation,
with 2 Digit Exponent after a Sign.

Floating
Point

Same as for D above, or Dw.dEe,


to include a e Digit Exponent.

Floating
Point

Same as for E above,


but resulting in same Output as F,
when Value small enough to fit Field
in Fixed Point Notation.

138

Fortran Files And I/O (Input/Output) - Part 28


==============================================
- 16/ Formatted Record Layout, FORMAT Statements (continued) :
Main Control and String (non Data) Format Descriptors :
Descr.
-----BN
BZ

Description
---------------------------------------------------Set Blank to Null (Spaces of no effect on Numerics).
Set Blank to Zero for Numeric Fields.

SS
SP

No Plus (+) Signs in Positive Numeric Fields.


Plus (+) Signs prepended to Positive Numerics.

Tnn

Next transfer at Position (Byte) nn in Record.

TLnn
TRnn

Next transfer nn places to left of previous.


"
"
nn
"
" right of previous.

Ignore rest of Descriptors when no more Values


sent or received from Program.

Advance one Line in (Sequential) File.

Xnn

Move nn Places or Write nn Blanks.

cc

On Output, write CHARACTER Constant cc verbatim.


Use two consecutive Single Quotes for each Quote
to appear internally in the String.

Hcc

On Output, write nn Byte CHARACTER Constant


immediately following Hnn verbatim (obsolete).
The CHARACTER Constant should not be inside Quotes,
and Internal Quotes should not be doubled up.

139

Fortran Files And I/O (Input/Output) - Part 29


==============================================
- 17/ Formatted Record Layout, FORMAT Statements examples :
For CHARACTER Variables :
CHARACTER * 8
WRITE
1000 FORMAT

CVAR
( 8, 1000 ) CVAR
( A )

Uses the Length of the Variable CVAR, so 8 Bytes, but :


1001 FORMAT

( A16 )

would result in the last 8 (Right Hand) Characters being Input,


or spaces being appended on Output. With the reverse situation :
1002 FORMAT

( A6

The 8 Byte Variable will receive Blank padding on Input,


but on Output the right hand (last) 2 Bytes will get truncated.
For typical Default Unit Messages, with CHARACTER Constants :
WRITE
1100 FORMAT
1
1

( *, 1100 )
( /, Same non Extant File Name keyed,
/,
/, Please try again : )

WRITE
1101 FORMAT

( *, 1101 )
IVAL
( /, Value (, I6, ) not positive )

Presenting Numerical Data with spacing between Fields :


WRITE
1200 FORMAT
WRITE
1201 FORMAT

( *, 1200 ) IREC, DVA1, DVA2, DVA3, DVA4


( 1X, I8, 4 ( 2X, F12.4 ) )
( *, 1201 ) ( DAR1 ( IA ), IA = 1, 200 )
( F12.4, 9 ( 2X, F12.4 ) )

These two examples show Repeat Specifications. In the second case,


where more Values than Data Edit Descriptors are provided, the
available Descriptors will be repeated till no more Data is sent
from the Ouptut Statement.

140

Fortran Files And I/O (Input/Output) - Part 30


==============================================
- 17/ Formatted Record Layout, FORMAT Statements examples (continued) :
For Output beginning at Position 21 in the Records, with then 3
14 Byte Numeric Fields laid as 2 leading Blanks, an eventual Sign,
one Mantissa Digit, the Decimal Point, 4 Decimals, the E Symbol,
a Sign and a 3 Digit exponent to sum up to 14 Bytes) :
WRITE
1300 FORMAT

( 8, 1300 ) DVA1, DVA2, DVA3


( T21, BN, E14.4E3, E14.4E3, E14.4E3 )

When a Numeric Value does not exceed the Maximum which could go
into its Destination Field, but presents too long a Decimal Part,
this will be rounded to the nearest total number of Digits :
DVAX
WRITE
1400 FORMAT

= 34.98765D0
( NUOD, 1400 ) DVAX
( F6.3
)

will result in 34.988 being written to the Field. However, were


the Value to have been over 99.9995, then ****** would show.

141

Fortran Program Units - Part 1


===============================
-

1/ Introduction :
Program Units represent self contained procedures, which may be
processed independently of others. In Fortran, they can be (Main)
Programs, BLOCK DATA Subprograms, Functions or Subroutines. They all
finish with an END Statement.
In the literature, "Routine" commonly stands for executable Units,
that is, any except BLOCK DATA Subprograms. While Main Programs (or
Routines) are started from the Operating System of a computer, other
executable Routines, that is, Functions or Subroutines are invoked,
or "called" from either a Main Routine or another Subprogram.
When a Subprogram is invoked, it gets processed as if it formed part
of the calling Routine. Subprograms, like Main Routines, contain a
Non Executable Part, for Variable declarations, and after that, an
Executable Part where processing takes place. Once that is complete,
the calling Routine resumes control.
BLOCK DATA Subprograms are not invoked by other Program Units. They
serve the sole purpose of initialising Common Block Variables (which
may not appear in DATA Statements elsewhere), and were covered in an
earlier chapter of these notes.
When called, Functions or Subroutines may receive (or get passed)
Arguments which are Variables or Arrays of any Type. Functions will
return a single Value. The Type of that Value defines the Functions
own Type. Subroutine may use some of their Arguments to feed back
information to their calling Routine. Both Functions and Subroutines
may use and alter Variables in Common Blocks.
When passing Arrays and CHARACTER Variables, that is, entities with
a "Size" (for a CHARACTER Variable, its Length), a special mechanism
allows Subprograms to take that Size from the calling Routine.
Fortran provides a large number of "Intrinsic" Functions. They allow
Type conversion, computation of mathematical results like Logarithms
and Trigonometric functions, or searching CHARACTER Strings. Fortran
90 introduced many new Intrinsic Functions.

142

Fortran Program Units - Part 2


===============================
-

2/ Invoking Subprograms :
Subprograms can be invoked, or called, from the Executable Part of
any other Routine in the current execution unit. That is formed by
the Main Program, which must exist and be unique, and any number
of Subprograms, jointly loaded by the Operating System before it
starts the Main Program. BLOCK DATA Subprograms get loaded, but not
executed. They are not called like Executable Routines. They were
covered earlier in these notes and will not be dealt with further.
Like BLOCK DATA Subprograms, Functions and Subroutines must bear a
unique Name, under the same rules as Main Program or Variable Names
(Beginning with a Letter, and including no more than 6 Letters or
Digits in Standard Fortran 77 or 31 in Fortran 90).
A Function is called, by its Name, and eventual Argument List in
Parentheses following, appearing in an Executable Statement. Before
any other processing, control moves to the Function. Once that has
completed, the result is inserted in the calling Statement where the
Functions Name appeared, and the Statement completed.
A Subroutine is always invoked with the CALL Statement. Then control
passes to it. When the Subroutine finishes, execution normally goes
back to the calling Routine at the Statement following the CALL. In
effect, the Subroutines Executable Part could have been expanded in
that of the calling Routine at that point, while the Non Executable
Part would have appeared in the callers.
This ignores the "Alternate Return" mechanism, whereby a Subroutine
can receive specially marked Arguments, representing the Labels of
Statements in the calling Routine where execution can selectively be
transferred at completion of the Subroutine. Thats as if a GOTO in
the Subroutine were branching back into the calling Routine at one
of the Alternate Return Labels. This is not advised in general.
Functions or Subroutines may be started at other positions than the
top by placing ENTRY Statements where required. The Keyword precedes
a Name (different from that of the Routine), which when used to call
the Routine, initiates it at that point in the Code. Arguments in
Parentheses can follow the Name, and need not match those elsewhere.
Use of ENTRY is not encouraged and is not covered in these notes.

143

Fortran Program Units - Part 3


===============================
-

2/ Invoking Subprograms (continued) :


The first Subprogram call must be from the Main program, but nothing
prevents Subprograms then calling other Subprograms before control
returns to the Main Program. However, Subprograms must not invoke
themselves (a process called "Recursion"). Neither can Subprograms
be called in a circular manner, such that later calls are made while
execution of an earlier call is incomplete, implying Recursion.
For example, a valid call sequence could be :
Routine A : Calls Routine B,
Routine B : Calls Routine C,
Routine C completes : Routine B resumes,
Routine B completes : Routine A resumes,
Routine A completes : Caller to A resumes.
But this call sequence would imply Recursion :
Routine A : Calls Routine B,
Routine B : Calls Routine C,
Routine C : Calls Routine A.
When Routine A is invoked for the second time, the first call has
yet to complete. This is not permitted as it breaks the requirement
in Fortran that all Storage (Memory) needs must be known at compile
time. Fortran 90 allows recursion, with the special RECURSIVE Prefix
to the FUNCTION or SUBROUTINE Keyword. Recursion should be used only
if strictly necessary. It is not covered further in these notes.
Functions may call Subroutines or other Functions, and likewise,
Subroutines can invoke Functions or other Subroutines. No set limits
exist as to the overall number of calls in any Routine, to how many
different Routines are present in an execution Unit, or to how many
times a given Routine may be called. The Standards do not specify a
maximum nesting level for Subprogram calls, and for all practical
purposes it can be taken as unlimited.

144

Fortran Program Units - Part 4


===============================
-

3/ Subprogram Structure and Variables :


Subprograms represent self standing procedures. Each Subprogram will
contain a Non Executable Part followed by an Executable Part, as was
described for Main Programs. Likewise Statements fall into one or
the other Part, with no mixing. In effect, Type, Parameter and DATA
Statements must appear before all Executable Statements.
Because they constitute independent units, Subprograms can contain
their own Statement Labels and Variables, available while they run,
but only over their execution.
Any Values assigned to Subprogram internal Variables will be lost at
completion with three exceptions : Parameters constitute Constants
assigned at compilation, Internal Variables may be saved with SAVE
Statements, and the passed Arguments do not actually belong to the
Subprograms but to the calling Routines.
Due to DATA Statements only taking effect once, in Subprograms, the
Variables in DATA Statements will only get initialised the very first
occasion the Subprogram is invoked. Other methods are required if the
same starting Values are needed for Variables over several runs of a
Subprogram, like (Executable Part) direct assignments of (in Line or
Parameter) Constants, or passing the initial Values as Arguments.
No restrictions affect the Names of Variables in Subprograms, apart
from the standard ones (Length of Names, and allowed Characters). As
Subprogram own their own Variable Name space, the Names can match
those in other Routines without causing errors. In storage (Memory),
the entities will remain distinct. Also, Subprograms operate under
their own implicit Variable typing. Any IMPLICIT Statement will only
affect the Variables in the Routines where they appear.
The passed or "call" Arguments from the calling Routine form an
exception to the "local Memory" rule. Memory is not held for them
in Subprograms but in the callers. For their passed Arguments, all
Subprograms use Dummy Names, effectively place holders in the Code.
However, the Arguments must still be declared, under the Dummy Names
which identify them, in all Subprograms (unless Implicitly declared).

145

Fortran Program Units - Part 5


===============================
-

4/ Subprogram Execution and Termination :


Any Executable Statement may be used in a Subprogram. I/O to the
default Units, or to External Files is permitted, even when opened
in other Routines. Likewise, Files read or written to elsewhere may
be opened, closed, rewound or backspaced.
However, Label References only apply to Statements within a Routine,
and references may not be made to Statements outside that Routine.
As mentioned above, Subprograms must feature an END as their last
executable Statement. When END is reached, control returns to the
calling Routine, with loss of all Internal Variable Values, unless
the subject of SAVE Statements. For example :
SAVE VAR1, VAR2, VAR3
would preserve the Values (as at exit from the Routine) of the three
Variables listed, so they would be present the next time the Routine
is invoked from anywhere in the Execution Unit.
However, the RETURN Statement can force completion of a Subprogram
at any stage in the Executable Part. RETURN, like END, leads to loss
of all Internal Variable data.
As mentioned already, Subroutines may pick the point in the calling
Routine where execution resumes by the inclusion of Alternate Return
Arguments and appending a Return Index to RETURN Statements. Refer
to the notes on Subroutines below for details.
STOP Statements may be coded in Subprograms, with the same effect as
in Main Programs of causing immediate termination of the whole Unit,
Main Program included. When an Integer or CHARACTER Constant (in
Single Quotes follows the STOP Keyword, it gets reproduced (less the
Quotes) on the Default Output Unit (usually a Terminal).

146

Fortran Program Units - Part 6


===============================
-

5/ Function Subprograms :
Function Subprograms represent "Many to One" mappings, such that a
single Value is always returned. The Type of that Value defines that
of the Function. When no Type is specified, it is inferred from the
Implicit Name rule applying to Variables (by default, INTEGER when
starting with a Letter between I and N, REAL otherwise).
Functions should be used when lengthy computations of a Value take
place repeatedly, possibly in several places in an executable Unit,
or when such long calculations are to appear in many Programs.
The Keyword FUNCTION marks the beginning of a Function Subprogram.
It can be preceded by the Functions Type. It must be followed by
the Functions Name, and then a Pair of Parentheses. Inside these,
a list of comma separated Argument Names may optionally appear.
Argument Names in a FUNCTION Statement are commonly called "Dummy"
Arguments for they represent place holders for the Actual Arguments
presented when the Function is invoked. The Dummy Arguments are in
some manuals described as "Formal".
Example FUNCTION Statements :
CHARACTER * 12

FUNCTION

CHARF1 ( CAR1, CAR2 )

DOUBLE PRECISION

FUNCTION

RANGEN ( )

FUNCTION

AVRAGE ( SAMPLE )

The first example present a Function returning a 12 Byte CHARACTER


Variable, and expecting 2 Arguments. The second case sends back a
DOUBLE PRECISION result, but receives no Arguments, while the third,
gets the Type of its Value imputed from the first Letter A and
expects one Argument.
While the Functions Type is established by the FUNCTION Statement,
those of the Arguments are set by ordinary Type Statements against
the Dummy Names in the Functions Non Executable Part.

147

Fortran Program Units - Part 7


===============================
-

5/ Function Subprograms (continued) :


In their calling Routines, Functions are invoked by simply entering
their Names and list of Actual Arguments in Expressions. They cannot
appear as the Targets of assignments (in effect always being part of
the Source). For example, for the earlier FUNCTION Statements :
CHARACTER * 12

CST1, CST2, CRS1

DOUBLE PRECISION

DATSAM

CRS1

= CHARF1 ( CST1,

SMAV

= AVRAGE ( DATSAM )

( 100 ), SMAV
CST2 )

the first call invokes CHARF1 with the Actual Arguments CST1
and CST2 replacing the CAR1 and CAR2 Dummies, and the second
call puts the result of AVRAGE with Argument DATSAM into SMAV.
Distinct from Subprogram Functions, special single Line "Statement
Function" may be coded as part of any Routine. They do not make up
Subprograms as they appear inside other Routines, and cannot be
invoked outside them. Their use avoids repeated coding of the same,
possibly long Expressions.
Statement Functions take the form of the Functions Name and any
comma separated Arguments in Parentheses, followed by an Equal Sign
and an Expression computing the Function Value. The Arguments need
not be of the same Type as the Result. For example :
IMPLICIT

DOUBLE PRECISION ( A, B, X-Z )

AVG3 ( I1, I2, I3 ) = ( DBLE ( I1 + I2 + I3 ) / 3.0D0 )


this computes the DOUBLE PRECISION average of three INTEGER Values,
which would be inserted in Expressions where the Name AVG3 shows :
XX

= ( YY + ZZ + AVG3 ( J1, J2, J3 ) )

would have equated to writing ( DBLE ( J1 + J2 + J3 ) / 3.0D0 )


where the reference to AVG3 shows in the above assignment to XX.

148

Fortran Program Units - Part 8


===============================
-

6/ Subroutine Subprograms :
Subroutine Subprograms represent "Many to many" mappings, such that
any number of Values, including Arrays may be made available to the
calling Routine after a Subroutine has completed. Unlike Functions,
Subroutines do not get attached a Type.
Subroutines may be used when lengthy computations happen repeatedly,
possibly in several places in an executable Unit, or when such long
processing is to appear in many Programs. But, they can also serve
to modularise Code, even when no computational gain accrues (may be
the contrary) as against monolithic coding.
Subroutine Subprograms begin with the SUBROUTINE Statement.
The SUBROUTINE Keyword must be followed by the Routines Name, and
optionally a Pair of Parentheses. Inside these, an optional list of
comma separated Argument Names may appear. Parentheses must be used
when any Argument Names show.
as was the case for Functions, Arguments in a SUBROUTINE Statement
are often called "Dummy" Argument Names for they form place holders
for the Actual Arguments given when the Subroutine is invoked. Dummy
Arguments are sometimes described as "Formal".
The Type of the Dummy Arguments are set by ordinary Type Statements
against the Dummy Names in the Non Executable Part of the Subroutine.
Unlike those of Functions, Subroutine Arguments serve for two way
communication with calling a Routine. They can provide data at call
time, and their exit or end Values may be used by a calling Routine
when it resumes control after the Subroutine has completed.
Example SUBROUTINE Statements :
SUBROUTINE

CHSUB1 ( CAR1, CAR2, CAR3 )

SUBROUTINE

CHSUB2 ( )

SUBROUTINE

CHSUB3

The first example present a Subroutine called CHSUB1 with three


Arguments, CAR1, CAR2 and CAR3. The last two examples show the
two ways of coding SUBROUTINE Statements when no Arguments are used.

149

Fortran Program Units - Part 9


===============================
-

6/ Subroutine Subprograms (continued) :


In their calling Routines, CALL Statements are required to launch
Subroutines, with the Keyword followed by the Subroutine Name and
eventual list of Actual Arguments. Subroutine calls cannot show in
Expressions, or assignments.
For example, for the earlier SUBROUTINE Statements :
CHARACTER * 24

CSR1, CSR2, CSR3

CALL

CHSUB1 ( CSR1, CSR2, CSR3 )

CALL

CHSUB2 ( )

the first call invokes CHSUB1 with CSR1, CSR2 and CSR3 in
for the CAR1, CAR2 and CAR3 Dummies, and the second example
merely needs the Subroutine Name as it features no Arguments. Note
the Parentheses become optional in such a case.
Also note no ways exist to differentiate between Arguments acting
to pass and those used to receive Values. The Values of any Argument
may be changed in a Subroutine. The Types of the Actual Arguments
should match those of the Dummy Arguments, and in Fortran 77, all
Arguments listed are compulsory.
Fortran 90 introduced the INTENT Attribute to tell whether an
Argument was Input or Output (changed in the Subroutine), and also
an OPTIONAL Attribute so some Arguments can be omitted. These do
require Free Form declarations of the Arguments however.
Fortran 90 allows nested Subprograms, with the CONTAINS Statement
as a marker in Routines where such Functions or Subroutines appear.
CONTAINS must immediately precede one or more Internal Subprograms.

150

Fortran Program Units - Part 10


===============================
-

6/ Subroutine Subprograms (continued) :


In addition to completion with END, plain RETURN or STOP Statements,
Subroutines may be ended with the specification of Alternate Return
Points. For each Alternate Return, a special Asterisk (*) marker
Argument must show in the list with the SUBROUTINE Statement.
When Alternate Return (Arguments) are available, RETURN Statements
can be followed by an Integer Constant or Variable, to select an
Alternate Return by its place in the list. The list begins at 1,
and the Integer Constant or Variable should not exceed the total
number of Alternate Returns (Asterisk Arguments).
For example, this Subroutine :
SUBROUTINE TSTALT ( ARG1, ARG2, *, *, * )
allows three alternate Returns, as per the Asterisks after the two
Dummy Arguments ARG1 and ARG2. A Return to the second alternate
could be coded as one of :
RETURN 2
RETURN IALT
where the Variable IALT had been assigned the Value 2.
In the calling Routine, the Asterisks of the SUBROUTINE Statement
are replaced by the Labels of the Statements where the Alternate
returns are intended to go. For example, with the above Routine :
CALL

TSTALT ( DPA1, DPA2, 100, 200, 300 )

would invoke TSTALT with the Variables (or Arrays) DPA1, DPA2,
and the Labels 100, 200 and 300 as places in the code where
Returns could be made, on top of the Statement following the CALL,
used upon a plain END, or RETURN. The RETURN 2 above would thus
restart the callers execution at the Statement labelled 200.
Just like ENTRY Statements, Alternate Returns should be avoided.

151

Fortran Program Units - Part 11


===============================
-

7/ Assumed Size Arrays and CHARACTER Variables :


When Arrays of any Data Type are passed as Arguments to Subprograms,
the corresponding Dummy Arguments may appear (in that Subprogram)
with the Upper Bound of the Last Dimension defaulted. An Asterisk
(*) in this position indicates an "Assumed Size" Array, where the
Size in the last Dimension is taken from the calling Routine. For
example, with, in the calling Routine :
DOUBLE PRECISION
1
CALL

DATSM1 ( 100 )
DATSM2 ( 100, 100, 20 )
AVRAGE ( DATSM1 )

the SUBROUTINE Statement and Argument declaration could equally be :


SUBROUTINE

AVRAGE ( SAMRRY )

DOUBLE PRECISION

SAMRRY ( 100 )

or, using an Assumed Size Array for the Argument SAMRRY :


SUBROUTINE

AVRAGE ( SAMRRY )

DOUBLE PRECISION

SAMRRY ( * )

With more than one Dimension, only the last one, that is, the right
hand end of the list, can be defaulted like this. So, for instance :
SUBROUTINE

MDSTAT ( MDSMRY )

DOUBLE PRECISION

MDSMRY ( 100, 100, * )

Would be possible (and advised), but not :


DOUBLE PRECISION

MDSMRY ( *, *, * )

which should produce a compilation error.

152

Fortran Program Units - Part 12


===============================
-

7/ Assumed Size Arrays and CHARACTER Variables (continued) :


The Lengths of CHARACTER Type Dummy Arguments may also be entered as
Asterisks (*) in Subprograms, to give "Assumed Length" Variables.
For example, for one of the earlier SUBROUTINE calls :
CHARACTER * 24

CSR1, CSR2, CSR3

CALL

CHSUB1 ( CSR1, CSR2, CSR3 )

the Subroutine could present either form of declarations :


CHARACTER * (*)

CAR1, CAR2, CAR3

CHARACTER

CAR1 * (*), CAR2 * (*), CAR3 * (*)

Functions may specify Assumed Length CHARACTER results, where the


Length of the receiving Value in the calling Routine will apply :
CHARACTER * (*)

FUNCTION CHRFNC ( CAR1, CAR2 )

Assumed Length CHARACTER Arrays are permitted, for example :


CHARACTER * 24

CSA1 ( 100, 50 )

CALL

CHSUB2 ( CSA1

SUBROUTINE

CHSUB2 ( CSA1

CHARACTER * (*)

CSA1 ( 100, *

With CHARACTER Type Arguments, the Length of an Actual Argument may


exceed that declared for a Dummy Argument. In that case, the part
of the Actual Argument in excess of the Dummy gets dropped. Dummy
CHARACTER Arguments cannot exceed the Length of Actual Arguments.
With Arrays, this applies, but to the whole Array, such that the
overall Array times Element Size product in a Subprogram cannot be
greater than the equivalent Length in the calling Routine.

153

Fortran Program Units - Part 13


===============================
-

8/ Function Subprogram example :


The following small Program requests and verifies three INTEGER
Values as seeds for a Pseudo Random Number Generator Function :
PROGRAM TTRAND
CCCC
CCCC

PROGRAM TO SHOW RANDOM NUMBER, OFF WICHMANN HILL FUNCTION.


PROGRAM CONFORMS TO A.N.S.I. 1978 FORTRAN 77 STANDARD.

CCCC

RANDOM 0-1 NUMBER AND GENERATION INTEGER SEEDS.


DOUBLE

PRECISION RNTEST

INTEGER NSD1, NSD2, NSD3, NSTT


CCCC

EXECUTABLE PART, REQUEST THREE INTEGER SEEDS.

100 WRITE
1000 FORMAT

( *, 1000 )
( /, Enter 3 Random Seeds or 0 0 0 to exit )

READ

( *, *, IOSTAT = NSTT ) NSD1, NSD2, NSD3

IF

( NSTT

.NE.

WRITE
FORMAT
GOTO

( *,
( /,
100

1002

0 ) THEN
1002 )
Not an Integer. Try again )

ENDIF
IF
1
1
CCCC
CCCC

( ( NSD1 .EQ. 0 ) .AND.


( NSD2 .EQ. 0 ) .AND.
( NSD3 .EQ. 0 ) )
STOP

COMPUTE AND DISPLAY 0-1 WICHMANN HILL RANDOM NUMBER, THEN


BRANCH BACK FOR OTHER SEEDS OR EXIT FROM SEED ENTRY LOOP.
RNTEST

WRITE
2000 FORMAT
GOTO

= FNDUWH

( NSD1, NSD2, NSD3 )

( *, 2000 ) RNTEST
( /, 0-1 Random Uniform Number = , F12.10 )
100

END

154

Fortran Program Units - Part 14


===============================
-

8/ Function Subprogram example (continued) :


Example Function Subprogram as called by above Program :
DOUBLE PRECISION

FUNCTION FNDUWH ( NSD1, NSD2, NSD3 )

CCCC

FUNCTION TO GENERATE RANDOM NUMBER - WICHMANN HILL

CCCC
CCCC
CCCC
CCCC

FUNCTION COMPUTES PSEUDO RANDOM NUMBER IN 0-1 RANGE (UNDER


UNIFORM DISTRIBUTION) BASED ON WICHMANN - HILL ALGORITHM.
THIS REQUIRES THREE INTEGER SEEDS (ARGUMENTS 1, 2 AND 3),
WHICH MAY BE RESULTS FROM PREVIOUS RUN LEFT IN PLACE).

CCCC

NON EXECUTABLE PART.

CCCC

PASSED AND LOCAL CONGRUENTIAL INTEGER SEEDS.


INTEGER NSD1, NSD2, NSD3,
1
ISD1, ISD2, ISD3

CCCC

EXECUTABLE PART.

CCCC
CCCC

COMPUTE CONGRUENTIAL PSEUDO RANDOM INTEGER NUMBERS,


ASSIGNING LOCAL VALUES FROM PASSED INPUT SEEDS.

100 ISD1
ISD2
ISD3
CCCC

= MOD
= MOD
= MOD

( ( NSD1 *
( ( NSD2 *
( ( NSD3 *

171 ),
172 ),
170 ),

30269 )
30307 )
30323 )

RESET ANY NEGATIVE SEEDS TO POSITIVE VALUE.


IF
IF
IF

CCCC
CCCC
CCCC

( ISD1
( ISD2
( ISD3

.LT.
.LT.
.LT.

0 ) ISD1
0 ) ISD2
0 ) ISD3

= -ISD1
= -ISD2
= -ISD3

GET ZERO TO ONE DOUBLE PREC. PSEUDO RANDOM RESULT,


CONVERTING ABOVE INTEGERS TO ZERO TO ONE RANGE,
SUMMING THEM UP AND KEEPING ONLY DECIMAL PART.
FNDUWH
1
1

= MOD ( ( ( DBLE ( ISD1 ) / 30269.0 D0 )


+ ( DBLE ( ISD2 ) / 30307.0 D0 )
+ ( DBLE ( ISD3 ) / 30323.0 D0 ) ), 1.0 D0 )

END

155

Fortran Program Units - Part 15


===============================
-

9/ Subroutine Subprogram example :


Amending the Program example presented earlier in the notes to do
the computation of Pentagonal Numbers in a Subroutine could give :
PROGRAM CLPTSB
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC

PROGRAM COMPUTES PENTAGONAL NUMBER FOR INDEX ENTERED BY USER,


AND NEXT 3 (PENTAGONAL FOR N = ( ( 3 N ** 2 - N ) / 2 ).
PROGRAM INVOKES SUBROUTINE SBPENT TO COMPUTE RESULTS.
PROGRAM CONFORMS TO A.N.S.I. 1978 FORTRAN 77 STANDARD.

CCCC

INDEX, INPUT STATUS AND PENTAGONAL NUMBER ARRAY.


INTEGER NPINDX, NPSTAT, NPENTG ( 4 ), IP

CCCC

EXECUTABLE PART, REQUEST STARTING INDEX ENTRY.

100 WRITE
1000 FORMAT

( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )

READ
1001 FORMAT

( *, 1001, IOSTAT = NPSTAT ) NPINDX


( I80
)

IF

( NPSTAT
WRITE
FORMAT
GOTO

1002

.NE.

( *,
( /,
100

0 ) THEN
1002 )
Not an Integer. Try again )

ENDIF
CCCC

COMPUTE PENTAGONAL NUMBERS FROM INDEX AND SHOW THEM.


CALL

SBPENT ( NPINDX, NPENTG, NPSTAT )

IF

( NPSTAT

WRITE
1
2000 FORMAT
1
END

.NE.

0 ) GOTO 100

( *, 2000 ) NPINDX,
( NPENTG ( IP ), IP = 1, 4 )
( /, Pentagonal Numbers from Index , I6, :, /,
/, 4 ( I8, 1X )
)

156

Fortran Program Units - Part 16


===============================
-

9/ Subroutine Subprogram example (continued) :


Example Subroutine Subprogram as called by above Program :
SUBROUTINE SBPENT ( INDX, IPNT, ICDE )
CCCC
CCCC
CCCC
CCCC

ROUTINE COMPUTES PENTAGONAL NUMBER FOR PASSED INDEX,


AND NEXT 3 (PENTAGONAL FOR N = ( ( 3 N ** 2 - N ) / 2 ).
ROUTINE CONFORMS TO A.N.S.I. 1978 FORTRAN 77 STANDARD.

CCCC

NON EXECUTABLE PART (DATA DECLARATIONS).

CCCC

INDEX, INPUT STATUS AND FOUR PENTAGONAL NUMBERS.


INTEGER INDX, IPNT ( 4 ), IP

CCCC

EXECUTABLE PART, CHECK INDEX, RET. CODE 1 WHEN NOT.


IF

1000

( INDX .LT. 1

) THEN

ICDE

= 1

WRITE

( *, 1000 ) INDX

FORMAT ( Index Number (, I4, ) below 1 invalid )


RETURN
ENDIF

CCCC

COMPUTE PENTAGONAL NUMBERS FROM INDEX AND SHOW THEM.


DO

200

IP = 1, 4

IPNT ( IP ) = ( ( 3 * INDX ** 2 - INDX ) / 2 )


INDX
= ( INDX + 1
)
200 CONTINUE
ICDE

= 0

END

157

Fortran Program Units - Part 17


===============================
- 10/ Intrinsic Functions :
Fortran provides many Intrinsic Functions. These support :
Type Conversion between the Numeric Types,
CHARACTER String scans (for a given other String), Length,
and Individual Character position in the Collating Sequence,
Mathematical results, like Absolute Values, Logarithms,
Trigonometric and Hyperbolic Functions, Complex Conjugate,
INTEGER Moduli, Sign inversion, Maximum and Minimum Values,
Nearest Integer, Truncation (Round down to INTEGER below).
Intrinsic Functions may be invoked anywhere a Function may be,
which means in any Expression where entities of the Type produced
by the Function are valid. Several Intrinsic Function references
can appear in an Expression, and they can be mixed with External
Function references. For example :
NPOS = INDEX ( CSTR, abc )
DLSM = ( LOG ( ABS ( D1 ) ) + LOG ( ABS ( D2 ) ) )
respectively obtain the position of the String abc in CSTR,
which must be a CHARACTER Variable, returning Zero when not found,
and compute the Sum of two Natural Logarithms, ensuring Arguments
to the LOG Function are positive.
The Functions dealing with Numerical Variables which may be of
several Types (like Positive Difference, or Absolute Values) bear
a Generic Name, and also one Specific to the Data Type of the
Arguments. The Specific Name may be used directly, but only with
Arguments of the appropriate Type. When the Generic Name is used,
the correct Function is called at run time.
Implementation manuals as well as all general texts will list the
Intrinsic Functions, with Generic and Specific Names, and expected
Arguments with their Type. A Generic list is presented below.
Fortran 90 expanded the set of Intrinsic Functions to handle Bit
strings, Array Aggregates, and provide several additional numeric
and CHARACTER Utilities.

158

Fortran Program Units - Part 18


===============================
- 11/ Selected Intrinsic Functions :
CHARACTER String handling Functions :
Name
-----CHAR

Result
--------CHARACTER

Arguments and Description


----------------------------------------Returns Character in Collating Sequence
at Position given by INTEGER Argument.

ICHAR

INTEGER

Returns Position in Collating Sequence


of Single Character passed as Argument.

INDEX

CHARACTER

Returns (first) Position in Argument 1


where Argument 2 found, or Zero when not.
Both Arguments must be CHARACTER.

LEN

INTEGER

Returns declared Length of Argument,


which must be of Type CHARACTER.

Numeric Data Conversion Functions :


Name
-----CMPLX

Result
--------COMPLEX

Arguments and Description


----------------------------------------When 1 INTEGER or Floating Point Argument
that becomes Real Part of Result,
When 2 non COMPLEX Arguments,
form Real and Imaginary Parts of Result,
When 1 COMPLEX Argument Result same.

DBLE

DOUBLE
PRECISION

Convert Argument to DOUBLE PRECISION,


using Real Part when Argument COMPLEX.

FLOAT

REAL

Convert single INTEGER Argument to REAL.

INT

INTEGER

Convert single Argument to INTEGER,


by truncation of Decimal part.
Uses Real Part when Argument COMPLEX.

REAL

REAL

Convert single Argument to REAL,


using Real Part when Argument COMPLEX.

159

Fortran Program Units - Part 19


===============================
- 11/ Selected Intrinsic Functions (continued) :
Numeric General Purpose (Generic) Functions :
Name
-----ABS

Result
--------Same as
Argument

Arguments and Description


----------------------------------------Absolute Value of single Numeric Argument
using Real Part of COMPLEX Type Value.

AINT

Same as
Argument

Truncation to largest Integer Value


in single Floating Point Argument.

CONJG

COMPLEX

Gives Conjugate of COMPLEX Argument,


that is, flips Imaginary Part Sign.

DIM

Same as
Args.

Gives Positive Difference


between Numeric Arguments 1 and 2,
being Zero when Argument 2 largest.

IMAG

REAL

Gives Imaginary Part


of single COMPLEX Argument.

MAX

Same as
Args.

Maximum in List of Numeric Arguments,


which must be of same Type.

MIN

Same as
Args.

Minimum in List of Numeric Arguments,


which must be of same Type.

MOD

Same as
Args.

Remainder under Division (Modulus)


of Argument 1 by Argument 2.

NINT

Same as
Argument

Nearest Integer in Numeric Argument,


which must be Floating Point.

SIGN

Same as
Argument

Arithmetic Sign Transfer,


from Argument 2 to Argument 1.

SQRT

Same as
Argument

Gives Square Root


of single Numeric Argument.

160

Fortran Program Units - Part 20


===============================
- 11/ Selected Intrinsic Functions (continued) :
Numeric Exponential and Trigonometric Functions :
Apart from the "Arc" Inverse Trigonometric Functions,
all the Functions below accept COMPLEX Type Arguments.
Name
-----ACOS

Result
--------Same as
Argument

Arguments and Description


----------------------------------------Gives ArcCosine in Radians
of single Numeric Argument.

ASIN

Same as
Argument

Gives ArcSine in Radians


of single Numeric Argument.

ATAN

Same as
Argument

Gives ArcTangent in Radians


of single Numeric Argument.

COS

Same as
Argument

Gives Cosine
of single Numeric Argument (in Radians).

COSH

Same as
Argument

Gives Hyperbolic Cosine


of single Numeric Argument.

EXP

Same as
Argument

Gives Exponential ("e ** Argument"),


of single Numeric Argument.

LOG

Same as
Argument

Gives Base "e" (Natural) Logarithm


of single Floating Point Argument.

LOG10

Same as
Argument

Gives Base 10 (Decimal) Logarithm


of single Floating Point Argument.

SIN

Same as
Argument

Gives Sine
of single Numeric Argument (in Radians).

SINH

Same as
Argument

Gives Hyperbolic Sine


of single Numeric Argument.

TAN

Same as
Argument

Gives Tangent (Sine / Cosine)


of single Numeric Argument (in Radians).

TANH

Same as
Argument

Gives Hyperbolic Tangent


of single Numeric Argument.

161

Fortran Program Units - Part 21


===============================
- 12/ Selected Intrinsic Functions New in Fortran 90 :
Many of the new Array Intrinsic Functions were seen in the earlier
chapters. New Character String, Bit Field and utility Functions came
in too. The main non Array new Functions are listed below :
Name
-------ADJUSTL

Result
--------CHARACTER

Arguments and Description


----------------------------------------Moves non Blank Data in String to Left,
with Blanks inserted to the Right.

ADJUSTR

CHARACTER

Moves non Blank Data in String to Right


with Blanks inserted to the Left.

BIT_SIZE

INTEGER

Gives Total 1 Bits in (INTEGER) Field.

BTEST

LOGICAL

When Bit at Position in Argument 2 Set,


in INTEGER Arg. 1, returns .TRUE..

EPSILON

Floating
Point

Difference between 1 and next number


which can be represented in Type.

IAND
IEOR
IOR

INTEGER

Perform Logical "And", "Exclusive Or",


and "Or" between INTEGER Args. 1 and 2,
when treated as Bit Fields.

IBCLR
IBSET

INTEGER

Give 1 when Bit at Position in Arg. 2


respectively clear or set in Argument 1.

NOT

INTEGER

Complements (Flips) all Bits in Arg.

SCAN

INTEGER

Tells first Position of any Character


from Arg. 2 found in String in Arg. 1,
from Left, or Right with BACK Arg. 3.

TRIM

CHARACTER

Removes Trailing Blanks from String.

VERIFY

INTEGER

Inverse of SCAN,
Position of first Char. not in String.

An Intrinsic Subroutine DATE_AND_TIME ( DT, TM, ZN, VL ), gives


in CHARACTER Strings a CCYYMMDD, HHMMSS.SS, SHHMM Date, and in
the INTEGER Array VL 8 Date entities. A RANDOM_NUMBER Subroutine
sets a Uniformly Distributed (Zero to One) Random Number.

162

Fortran Program Units - Part 22


===============================
- 13/ Subprograms as Call Arguments :
Subprogram Names may be used as Arguments when calling (different)
Subprograms with the EXTERNAL Statement. This also allows any of
the Intrinsic Functions to be replaced by custom Subprograms. When
Functions are involved, Type Statements should also declare the
Name, which will otherwise be implicitly typed.
For example, invoking Subprograms with External Arguments :
EXTERNAL

EXSUB1, EXFNC1

DOUBLE PRECISION

EXFNC1, DPARG1, DPLOC1, DPLOC2

CALL

DPSUB2

DPLOC2

= EXFNC1 ( DPLOC1 )

( DPARG1, EXSUB1 )

requires the corresponding Subprogram Statements :


SUBROUTINE

DPSUB2 ( ARG1, SUB1 )

EXTERNAL

SUB1

DOUBLE PRECISION

ARG1

so that the Subprogram EXSUB1, when passed to the Dummy SUB1


Argument will be called every time a CALL against SUB1 appears
in the (DPSUB2) Subroutine.
When Intrinsic Function Names are to be passed as (Actual) Arguments
to Subprograms, they should appear with INTRINSIC Statements. So :
INTRINSIC

COS, SIN, TAN

allows the Cosine, Sine and Tangent Intrinsic Function Names to be


listed as Arguments when Subprograms are called, as was shown above
for External (custom) Subprograms.
Names may not appear with both EXTERNAL and INTRINSIC Statements.

163

Fortran Program Example - Part 1


=================================
-

1/ Introduction :
The following Program illustrate more typical "Production" Code than
the earlier examples in terms of both size and scope. The Code takes
just over 1150 Lines, including about 380 spacers, 350 Comments, and
420 Lines of actual Code, split into 300 Statements, of which about
100 feature Continuations over one or more extra Lines.
Some Programs will easily exceed the above figures, while proving
hard to divide into smaller execution Units. However, in most cases,
only a small portion of the Code carries out most of the processing.
In the example below, initial Comments describing the processing
fill 140 Lines. The Non Executable Part then takes just under 200
Lines. Another 520 Lines represent initial Parameter checks. The
actual Data handling fills only 170 Lines. 170 more Lines contain
error exit messages and file handling.
The example Program executes a reformatting task, without numerical
work. If performance was to prove an issue, I/O efficiency should be
improved, possibly by reading and writing Data in larger portions.
Also, if the Output were to be fed into numerical processes, it may
be written in Binary, Unformatted fashion.
The example Program is written in strict ANSI Fortran 77. It calls
no Subroutines or non Intrinsic Functions, but requires a Control
Parameters and a Data Input File to operate.
The Code for the Program is shown in full, then samples of typical
Input Files and the resulting Output, including the Report produced
when the Program is submitted. Observations and a discussion about
the way the Code was written follow. Finally a few general (Fortran)
programming guidelines are presented.

164

Fortran Program Example - Part 2


=================================
-

2/ Example Program Source Code :

PROGRAM SPLRFB
C***********************************************************************
CCCC SIEMENS BATCH SPL COMPLEX DATA INPUT AND REFORMAT
C----------------------------------------------------------------------CCCC PROGRAM READS IN BLOCKS OF COMPLEX DATA ITEMS,
CCCC AS PRODUCED BY SIEMENS SPL PULSE PROGRAM sp_dump COMMAND,
CCCC AND REWRITES THEM IN MATRIX FORMAT, WITHOUT ITEM INDEXES.
CCCC
CCCC SPL WRITES DATA IN BLOCKS, EACH A ONE DIMENSIONAL ARRAY,
CCCC OF COMPLEX ITEMS, EACH LINE IN BLOCK HOLDING FOUR OF THEM,
CCCC THUS EIGHT VALUES, AFTER AN OFFSET NUMBER FOR FIRST ITEM.
CCCC HEADER AND TRAILER LINES SURROUND EACH BLOCKS DATA LINES.
CCCC LINES NOT PART OF sp_dump BLOCKS MAY SHOW IN INPUT FILE.
CCCC THESE ARE IGNORED BY PROGRAM, WHICH SPOTS sp_dump BLOCKS,
CCCC BY THEIR DATA DESCRIPTION (FIRST) HEADER LINE.
CCCC THIS BEGINS WITH A sp_dump> /source FLAG STRING.
CCCC
CCCC OUTPUT DATA PRODUCED IN ONE LINE PER INPUT BLOCK FORM,
CCCC IN EITHER ASCII TEXT OR BINARY (UNFORMATTED) FORM.
CCCC TO ALLOW EVENTUAL PROCESSING IN STANDARD PACKAGES,
CCCC AND MINIMUM PROGRAM (ARRAY) MEMORY REQUIREMENTS.
CCCC USER ENTERED BLOCKS TOTAL DEFINES NUMBER OF BLOCK PICKED,
CCCC OFF INPUT, AND WRITTEN OUT, AS LINES OF OUTPUT FILE.
CCCC
CCCC DESIRED FILES AND OPTIONS GIVEN BY CONTROL FILE ENTRIES,
CCCC ALL OF WHICH MAY BE DEFAULTED DEFAULTS AND ARE VALIDATED.
C----------------------------------------------------------------------CCCC COPYRIGHT : UNIVERSITY OF CAMBRIDGE, SEPTEMBER 2000.
C-----------------------------------------------------------------------

165

Fortran Program Example - Part 3


=================================
C----------------------------------------------------------------------CCCC PROGRAM FILES :
CCCC
CCCC
- 1/ CONTROL DATA INPUT : NAME
IN VARIABLE CCFN,
CCCC
UNIT

NUCN,
CCCC
DEFAULT NAME : PARM. CCDN,
CCCC
UNIT : 3
).
CCCC
CCCC
- 2/ SPL DATA INPUT
: NAME
IN VARIABLE CIFN,
CCCC
UNIT

NUIN,
CCCC
DEFAULT NAME : PARM. CIDN,
CCCC
UNIT : 8
).
CCCC
CCCC
- 3/ OUTPUT DATA
: NAME
IN VARIABLE COFN,
CCCC
UNIT

NUON,
CCCC
DEFAULT NAME : PARM. CODN,
CCCC
UNIT : 9
).
CCCC
CCCC REPORTS :
CCCC
CCCC
- 1/ PROGRAM LOG
: NORMAL, ERROR, ABORT MESSAGES,
CCCC
ON DEFAULT OUTPUT UNIT
CCCC
(UNIT 6 IN MVS, OR UNIX).
CCCC
CCCC PROGRAM OPTIONS (PART OF CONTROL PARAMETERS) :
CCCC
CCCC
- 1/ DATA BLOCKS INPUT : TOTAL BLOCKS TO PROCESS,
CCCC
FROM SPL DATA INPUT FILE,
CCCC
AND OUTPUT DATA FILE LINES.
CCCC
CCCC
- 2/ DATA BLOCK SIZE
: TOTAL ITEMS PER SPL DATA BLOCK,
CCCC
AND PER LINE IN OUTPUT FILE,
CCCC
EACH ITEM A 2 PART COMPLEX.
CCCC
CCCC
- 3/ OUTPUT FORMAT
: COMPLEX NUMBER TYPE FORMATTING,
CCCC
WITH COMMA BETWEEN PARTS,
CCCC
AND BOTH INSIDE BRACKETS,
CCCC
OR VALUES CONCATENATED ON LINE,
CCCC
REPRESENTING ONE INPUT BLOCK.
C-----------------------------------------------------------------------

166

Fortran Program Example - Part 4


=================================
C----------------------------------------------------------------------CCCC RESTRICTIONS :
CCCC
CCCC
- 1/ INPUT DATA OBSERVATIONS IN CONSTANT SIZE FIELDS,
CCCC
AS PER VALUE OF NILN PARAMETER BELOW.
CCCC
CCCC
- 2/ DOUBLE PRECISION TYPE FOR ALL DECIMAL VARIABLES,
CCCC
INCLUDING COMPLEX NUMBER REAL AND IMAGINARY PARTS.
CCCC
CCCC
- 3/ INPUT AND OUTPUT INDIVIDUAL DATA VALUES
CCCC
OF SAME TYPE (DOUBLE PRECISION) AND FORMAT,
CCCC
AS PER 1/ ABOVE, WITH 5 DECIMAL DIGITS.
CCCC
CCCC
- 4/ MAXIMUM DATA BLOCKS AND ITEMS PER BLOCK,
CCCC
AS PER VALUE OF NDMX PARAMETER BELOW.
C----------------------------------------------------------------------C----------------------------------------------------------------------CCCC TO RUN ON MVS (VS FORTRAN) :
CCCC
CCCC
- 1/ SET J.C.L. FILE TO RUN COMPILED LOAD MODULE,
CCCC
WITH FT06F001 DD LINE FOR DEFAULT OUTPUT,
CCCC
AND DD STATEMENTS FOR ABOVE PROGRAM FILES.
CCCC
CCCC
- 2/ SUBMIT ABOVE J.C.L. FILE.
CCCC
CCCC TO RUN ON UNIX :
CCCC
CCCC
- 1/ INVOKE LOAD MODULE (NEEDS EXECUTE PERMISSION).
CCCC
THEN ENTER CONTROL FILE NAME WHEN PROMPTED.
CCCC
CCCC
- 2/ ALTERNATIVELY, TO RUN LOAD MODULE module,
CCCC
ENTER :
echo "control_name" | module
CCCC
WHERE control_file CONTROL DATA FILE NAME.
CCCC
CCCC TO RUN ON PC (DOS OPERATING SYSTEM) :
CCCC
CCCC
- 1/ INVOKE LOAD MODULE (NEEDS .EXE EXTENSION),
CCCC
THEN ENTER CONTROL FILE NAME WHEN PROMPTED.
CCCC
CCCC
- 2/ AS PER UNIX INSTRUCTIONS.
CCCC
CCCC NOTE :
CCCC
CCCC
- 1/ PROGRAM AND ITS SUBROUTINES ENTIRELY CONFORM TO
CCCC
A.N.S.I. X3.8 1978 FORTRAN STANDARD.
C***********************************************************************

167

Fortran Program Example - Part 5


=================================
C***********************************************************************
CCCC
NON EXECUTABLE PART.
C----------------------------------------------------------------------CCCC
CHARACTER TYPE CONSTANTS :
CCCC
---------------------------CCCC

CONTROL DATA, INPUT AND OUTPUT FILE DEFAULT NAMES.

CHARACTER CCDN * 6,
1
CIDN * 6,
1
CODN * 6
C----------------------------------------------------------------------CCCC
INTEGER TYPE CONSTANTS :
CCCC
-------------------------CCCC
CCCC

INDIVIDUAL DATA VALUE FIELD LENGTH IN INPUT FILE,


AND MAXIMUM PROCESSED BLOCKS AND ITEMS PER BLOCK.
INTEGER
1

CCCC

NILN,
NDMX
DEFAULT PROCESSED BLOCKS AND ITEMS PER BLOCK.

INTEGER
NDDF
C----------------------------------------------------------------------CCCC
CONSTANT ASSIGNMENTS :
CCCC
---------------------CCCC

CONTROL DATA, INPUT AND OUTPUT FILE DEFAULT NAMES.


PARAMETER ( CCDN = SPLCDT,
1
CIDN = SPLRIN,
1
CODN = SPLROU )

CCCC
CCCC

INDIVIDUAL DATA VALUE FIELD LENGTH IN INPUT FILE,


AND MAXIMUM PROCESSED BLOCKS AND ITEMS PER BLOCK.
PARAMETER ( NILN =
1
NDMX =

CCCC

12,
1024 )

DEFAULT PROCESSED BLOCKS AND ITEMS PER BLOCK.

PARAMETER ( NDDF = ( NDMX / 16 ) )


C-----------------------------------------------------------------------

168

Fortran Program Example - Part 6


=================================
C----------------------------------------------------------------------CCCC
CHARACTER TYPE VARIABLES :
CCCC
---------------------------CCCC
CCCC

INDIVIDUAL DATA VALUE FORMAT DESCRIPTOR STRING,


FOR SPL DATA ITEM REAL AND IMAGINARY PARTS.
CHARACTER CFIV *

CCCC
CCCC

INPUT AND OUTPUT DATA FILE RECORD FORMAT STRINGS,


FOR WHOLE RECORD (LINE) WITH MULTIPLE DATA VALUES.
CHARACTER CFIF *
1
CFOF *

CCCC
CCCC
CCCC

255

OUTPUT DATA FILE NAME AND FORMAT OPTION.


CHARACTER COFN *
1
COOF *

CCCC
CCCC

255

FILE NAMES AND PROGRAM OPTIONS INPUT STRING.


CHARACTER CIST *

CCCC

255,
9

INPUT FILE DATA BLOCK HEADER LINE INPUT STRING.


CHARACTER CIHL *

CCCC

255,
255,
9

SPL DATA INPUT FILE NAME,


AND DATA FORMAT (FROM FILE FORMAT QUERY).
CHARACTER CIFN *
1
CINF *

CCCC

64,
64

SPL CONTROL DATA FILE NAME, PREVIOUS KEYED NAME,


FOR EXIT WHEN REPEATED NON EXTANT FILE ENTRY,
AND DATA FORMAT (FROM FILE FORMAT QUERY).
CHARACTER CCFN *
1
CICP *
1
CICF *

CCCC
CCCC

10

255,
1

ENTRY STRINGS FOR TOTAL BLOCKS AND BLOCK SIZE,


THAT IS, LINES AND ITEMS PER LINE IN OUTPUT FILE.

CHARACTER CTBK *
6,
1
CTIT *
6
C-----------------------------------------------------------------------

169

Fortran Program Example - Part 7


=================================
C----------------------------------------------------------------------CCCC
INTEGER TYPE VARIABLES :
CCCC
-------------------------CCCC

DATA INPUT STRING CURRENT CHARACTER.


INTEGER

CCCC

IINC
CONTROL AND SPL DATA FILE NAMES NON BLANK LENGTH.

INTEGER
1
CCCC

ICNL,
IINL
CONTROL DATA FILE OPEN STATUS.

INTEGER
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC

ICST
FIRST AND LAST DATA VALUES IN BLOCK SUBSCRIPTS,
AND LINE INDEX (POSITION) IN BLOCK,
FOR CURRENT LINE IN DATA BLOCK BEING INPUT.
WITH 4 2 VALUES COMPLEX ITEMS ON LINE,
FIRST LINE HAS VALUE PAIRS FOR ITEMS 1 TO 4,
TAKEN AS LINE ARRAY VALUES 1 TO 8, AND SO ON.

INTEGER
1
1
CCCC
CCCC
CCCC

ILIF,
ILIL,
ILNE
CURRENT DATA INPUT BLOCK, ALSO OUTPUT LINE,
AND CURRENT (REAL OR IMAGINARY) ACTUAL VALUE,
IN INPUT BLOCK AND OUTPUT DATA FILE LINE.

INTEGER
1
CCCC

INBK,
INVA
NON BLANK LENGTH FOR OUTPUT DATA FILE NAME.

INTEGER
CCCC
CCCC

IODL
NON BLANK LENGTHS FOR ENTRY STRINGS,
FOR TOTAL BLOCKS AND BLOCK SIZE.

INTEGER
1
CCCC

ITBL,
ITIL
INPUT DATA FILE LINES PER BLOCK OF ITEMS.

INTEGER

NLMB

170

Fortran Program Example - Part 8


=================================
CCCC
CCCC
CCCC

TOTAL INPUT BLOCKS PROCESSED AND BLOCK SIZE,


THAT IS, LINES AND ITEMS PER LINE IN OUTPUT FILE,
AND INDIVIDUAL NUMERIC VALUES PER BLOCK OR LINE.
INTEGER
1
1

CCCC

NTBK,
NTIT,
NTVA
SPL CONTROL DATA, INPUT AND OUTPUT FILE UNITS.

INTEGER
NUCN,
1
NUIN,
1
NUON
C----------------------------------------------------------------------C----------------------------------------------------------------------CCCC
LOGICAL TYPE VARIABLES :
CCCC
-------------------------CCCC

SPL INPUT DATA FILE EXISTENCE FLAG.

LOGICAL
LIEX
C----------------------------------------------------------------------CCCC
DOUBLE PRECISION TYPE VARIABLES :
CCCC
----------------------------------CCCC
CCCC
CCCC

CURRENT INPUT BLOCK OR OUTPUT LINE DATA VALUES,


EACH A COMPLEX NUMBERS REAL OR IMAGINARY PART,
WHICH FILE FORMAT PREVENTS BEING INPUT AS SUCH.

DOUBLE
PRECISION
1
DIVA (NDMX * 2)
C----------------------------------------------------------------------CCCC
DATA INITIALISATIONS :
CCCC
---------------------CCCC

CURRENT DATA INPUT BLOCK, ALSO OUTPUT LINE.


DATA

CCCC

INBK /

0 /

SPL CONTROL DATA, INPUT AND OUTPUT FILE UNITS.

DATA
NUCN / 3 /,
1
NUIN / 8 /,
1
NUON / 9 /
C***********************************************************************

171

Fortran Program Example - Part 9


=================================
C***********************************************************************
CCCC
EXECUTABLE PART.
C----------------------------------------------------------------------CCCC
CCCC

OUTPUT INITIAL HEADERS ON LOG (DEFAULT OUTPUT),


THEN COPYRIGHT NOTICE, TO FORCE IN LOAD MODULE.

10 WRITE
( *, 99)
99 FORMAT ( /, SPL COMPLEX DATA BATCH REFORMATTING : ,
1
/, ************************************* ,
1
/, Copyright University of Cambridge, 2000 )
C----------------------------------------------------------------------C----------------------------------------------------------------------CCCC
PICK CONTROL DATA FILE NAME :
CCCC
----------------------------CCCC

REQUEST ENTRY OF CONTROL DATA FILE NAME.

100 WRITE

( *, 1000 ) CCDN

1000 FORMAT
1
1

( /, Enter Control Data File Name ,


(Default
, A , ),
/,
or 999 to Exit
)

CIST
READ
1001 FORMAT

=
( *, 1001,
( A )

CCCC

WHEN EXIT REQUESTED, BRANCH TO MESSAGE AND EXIT.


IF
1

CCCC

END = 101, ERR = 101 ) CIST

( CIST .EQ. 999 )


GOTO
990
WHEN NO CONTROL DATA NAME KEYED, IMPLEMENT DEFAULT.

101 IF
( CIST .EQ. )
1
CIST
=
CCDN
C-----------------------------------------------------------------------

172

Fortran Program Example - Part 10


=================================
C----------------------------------------------------------------------CCCC
CHECK CONTROL DATA FILE :
CCCC
------------------------CCCC
CCCC
CCCC
CCCC

SET CONTROL DATA FILE NAME LENGTH TO ZERO,


AND PASS ANY LEADING BLANKS IN USER KEYED NAME,
THEN FOR EACH NON BLANK, INCREMENT FILE NAME LENGTH,
AND LEFT JUSTIFY CHARACTERS TILL ANOTHER BLANK FOUND.

110 ICNL
DO 111

= 0
IINC

1,

LEN

( CIST )

IF

( CIST ( IINC : IINC )

.NE.

) THEN

ICNL = ( ICNL + 1
)
CCFN
( ICNL : ICNL ) = CIST ( IINC : IINC )
ELSE
IF

( ICNL .GT. 0 )

GOTO

112

ENDIF
111 CONTINUE
CCCC

FORCE TAIL END OF CONTROL FILE NAME TO BLANK.

112 CCFN
CCCC

( ( ICNL + 1 )

: ) =

OPEN CONTROL DATA FILE.


OPEN
1
1
1
1
1
1

CCCC
CCCC

=
=
=
=
=
=
=

NUCN
,
CCFN ( 1 : ICNL ),
OLD
,
SEQUENTIAL
,
FORMATTED
,
NULL
,
ICST
)

WHEN CONTROL DATA FILE OPEN FAILS, ISSUE WARNING,


AND BRANCH BACK TO NAME INPUT (OR EXIT REQUEST).
IF

1100

( UNIT
FILE
STATUS
ACCESS
FORM
BLANK
IOSTAT

( ICST

.NE.

0 ) THEN

WRITE

( *, 1100 ) CCFN ( 1 : ICNL )

FORMAT

( /, Control File , A, cannot open )

GOTO
100
ENDIF
C-----------------------------------------------------------------------

173

Fortran Program Example - Part 11


=================================
C----------------------------------------------------------------------CCCC
PICK AND CHECK SPL DATA INPUT FILE NAME :
CCCC
----------------------------------------CCCC
CCCC

PICK SPL INPUT DATA FILE NAME OFF CONTROL FILE,


BYPASSING 6 LINES OF HEADINGS AND COMMENT.

120 CIST
READ
1200 FORMAT
CCCC

=
( NUCN, 1200, END = 121, ERR = 121 ) CIST
( //////, A )
WHEN NO INPUT DATA NAME FOUND, IMPLEMENT DEFAULT.

121 IF
CCCC
CCCC
CCCC
CCCC

( CIST .EQ.

) CIST = CIDN

SET SPL DATA INPUT FILE NAME LENGTH TO ZERO,


AND PASS ANY LEADING BLANKS IN FILE NAME STRING,
THEN FOR EACH NON BLANK, INCREMENT FILE NAME LENGTH,
AND LEFT JUSTIFY CHARACTERS TILL ANOTHER BLANK FOUND.
IINL
DO 122

= 0
IINC

1,

LEN

( CIST )

IF

( CIST ( IINC : IINC )

.NE.

) THEN

IINL = ( IINL + 1
)
CIFN
( IINL : IINL ) = CIST ( IINC : IINC )
ELSE
IF

( IINL .GT. 0 )

GOTO

123

ENDIF
122 CONTINUE
CCCC

FORCE TAIL END OF INPUT FILE NAME TO BLANK.

123 CIFN
CCCC

( ( IINL + 1 )

: ) =

CHECK REQUESTED SPL INPUT DATA FILE EXISTS.


INQUIRE ( FILE
1
EXIST
IF
( LIEX

CCCC

= CIFN ( 1 : IINL ),
= LIEX
)
) GOTO
130

WHEN INPUT FILE NOT FOUND ABORT RUN WITH MESSAGE.


WRITE

( *,

1201 ) CIFN ( 1 : IINL )

1201 FORMAT ( /, SPL Data Input File , A, Not Found )


GOTO
990
C-----------------------------------------------------------------------

174

Fortran Program Example - Part 12


=================================
C----------------------------------------------------------------------CCCC
PICK AND CHECK SPL DATA INPUT FILE NAME :
CCCC
----------------------------------------CCCC

PICK SPL INPUT DATA FILE NAME OFF CONTROL FILE.

130 CIST
READ
1300 FORMAT
CCCC

=
( NUCN, 1300, ERR = 131 ) CIST
( A
)
WHEN NO OUTPUT DATA NAME FOUND, IMPLEMENT DEFAULT,

131 IF
1
CCCC
CCCC
CCCC
CCCC

( CIST .EQ. )
CIST =
CODN
SET DATA
AND PASS
THEN FOR
AND LEFT

IODL
DO 132

OUTPUT FILE NAME LENGTH TO ZERO,


ANY LEADING BLANKS IN FILE NAME STRING,
EACH NON BLANK, INCREMENT FILE NAME LENGTH,
JUSTIFY CHARACTERS TILL ANOTHER BLANK FOUND.

= 0
IINC

1,

LEN

( CIST )

IF

( CIST ( IINC : IINC )

.NE.

) THEN

IODL = ( IODL + 1
)
COFN
( IODL : IODL ) = CIST ( IINC : IINC )
ELSE
IF

( IODL .GT. 0 )

GOTO

133

ENDIF
132 CONTINUE
CCCC

FORCE TAIL END OF DATA OUTPUT FILE NAME TO BLANK.

133 COFN
CCCC
CCCC

( ( IODL + 1 )

: ) =

WHEN OUTPUT DATA FILE NAME SAME AS INPUT,


ABORT RUN WITH MESSAGE TO NOT OVERWRITE INPUT.
IF

1301
1

( COFN

( 1 : IODL ) .EQ. CIFN ( 1 : IINL ) ) THEN

WRITE

( *,

FORMAT

( /, Output Data File , A, ,


same as Input )
990

1301 ) COFN ( 1 : IODL )

GOTO
ENDIF
C-----------------------------------------------------------------------

175

Fortran Program Example - Part 13


=================================
C----------------------------------------------------------------------CCCC
ECHO FILE DETAILS AND CHECK INPUT FORMAT :
CCCC
-----------------------------------------CCCC
CCCC
CCCC

ONCE EXTANT SPL DATA INPUT FILE NAME,


AND NON CONFLICTING OUTPUT FILE NAME,
ECHO FILE NAME DETAILS TO SCREEN.

190 WRITE
1
1
1
1900 FORMAT
1
1
CCCC
CCCC

( *,
CCFN ( 1 :
CIFN ( 1 :
COFN ( 1 :

1900
ICNL
IINL
IODL

)
),
),
)

( /, SPL Control Data : , A, ,


/, SPL
Data File : , A, ,
/, Output "
"
: , A, )
CHECK INPUT SPL DATA INPUT FILE FORMAT.
WHEN INVALID, BRANCH TO MESSAGE OUTPUT AND ABORT.

INQUIRE ( FILE = CIFN ( 1 : IINL ),


1
FORM = CINF
)
IF
( CINF .EQ. UNFORMATTED )
1
GOTO
900
C-----------------------------------------------------------------------

176

Fortran Program Example - Part 14


=================================
C----------------------------------------------------------------------CCCC
PICK SPL DATA BLOCKS TO INPUT :
CCCC
------------------------------CCCC

PICK SPL BLOCKS TO PROCESS FROM CONTROL FILE.

200 READ
2000 FORMAT
CCCC
CCCC

( NUCN, 2000, ERR = 201 ) CIST


( A
)
WHEN NO VALUE KEYED, IMPLEMENT DEFAULT,
AND BRANCH OVER KEYED ENTRY VALIDATION.

201 IF

( CIST

.EQ.

NTBK
GOTO

=
220

) THEN
NDDF

ENDIF
CCCC
CCCC
CCCC
CCCC

SET SPL DATA BLOCKS ENTRY LENGTH TO ZERO.


PASS ANY LEADING BLANKS IN SPL BLOCKS ENTRY,
THEN FOR EACH NON BLANK, INCREMENT ENTRY LENGTH,
AND LEFT JUSTIFY CHARACTERS TILL ANOTHER BLANK FOUND.

202 ITBL
DO 203

= 0
IINC

1,

LEN

( CIST )

IF

( CIST ( IINC : IINC )

.NE.

) THEN

ITBL = ( ITBL + 1
)
CTBK
( ITBL : ITBL ) = CIST ( IINC : IINC )
ELSE
IF

( ITBL .GT. 0 )

GOTO

204

ENDIF
203 CONTINUE
CCCC

FORCE TAIL END OF SPL DATA BLOCKS ENTRY TO BLANK.

204 CTBK
( ( ITBL + 1 ) : ) =
C-----------------------------------------------------------------------

177

Fortran Program Example - Part 15


=================================
C----------------------------------------------------------------------CCCC
SPL DATA BLOCKS TO INPUT CONVERSION :
CCCC
------------------------------------CCCC
CCCC
CCCC
CCCC

CHECK VALID DEFAULT, PRESET OR KEYED BLOCKS TOTAL,


BY CONVERSION TO INTEGER FORMAT AND RANGE TEST.
WHEN INVALID, ISSUE WARNING, RESET ENTRY STRINGS,
AND BRANCH BACK TO REQUEST REENTRY.

210 READ
2100 FORMAT
GOTO
CCCC

( CTBK, 2100, ERR = 211 ) NTBK


( I5
)
212
NON NUMERIC ERROR MESSAGE AND BRANCH TO ABORT.

211 WRITE
2101 FORMAT
GOTO
CCCC

( *, 2101 )
( /, Non Numeric (Integer) Total Blocks )
990
OUT OF RANGE ERROR MESSAGE AND BRANCH TO ABORT.

212 IF
1
1
WRITE
2102 FORMAT

( ( NTBK .GE.
1 ) .AND.
( NTBK .LE. NDMX ) )
GOTO
220
( *,

2102 ) NDMX

( /, Total Blocks not in 0 to , I5, Range )

GOTO
990
C-----------------------------------------------------------------------

178

Fortran Program Example - Part 16


=================================
C----------------------------------------------------------------------CCCC
PICK SPL DATA BLOCK SIZE :
CCCC
-------------------------CCCC

PICK SPL DATA BLOCK SIZE FROM CONTROL FILE.

220 READ
2200 FORMAT
CCCC
CCCC

( NUCN, 2200, ERR = 221 ) CIST


( A
)
WHEN NO VALUE FOUND, IMPLEMENT DEFAULT,
AND BRANCH OVER KEYED ENTRY VALIDATION.

221 IF

( CIST

.EQ.

NTIT
GOTO

=
240

) THEN
NDDF

ENDIF
CCCC
CCCC
CCCC
CCCC

SET SPL DATA BLOCK SIZE ENTRY LENGTH TO ZERO.


PASS ANY LEADING BLANKS IN SPL BLOCK SIZE ENTRY,
THEN FOR EACH NON BLANK, INCREMENT ENTRY LENGTH,
AND LEFT JUSTIFY CHARACTERS TILL ANOTHER BLANK FOUND.

222 ITIL
DO 223

= 0
IINC

1,

LEN

( CIST )

IF

( CIST ( IINC : IINC )

.NE.

) THEN

ITIL = ( ITIL + 1
)
CTIT
( ITIL : ITIL ) = CIST ( IINC : IINC )
ELSE
IF

( ITIL .GT. 0 )

GOTO

224

ENDIF
223 CONTINUE
CCCC

FORCE TAIL END OF DATA BLOCK SIZE ENTRY TO BLANK.

224 CTIT
( ( ITIL + 1 ) : ) =
C-----------------------------------------------------------------------

179

Fortran Program Example - Part 17


=================================
C----------------------------------------------------------------------CCCC
SPL DATA BLOCK CONVERSION :
CCCC
--------------------------CCCC
CCCC
CCCC
CCCC

CHECK VALID DEFAULT, PRESET OR KEYED BLOCK SIZE,


BY CONVERSION TO INTEGER FORMAT AND RANGE TEST.
WHEN INVALID, ISSUE WARNING, RESET ENTRY STRINGS,
AND BRANCH BACK TO REQUEST REENTRY.

230 READ
2300 FORMAT
GOTO
CCCC

( CTIT, 2300, ERR = 231 ) NTIT


( I5
)
232
NON NUMERIC ERROR MESSAGE AND BRANCH TO ABORT.

231 WRITE
2301 FORMAT
GOTO
CCCC

( *, 2301 )
( /, Non Numeric (Integer) Block Size )
990
OUT OF RANGE ERROR MESSAGE AND BRANCH TO ABORT.

232 IF
1
1
WRITE
2302 FORMAT

( ( NTIT .GE.
1 ) .AND.
( NTIT .LE. NDMX ) )
GOTO
240
( *,

2302 ) NDMX

( /, Block Size not in 1 to , I5, Range )

GOTO
990
C-----------------------------------------------------------------------

180

Fortran Program Example - Part 18


=================================
C----------------------------------------------------------------------CCCC
PICK OUTPUT FORMAT OPTION :
CCCC
--------------------------CCCC

PICK OUTPUT FORMAT OPTION FROM CONTROL FILE.

240 READ
2400 FORMAT
CCCC

( NUCN, 2400, ERR = 241 ) CIST


( A
)
WHEN NO OPTION FOUND, IMPLEMENT DEFAULT.

241 IF

( CIST

.EQ. ) THEN

CIST

ENDIF
CCCC
CCCC
242 DO 243

START SCAN FOR OUTPUT FORMAT OPTION IN INPUT STRING,


TAKEN AS FIRST NON BLANK CHARACTER FOUND.
IINC

IF

( CIST ( IINC : IINC ) .NE. ) THEN


COOF
GOTO

1,

LEN

( CIST )

= CIST ( IINC : IINC )


250

ENDIF
243 CONTINUE
C-----------------------------------------------------------------------

181

Fortran Program Example - Part 19


=================================
C----------------------------------------------------------------------CCCC
ECHO SPL DATA DETAILS, CHECK OUTPUT FORMAT OPTION :
CCCC
--------------------------------------------------CCCC
CCCC

ONCE SPL DATA BLOCKS AND BLOCK SIZE VALIDATED,


ECHO SPL INPUT DATA DETAILS TO SCREEN.

250 WRITE
1
1
2500 FORMAT
1
CCCC
CCCC

SET INDIVIDUAL NUMERIC VALUES PER SPL DATA BLOCK,


AS COMPLEX TYPE MEANS TWO VALUES PER DATA ITEM.
NTVA

CCCC

= ( NTIT * 2 )
ECHO OUTPUT FORMAT OPTIONS, OR ERROR NOTE AND ABORT.

IF

2501
1
ELSEIF

2502
1
ELSE
2503

( *, 2500 )
NTBK,
NTIT
( /, Total Blocks in File to process : , I5,
/, "
Items per Block
: , I5 )

( COOF

.EQ. 1

) THEN

WRITE
FORMAT

( *, 2501 )
( /, Output Lines Form : Complex ,
(Item : (real,imag) )
)

( COOF

.EQ. 2

WRITE
FORMAT

( *, 2502 )
( /, Output Lines Form : No Separators ,
(all Values in Block concatenated) )

WRITE
FORMAT

( *, 2503 )
( /, Output Format Opt. not 1 or 2 )

GOTO

990

) THEN

ENDIF
C-----------------------------------------------------------------------

182

Fortran Program Example - Part 20


=================================
C----------------------------------------------------------------------CCCC
CHECK INDIVIDUAL DATA VALUE FORMAT :
CCCC
-----------------------------------CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC

INDIVIDUAL DATA VALUES PICKED OFF AND OUTPUT,


VIA Ex.y FORMAT DESCRIPTOR, WITH y DECIMALS,
OUT OF x OVERALL LENGTH AS PER PASSED PARAMETER.
TO ACCOMMODATE si.d...dEsee OR si.d...d FORMS,
s SIGN, i INTEGER PART, d...d DECIMALS,
AND POSSIBLY E, s SIGN, ee POWER OF 10 EXPONENT,
AT LEAST 8 CHARACTERS NEEDED IN FIELD,
GIVING MINIMUM 1 DECIMAL IN si.dEs.e FORMAT.

CCCC
CCCC

CHECK DATA VALUE LENGTH AT LEAST MINIMUM,


WHEN NOT, BRANCH TO OUTPUT MESSAGE AND ABORTED EXIT.

300 IF
1
CCCC
CCCC
301 IF
1
CCCC
CCCC
CCCC

( NILN .LT.
GOTO
920

8 )

CHECK DATA VALUE LENGTH BELOW MAX. (FOR I2 FORMAT),


WHEN NOT, BRANCH TO OUTPUT MESSAGE AND ABORTED EXIT.
( NILN .GT. 24 )
GOTO
921
SET UP Ex.y FORMAT DESCRIPTOR FOR DATA VALUES,
WITH y GIVEN BY FIELD LENGTH LESS NON DECIMALS,
IN EXPONENT NOTATION, TO GET AT LEAST ONE DECIMAL.

302 WRITE
( CFIV, 3002 )
1
NILN
,
1
( NILN - 7 )
3002 FORMAT ( E, I2.2, ., I2.2 )
C-----------------------------------------------------------------------

183

Fortran Program Example - Part 21


=================================
C----------------------------------------------------------------------CCCC
SET INPUT AND OUTPUT FILE RECORD FORMAT STRINGS :
CCCC
------------------------------------------------CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC

INPUT SPL DATA FILE HOLDS VALUES IN BLOCKS,


EACH A ONE DIM. ARRAY OF 2 VALUE COMPLEX NUMBERS.
EACH BLOCK SURROUNDED BY HEADING AND TRAILER LINES.
BETWEEN THESE LIE DATA ITEM LINES,
WITH COMPLEX ITEMS HELD 4 PER LINE (SO 8 VALUES),
AFTER FIRST ITEM SUBSCRIPT AND WITH SEPARATORS.
INPUT FORMAT PICKS ABOVE 8 VALUES, DISCARDING REST,
AND MADE UP USING INDIVIDUAL VALUE FORMAT SET ABOVE.

310 WRITE
1
1
3100 FORMAT
CCCC

( CFIF, 3100 )
CFIV,
CFIV
( ( T5, 4 ( TR3, , A, , TR2, , A, ) ) )
ASSIGN INPUT FILE LINES PER SPL DATA BLOCK.

NLMB
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC

= ( NTIT / 4 )
OUTPUT DATA SENT TO OUTPUT FILE ONE BLOCK PER LINE,
IN COMPLEX FORM, REAL-IMAG. PAIRS BETWEEN BRACKETS,
WITH COMMA SEPARATION AND TRAILING SPACE,
OR ALL VALUES IN BLOCK CONCATENATED WITH NO SPACES.
EACH BLOCK WITH TWICE AS MANY FIELDS AS ITEMS,
AS TWO VALUES PER COMPLEX DATA ITEM.
INDIVIDUAL VALUES WITH SAME FORMAT AS INPUT.

IF

( COOF .EQ. 1 ) THEN


WRITE

1
1
1
3101
1
ELSE

FORMAT

( CFOF, 3101 )
NTIT,
CFIV,
CFIV
( ( SP, , I5 ,
( (, A, ,,,, A, ) ) ) )

WRITE
( CFOF, 3102 )
1
NTVA,
1
CFIV
3102
FORMAT ( ( , I5,
1
( , A, ) ) )
ENDIF
C-----------------------------------------------------------------------

184

Fortran Program Example - Part 22


=================================
C----------------------------------------------------------------------CCCC
OPEN SPL DATA INPUT AND OUTPUT FILES :
CCCC
-------------------------------------CCCC
CCCC

SPL DATA INPUT FILE PRE-CHECKED OF VALID FORMAT,


AND OUTPUT FILE NAMES TO NOT CONFLICT WITH INPUT.

CCCC

OPEN SPL DATA INPUT FILE.

400 OPEN
1
1
1
1
1
1
CCCC

( UNIT
FILE
STATUS
ACCESS
FORM
BLANK
ERR

=
=
=
=
=
=
=

NUIN
,
CIFN ( 1 : IINL ),
OLD
,
SEQUENTIAL
,
FORMATTED
,
NULL
,
910
)

OPEN OUTPUT DATA FILE.

OPEN
( UNIT
= NUON
,
1
FILE
= COFN ( 1 : IODL ),
1
STATUS = UNKNOWN
,
1
ACCESS = SEQUENTIAL
,
1
FORM
= FORMATTED
,
1
BLANK = NULL
,
1
ERR
= 911
)
C----------------------------------------------------------------------C----------------------------------------------------------------------CCCC
PICK NEXT SPL INPUT DATA FILE BLOCK :
CCCC
------------------------------------CCCC
410
CCCC
CCCC
CCCC
CCCC
CCCC
411 READ
1
4100 FORMAT

INCREMENT CURRENT BLOCK COUNTER (PRESET TO ZERO).


INBK = ( INBK + 1 )
PASS EVENTUAL PREVIOUS BLOCKS TRAILING LINES,
AND ANY NUMBER OF NON sp_dump ORIGINATED LINES,
COMING BEFORE BLOCK DESCRIPTION HEADER LINE.
AS INDICATED BY sp_dump> /source LEFT HAND FLAG.
BLOCK DETAILS SAVED IN HEADER LINE CHARACTER STRING.
( NUIN, 4100, END = 930, ERR = 940 )
CIHL
( A )

IF
( CIHL ( 1 : 16 ) .NE. sp_dump> /source )
1
GOTO
411
C-----------------------------------------------------------------------

185

Fortran Program Example - Part 23


=================================
C----------------------------------------------------------------------CCCC
PROCESS SPL INPUT DATA FILE BLOCK SIZE :
CCCC
---------------------------------------CCCC
CCCC

PICK TOTAL ITEMS IN BLOCK VALUE OFF BLOCK DETAILS,


WITH EXACT TOTAL DIGITS FORMAT SPECIFICATION.

420 IF

( NTIT .LE.
READ

1
4200
ELSEIF

FORMAT
( NTIT .LE.
READ

1
4201
ELSEIF

FORMAT
( NTIT .LE.
READ

1
4202
ELSEIF

FORMAT

FORMAT
READ

1
4204
ENDIF
CCCC

( CIHL, 4200, END = 931, ERR = 941 )


ITRW
( T49, I1 )
99 ) THEN
( CIHL, 4201, END = 931, ERR = 941 )
ITRW
( T49, I2 )
999 ) THEN
( CIHL, 4202, END = 931, ERR = 941 )
ITRW
( T49, I3 )

( NTIT .LE. 9999 ) THEN


READ

1
4203
ELSE

9 ) THEN

FORMAT

( CIHL, 4203, END = 931, ERR = 941 )


ITRW
( T49, I4 )
( CIHL, 4204, END = 931, ERR = 941 )
ITRW
( T49, I5 )

WARNING WHEN BLOCK SIZE OFF FILE NOT AS EXPECTED.


IF
1

( ITRW .EQ. NTIT )


GOTO
430

WRITE
( *,
4205 )
1
ITRW,
1
INBK
4205 FORMAT ( /, Block Size in File ( , I5, ) Not as Chosen,
1
/, for
SPL Data Block , I5
)
C-----------------------------------------------------------------------

186

Fortran Program Example - Part 24


=================================
C----------------------------------------------------------------------CCCC
PROCESS INPUT DATA FILE BLOCK DATA VALUES :
CCCC
------------------------------------------CCCC

PASS OVER BLANK LINE BELOW BLOCK DETAILS IN FILE.

430 READ
4300 FORMAT
CCCC
CCCC

( NUIN, 4300, END = 930, ERR = 940 )


( )
INITIALISE FIRST AND LAST VALUE FOR FIRST INPUT LINE,
WHERE 2 VALUES MAKE ONE COMPLEX DATA ITEM.

ILIF
ILIL
CCCC
CCCC
CCCC
CCCC
CCCC

= 1
= 8
PICK DATA VALUES, IN LINES OF 4 COMPLEX ENTRIES,
THAT IS, 8 INDIVIDUAL NUMERIC VALUES,
WITH 3 LEADING BLANKS AND COMMA-BLANK SEPARATION,
AND 4 DIGIT OFFSET OF FIRST VALUE AT BEGINNING,
THEN SET FIRST AND LAST VALUE INDEXES FOR NEXT LINE.

DO 432

ILNE =

1,

NLMB

READ

(
(

NUIN, CFIF , END = 932 , ERR


DIVA (INVA), INVA = ILIF, ILIL

ILIF
ILIL

= ( ILIF + 8 )
= ( ILIL + 8 )

= 942 )
)

432 CONTINUE
CCCC
CCCC

PICK ANY LAST LINE WITH LESS THAN FULL COMPLEMENT,


AS INDICATED BY INTEGER DIVIDE THEN MULTIPLY SIZE.
IF
1
1

CCCC
CCCC

= 942 )
)

COPY ARRAY OF DATA VALUES IN BLOCK AS ONE LINE,


OF CONCATENATED REAL-IMAGINARY PARTS TO OUTPUT FILE.
WRITE
1

CCCC
CCCC

( ( NLMB * 4 ) .LT.
NTIT )
READ
( NUIN, CFIF , END = 932 , ERR
( DIVA (INVA), INVA = ILIF, NTVA

( NUON, CFOF, ERR =


950 )
( DIVA (INVA), INVA = 1, NTVA )
WHEN BLOCKS LEFT TO PROCESS IN SPL DATA FILE,
BRANCH BACK TO INCREMENT BLOCK AND REPEAT INPUT.

IF
( INBK .LT. NTBK ) GOTO 410
C-----------------------------------------------------------------------

187

Fortran Program Example - Part 25


=================================
C----------------------------------------------------------------------CCCC
END OF SPL DATA FILE PROCESSING :
CCCC
--------------------------------CCCC
CCCC
CCCC

ONCE DESIRED NUMBER OF SPL DATA BLOCKS PICKED,


OFF SPL DATA INPUT FILE, OUTPUT ADVISORY MESSAGE.
NOTE ANY SUBSEQUENT DATA IN FILE IGNORED.

500 WRITE
1
5000 FORMAT
CCCC

CCCC

( *, 5000 )
INBK
( /, End of Data Input : , I5, Blocks )
CLOSE CONTROL, SPL DATA INPUT AND OUTPUT FILES.

CLOSE
1

( UNIT = NUCN,
ERR = 960 )

CLOSE
1

( UNIT = NUIN,
ERR = 961 )

CLOSE
1

( UNIT = NUON,
ERR = 962 )
BRANCH OFF TO SUCCESSFUL COMPLETION OF RUN.

GOTO
999
C-----------------------------------------------------------------------

188

Fortran Program Example - Part 26


=================================
C----------------------------------------------------------------------CCCC
ERROR MESSAGE OUTPUTS AND ABORTED EXITS (1) :
CCCC
--------------------------------------------CCCC
CCCC

IN ALL CASES, MESSAGE (AND COORDINATES) OUTPUT,


AND FILES OPENED AT THAT STAGE CLOSED.

900 WRITE
1
9000 FORMAT
GOTO

( *, 9000 )
CINF
( /, Input Data File Format : , A, invalid )
990

910 WRITE
9100 FORMAT
GOTO

( *, 9100 )
( /, Error Opening Input Data File )
990

911 WRITE
9101 FORMAT

( *, 9101 )
( /, Error Opening Output Data File )

CLOSE
GOTO
920 WRITE
1
9200 FORMAT
CLOSE
CLOSE
GOTO
921 WRITE
1
9201 FORMAT

( NUIN, ERR = 960


990

( *, 9200 )
NILN
( /, Data Value Length , I5, below Min. 8 Bytes )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9201 )
NILN
( /, Data Value Length , I5, over Max. 24 Bytes )

CLOSE
( NUIN, ERR = 960 )
CLOSE
( NUON, ERR = 961, STATUS = DELETE )
GOTO
990
C-----------------------------------------------------------------------

189

Fortran Program Example - Part 27


=================================
C----------------------------------------------------------------------CCCC
ERROR MESSAGE OUTPUTS AND ABORTED EXITS (2) :
CCCC
--------------------------------------------CCCC
CCCC

IN ALL CASES, MESSAGE (AND COORDINATES) OUTPUT,


AND FILES OPENED AT THAT STAGE CLOSED.

930 WRITE
1
9300 FORMAT
1
CLOSE
CLOSE
GOTO
931 WRITE
1
9301 FORMAT
1
CLOSE
CLOSE
GOTO
932 WRITE
1
1
9302 FORMAT
1

( *, 9300 )
INBK
( /, Input Data File End,
,
/, in Heading Lines before Block , I5, Data )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9301 )
INBK
( /, Input Data File End,
,
/, in Block Details above Block , I5, Data )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9302 )
ILNE,
INBK
( /, Input Data File End,
,
/, in Line , I5, of Block , I5, Data )

CLOSE
( NUIN, ERR = 960 )
CLOSE
( NUON, ERR = 961, STATUS = DELETE )
GOTO
990
C-----------------------------------------------------------------------

190

Fortran Program Example - Part 28


=================================
C----------------------------------------------------------------------CCCC
ERROR MESSAGE OUTPUTS AND ABORTED EXITS (3) :
CCCC
--------------------------------------------CCCC
CCCC

IN ALL CASES, MESSAGE (AND COORDINATES) OUTPUT,


AND FILES OPENED AT THAT STAGE CLOSED.

940 WRITE
1
9400 FORMAT
1
CLOSE
CLOSE
GOTO
941 WRITE
1
9401 FORMAT
1
CLOSE
CLOSE
GOTO
942 WRITE
1
1
9402 FORMAT
1

( *, 9400 )
INBK
( /, Input Data File Input Error, ,
/, in Heading Lines above Block , I5, Data )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9401 )
INBK
( /, Input Data File Block Size Error, ,
/, in Block Details above Block , I5, Data )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9402 )
ILNE,
INBK
( /, Input Data File Input Error, ,
/, in Line , I5, of Block , I5, Data )

CLOSE
( NUIN, ERR = 960 )
CLOSE
( NUON, ERR = 961, STATUS = DELETE )
GOTO
990
C-----------------------------------------------------------------------

191

Fortran Program Example - Part 29


=================================
C----------------------------------------------------------------------CCCC
ERROR MESSAGE OUTPUTS AND ABORTED EXITS (4) :
CCCC
--------------------------------------------CCCC
CCCC

IN ALL CASES, MESSAGE (AND COORDINATES) OUTPUT,


AND FILES OPENED AT THAT STAGE CLOSED.

950 WRITE
1
9500 FORMAT
CLOSE
CLOSE
GOTO
960 WRITE
9600 FORMAT
CLOSE
CLOSE
GOTO
961 WRITE
9601 FORMAT
CLOSE
GOTO

( *, 9500 )
INBK
( /, Output Data File Write Error, Line , I5 )
( NUIN, ERR = 960 )
( NUON, ERR = 961, STATUS = DELETE )
990
( *, 9600 )
( /, Error Closing Control Data File )
( NUIN, ERR = 961 )
( NUON, ERR = 962 )
990
( *, 9601 )
( /, Error Closing Input Data File )
( NUON, ERR = 962 )
990

962 WRITE
( *, 9602 )
9602 FORMAT ( /, Error Closing Output Data File )
GOTO
990
C----------------------------------------------------------------------C----------------------------------------------------------------------CCCC
ERROR ABORTED AND NORMAL EXITS :
CCCC
-------------------------------CCCC
990 WRITE
9900 FORMAT
STOP
CCCC

ABORT MESSAGE OUTPUT AND EXIT.


( *, 9900 )
( /, **** RUN ABORTED **** )

NORMAL END OF RUN MESSAGE AND EXIT.

999 WRITE
( *, 9999 )
9999 FORMAT ( /, **** RUN COMPLETED **** )
C***********************************************************************
END

192

Fortran Program Example - Part 30


=================================
-

3/ Example Program Control Parameters File :


Using Files to provide Parameters controlling the execution of
Programs, like File Names, or various properties of the Data allows
easy reruns with the same inputs as well as Batch operations, which
would be the choice method when large amounts of Data are involved.
Note the File is arranged so as to inform casual readers of its
purpose, with Heading Lines, which are bypassed when the File is
input. Only the first Field in each Data Line serves to present a
Value to the Program so comments may be added to describe the Data
and what constraints may apply. Leading blanks are allowed, to
provide flexibility in writing the File.
Once the necessary inputs are completed, the File is no longer used
by the Program, so additional notes could follow the last Entry.
Control File for splrfb SPL Reformatter Program
*************************************************
Lines 7-11 give Parameters needed by Program at Execution :
Parameter Value
--------------SPLRIN
splout.dat
12
64
1

Description
---------------------------------------Input SPL Data File Name
Output File Name, reformatted Data
Blocks to process in Input (Integer)
Fields in each Input Block (Integer)
Output Format Option (1 or 2)

The Program implements defaults for the File Names and the Output
format, so those Lines may be left empty, but the Blocks and Fields
per Block Counts must be provided as Positive Integers. The Values
are always expected on Lines 7 to 11 in the File.

193

Fortran Program Example - Part 31


=================================
-

4/ Example Program Input Data File :


The Input File shows numeric dump data from another process.
The File consists of a series of Blocks of 64 Pairs of Values, in
Lines of 4, with an Offset Prefix. The Block Size forms one of the
Entries in the Control File above. Lines are shown broken over two
Lines with the ... indicating the continued Lines. Blocks may be
surrounded by system messages with sp_dump labels. Such Lines are
bypassed when the File is processed.
sp_dump> /source object is of type cfloat; Len0=64, Len1=1.
0
4
8
12
16
20
24
28
32
36
40
44
48
52
56
60

-7.85156e+01,
-1.11516e+02,
+1.34484e+02,
+6.24844e+01,
+2.74844e+01,
+3.66484e+02,
+1.74844e+01,
-2.85516e+02,
+6.34844e+01,
+7.64844e+01,
+1.20484e+02,
+2.37484e+02,
-3.15156e+01,
-1.44516e+02,
+1.14844e+01,
+2.66484e+02,
+6.40484e+02,
+4.89484e+02,
+1.32484e+02,
+1.47484e+02,
+1.18484e+02,
+7.04844e+01,
+5.44844e+01,
-8.51563e+00,
+2.39484e+02,
+1.61484e+02,
-1.29516e+02,
+1.75484e+02,
+1.32484e+02,
-4.02516e+02,
-1.05156e+01,
+6.14844e+01,

-2.02500e+02
+4.23500e+02
+1.35000e+01
+1.23500e+02
-3.24500e+02
-6.51500e+02
+2.14500e+02
+2.64500e+02
+7.45000e+01
+1.02500e+02
-7.05000e+01
-2.52500e+02
-2.66500e+02
-6.35000e+01
+6.35000e+01
+5.95000e+01
+1.50500e+02
+1.32500e+02
-1.07500e+02
-5.15000e+01
-5.95000e+01
-1.26500e+02
+7.95000e+01
+9.50000e+00
-8.15000e+01
+1.52500e+02
+1.29500e+02
-6.35000e+01
-1.25500e+02
-1.09500e+02
-9.25000e+01
+8.50000e+00

-1.17516e+02,
-3.75156e+01,
+1.59484e+02,
-1.45156e+01,
+2.37484e+02,
+3.01484e+02,
-2.41516e+02,
-1.39516e+02,
+1.12484e+02,
+9.48438e+00,
+2.18484e+02,
+1.21484e+02,
-1.38516e+02,
-6.35156e+01,
+1.15484e+02,
+4.68484e+02,
+6.57484e+02,
+2.74484e+02,
+1.15484e+02,
+1.57484e+02,
+6.94844e+01,
+7.24844e+01,
-1.25156e+01,
+9.44844e+01,
+2.92484e+02,
-1.65156e+01,
-3.25156e+01,
+3.02484e+02,
-2.04516e+02,
-2.68516e+02,
+6.84844e+01,
+1.43484e+02,

sp_dump> End

194

+1.22500e+02
+3.23500e+02
-6.15000e+01
+9.95000e+01
-7.10500e+02
-1.93500e+02
+3.81500e+02
+1.00500e+02
+8.55000e+01
+6.05000e+01
-1.93500e+02
-2.89500e+02
-1.88500e+02
+2.65000e+01
+6.35000e+01
+7.95000e+01
+2.17500e+02
+1.05000e+01
-9.45000e+01
-2.95000e+01
-1.69500e+02
-6.25000e+01
+7.85000e+01
-1.34500e+02
+5.50000e+00
+1.83500e+02
-2.55000e+01
-1.43500e+02
-1.25500e+02
-1.01500e+02
-3.85000e+01
-4.50000e+00

...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...

Fortran Program Example - Part 32


=================================
-

5/ Example Program Output Data File and Run Report :


The Blocks from the Input Data File are validated and written out
as Complex Pairs (in the same way COMPLEX Values would be presented
in Fortran Source Code). The multi Line Blocks are reduced to one
Line on Output. In the 64 Pairs of Values per Block data above, this
gives Lines too long to be represented in full here.
(-0.78516E+02,-0.20250E+03)
(-0.16348E+03,+0.21500E+02)
(-0.26952E+03,+0.83500E+02)
(-0.14548E+03,-0.12500E+02)
(+0.57484E+02,-0.64500E+02)
(+0.53516E+02,-0.65500E+02)
(+0.20484E+02,-0.32500E+02)
(+0.51562E+00,+0.35000E+01)
(+0.47484E+02,+0.17500E+02)
(-0.65484E+02,-0.18500E+02)
(-0.10552E+03,-0.76500E+02)
(-0.84844E+01,-0.50500E+02)

(-0.11752E+03,+0.12250E+03)
(-0.12548E+03,+0.27550E+03)
(-0.17452E+03,+0.25500E+02)
(-0.32484E+02,-0.17350E+03)
(+0.11484E+02,-0.13150E+03)
(-0.58484E+02,-0.42500E+02)
(-0.16516E+02,-0.25000E+01)
(+0.14516E+02,-0.24500E+02)
(-0.22516E+02,-0.23500E+02)
(-0.78484E+02,-0.26500E+02)
(-0.24516E+02,-0.16500E+02)
(+0.80516E+02,+0.65500E+02)

...
...
...
...
...
...
...
...
...
...
...
...

Running the Program with the Default Control Parameters File,


the following Headings, Prompt and summary details would show :
SPL COMPLEX DATA BATCH REFORMATTING :
*************************************
Copyright University of Cambridge, 2000
Enter Control Data File Name
or 999 to Exit

(Default SPLCDT)

SPL Control Data : SPLCDT


SPL
Data File : SPLRIN
Output "
"
: splout.dat
Total Blocks in File to process :
"
Items per Block
:

12
64

Output Lines Form : Complex (Item : (real,imag) )


End of Data Input :

12 Blocks

**** RUN COMPLETED ****


This report could easily be sent to a File by Redirection as found
on Unix or DOS, so large numbers of runs can be submitted in Batch.

195

Fortran Program Example - Part 33


=================================
-

6/ Observations from Example Program :


Before the actual Code begins, and in the Non Executable Part :
- The Comments at the Top describe the processing.
Comments should also give details of Input and Output (Disk) Files,
any called Routines (with the Language when not coded in Fortran),
and all Reports and Error or Run Logs.
Standards (say ANSI) and limitations should also be notified.
- Note the generous use of space and Comments. Also, the - Spacer
Lines fill the dual role of separators for various stages of the
processing and Right Hand Limit for the Code (Column 72).
- The Non Executable Part begins with Type (declaration)
and PARAMETER Statements for all the Named Constants.
Then, all Variable declarations are grouped by Type, with one
Variable only per Line, and mainly alphabetical order within Type.
Initialisations (DATA Statements) are grouped at the end of the
Non Executable Part, in the same sequence as the declarations.
- Avoid Single Letter Variable Names, clashes with Language Keywords,
and possibly common English and Mathematical terms. Note the first
Letter of Names keeps its role of indicating Type, despite Variables
all being declared, with :
C
for CHARACTER entities.
D
" DOUBLE PRECISION (all Floating Point) Variables,
L
" LOGICAL Variables,
I-N " INTEGER Variables.
- An IMPLICIT CHARACTER ( A-Z ) could have been added to reduce
the risk of miskeyed Names passing through compilation undetected.
Then any non declared Variable showing in an Arithmetic Expression
would cause compilation failure.

196

Fortran Program Example - Part 34


=================================
-

6/ Observations from Example Program (continued) :


In the Executable Part :
- Labels should proceed a logical sequence.
In the example, Labels 1000 on are reserved for FORMAT Statements
while Labels 100 to 999 serve as Markers or Branch Targets.
- Sections of the Code are made evident in the presentation, and
each Section is only entered via its initial (labelled) Statement,
where the Label forms a multiple of ten.
- Upward Branches only return to the Entry Label of sections of Code.
In the Program all such Labels make a straight multiple of ten, and
follow a clear division in the general presentation.
File Handling and Input/Output :
- Request File Names in a consistent way, with Prompt and Defaults.
When Default Disk Files are used, their Names should be indicated,
so the user can easily find them outside the scope of the Program.
- All File OPEN, CLOSE and I/O Statements should include an ERR =
or IOSTAT = Error recovery or Return Code, and the Program either
take corrective action, or abort with an appropriate Message.
In the Program all such handling appears at the end of the Code.
- Note all READ and WRITE Statements make reference to a separate
FORMAT Statement unique to the READ or WRITE. All I/O to or from
Files or the Screen is Formatted.
Also, the FORMAT Statements are presented immediately after the
READ or WRITE Statements making reference to them. Some writers
prefer to group them at the end of the Code.
- Release Disk Files once no more I/O from or to them is required.
- In the example, all File Error processing is bundled at the end.
An alternative would be to place the Statements relating to errors
near the Statements giving rise to them.

197

Fortran Program Example - Part 35


=================================
-

6/ Observations from Example Program (continued) :


Regarding Numeric Data :
- Validate all Numeric Variable Inputs, via initially reading them
as CHARACTER Variables, then to act as Internal Files for reading
the Data once confident it includes no undesired Characters.
- Write any implicit conversions explicitly to clarify the Types
of all entities in Expressions and assignments. In Line DOUBLE
PRECISION Constants should appear with a D0 Suffix.
- Pick DOUBLE PRECISION for Floating Point entities. This provides
15 to 16 (decimal) Digit accuracy, rather than the 7 to 8 Digits
of REAL entities.
- If writing out large amounts of Floating Point Data, Unformatted
Files (4 Bytes per REAL and 8 Bytes per DOUBLE PRECISION Value)
save (Disk) space but also preserve numerical accuracy. Even when
Fields of sufficient width are used in Formatted Files, rounding
errors are likely to creep in. However, Unformatted Files cannot
be displayed or edited with simple Text utilities.
About Code Usage and Structure :
- Avoid obsolete constructs like Arithmetic IF Statements, or usage
breaking simple rules with respect to blocks of Code. Subprograms
are expected to start at the top, and execution to continue at the
Statement following a Subroutine Call. This means Alternate Entry
and exits to Subprograms should not be used.
Provision of User Feedback :
- Flag the start of Executable Statements with a Screen Message or
Header, so the user knows which Program Unit is currently running.
- Present a basic feedback (Results summary) Report at completion,
and send an End of Run Note to the Screen, to inform the user.
- Use a common form for Aborts, here with a different final Message.

198

Fortran Program Example - Part 36


=================================
-

7/ General Guidelines :
- Use a consistent Style and Syntax, in effect set up a Paradigm
for the Code to minimise risks or errors or confusion. If editing
an existing Program, adhere to its style to keep it consistent.
Mention any Extensions to the standard the Program aims to follow.
- Space out Code Keywords, Symbols, Operators and Variable Names,
especially in Calculations, which can be spread over several Lines.
- Indent the Code at each Level of Nesting, in DO Loops or Block IF
sets of Statements. All DO Loops are ended with a CONTINUE Line.
- Small (single or few Characters) Symbols can have a great impact,
so space out items like ( ), or Arithmetic Operators, and also
enclose secondary Calculations in nested Brackets.
- Use only a subset of the Statements, even at the cost of more Code
(but not necessarily less speed), and keep them to their simplest
form whenever possible.
- Consider splitting long Programs into several Routines.
Shift Code fragments of potential value elsewhere to Functions or
Subroutines, though anything less then a dozen Statements would not
warrant the complexity (and loss of processing efficiency).
- Be generous with Comments and space inside the Code, and providing
feedback when the Program is run, possibly including an unambiguous
final "Successful" or "Failed" Message.

199

Appendix 1 : Fortran Resources - Part 1


========================================
-

1/ Overview :
With now over a half century since the release of IBMs first Manual
in October 1956, a lot of papers, books, references and user guides
have been written. Five ANSI standards and many implementations on,
a lot of those have lost relevance, apart from historical. However,
as a large body of Fortran 77 Code is still in use, and some fresh
code produced, most publications from the last 25 to 30 years remain
useful, at least to some extent. On top of books and manuals, a lot
can be found on the Web, and below are listed some useful notes and
starting points for picking material there.
The University Library showed 390 catalogue entries on "Fortran".
The lists of references below are derived from it and a few other
catalogues garnered on the World Wide Web. Titles from before the 77
Standard, or more obscure or hard to obtain have been left out.
The Fortran 77 and 90 and later literature are split into distinct
lists. Some common numerical application books are shown separately.
So are a few more general programming and then performance related
publications at the end. In all five lists, entries in the Library
catalogue are marked with a +. Titles also in the collection of
the author are indicated with a *.
Much as plenty of Fortran 77 literature was published, a lot has
gone out of print, though many of the well reputed books appear on
the Web sites of second hand dealers, or at online auctions. Amazon
would be a good starting point to find if a book can be obtained.
The Fortran 90 literature counts markedly fewer titles than were
written about the earlier versions, but most remains available, and
for many, with later editions going into the 95 and 2003 standards.
For straight treatment of the language, the manufacturer manuals can
be the best. IBMs Mainframe ("VS Fortran") and Unix ("XL Fortran")
manuals can be found online, and ditto for HPs Fortran manuals.
For a more course like (and opinionated) coverage, the sequence of
books by series from W.C. Brainerd, J.C. Adams et al (MIT Press),
attracted fine reviews. Many editions of the books by M. Metcalf et
al (Oxford) have been released over the last 30 years too. The now
out of print "Migrating to Fortran 90", J.F. Kerrigan, OReilly and
Associates, explains the new features of Fortran 90 very well.

200

Appendix 1 : Fortran Resources - Part 2


========================================
-

2/ Numerical, General Programming and Specialist Resources :


Vast numbers of books on numerical analysis have been written. They
can help regarding algorithm design and general issues of accuracy
or performance. Not quite so many go into actual Code details, but
a selection is shown, with most available at the University Library.
Many of the general Fortran texts will also visit the subject.
The "Numerical Recipes" series, from Cambridge University Press" has
become a best seller, and explains techniques well. Unfortunately it
gives very poorly laid code examples. LAPACK and NAg texts are given
as these Libraries have become de facto industry standards.
The Microsoft "Code Complete" by McConnell makes a fine read on good
programming practise, and has attracted excellent reviews, from even
quarters not necessarily fanatical about its publisher. The recently
out CUP "Writing Scientific Software, A Guide to Good Style" by S.
Oliveira and D. Stewart gives a good overview of the subject, even
if using C++ or Java more often than Fortran in its examples.
In "Imperative Programming Languages", volume II of the "Handbook of
Programming Languages" set, Fortran is covered in Chapter 1, with a
short history and summary of the languages features. C and Pascal
are treated later on, making it a good comparative reference.
Regarding performance, through careful coding, compiler aspects and
hardware features, quite a lot of literature exists. Right from the
first Fortran compiler, good performance was deemed essential. The
OReilly "High Performance Computing", by K. Dowd and C. Severance
makes a great introduction to the subject, with a lot of its Code
examples in Fortran.
For an excellent and extensive treatment at the next level, again,
focusing on Fortran as the language of choice, see Morgan Kaufmann
(Academic Press)s "Optimizing Compilers for Modern Architectures",
by R. Allen, K. Kennedy.

201

Appendix 1 : Fortran Resources - Part 3


========================================
-

3/ ANSI (and ISO) Fortran Standards :


ANSI X3.9-1966,
USA Standard FORTRAN, informally known as FORTRAN 66.
* ANSI X3.9-1978,
American National Standard Programming Language FORTRAN,
also known as ISO 1539-1980, informally known as FORTRAN 77.
An online Version of the 77 Standard exists. See the Link at :
http://www.nsc.liu.se/~boein/f77to90/references.html.
ANSI X3.198-1992 (R1997),
American National Standard Programming Language Fortran Extended,
informally known as Fortran 90.
ISO/IEC 1539-1:1997,
Information Technology Programming Languages, Fortran,
Part 1 : Base Language, informally known as Fortran 95.
ISO/IEC 1539-1:2004,
Information Technology Programming Languages, Fortran,
Part 1 : Base Language, informally known as Fortran 2003.

202

Appendix 1 : Fortran Resources - Part 4


========================================
-

4/ Compiler and Implementation Manuals :


Searching against "Fortran" at http://docs.hp.com/cgi-bin/search,
or http://www.ibm.com rapidly leads to documentation and manuals.
- Hewlett Packard Fortran Manuals :
* Document B2408-90009,
HP Fortran 9000, Programmers Guide.
* Document B2408-90010,
HP Fortran 9000, Programmers Reference.
Document B3908-90002,
HP Fortran 90, Programmers Guide,
http://www.hp.com/en/B3908-90002/B3908-90002.pdf.
Document B3908-90015,
HP Fortran Programmers Reference, Eighth Ed,
http://www.hp.com/en/B3908-90015/B3908-90015.pdf.
- IBM Mainframe Fortran Manuals :
* VS Fortran (1), Language and Library Reference, SC26-4119-1.
* VS Fortran (1), Programming Guide, SC26-4118-0.
VS Fortran 2.6, General Information, GC26-4219-10,
http://publibfp.boulder.ibm.com/epubs/pdf/afbgim00.pdf.
* VS Fortran 2.6, Language and Library Reference, SC26-4221-08,
http://publibfp.boulder.ibm.com/epubs/pdf/afbr1001.pdf.
VS Fortran 2.6, Programming Guide for CMS and MVS, SC26-4222-07,
http://publibfp.boulder.ibm.com/epubs/pdf/afbu2002.pdf.
VS Fortran 2.6, Reference Summary, SX26-3751-07,
http://publibfp.boulder.ibm.com/epubs/pdf/afbrs000.pdf.
VS FORTRAN Version 2, Master Index, SC26-4603-04.

203

Appendix 1 : Fortran Resources - Part 5


========================================
-

5/ Fortran Resources on the World Wide Web :


- Simply submitting a Google search against "Fortran" gives plenty
of starting Points, and so does the Wikipedia Page given below :
http://en.wikipedia.org/wiki/Fortran.
Besides the main manufacturers (like HP and IBM) offering manuals,
several Universities in the U.K. or overseas run courses for which
the notes and associated material may be downloaded.
- Courses in Fortran 77 and 90 at Belfast :
http://www.pcc.qub.ac.uk/tec/courses/f77tof90/ohp/f90ohp_2.html,
http://www.pcc.qub.ac.uk/tec/courses/f90/stu-notes/f90-stu.html
- Courses and other material at Kings College, London :
http://www.kcl.ac.uk/fortran/pdfs/fortran_resources.pdf,
http://www.kcl.ac.uk/kis/support/cit/fortran/engfaq.html,
http://www.kcl.ac.uk/kis/support/cit/fortran/f90home.html.
- Courses in Fortran 90 and High Performance Fortran at Liverpool :
http://www.liv.ac.uk/HPC/F90page.html,
http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotes.html,
http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseSlides.html,
http://www.liv.ac.uk/HPC/HTMLHPFCourse/HTMLHPFCourseNotes.html,
http://www.liv.ac.uk/HPC/HTMLHPFCourse/HTMLHPFCourseSlide.html.
- Tutorials in Fortran 77 and 90 at Chemistry and Physics in Oxford :
http://www.chem.ox.ac.uk/fortran/
http://www-teaching.physics.ox.ac.uk/Unix+Prog/hargrove/tutorial_77,
http://www-teaching.physics.ox.ac.uk/Unix+Prog/hargrove/tutorial_90.
- Examples at the School of Computer Science, Florida State :
http://people.scs.fsu.edu/~burkardt/f77_src/f77/f77.html,
http://people.scs.fsu.edu/~burkardt/f_src/f90/f90.html,
http://people.scs.fsu.edu/~burkardt/f_src/mpi/mpi.html,
http://people.scs.fsu.edu/~burkardt/f_src/mixed/mixed.html.

204

Appendix 1 : Fortran Resources - Part 6


========================================
-

6/ Selected Fortran 77 Literature :


+ P. Adman,
Fortran 77 : Solutions to Non Scientific Problems,
Chartwell Bratt, 1985, ISBN 0-862-38087-1.
A. Balfour, D.H. Marwick,
Fortran 77,
W.E.B. Publishing, 1979, ISBN 0-435-77486-7.
+ A. Balfour, D.H. Marwick,
Programming in Standard FORTRAN 77,
Heinemann Educational, 1982, ISBN 0-435-77486-7.
+ H.C. Bezner,
Fortran 77,
Prentice-Hall, 1989, ISBN 0-13-329087-5.
+ W.C. Brainerd, C.H. Goldberg, J.L. Gross,
FORTRAN 77 Programming,
Harper and Row, 1978, ISBN 0-060-42394-3.
+ V.J. Calderbank,
Programming in Fortran,
Chapman and Hall, 3rd Edition, 1989, ISBN 0-412-30510-0.
+ R.S. Dhaliwal, S. Kumar, S.K. Gupta,
Programming with FORTRAN 77 : a Structured Approach,
John Wiley, 1989, ISBN 0-470-21356-6.
+ T.M.R. Ellis,
Fortran 77 Programming,
with an Introduction to the Fortran 90 Standard,
Addison Wesley, 2nd Edition, 1990, ISBN 0-201-41638-7.
+ T.M.R. Ellis,
A Structured Approach to Fortran 77 Programming,
Addison Wesley, 1983, ISBN 0-201-13790-9.
+ D.M. Etter,
Structured FORTRAN 77 for Engineers and Scientists,
John Wiley, 5th Edition, 1997, ISBN 978-0-201-49854-7

205

Appendix 1 : Fortran Resources - Part 7


========================================
-

6/ Selected Fortran 77 Literature (continued) :


+ B.D. Hahn,
Problem Solving with Fortran 77,
Butterworth-Heinemann, 1987, ISBN 0-713-13592-1.
+ N. Kantaris,
Programming in Fortran 77,
Babani, 1988, ISBN 0-85934-195-X.
+ H. Katzan,
FORTRAN 77,
Van Nostrand, 1982, ISBN 0-442-25428-8.
+ E.B. Koffman, F.L. Friedman,
Problem Solving and Structured Programming in FORTRAN 77,
Addison Wesley, 1988, ISBN 0-201-11561-1.
+ G. Lamprecht,
Introduction to FORTRAN 77,
Friedrich Vieweg Verlag, ISBN 3-528-03360-6.
+ N.K. Lehmkuhl,
FORTRAN 77, a Top Down Approach,
Macmillan, 1983, ISBN 0-02-369390-8.
+ S.L. Marateck,
FORTRAN 77,
Academic Presx, 1983, ISBN 0-12-470463-8.
+ D.D. McCracken, W.I. Salmon,
Computing for Engineers and Scientists with Fortran 77,
John Wiley, 1988, ISBN 0-471-62552-3.
+ L.P. Meissner, E.I. Organick,
Fortran 77 : Featuring Structured Programming,
Addison Wesley, 1984, ISBN 0-07-582328-4.
+ M. Metcalf,
Effective Fortran 77,
Oxford University Press, 1986, ISBN 0-19-853709-3.

206

Appendix 1 : Fortran Resources - Part 8


========================================
-

6/ Selected Fortran 77 Literature (continued) :


+ R. Mojena, R. Ageloff,
FORTRAN 77,
Thompson Learning, 1990, ISBN 0-534-11742-2.
+ D.M. Monro,
Fortran 77,
Arnorld, 1982, ISBN 0-713-12794-5.
+ J.S. Morgan, J.L. Schonfelder,
Introduction to Programming in Fortran 77,
McGraw Hill, 1988, ISBN 0-632-01184-X.
+ G.A. Moses,
Engineering Applications Software Development Using Fortran 77,
John Wiley, 1988, ISBN 0-471-63851-X.
+ L.R. Nyhoff, S. Leestma,
FORTRAN 77 for Engineers and Scientists,
with an Introduction to Fortran 90,
Prentice Hall, 4th Edition, 1995, ISBN 0-13-363003-X.
+ L.R. Nyhoff, S. Leestma,
FORTRAN 77 for Engineers and Scientists,
Prentice Hall, 3rd Edition, 1992, ISBN 0-023-88655-2.
+ C.G. Page,
Professional Programmers Guide to Fortran 77,
Taylor and Francis Books, 1988, ISBN 0-273-02856-1.
+ J. Shelley,G. Silverman,
Essentials of Fortran 77,
John Wiley, 1989, ISBN 0-471-92378-8.
+ W.M. Turner,
Scientific Programming : Using Fortran 77,
Hutchinson Education, 1986, ISBN 0-09-161601-8.

207

Appendix 1 : Fortran Resources - Part 9


========================================
-

7/ Selected Fortran 90, 95 and 2003 Literature :


J.C. Adams, W.C. Brainerd, J.T. Martin, B.T. Smith,
Fortran Top 90, Ninety Key Features of Fortran 90,
Unicomp, 1994, ISBN 0-96401-350-9.
J.C. Adams, W.C. Brainerd, J.T. Martin, B.T. Smith, J.L. Wagener,
Fortran 90 Handbook,
McGraw-Hill, 1992, ISBN 0-07-000406-4.
+ J.C. Adams, W.C. Brainerd, J.T. Martin, B.T. Smith, J.L. Wagener,
Fortran 95 Handbook,
MIT Press, 1997, ISBN 0-262-51096-0.
* E. Akin,
Object-Oriented Programming via Fortran 90/95,
Cambridge University Press, 2003, ISBN 0-521-52408-3.
W.C. Brainerd, C.H. Goldberg, J.C. Adams,
Programmers Guide to Fortran 90, 3rd Edition,
Springer-Verlag, 1995, ISBN 3-879-4570-9.
D.R. Brooks,
Problem Solving with Fortran 90 : for Scientists and Engineers,
Springer-Verlag, 1997, ISBN 0-387-98229-9.
* L. Chamberland,
Fortran 90 : A Reference Guide (IBM Manual),
Prentice Hall, 1995, ISBN 0-13-397332-8.
+ S.J. Chapman,
Fortran 90/95 for Scientists and Engineers,
McGraw-Hill, 2nd Edition, 2003, ISBN 0-07-282575-8.
S.J. Chapman,
Fortran 95/2003 for Scientists and Engineers,
McGraw-Hill, 3rd Edition, 2007, ISBN 978-0-07-319157-7.
S.J. Chapman,
Introduction to Fortran 90/95,
McGraw-Hill, 1997, ISBN 0-070-11969-4.

208

Appendix 1 : Fortran Resources - Part 10


========================================
-

7/ Selected Fortran 90, 95 and 2003 Literature (continued) :


+ I.D. Chivers, J. Sleightholme,
Introducing Fortran 90,
Springer-Verlag, 1995, ISBN 3-540-19940-3.
+ I.D. Chivers, J. Sleightholme,
Introducing Fortran 95,
Springer-Verlag, 1995, ISBN 1-85233-276-X.
+ I.D. Chivers, J. Sleightholme,
Introduction to Programming with Fortran,
with Coverage of Fortran 90, 95, 2003 and 77,
Springer-Verlag, 2006, ISBN 1-84628-053-2.
+ M. Counihan,
Fortran 90,
Routledge, 1991, ISBN 0-273-03073-6.
M. Counihan,
Fortran 95,
CRC, 2nd Edition, 1996, ISBN 1-857-28367-8.
+ T.M.R. Ellis, T. Lahey, I. Philips,
Fortran 90 Programming (International Computer Science Series),
Addison Wesley, 1994, ISBN 0-201-54446-6.
D.M. Etter,
Fortran 90 for Engineers,
John Wiley, 1995, ISBN 978-0-471-36426-9.
* W. Gehrke,
Fortran 90 Language Guide,
Springer-Verlag, 1995, ISBN 3-540-19926-8.
+ W. Gehrke,
Fortran 95 Language Guide,
Springer-Verlag, 1996, ISBN 3-540-76062-8.
* B.D. Hahn,
Fortran 90 for Scientists and Engineers,
Edward Arnold, 1994, ISBN 0-340-60034-9.

209

Appendix 1 : Fortran Resources - Part 11


========================================
-

7/ Selected Fortran 90, 95 and 2003 Literature (continued) :


J.V. Huddleston,
Fortran 90,
Exchange Publ. Division, Buffalo, NY, 1996, ISBN 0-945261-07-1.
* J.F. Kerrigan,
Migrating to Fortran 90,
OReilly and Associates, 1993, ISBN 1-56592-049-X.
W.E. Mayo, M. Cwiakala,
Programming in Fortran 90,
Mc Graw Hill, 1996, ISBN 0-07-041156-5.
+ L.P. Meissner,
Fortran 90,
PWS Kent, 1995, ISBN 0-534-93372-6.
L.P. Meissner,
Essential Fortran 90 and 95,
Unicomp, 1997, ISBN 0-9640135-3-3.
+ M. Metcalf, J. Reid,
Fortran 90/95 Explained,
Oxford University Press, 2nd Edition, 1999, ISBN 0-19-850558-2.
* M. Metcalf, J. Reid, M. Cohen,
Fortran 95/2003 Explained,
Oxford University Press, 2004, ISBN 0-19-852692-X.
+ J.S. Morgan, J.L. Schonfelder,
Programming in Fortran 90,
Alfred Waller, 1993, ISBN 0-632-02838-6.
+ L.R. Nyhoff, S. Leestma,
Fortran 90 for Engineers and Scientists,
Prentice Hall, 1996, ISBN 0-13-519729-5.
+ L.R. Nyhoff, S. Leestma,
An Introduction to Fortran 90 for Engineers and Scientists,
Prentice Hall, 1996, ISBN 0-13-505215-7.

210

Appendix 1 : Fortran Resources - Part 12


========================================
-

7/ Selected Fortran 90, 95 and 2003 Literature (continued) :


J.M. Ortega,
Introduction to Fortran 90 for Scientific Computing,
Oxford University Press, 2003 (reprint), ISBN 0-19517-213-2.
C. Redwine,
Upgrading to Fortran 90,
Springer, 1995, ISBN 0-387-97995-6.
+ W. Schick, G. Silverman,
Fortran90 and Engineering Computations,
John Wiley, 1995, ISBN 0-471-58512-2.
+ I.M. Smith,
Programming in Fortran 90,
A First Course for Engineers and Scientists,
John Wiley, 1995, ISBN 0-471-94185-9.
+ G. Zirkel, E. Berlinger,
Understanding Fortran 77 and 90,
PWS Publishers, 1994, ISBN 0-534-93447-1.

211

Appendix 1 : Fortran Resources - Part 13


========================================
-

8/ Numerical Applications Literature :


+ E. Anderson et al,
LAPACK Users Guide,
Society for Industrial and Applied Mathematics,
2nd Edition, 1995, ISBN, 0-898-71345-5.
+ L.V. Atkinson, P.J. Hurley, J.D. Hudson,
Numerical Methods with Fortran 77, a Practical Introduction,
Addison Wesley, 1989, ISBN 0-201-17430-8.
C.H. Koelbel et al,
High Performance Fortran Handbook,
MIT Press, 1994, ISBN 0-262-11185-3, 0-262-61094-9 (paperback).
+ T. Hopkins, C. Phillips,
Numerical Methods in Practice : Using the NAG Library,
Addison-Wesley, 1988, ISBN 0-201-19248-9.
+ M. Metcalf,
FORTRAN Optimization,
Academic Press, 1982, ISBN 0-124-92480-8.
+ L.R. Nyhoff, S. Leestma,
FORTRAN 77 and Numerical Methods for Engineers and Scientists,
Prentice Hall, 4th Edition, 1995, ISBN 0-023-88741-9.
* W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery,
Numerical Recipes in FORTRAN, The Art of Scientific Computing,
Cambridge University Press, 1992, ISBN 0-521-43064-X.
* W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery,
Numerical Recipes in Fortran 90,
The Art of Parallel Scientific Computing,
Cambridge University Press, 1996, ISBN 0-521-57439-0.
+ G.W. Sabot (Editor),
High Performance Computing : Problem Solving with
Parallel and Vector Architectures,
Addison-Wesley, 1995, ISBN 0-201-59830-2.
+ D.R. Wille,
Advanced Scientific Fortran,
John Wiley, 1995, ISBN 0-471-95383-0.

212

Appendix 1 : Fortran Resources - Part 14


========================================
-

9/ General Programming Literature :


* W. Brainerd, R. Cytron, R.E. Griswold, G. Grotzinger,
D.M. Ritchie, S. Summit,
Handbook of Programming Languages (P.H. Salus Editor),
Volume II, Imperative Programming Languages,
Macmillan Technical Publishing, 1998, ISBN 1-57870-009-4.
* S. McConnell,
Code Complete (2nd Edition),
Microsoft Press, 2004, ISBN 0-735-61967-0.
* S. Oliveira, D. Stewart,
Writing Scientific Software, a Guide to Good Style,
Cambridge University Press, 2006, ISBN 978-0-521-85896-0.

- 10/ Hardware Design and Performance Literature :


* R. Allen, K. Kennedy,
Optimizing Compilers for Modern Architectures,
Morgan Kaufmann (Academic Press), 2002, ISBN 1-55860-286-0.
* K. Dowd, C. Severance,
High Performance Computing,
OReilly and Associates, 2nd Edition, 1998, ISBN 1-56592-312-X.
* W. Stallings,
Computer Organization and Architecture, Designing for Performance,
Prentice Hall, 4th Edition, 1996, ISBN 0-13-394255-4.
* B. Wilkinson,
Computer Architecture, Design and Performance,
Prentice Hall, 2nd Edition, 1996, ISBN 0-13-518200-X.

213

Appendix 2 : Downloading and Running the Examples - Part 1


===========================================================
-

1/ Downloading the Example Routines and Data Files :


The Source and Data Files to Compile and run the example Fortran
Programs and Routines presented over the course are listed below.
They may all be downloaded from the online version of this page,
accessible from the "Example Program Files and Data" Link present
on both the Course Timetable and Outline Pages.
All Routines are coded in Fortran 77 unless otherwise indicated.
For a description of the processing refer to the comments at the
beginning of the Program Source Files *.for or *.f90.
Fortran Routine Source Files and Program Binaries :
Description
--------------------------------------Pentagonal Numbers, Fortran 77
"
"
,
"
90

File to Download
---------------clpent.for
clpent.f90

Pentagonal Numbers with Subroutine Call


Subroutine computing Pentagonal Number

clptsb.for
sbpent.for

Pseudo Random Number (return) Function


"
"
"
Subroutine
"
"
"
Display Program

fnduwh.for
rnduwh.for
ttrand.for

Interactive Version of Example Program


Course Example Program

splref.for
splrfb.for

Compiled Linux Binary for clpent.for


"
"
"
" clptsb.for
"
"
"
" splref.for
"
"
"
" splrfb.for
"
"
"
" ttrand.for

clpent.bin
clptsb.bin
splref.bin
splrfb.bin
ttrand.bin

Sample Data Files to run the Course Example Programs against :


Description
--------------------------------------Data Parameters for splrfb.bin
Sample Input Data for splref.bin,
or splrfb.bin
Sample Output Data from splrfb.bin

214

File to Download
---------------SPLCDT
SPLRIN
SPLROU

Appendix 2 : Downloading and Running the Examples - Part 2


===========================================================
-

2/ Compiling and Running the Example Routines :


- To run the Example Programs, download the Source Files with for
and f90 Extensions and then Compile them, or pick the ready made
Binary bin Files, which should run directly on a recent version
of Linux. In addition, splref.bin and splrfb.bin will need the
Data File SPLRIN and in the case of splrfb.bin, the Control
Parameters File SPLCDT too.
- To compile the Source Files, on a Unix computer or PC with Linux,
either the GNU gfortran or Intel ifort Compilers should work.
The latter requires a licence. gfortran does not, and comes as
part of recent Linux Distributions. Both accept Fortran 77 for,
or Fortran 90 f90 Source Files.
For example, using the clpent Program :
gfortran -o clpent.bin clpent.for
ifort

-o clpent.bin clpent.for

produce a local Version of the Binary clpent.bin.


When a Subroutines or Functions are involved, with the Source Code
in separate Files, the Main Program File and all Subprogram Files
should be jointly submitted to the Compiler. For example :
gfortran -o clptsb.bin clptsb.for sbpent.for
writes a Binary for the Program clptsb and Subroutine sbpent.
On some older Linux systems, the GNU Fortran compiler may be g77,
with only partial support for Fortran 90, or any later standards.
- Invoke the Binary on the Command Line, and respond to the Prompts.
The Interactive Version of the Course Example Program, splref.bin
will successfully run with replies SPLRIN, SPLROU, 12, 64,
and 1 or 2. The first two and last may be defaulted. The Values
correspond to those in the SPLCDT Control File for splrfb.bin.

215

You might also like