Professional Documents
Culture Documents
***********************************************************
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
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
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
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
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
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
: Executable Statements
END
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.
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
10
11
Col 6
----Cont.
Mark
Col 7-72
---------------------Fortran Statement Text
Col 73 onwards
-------------Ignored
12
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 >
!
&
;
?
13
CC
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
15
16
CCCC
CCCC
CCCC
100 WRITE
1000 FORMAT
( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )
READ
1001 FORMAT
IF
1002
( NPSTAT
.NE.
WRITE
FORMAT
( *,
( /,
GOTO
100
0 ) THEN
1002 )
Not an Integer. Try again )
ENDIF
CCCC
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
100 WRITE
1000 FORMAT
( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )
READ
1001 FORMAT
IF
1002
( NPSTAT
.NE.
WRITE
FORMAT
( *,
( /,
GOTO
100
ENDIF
!
= ( ( 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 )
END
18
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
CHS1,
CHS2,
CHS3
CHVAR1, CHVAR2, CHVAR3
INTEGER
LOGICAL
LGVAR1
REAL
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 90
21
C1, C2, C3
C1*12,
C2*12,
C3*12
CHARACTER
C1 * 12,
C2 * 12,
C3 * 12
1
1
1
1
C1 * 12,
C2 * 12,
C3 * 10
1
1
22
( 12 )
C1, C2, C3
CHARACTER ( LEN = 12 )
C1, C2, C3
C1, C2
CHARACTER ( LEN = 10 )
C3
23
- Integer entity.
- Example : to declare Integers I1, I2, I3,
INTEGER
I1, I2, I3
- On or Off Switch,
with Value .TRUE. or .FALSE..
- Example : to declare Variables LG1, LG2,
LOGICAL
XC1, XC2
24
DOUBLE PRECISION
D1, D2, D3
25
XC1, XC2
26
( A-B )
( C
( L
),
)
( I-K )
27
for
for
for
for
Data_String,
the Digits 0 to 7,
OBrien,
one Single Quote.
for
for
for
for
Data_String,
the Digits 0 to 7,
OBrien,
one Single Quote.
28
(Decimal Point)
(comma in Field)
-214748648
LOGICAL
29
(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
COMPLEX
( -0.31E-3, +7.50E+2 )
31
CFILE1
INTEGER
IFILE1
PARAMETER
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 ) )
32
IPR1
( IPR1 = 10.5 )
REAL
RPR2
DOUBLE PRECISION
DPR3
PARAMETER
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 )
( ICHL = 12 )
CHARACTER *7 ( I-J )
33
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
INTEGER
1
DATA
DATA
REAL
DOUBLE PRECISION
RDT1
DDT2
DATA
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
/ 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
CHS1, CHS2
DATA
CHS1, CHS2
CHS1 ( 5 : 7 ), CHS1 ( 3 : )
/ xx
, 123456789 /
35
IDT1,
/ 10 ,
IDT5,
/ 11 ,
IDT2,
10 ,
IDT6,
12 ,
IDT3,
10 ,
RDT1,
20.0,
IDT4
10
/
DDT2
24.0D0 /
/ 4 * 10 /
INTEGER
INTEGER
REAL
DOUBLE PRECISION
RDT1 = 20.0
DDT2 = 24.0D0
36
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
DOUBLE PRECISION
1
COMMON
1
COMMON
1
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
...
COMMON
37
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
38
39
EQUIVALENCE
( IEA1, IEA2 )
EQUIVALENCE
EQUIVALENCE
|====|
|====|
|====|----|
|====|====|
|====|====|
|====|----|
|====|
40
= 49153
EQUIVALENCE
( CEQ1 ( 4 : 6 ), CEQ2 )
EQUIVALENCE
( CEQ3, CEQ4 ( 9 : )
CEQ3 Memory
CEQ4
"
41
42
DATA
END
Example Named BLOCK DATA Subprogram :
BLOCK DATA BKDT01
DOUBLE PRECISION
DOUBLE PRECISION
COMMON
COMMON
DATA
DATA
END
43
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.
44
45
INTEGER
INV1, INV2
REAL
DOUBLE PRECISION
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
= 120
= 1200.0
= RLV3
RLV1
RLV2
RLV3
= 10
= 8E-03
= DPV1
INV1
INV2
= 10.5
= RLV2
= DBLE ( RLV3 )
= REAL ( DPV3 )
= 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
CXV1, CXV2,
CXV3, CXV4
REAL
RLV1
RLV1
= -2.2E-2
= +0.05
CXV1
CXV2
= ( 12.4, 28.6 )
= ( RLV1, RLV2 )
CXV3
CXV4
=
CXV1
= ( RLV1, -3.0 )
CXV1, CXV2
DOUBLE PRECISION
INTEGER
DPV1
INV1, INV2
DPV1
INV1
= 120.0D0
= -300
CXV1
CXV2
= ( DPV1
, INV1 )
= ( 120.0D0, -300 )
48
= DPV1
= INV1
RLV2
INV2
= CXV3
= CXV4
= ( DPV1, 0.0 )
= ( INV1, 0.0 )
RLV2
INV2
=
= INT
REAL ( CXV3 )
( REAL ( CXV4 ) )
= CMPLX ( DPV1 )
= CMPLX ( INV1 )
or more clearly :
CXV1
CXV2
49
=
AIMAG ( CXV3 )
= INT ( AIMAG ( CXV4 ) )
=
=
CXV1
CXV2
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
LGV1
LGV2
= .FALSE.
= .TRUE.
LGV3
= LGV1
51
= 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
result in :
CVR1
CVR2
CVR3
= Data_String
=
Long Tail
=
= 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
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
INV1
REAL
RLV1, RLV2
DOUBLE PRECISION
DPV1, DPV2
INV1
DPV2
= RLV1 + 52 * DPV1
= RLV2
* 12.6D2
54
(Exponentiation),
(Multiplication),
(Division),
(Addition),
(Subtraction).
55
56
57
58
CHV1
CHV2
CHV3
= 01 // 234567
= CHV1 // 89
= CHV1 // 89 // ABCDEF
= 01
// 234567
= CHV1 ( 1 : 8 ) // 89
= CHV2 ( 1 : 10 ) // ABCDEF
= 01234567xx
// ab
= CHV1 ( 1 : 8 ) // 89
= CHV2 ( 1 : 10 ) // ABCDEF
59
= 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
60
.AND.
.OR.
.EQV.
.NEQV.
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.
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
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
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
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
Relational
Operator
Arithmetic
Expression B (Right)
Relational
Operator
CHARACTER
Expression B (Right)
64
.GE.
.LE.
.GT.
.LT.
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.
>=
<=
for
for
.GE.
.LE.
>
<
for
for
.GT.
.LT.
The same rules apply for spacing as with the older style Operators.
65
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
67
CVR1, CVR2
CVR1
CVR2
= Data_String
= 01234567
68
.LGT.
.LLT.
.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
.AND.
.OR.
.EQV.
.NEQV.
CVR1, CVR2
LVL1
INTEGER
INV1, INV2
REAL
DOUBLE PRECISION
RLV1, RLV2
DPV1, DPV2
.NEQV.
INV1 .NE. 0
.EQV.
.AND.
.AND.
.OR.
.OR.
CVR2 .GE. 0
70
evaluated first,
"
after all .NOT.,
"
"
" .NOT. and .AND.,
"
last, after other Operators.
( INV1 .NE. 0
) .EQV.
( INV2 .GE.
INV1 ** 2 + 5 )
71
( INV1 .NE.
0
( INV2 .GE. ( INV1 ** 2 + 5
)
) )
INV1 = INV1 + 2
GOTO 200
) STOP
IF
1
IF
1
72
73
( INV1 .NE.
) THEN
INV1 = INV1 + 2
ENDIF
IF
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
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
ELSEIF
9 :
) THEN
9 ) = 8
= 9
) THEN
CHV1 ( 10 : 10 ) = 9
CBSE
= A
ELSEIF
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
ELSEIF
300
9 :
) THEN
9 ) = 8
300
) THEN
CHV1 ( 10 : 10 ) = 9
GOTO
500
ELSE
400
INV1
IBSE
IF
= INV1 + 2
= IBSE + 1
( IBSE .LE. 20 )
GOTO 400
ENDIF
500 IF
76
Block, as well
valid as the
Statements, and
IF.
) THEN
IF
) THEN
( CHV2 .GT.
CHV1 (
9 : 10 ) = 89
ENDIF
ELSEIF
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
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
IF
IF
IF
IF
78
79
100 CONTINUE
DO
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
DO
100
CONTINUE
DPV5 = ( DPV6 - DBLE ( ICNT ) )
200 CONTINUE
This two Level DO Loop Nest would be valid :
DO
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
100
IF
GOTO 300
200 CONTINUE
300 IF
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
83
84
85
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
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
88
89
90
91
CAR1 ( 200 ),
CAR2 ( 100 )
CAR3 ( 200 ) * 8, CAR4 ( 100 ) * 2
INTEGER
DOUBLE PRECISION
IAR1 ( 300),
DAR1 ( 0 : 24 ),
IAR2 ( 300 )
DAR2 ( 0 : 24 )
CAR1,
CAR2
CAR3 * 8, CAR4 * 2
INTEGER
DOUBLE PRECISION
IAR1, IAR2
DAR1, DAR2
DIMENSION
DIMENSION
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
92
CHARACTER*12 (C)
IMPLICIT
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
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
CAR1 ( 200 ),
CAR2 ( 100 )
CAR3 ( 200 ) * 8, CAR4 ( 100 ) * 2
INTEGER
DOUBLE PRECISION
DIMENSION
DAR1 ( 0 : 24 ), DAR2 ( 0 : 24 )
COMMON
COMMON
CAR1,
CAR2
CAR3 * 8, CAR4 * 2
INTEGER
DOUBLE PRECISION
IAR1, IAR2
DAR1, DAR2
COMMON
1
COMMON
1
where Array declarations happen when the Common Block are specified.
Note the CHARACTER and Numeric entities necessitate distinct Blocks.
95
IARR ( 8 )
thus fill
gets stored
it. So, the
:
IARR ( 6, 4 )
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
96
IARR ( 6, 3, 4 )
97
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
DATA
1
IAR2 (
/ 3000,
DATA
1
98
48 ) / 2 * 112 /,
96 ) / 2 * 124 /
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 /
99
I1, I2, I3
DATA
1
DATA
1
1
1
1, 10 )
1, 10 )
0, 9 )
* 0.0D0 /
However, whatever the way the lists of Variables and Values appear,
the number of Values must always match the number of Variables.
100
CARY ( 12 ), CSTR
INTEGER
DATA
1
CARY ( 12 )
= 012345
CARY ( 11 )( 7: ) = xxxxxx
CSTR
IAR2 (
IAR2 (
INVR
= IAR1 ( 11 ) ** 2
= IAR2 ( 21 ) ** 2
= IAR2 ( 3 ) * IAR1 ( 1 ) - 2
101
DO 100
INDX
= 1, 120
INDX
= 5, 110, 15
102
I3
= 1, 20
I2
= 1, 20
DO 100 I1
= 1, 20
DO 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
103
I3
= 1, 20
I2
= 1, 20
DO 100 I1
= 1, 20
DO 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
105
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
106
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
IAR1 (
8 )
IAR2 ( 100, 100 )
IAR3 (
8 )
IAR1
IAR3
= IAR2 ( IAR1, 1 )
IAR4 ( 6 )
IAR5 ( 8, 6 )
IAR4
IAR5
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
LBOUND
UBOUND
SHAPE
PRODUCT
MAXVAL
MINVAL
MAXLOC
MINLOC
=
MAXVAL ( IAR5, 3 )
= DBLE ( SUM
( IAR5 ) ) / DBLE ( SIZE ( IAR5 ) )
109
Array ARRY
Array SHPE.
the old. For
allows the
CSHIFT
EOSHIFT
110
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
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
113
114
which
Specifier
depending
neither
115
( 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
STATUS
One of : OLD
ACCESS
FORM
RECL
BLANK
117
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
)
118
( UNIT
STATUS
ACCESS
FORM
ERR
=
=
=
=
=
1
,
SCRATCH
,
SEQUENTIAL ,
UNFORMATTED,
920
)
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
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
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
FORMATTED
YES
NO
CHARACTER
Set to YES
for Formatted Files
NAME
ffff
CHARACTER
NAMED
.TRUE.
.FALSE.
LOGICAL
Set to .TRUE.
when File bears a Name
(continued on next page)
121
Values
----------nnnn
Type
--------INTEGER
Description
-----------------------Number of Next Record,
or 1 when at beginning
NUMBER
nnnn
INTEGER
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
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
123
END
REC
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
(8,1000,END=200,ERR=800) DVR1,DVR2,DVR3
READ
1
READ
1
1
1
1
( UNIT
FMT
END
ERR
IOSTAT
=
=
=
=
=
8
,
1000,
200 ,
800 ,
IOST ) DVR1, DVR2, DVR3
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
( 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
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
( 9
,
1300,
END = 230 ,
ERR = 830 ) DVA1
DVA1
DVA1
DVA1
(
(
(
(
12
14
16
18
),
),
),
),
DVA1
DVA1
DVA1
DVA1
(
(
(
(
13
15
17
19
),
),
),
)
IVAL
( 9
,
1300,
END = 230,
ERR = 830 ) ( DVA1 ( IVAL ), IVAL = 12, 19 )
127
IA2,
= 1,
= 1,
= 1,
IV3 ),
124
)
124
)
124
)
( 10 ,
1400,
END = 240,
ERR = 840 ) DVAR
( 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
IA2,
= 1,
= 1,
= 1,
IV3 ),
100
)
100
)
100
)
129
130
CHS1, CHS2,
CHS3, CHS4
DOUBLE PRECISION
INTEGER
DX01, DX02
INC1, INC2
COMPLEX
CNC1, CNC2
READ
READ
131
CHR1, CHR2
DOUBLE PRECISION
INTEGER
DX01, DX02
INC1, INC2
READ
READ
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
133
134
( UNIT
FMT
ERR
= 11 ,
= 4000,
= 900 ) DVR1, DVR2, DVR3
WRITE
1
1
1
1
( 10 ,
ERR = 840 ) ( ( ( DVAR ( IA1,
IA1
IA2
IA3
WRITE
WRITE
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
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
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
137
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
INTEGER
Floating
Point
Floating
Point
Floating
Point
Floating
Point
138
Description
---------------------------------------------------Set Blank to Null (Spaces of no effect on Numerics).
Set Blank to Zero for Numeric Fields.
SS
SP
Tnn
TLnn
TRnn
Xnn
cc
Hcc
139
CVAR
( 8, 1000 ) CVAR
( A )
( A16 )
( A6
( *, 1100 )
( /, Same non Extant File Name keyed,
/,
/, Please try again : )
WRITE
1101 FORMAT
( *, 1101 )
IVAL
( /, Value (, I6, ) not positive )
140
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
)
141
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
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
144
145
146
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
DOUBLE PRECISION
FUNCTION
RANGEN ( )
FUNCTION
AVRAGE ( SAMPLE )
147
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
148
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
SUBROUTINE
CHSUB2 ( )
SUBROUTINE
CHSUB3
149
CALL
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
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
DATSM1 ( 100 )
DATSM2 ( 100, 100, 20 )
AVRAGE ( DATSM1 )
AVRAGE ( SAMRRY )
DOUBLE PRECISION
SAMRRY ( 100 )
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 ( *, *, * )
152
CALL
CHARACTER
CSA1 ( 100, 50 )
CALL
CHSUB2 ( CSA1
SUBROUTINE
CHSUB2 ( CSA1
CHARACTER * (*)
CSA1 ( 100, *
153
CCCC
PRECISION RNTEST
100 WRITE
1000 FORMAT
( *, 1000 )
( /, Enter 3 Random Seeds or 0 0 0 to exit )
READ
IF
( NSTT
.NE.
WRITE
FORMAT
GOTO
( *,
( /,
100
1002
0 ) THEN
1002 )
Not an Integer. Try again )
ENDIF
IF
1
1
CCCC
CCCC
WRITE
2000 FORMAT
GOTO
= FNDUWH
( *, 2000 ) RNTEST
( /, 0-1 Random Uniform Number = , F12.10 )
100
END
154
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
CCCC
EXECUTABLE PART.
CCCC
CCCC
100 ISD1
ISD2
ISD3
CCCC
= MOD
= MOD
= MOD
( ( NSD1 *
( ( NSD2 *
( ( NSD3 *
171 ),
172 ),
170 ),
30269 )
30307 )
30323 )
CCCC
CCCC
CCCC
( ISD1
( ISD2
( ISD3
.LT.
.LT.
.LT.
0 ) ISD1
0 ) ISD2
0 ) ISD3
= -ISD1
= -ISD2
= -ISD3
END
155
CCCC
CCCC
100 WRITE
1000 FORMAT
( *, 1000 )
( /, Pentagonal Numbers, Enter Start Index : )
READ
1001 FORMAT
IF
( NPSTAT
WRITE
FORMAT
GOTO
1002
.NE.
( *,
( /,
100
0 ) THEN
1002 )
Not an Integer. Try again )
ENDIF
CCCC
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
CCCC
CCCC
CCCC
1000
( INDX .LT. 1
) THEN
ICDE
= 1
WRITE
( *, 1000 ) INDX
CCCC
200
IP = 1, 4
= 0
END
157
158
Result
--------CHARACTER
ICHAR
INTEGER
INDEX
CHARACTER
LEN
INTEGER
Result
--------COMPLEX
DBLE
DOUBLE
PRECISION
FLOAT
REAL
INT
INTEGER
REAL
REAL
159
Result
--------Same as
Argument
AINT
Same as
Argument
CONJG
COMPLEX
DIM
Same as
Args.
IMAG
REAL
MAX
Same as
Args.
MIN
Same as
Args.
MOD
Same as
Args.
NINT
Same as
Argument
SIGN
Same as
Argument
SQRT
Same as
Argument
160
Result
--------Same as
Argument
ASIN
Same as
Argument
ATAN
Same as
Argument
COS
Same as
Argument
Gives Cosine
of single Numeric Argument (in Radians).
COSH
Same as
Argument
EXP
Same as
Argument
LOG
Same as
Argument
LOG10
Same as
Argument
SIN
Same as
Argument
Gives Sine
of single Numeric Argument (in Radians).
SINH
Same as
Argument
TAN
Same as
Argument
TANH
Same as
Argument
161
Result
--------CHARACTER
ADJUSTR
CHARACTER
BIT_SIZE
INTEGER
BTEST
LOGICAL
EPSILON
Floating
Point
IAND
IEOR
IOR
INTEGER
IBCLR
IBSET
INTEGER
NOT
INTEGER
SCAN
INTEGER
TRIM
CHARACTER
VERIFY
INTEGER
Inverse of SCAN,
Position of first Char. not in String.
162
EXSUB1, EXFNC1
DOUBLE PRECISION
CALL
DPSUB2
DPLOC2
= EXFNC1 ( DPLOC1 )
( DPARG1, EXSUB1 )
EXTERNAL
SUB1
DOUBLE PRECISION
ARG1
163
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
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
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
167
CHARACTER CCDN * 6,
1
CIDN * 6,
1
CODN * 6
C----------------------------------------------------------------------CCCC
INTEGER TYPE CONSTANTS :
CCCC
-------------------------CCCC
CCCC
CCCC
NILN,
NDMX
DEFAULT PROCESSED BLOCKS AND ITEMS PER BLOCK.
INTEGER
NDDF
C----------------------------------------------------------------------CCCC
CONSTANT ASSIGNMENTS :
CCCC
---------------------CCCC
CCCC
CCCC
CCCC
12,
1024 )
168
CCCC
CCCC
CCCC
CCCC
CCCC
255
CCCC
CCCC
255
CCCC
255,
9
CCCC
255,
255,
9
CCCC
64,
64
CCCC
CCCC
10
255,
1
CHARACTER CTBK *
6,
1
CTIT *
6
C-----------------------------------------------------------------------
169
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
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
LOGICAL
LIEX
C----------------------------------------------------------------------CCCC
DOUBLE PRECISION TYPE VARIABLES :
CCCC
----------------------------------CCCC
CCCC
CCCC
DOUBLE
PRECISION
1
DIVA (NDMX * 2)
C----------------------------------------------------------------------CCCC
DATA INITIALISATIONS :
CCCC
---------------------CCCC
CCCC
INBK /
0 /
DATA
NUCN / 3 /,
1
NUIN / 8 /,
1
NUON / 9 /
C***********************************************************************
171
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
100 WRITE
( *, 1000 ) CCDN
1000 FORMAT
1
1
CIST
READ
1001 FORMAT
=
( *, 1001,
( A )
CCCC
CCCC
101 IF
( CIST .EQ. )
1
CIST
=
CCDN
C-----------------------------------------------------------------------
172
110 ICNL
DO 111
= 0
IINC
1,
LEN
( CIST )
IF
.NE.
) THEN
ICNL = ( ICNL + 1
)
CCFN
( ICNL : ICNL ) = CIST ( IINC : IINC )
ELSE
IF
( ICNL .GT. 0 )
GOTO
112
ENDIF
111 CONTINUE
CCCC
112 CCFN
CCCC
( ( ICNL + 1 )
: ) =
CCCC
CCCC
=
=
=
=
=
=
=
NUCN
,
CCFN ( 1 : ICNL ),
OLD
,
SEQUENTIAL
,
FORMATTED
,
NULL
,
ICST
)
1100
( UNIT
FILE
STATUS
ACCESS
FORM
BLANK
IOSTAT
( ICST
.NE.
0 ) THEN
WRITE
FORMAT
GOTO
100
ENDIF
C-----------------------------------------------------------------------
173
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
= 0
IINC
1,
LEN
( CIST )
IF
.NE.
) THEN
IINL = ( IINL + 1
)
CIFN
( IINL : IINL ) = CIST ( IINC : IINC )
ELSE
IF
( IINL .GT. 0 )
GOTO
123
ENDIF
122 CONTINUE
CCCC
123 CIFN
CCCC
( ( IINL + 1 )
: ) =
CCCC
= CIFN ( 1 : IINL ),
= LIEX
)
) GOTO
130
( *,
174
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
= 0
IINC
1,
LEN
( CIST )
IF
.NE.
) THEN
IODL = ( IODL + 1
)
COFN
( IODL : IODL ) = CIST ( IINC : IINC )
ELSE
IF
( IODL .GT. 0 )
GOTO
133
ENDIF
132 CONTINUE
CCCC
133 COFN
CCCC
CCCC
( ( IODL + 1 )
: ) =
1301
1
( COFN
WRITE
( *,
FORMAT
GOTO
ENDIF
C-----------------------------------------------------------------------
175
190 WRITE
1
1
1
1900 FORMAT
1
1
CCCC
CCCC
( *,
CCFN ( 1 :
CIFN ( 1 :
COFN ( 1 :
1900
ICNL
IINL
IODL
)
),
),
)
176
200 READ
2000 FORMAT
CCCC
CCCC
201 IF
( CIST
.EQ.
NTBK
GOTO
=
220
) THEN
NDDF
ENDIF
CCCC
CCCC
CCCC
CCCC
202 ITBL
DO 203
= 0
IINC
1,
LEN
( CIST )
IF
.NE.
) THEN
ITBL = ( ITBL + 1
)
CTBK
( ITBL : ITBL ) = CIST ( IINC : IINC )
ELSE
IF
( ITBL .GT. 0 )
GOTO
204
ENDIF
203 CONTINUE
CCCC
204 CTBK
( ( ITBL + 1 ) : ) =
C-----------------------------------------------------------------------
177
210 READ
2100 FORMAT
GOTO
CCCC
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
GOTO
990
C-----------------------------------------------------------------------
178
220 READ
2200 FORMAT
CCCC
CCCC
221 IF
( CIST
.EQ.
NTIT
GOTO
=
240
) THEN
NDDF
ENDIF
CCCC
CCCC
CCCC
CCCC
222 ITIL
DO 223
= 0
IINC
1,
LEN
( CIST )
IF
.NE.
) THEN
ITIL = ( ITIL + 1
)
CTIT
( ITIL : ITIL ) = CIST ( IINC : IINC )
ELSE
IF
( ITIL .GT. 0 )
GOTO
224
ENDIF
223 CONTINUE
CCCC
224 CTIT
( ( ITIL + 1 ) : ) =
C-----------------------------------------------------------------------
179
230 READ
2300 FORMAT
GOTO
CCCC
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
GOTO
990
C-----------------------------------------------------------------------
180
240 READ
2400 FORMAT
CCCC
241 IF
( CIST
.EQ. ) THEN
CIST
ENDIF
CCCC
CCCC
242 DO 243
IF
1,
LEN
( CIST )
ENDIF
243 CONTINUE
C-----------------------------------------------------------------------
181
250 WRITE
1
1
2500 FORMAT
1
CCCC
CCCC
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
CCCC
CCCC
300 IF
1
CCCC
CCCC
301 IF
1
CCCC
CCCC
CCCC
( NILN .LT.
GOTO
920
8 )
302 WRITE
( CFIV, 3002 )
1
NILN
,
1
( NILN - 7 )
3002 FORMAT ( E, I2.2, ., I2.2 )
C-----------------------------------------------------------------------
183
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
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
CCCC
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
( 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
IF
( CIHL ( 1 : 16 ) .NE. sp_dump> /source )
1
GOTO
411
C-----------------------------------------------------------------------
185
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
1
4203
ELSE
9 ) THEN
FORMAT
WRITE
( *,
4205 )
1
ITRW,
1
INBK
4205 FORMAT ( /, Block Size in File ( , I5, ) Not as Chosen,
1
/, for
SPL Data Block , I5
)
C-----------------------------------------------------------------------
186
430 READ
4300 FORMAT
CCCC
CCCC
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
(
(
ILIF
ILIL
= ( ILIF + 8 )
= ( ILIL + 8 )
= 942 )
)
432 CONTINUE
CCCC
CCCC
CCCC
CCCC
= 942 )
)
CCCC
CCCC
( ( NLMB * 4 ) .LT.
NTIT )
READ
( NUIN, CFIF , END = 932 , ERR
( DIVA (INVA), INVA = ILIF, NTVA
IF
( INBK .LT. NTBK ) GOTO 410
C-----------------------------------------------------------------------
187
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
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
( *, 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
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
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
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
999 WRITE
( *, 9999 )
9999 FORMAT ( /, **** RUN COMPLETED **** )
C***********************************************************************
END
192
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
-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
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
(-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)
...
...
...
...
...
...
...
...
...
...
...
...
(Default SPLCDT)
12
64
12 Blocks
195
196
197
198
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
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
201
202
203
204
205
206
207
208
209
210
211
212
213
File to Download
---------------clpent.for
clpent.f90
clptsb.for
sbpent.for
fnduwh.for
rnduwh.for
ttrand.for
splref.for
splrfb.for
clpent.bin
clptsb.bin
splref.bin
splrfb.bin
ttrand.bin
214
File to Download
---------------SPLCDT
SPLRIN
SPLROU
-o clpent.bin clpent.for
215