Introduction To Structured Programming With Fortran: CISM/CÉCI Training Sessions 21/10/2016
Introduction To Structured Programming With Fortran: CISM/CÉCI Training Sessions 21/10/2016
http://soliton.ae.gatech.edu/classes/ae6382/fortran/
●
FORTRAN 66 (ISO Standard 1972)
●
FORTRAN 77 (1980)
●
Fortran 90 (1991)
●
Fortran 95 (1996)
●
Fortran 2003 (2004)
● Fortran 2008 (2010)
●
Fortran 2015 (ongoing)
Starting with Fortran77
● Old Fortran (Fortran77) provides only the absolute
minimum!
● Basic features : data containers (integer, float, ...),
arrays, basic operators, loops, I/O, subroutines and
functions
● But this language has flaws:
Fortran77: no dynamic memory allocation, old &
obsolete constructs, “spaghetti” code, etc.
● Is that enough to write code?
Fortran 77 – Fortran >90
If Fortran77 is so simple,
Why is it then so difficult to write good code?
Executable
Source Code Object Code Code
Libraries
●
FORTRAN 90/95 relaxes these requirements:
– allows free field input
– comments following statements (! delimiter)
– long variable names (31 characters)
Program Organization
● Most FORTRAN programs consist of a main
program and one or more subprograms
(subroutines, functions)
● There is a fixed order:
Heading
Declarations
Variable initializations
Program code
Format statements
Subprogram definitions
(functions & subroutines)
Data Type Declarations
● Basic data types are:
– INTEGER – integer numbers (+/-)
– REAL – floating point numbers
– DOUBLE PRECISION – extended precision floating point
– CHARACTER*n – string with up to n characters
– LOGICAL – takes on values .TRUE. or .FALSE.
● Integer and Reals can specify number of bytes to use
– Default is: INTEGER*4 and REAL*4
– DOUBLE PRECISION is same as REAL*8
● Arrays of any type must be declared:
– DIMENSION A(3,5) – declares a 3 x 5 array (implicitly
REAL)
– CHARACTER*30 NAME(50) – directly declares a character
array with 30 character strings in each element
● FORTRAN 90/95 allows user defined types
Implicit vs Explicit Declarations
●
By default, an implicit type is assumed depending on the
first letter of the variable name:
– A-H, O-Z define REAL variables
– I-N define INTEGER variable
●
Can use the IMPLICIT statement:
– IMPLICIT REAL (A-Z) makes all variables REAL if not
declared
– IMPLICIT CHARACTER*2 (W) makes variables starting with
W be 2-character strings
– IMPLICIT DOUBLE PRECISION (D) makes variables
starting with D be double precision
●
Good habit: force explicit type declarations
– IMPLICIT NONE
– User must explicitly declare all variable types
Assignment Statements
● Assignment statement:
<label> <variable> = <expression>
– <label> - statement label number (1 to 99999)
– <variable> - FORTRAN variable (max 6
characters, alphanumeric only for standard FTN-
77)
● Expression:
– Numeric expressions: VAR = 3.5*COS(THETA)
– Character expressions: DAY(1:3)=‘TUE’
– Relational expressions: FLAG= ANS .GT. 0
– Logical expressions: FLAG = F1 .OR. F2
Numeric Expressions
●
Very similar to other languages
– Arithmetic operators:
– Precedence: ** (high) →- (low)
Operator Function
** exponentiation
* multiplication
/ division
+ addition
- subtraction
– Casting: numeric expressions are up-cast to the highest data
type in the expression according to the precedence:
(low) logical – integer – real – complex (high) and smaller byte
size (low) to larger byte size (high)
●
Example
arith.f
Character Expressions
●
Only built-in operator is Concatenation
– defined by // - ‘ILL’//‘-’//‘ADVISED’
●
Character arrays are most commonly encountered…
– treated like any array (indexed using : notation)
– fixed length (usually padded with blanks)
– Example:
CODE OUTPUT
CHARACTER FAMILY*16
FAMILY = ‘GEORGE P. BURDELL’
PRINT*,FAMILY(:6) GEORGE
PRINT*,FAMILY(8:9) P.
PRINT*,FAMILY(11:) BURDELL
PRINT*,FAMILY(:6)//FAMILY(10:) GEORGE BURDELL
Relational Expressions
●
Two expressions whose values are compared to
determine whether the relation is true or false
– may be numeric (common) or non-numeric
– Relational operators:
Operator Relationship
.LT. or < less than
.LE. or <= less than or equal to
.EQ. or == equal to
.NE. or /= not equal to
.GT. or > greater than
.GE. or >= greater than or equal to
●
Character strings can be compared
– done character by character
– shorter string is padded with blanks for comparison
Logical Expressions
●
Consists of one or more logical operators and logical,
numeric or relational operands
– values are .TRUE. or .FALSE.
– Operators:
Operator Example Meaning
.AND. A .AND. B logical AND
.OR. A .OR. B logical OR
.NEQV. A .NEQV. B logical inequivalence
.XOR. A .XOR. B exclusive OR (same as .NEQV.)
.EQV. A .EQV. B logical equivalence
.NOT. .NOT. A logical negation
●
Need to consider overall operator precedence
●
Remark: can combine logical and integer data with
logical operators but this is tricky (avoid!)
Arrays in FORTRAN
●
Arrays can be multi-dimensional (up to 7) and are indexed
using ( ):
– TEST(3)
– FORCE(4,2)
●
Indices are normally defined as 1…N
●
Can specify index range in declaration
– REAL L(2:11,5) – L is dimensioned with rows numbered 2-
11 and columns numbered 1-5
– INTEGER K(0:11) – K is dimensioned from 0-11 (12
elements)
●
Arrays are stored in column order (1st column, 2nd column,
etc) so accessing by incrementing row index first usually
is fastest.
●
Whole array reference:
– K=-8 - assigns 8 to all elements in K (not in 77)
Execution Control in FORTRAN
● Branching statements (GO TO and variations)
● IF constructs (IF, IF-ELSE, etc)
● CASE (90+)
● Looping (DO, DO WHILE constructs)
● CONTINUE
NOTE:
● PAUSE We will try to present the
FORTRAN 77 versions and then
● STOP include some of the common
variations that may be encountered
● CALL in older versions.
● RETURN
● END
Unconditional GO TO
●
This is the only GOTO in FORTRAN 77
– Syntax: GO TO label
– Unconditional transfer to labeled statement
10 -code-
GO TO 30
-code that is bypassed-
30 -code that is target of GOTO-
-more code-
GO TO 10
●
Flowchart:
GOTO 30 30
●
Problem: leads to confusing “spaghetti code”
IF ELSE IF Statement
●
Basic version: KEY= 1?
yes
X=X+1
ENDIF
– If logical expr1 is true, execute statement1(s), if logical expr2 is
true, execute statement2(s), otherwise execute statemens3(s).
– Ex:
10 IF (KSTAT.EQ.1) THEN
CLASS=‘FRESHMAN’
ELSE IF (KSTAT.EQ.2) THEN
CLASS=‘SOPHOMORE’
ELSE IF (KSTAT.EQ.3) THEN
CLASS=‘JUNIOR’
ELSE IF (KSTAT.EQ.4) THEN
CLASS=‘SENIOR’
ELSE
CLASS=‘UNKNOWN’
ENDIF
Spaghetti Code
●
Use of GO TO and arithmetic IF’s leads to bad
code that is very hard to maintain
●
Here is the equivalent of an IF-THEN-ELSE
statement:
10 IF (KEY.LT.0) GO TO 20
TEST=TEST-1
THETA=ATAN(X,Y)
GO TO 30
20 TEST=TEST+1
THETA=ATAN(-X,Y)
30 CONTINUE
●
Now try to figure out what a complex IF ELSE IF
statement would look like coded with this kind of
simple IF. . .
Loop Statements
●
DO loop: structure that executes a specified number of times
●
Nonblock DO
– Syntax: DO label , loop_control
do_block
label terminating_statement
– Execute do_block including terminating statement, a number of
times determined by loop-control
– Ex: Spaghetti Code Version
CALL AVG3S(A,C,B,4.1)
NO: no return value is available
since 4.1 is a value and not a
reference to a variable!
Arguments – cont’d
●
Dummy arguments appearing in a Subprogram
declaration cannot be an individual array element
reference, e.g., A(2), or a literal, for obvious reasons!
●
Arguments used in invocation (by calling program)
may be variables, subscripted variables, array names,
literals, expressions, or function names.
●
Using symbolic arguments (variables or array names)
is the only way to return a value (result) from a
SUBROUTINE.
●
It is considered BAD coding practice, but FUNCTIONs
can return values by changing the value of arguments.
This type of use should be strictly avoided!
FUNCTION versus Array
●
How does FORTRAN distinguish between a FUNCTION
and an array having the same name?
– REMAINDER(4,3) could be a 2D array or it could be a
reference to a function that returns the remainder of 4/3
– If the name, including arguments, matches an array
declaration, then it is taken to be an array.
– Otherwise, it is assumed to be a FUNCTION
●
Be careful about implicit versus explicit Type declarations
with FUNCTIONs…
PROGRAM MAIN
INTEGER REMAINDER
...
KR=REMAINDER(4,3)
...
END
INTEGER FUNCTION REMAINDER(INUM,IDEN)
...
END
Arrays with Subprograms
●
Arrays present special problems in subprograms…
– Must pass by reference to subprogram since there is no way
to list array values explicitly as literals.
– How do you tell subprogram how large the array is? (Answer
varies with FORTRAN version and vendor (dialect)…
●
When an array element, e.g., A(1), is used in a
subprogram invocation (in calling program), it is passed
as a reference (address), just like a simple variable.
●
When an array is used by name in a subprogram
invocation (in calling program), it is passed as a
reference to the entire array. In this case the array
must be appropriately dimensioned in the subroutine
(and this can be tricky…).
COMMON MODULE Statement
●
The COMMON statement allows variables to
have a more extensive scope than otherwise.
– A variable declared in a Main Program can be made
accessible to subprograms (without appearing in
argument lists of a calling statement)
– This can be selective (don’t have to share all
everywhere)
– Placement: among type declarations, after IMPLICIT
or EXPLICIT, before DATA statements
– Can group into labeled COMMONs
●
With Fortran 90, it’s better to use the MODULE
subprogram instead of the COMMON statement
Some Other Interesting Stmts
● EQUIVALENCE statement
– Syntax: EQUIVALENCE (list_of_variables) [,…]
– Used to make two or more variables share the same storage in
memory. This used to be an important way to conserve memory
without having to use the same variable names everywhere. It
can also be used to access an array element using a scalar
variable name (or to represent a subarray with another name).
– Ex: A and B are same
●
Older code may include statements that transfer data
between variables or arrays and internal (main
memory) storage. This is a fast but temporary
storage mechanism that was popular before the
widespread appearance of disks.
●
One method is to use the ENCODE & DECODE pairs
– DECODE – translates data from character to internal form,
– ENCODE – translates data from internal to character form.
●
Another method that is in some FORTRAN 77
dialects and is in FORTRAN 90 is to use Internal
READ/WRITE statements.
Internal WRITE Statement
●
Internal WRITE does same as ENCODE
– Syntax: WRITE (dev_no, format_label [,IOSTAT=i_var]
[,ERR=label]) [var_list]
– Write variables in var_list to internal storage defined by
character variable used as dev_no where:
●
dev_no = default character variable (not an array),
●
format_label = points to FORMAT statement or * for list-directed,
●
var_list = list of variables to be written to internal storage.
– Ex: Variables Internal storage
INTEGER*4 J,K
CHARACTER*50 CHAR50 Padded with blanks
DATA J,K/1,2/
... Results:
WRITE(CHAR50,*)J,K CHAR50=‘ 1 2’