|
|
||
![]() |
Department of
Mathematics and Computer Science |
|
PROGRAM HELLO
WRITE(6,*) "Hello World!"
END
FORTRAN "0" report - 1954Fortran-90/95/2003 is usually written without all the letter in UPPERCASE.
FORTRAN I compiler - 1957
FORTRAN II - 1958
---> added subroutine definition and invocation
FORTRAN IV - developed 1960-62, definitive report in 1966
---> added logical IF, type declaration
special versions:
---> Univ. of Waterloo, Ontario -- WATFOR
---------> WATFIV (WATerloo Fortran IV)
---------> WATFIV-S (Structured -- Pascal influenced)
FORTRAN 77 (or FORTRAN 5) - 1977
---> Planned FORTRAN 88 eventually led to:
FORTRAN 90 - 1990
---> added recursion, pointers, modules, local routines
---> and numerous matrix features
FORTRAN 95 - 1995
---> added FORALL statement and other features
---> for parallel machines
FORTRAN 2003 - 2004
---> interoperability with C,
---> allocatable components of derived types,
---> object oriented programming features,
- - - > e.g., "class" variables (polymorphic variables)
---> function pointers,
---> command line arguments,
---> and numerous other improvements.See http://math.scu.edu/~dsmolars/ma60/notesfor2003.html for some additional information on Fortran 2003 and Chapter 19 of The Essentials of Fortran 90/95/2003 (http://math.scu.edu/~dsmolars/ma60/briefcont.html) (which also lists features of earlier versions of Fortran no longer part of Fortran-95 or Fortran-2003.
For scientific work, Fortran compilers still regularly produce faster code and have a more extensive library of numerical routines than code written in other scientific languages.
(A) If there was a C or * in column 1, the card/line is considered a comment. The rest of the line is ignored. (One can also use the exclamation point as in Free Source Code Format if one compiles using a Fortran-90/95/2003 compiler.)IMPORTANT NOTE: In Fixed Source Code format, a common problem is using very long statements (and expressions) and forgetting about the column 72 "limit." ANYTHING which appears past column "72" on a line is ignored, even if it is the middle and end of a variable identifier! Thus it is possible that the end part of long statements will not be read by the compiler.(B) OTHERWISE
Columns 1-5 are used for statement label number (usually blank).
Column 6 is used ONLY to indicate this line is a continuation of the previous line (if a non-blank character is inserted).
Columns 7-72 are for the FORTRAN statement.
Columns 73-80 are ignored.
I do not recommend using Fixed Source Code Format when one has the possibility of using Fortran-90/95/2003 Free Source Code Format. However, one should know the rules governing Fixed Source Code Format so that one can read older programs and conform to the older restrictions if there is no access to Fortran-90/95/2003. Thus, always use the extension .f90 (or .f95 if using a Fortran-95 compiler).
In FIXED SOURCE CODE FORMAT, blanks are ignored by the compiler (except between quotes in output or literal strings), thus
e.g., NUMBER <==> N UM BE RHOWEVER, blanks DO count as far as counting columns is concerned.
NOTE: even if one uses the "old" Fixed Source Code format to write a program in a file, one can still use any new Fortran 90/95/2003 statements.
PROGRAM identifier ! This line can be omitted.
[variable declarations]
[statements]
[STOP]
END
[SUBROUTINE and FUNCTION codes usually follow
in any order.]
Fortran has preserved default typing for non-declared variables! If the identifier begins with any letter between I and N (inclusive), the variable is considered to be if type INTEGER, otherwise it is considered to be REAL.
One can "turn off" this default typing and force all variables to be declared explicitly by using
IMPLICIT NONE
immediately before any declaration statement and after the initial
PROGRAM (or similar) line of the segment.
To declare variables explicitly, one lists them after the name of the type (and any "attribute" and an optional double colon) in a declaration statement, separating the identifers with commas (similar to C/C++ syntax). E.g.,
INTEGER I, J, K
REAL :: X, Y, Z
CHARACTER (LEN=10) :: NAME1, NAME2
The older style of declaration of character variables was as
follows:
CHARACTER*10 SURNAM
To declare an array, one can indicate the maximum subscript value in
parentheses (assuming the low value is 1) after the identifer
name. Alternatively, one includes the attribute DIMENSION after
a comma and the type name and before the double colon (for Fortran-90/95/2003).
One can also specify an alternative starting value for the subscript
by including low and high values together, separated by a colon. E.g.,
REAL A(50), B(-10:10)
INTEGER, DIMENSION(10) :: IDNUMBERS
INTEGER, DIMENSION(20:40) :: ROW_NUMBERS
Fortran-90/95/2003 permits designating an array as "ALLOCATABLE", indicating
the number of dimensions by using a colon, and then allocating space
using the ALLOCATE statement in the course of the program. One can
later DEALLOCATE an array, if it is no longer needed.
REAL :: A = 1.0
INTEGER :: I = 2, J = 3
Alternatively, one may use the older DATA statement to
initialize variables declared explicitly or by default.
DATA A/2.7/, I,J/3,5/
To specify an identifier as an unchangeable constant, Fortran-90/95/2003
style is to use the PARAMETER attribute when declaring
the variable and assigning it a value. For example,
REAL, PARAMETER :: PI = 3.1415926
For example, suppose we have the array A declared as INTEGER A(3,3). The elements are stored in this order:
A(1,1), A(2,1), A(3,1), A(1,2), A(2,2), A(3,2), A(1,3), A(2,3), A(3,3).
TYPE INFOLINE
CHARACTER (LEN = 30) :: NAME
CHARACTER (LEN = 50) :: ADDRESS
INTEGER :: ZIP
INTEGER :: ACCNTNUM
END TYPE INFOLINE
To declare variables of the new type, one again uses the keyword
TYPE, followed by the name of the derived type in
parentheses. For example,
TYPE (INFOLINE) :: ACCOUNT, LIST(100), TEMP
In general, the principles are the same as with C++ or Pascal for record variables, except that instead of using the period (dot), . , as a subdivider, one uses the percent sign, %. For example,
ACCOUNT%ZIP
LIST(1)%ACCNTNUM
INTEGERs are written without any decimal point. E.g., 5 or -2.REALs are written with a decimal point and (optionally) an exponent. E.g., 3.1415926 or 10.2E22
DOUBLE PRECISION reals are written with a decimal point and an exponent with a D before the exponent. E.g., 1.0D00.
Extended precision numeric constants can be written with an underscore and the identifier related to their precision. E.g., 1.0_DP (assuming DP has the appropriate value).
COMPLEX numbers are written as a pair of reals separated by a comma, within parentheses. E.g., (5.2,6.721)
LOGICAL constants are .TRUE. and .FALSE. They must be surrounded by periods!CHARACTER strings are enclosed in single (or double, for Fortran-90/95/2003) quotes, e.g., 'Hello'. In pre-Fortran-90, it was also permitted to use the "Hollerith" descriptor which was the letter H preceeded by the number of characters, e.g., 5HHello. (Note that the Hollerith descriptor was designated as an "obsolescent" feature and has been officialled dropped in Fortran 2003.)
INTEGER, DIMENSION(5) :: C = (/1, 3, 4, 0, 4 /)
The operators are +, -, *, /, and ** (for exponentiation).NOTE: As with C/C++ (and unlike Pascal), / is used both for integer and real division and takes its cue from the operands.
Precedence: ** take precedence over * and / which take precedence over + and -.
Evaluation: left to right except for repeated **.
Thus, e.g., 2**3**5 is equivalent to 2**(3**5).
Parentheses may be used as in algebra to supercede normal precedence.
5/2 evaluates to 2
2/5 evaluates to 0
5/2. evaluates to 2.5
2.0/5 evaluates to 0.4
F77 F90/95/2003
.EQ. ==
.LT. <
.LE. <=
.GT. >
.GE. >=
.NE. /=
Combinational Operators:
Fortran C++
.AND. &&
.OR. ||
.NOT. !
As in C++, logical expressions MUST be surrounded by parentheses.
Precedence:
The arithmetic operators have higher precedence
than relational, which have higher precedence than .NOT.
which has a higher precedence than .AND. which has a higher
precedence than .OR.
If B is declared as CHARACTER (LEN=7) and B = 'John' // 'son', then the value of B is Johnson
A = 2 + 3
Note: the left side must be a variable.Fortran-90/95/2003 permits the use of the assignment and arithmetic operators for array variables as well. For example, if A, B, and C are all arrays of the same dimension, an assignment (and arithmetic operation) such as
A = B + C
is legal, and adds corresponding elements in
arrays B and C
and places the result in A.
One can also multiply every element in an array by a constant in a similar manner, e.g., A = B * 3, or use a library function to operate on every element in an array, e.g., A = SQRT(B).
The older FORTRAN-77 style explicitly includes the statement number of the final statement of the DO loop. The final statement was often the CONTINUE statement, a statement which does absolutely nothing. As an example:
DO 20 I = 1, 20
...
20 CONTINUE
In this example, the loop variable I starts at the value of 1
and finishes with the value of 20.
Any legal statement number could be used to indicate the last
statement of the loop.
The Fortran-90/95/2003 style omits the statement label and uses an END DO as the final statement in the loop as this revised example shows:
DO I = 1, 20
...
END DO
To use a "stride" or "step," one adds another comma and number in
the header line, for example:
DO I = 1, 23, 2
...
END DO
In this example, I starts at the value of 1 and increases by increments of 2 to 23.
(To count "down," one may use a stride, e.g., -1.)
As a matter of style, one should not use the older DO-loop when a compiler accepts the Fortran-90/95/2003 version of DO loops!
In Fortran-66, a negative stride was not permitted, and the termination "test" was performed at the end of the loop. Thus, every DO-loop was performed at least once, even if the condition seemed otherwise inconsistent.
With Fortran-77 and Fortran-90/95/2003, the testing is performed at the beginning of the loop and so for appropriate start and stop loop values, the interior of the loop might never be performed.
Although Fortran-77 introduced the possibility of real variables and values as loop boundaries, this is now scheduled for obsolescence.
Using the following structure,
DO
...
END DO
forces an infinite loop. Though not too useful in itself, it can be
helpful if used with an EXIT clause.
The EXIT statement is used with a one-line IF (see next section) and forces a termination of a loop. Its form is exemplified as follows:
IF ( .NOT. (TOT <= 100) ) EXIT
This would end the looping and continue the program with the statement
after the END DO.
We can use CYCLE in a similar way to skip the rest of the statements in the loop but continue the loop process itself.
Fortran-90/95/2003 also includes the DO WHILE loop exemplified as follows:
DO WHILE ( condition )
...
END DO
As long as the condition is true, the loop will continue its operation,
but when the condition turns false, the loop is exited.
IF (A < B) THEN
...
ELSE
...
END IF
NOTE that the concluding END IF can be spelled as one word or two
on most systems. NOTE also that the IF...THEN, ELSE, ENDIF must be
on separate lines from the statements they govern.
The ELSE clause may be omitted, for example,
IF (A == B) THEN
...
END IF
One can include several ELSE clauses in one IF if one uses the
following form in which an ELSE IF is placed on a single line:
IF (A >= B) THEN
...
ELSE IF (A > C) THEN
...
ELSE
...
END IF
In place of the THEN, one can put a simple statement to condense
an IF statement to one line. For example,
IF (A <= 0 ) A = -A
This can be used in Fortran-90/95/2003 to EXIT out of an infinite loop (as
the example above demonstrated).
Older versions of Fortran include an "arithmetic IF" and an "(two-value) logical IF." Although still supported, they are not recommended for use, since they function by means of implicit "GO TO" statements, whose use is strongly discouraged by modern programming style.
SELECT CASE (IVAR)
CASE (1)
CALL SUB1
CASE (2:4)
CALL SUB2
CASE DEFAULT
CALL SUB3
END SELECT
NOTES:
(1) IVAR in parentheses after SELECT CASE is the variable whose value will be tested against options listed in the alternatives;
(2) the second alternative shows how to list a range of consecutive values;
(3) each option is a mutually exclusive alternative (unlike C++).
STOP is the last executable statment in the main program and will actually stop the program (similar to the exit call in C/C++).
RETURN is the last executable statment in the subprogram and will causes the subprogram to return back to the point from which it was invoked.
Usually, either statment comes, physically, right before the END statement, though not of necessity (depending on the logical flow of the program).
Fortran-90/95/2003 permits omitting the STOP or RETURN statement when it would occur immediately before the END.
A subprogram may also include a STOP statement if the desired effect is to cause an immediate termination of the program without returning to any calling point.
102 FORMAT(1X,I5,F10.3)
In for Integers:
n indicates the number of spaces needed.Ew.d Real number in Exponential form:
w corresponds to the total number of spaces needed.
d corresponds to the number of digits to the right of the decimal point.
An E descriptor (for output) needs one space for the letter E, three spaces for the exponent and its sign, three more spaces for the decimal point, an initial zero before the decimal point, and a possible minus sign. Thus, in general (for output), w should be greater than or equal to d + 7.Fw.d Real number in Fixed form:
w corresponds to the total number of spaces needed.
d corresponds to the number of digits to the right of the decimal point.An Alphanumeric (Characters):
n indicates the number of spaces needed.nX Blank Space:
n indicates the number of spaces needed. Note that the number precedes the letter.
12 FORMAT(3(2I3,F3.1))
is equivalent to
12 FORMAT(I3,I3,F3.1,I3,I3,F3.1,I3,I3,F3.1)
READ(idevice,iformat) var_list
READ(5,*) (A(I),I=2,20,2), B, C
READ(5,"(I2,F10.3)") I, X
The result is a statement very similar in format to what occurs
with standard C I/O in which, using a scanf statement,
descriptors and variables occur on one line with descriptors enclosed in quotes.
DO
READ(20,100,END=30) I
...
END DO
30 CONTINUE
WRITE(idevice,iformat) var_list
On the DEC Alpha server scuacc, numbers in the 20s may be used for datafiles and correspond to files named FOR020.DAT or similarly.
Fortran also includes specific statements to OPEN and CLOSE data files by name and associate them with specific device numbers.
For ease of understanding, it may be best to think that an output line begins with column 0 or column "cc" (carriage control) and the first VISIBLE column is the next column, i.e., column 1. Whatever appears in column 0 is not printed but is interpreted as a printer command.
To avoid unintended things from happening on output, common practice is to begin output FORMAT statements with a 1X or ' ' as the first field descriptor.
blank the rest of the line is printed on the same line 1 a "top-of-form" (page eject) is performed before the remaining information is printed (ignoring column 0 on the top of the next page). 0 "double space," i.e., a line is skipped before the rest of the line is printed (ignoring column 0 on the next line). + the previous line is overstruck (double printing).
NOTE: Most other characters are ignored (i.e., are intepreted as if they were a blank), although certain implementations allow other possibilities.
Note that Unix provides the system command asa to convert files with Fortran carriage controls to other formats. See the on-line documentation for more information.
PROGRAM TEST2
IMPLICIT NONE
INTEGER NUM
REAL MILES, KILOS
WRITE(6,100)
100 FORMAT(7X, 'Miles', 3X, 'Kilometers')
DO NUM = 5,60,5
MILES = NUM
KILOS = MILES*8.0/5.0
WRITE(6,'(2F10.1)') MILES, KILOS
END DO
STOP
END
The first line of a function indicates the data-type of the return value of the function, followed by the keyword FUNCTION, followed by the function name, followed by the argument list in parentheses. For example,
REAL FUNCTION ROOT(A,B,C)
REAL :: ROOT, A, B, C
RECURSIVE FUNCTION FIBONACCI (N) RESULT (FIB_RESULT)
The first line of a subroutine starts with the keyword SUBROUTINE, followed by the subroutine name, followed by the argument list in parentheses. For example,
SUBROUTINE ROOTS(A,B,C,X1,X2)
CALL ROOTS(A,B,C,PROOT,NROOT)
PROGRAM FINDROOT
REAL :: A,B,C,X1,X2
READ(5,*) A,B,C
CALL ROOTS(A,B,C,X1,X2)
WRITE(6,10) A,B,C
10 FORMAT(1X, 'The roots of', F10.2,'x**2 + ', &
F10.2,'x + ',F10.2,' are ')
WRITE(6,11) X1,X2
11 FORMAT(1X,F10.5,' AND ',F10.5)
STOP
END
!
SUBROUTINE ROOTS(A,B,C,XP,XN)
REAL :: A,B,C,XP,XN,RAD
RAD = SQRT(B**2 - 4.0*A*C)
XP = (-B+RAD)/(2.0*A)
XN = (-B-RAD)/(2.0*A)
RETURN
END
A simple example of a module containing data is the following:
MODULE SAMPLE1
INTEGER, DIMENSION (10) :: K
END MODULE
!
PROGRAM TEST8
USE SAMPLE1
INTEGER I
CALL SUB1
DO I = 1,10
WRITE(6,*) K(I)
END DO
END
!
SUBROUTINE SUB1
USE SAMPLE1
INTEGER I
DO I = 1, 10
K(I) = 21-2*I
END DO
RETURN
END
The following is an example of a module definition for a stack,
with the data being designated as PRIVATE and the member functions for
a stack being coded as local module routines.
MODULE STACK_MOD
TYPE STACK
PRIVATE
INTEGER :: STACKELEMENT(100)
INTEGER :: TOP
END TYPE
CONTAINS
SUBROUTINE INIT(S)
TYPE(STACK) :: S
S%TOP = 0
END SUBROUTINE
!
SUBROUTINE PUSH(S,ITEM)
TYPE(STACK) :: S
INTEGER :: ITEM
IF (S%TOP < 100) THEN
S%TOP=S%TOP+1
S%STACKELEMENT(S%TOP) = ITEM
ELSE
WRITE(*,*) "STACK OVERFLOW"
STOP
ENDIF
END SUBROUTINE
!
INTEGER FUNCTION POP(S)
TYPE(STACK) :: S
IF (S%TOP > 0) THEN
POP = S%STACKELEMENT(S%TOP)
S%TOP = S%TOP-1
ELSE
WRITE(*,*) "STACK UNDERFLOW"
STOP
ENDIF
END FUNCTION
END MODULE
One major difference in the ways "pointers" can be used in Fortran-90/95/2003 is that they can also be used to "point" to a section of a large data structure, for example, to a row or column of an array. In addition, they can be used as variables in their own right. Thus, the concept of a "pointer" variable in Fortran-90/95/2003 is much more versatile than similar variables in other programming languages.
REAL, POINTER :: Y
One also needs to identify those variables to which Y (or any other appropriate pointer) can point, and this is done by adding the attribute keyword TARGET in the variable declarations of such variables, as follows:
REAL, TARGET :: X
If X and Y are declared as in the previous section, and if one invokes the pointer assignment statement,
Y => X
then Y would, in effect, become an alias for
X. In other words, the memory
location associated with X is now also the
memory location associated with Y. Thus if the value of
X changes, so does the value of Y and vice versa,
since both X and Y refer to one and the same memory
location.
TYPE NODE
INTEGER :: INFO
TYPE (NODE), POINTER :: NEXT
END TYPE NODE
After defining this new data type NODE, one can then declare variables to be pointers to elements of this data type in the usual way, for example:
TYPE (NODE), POINTER :: LIST, TEMP
This statement would declare LIST and TEMP
to be variables which could be used as pointers to
memory sections of derived type NODE.
Note, however, that after declaration, LIST and TEMP do not contain any information, nor do they "point" to any node. This is so because there have been no variables declared with a "target" pointer attribute and no assocation has taken place!
To allocate memory for a node, one may make use of the library statement ALLOCATE, which is similar in function to the Pascal procedure new or the C++ function new when used with pointer variables. Invoking the following statement
ALLOCATE(LIST)
causes memory to be allocated for a derived variable of
the type of which LIST is declared to be (i.e., in this
case, of type NODE) and then the identifier LIST
can be used to access the fields of the node.
A pointer variable can be set or reset to "null" by invoking the library statement NULLIFY. (This has the same effect as using the Pascal nil or the C++ NULL in an assignment statement.) In Fortran-90/95/2003, this statement is used as in this example:
NULLIFY(LIST%NEXT)
Fortran-95 also permits LIST%NEXT => NULL()
IF(K.EQ.1) GO TO 212
IF(K.EQ.2) GO TO 18
GO TO 106
212 X(1) = 5.
Y(K) = K+2.5
32 IF(K*J.LE.4) GO TO 184
30 L4 = K*J-K+1
Y(L4) = 1.0
X(L4) = Y(L4)
210 IF(K-J.GE.7) GO TO 265
GO TO 184
18 X(K) = 6.
Y(K) = K-1.5
GO TO 32
106 IF(K.NE.3) GO TO 10
Y(K) = 0.0
X(K) = Y(K)
GO TO 23
265 IF(K.GE.J+7) GO TO 10
X(K-J+1) = 0.0
Y(K-J+1) = 1.0
GO TO 10
184 IF(K*J.LE.4) GO TO 23
180 L = K*J-2*K
Y(L) = 0.0
X(L) = Y(L)
23 IF(K-J.GE.7) X(K-J+1) = 1.0
IF(K*J.LE.4) GO TO 30
GO TO 265
10 IF(K-J.GE.7) Y(K-J+1) = 0.0
SELECT CASE (K)
CASE(1)
X(1) = 5.0
Y(K) = K+2.5
CASE(2)
X(K) = 6.
Y(K) = K-1.5
CASE(3)
X(K) = 0.0
Y(K) = 0.0
END SELECT
IF(K*J <= 4) THEN
L4 = K*J-K+1
X(L4) = 1.0
Y(L4) = 1.0
ELSE
L = K*J-2*K
X(L) = 0.0
Y(L) = 0.0
END IF
IF(K-J >= 7) THEN
X(K-J+1) = 1.0
Y(K-J+1) = 0.0
ELSE
X(K-J+1) = 0.0
Y(K-J+1) = 1.0
END IF
In older versions of Fortran, variable allocation was static. Fortran-90/95/2003 allows dynamic allocation of pointers and arrays. By default, all variables are local.
Because of the static variable allocation in older versions of Fortran, recursive subprogram calls did not exist.
Fortran's original informality of syntax led to concerns about completeness of specification, determination of legal expressions, resolutions of ambiguities.
The development of compiler theory indicated that earlier versions of Fortran were disasters for code translation and thus improvements were desirable. This accounted for some of the new features in more recent versions of Fortran.
Fortran was commonly blamed for a space disaster because of the "default type" declaration feature. (Although this "blame" is thought to be false nowadays.) The first U.S. Mariner I rocket, launched on July 22, 1962 from Cape Canaveral on the first mission to Venus, was destroyed at a cost of $18.5 million because it started veering toward populated areas. The blame was commonly placed on a mistake by a programmer. It was commonly said that instead of writing
DO 3 I=1,3 ! comma between 1 and 3
a programmer had written
DO 3 I=1.3 ! period between 1 and 3
The first statement is a legitimate initial statement for a counted
loop, but the second statement is a legitimate assignment statement
giving the REAL variable DO3I the value of 1.30.
By using the END DO statement and Free Source Code Format, this error would now be detected during compilation.
This page is maintained by Dennis C. Smolarski, S.J.
dsmolarski@math.scu.edu
Last updated: 28 September 2005.