Contact us Heritage collections Image license terms
HOME ACL Associates Technology Literature Applications Society Software revisited
Further reading □ Overview1962: An outline of Fortran1962: Operating experience with Fortran1962: Implementation of Fortran on Atlas1962: Proposed target language (BAS)1962: BAS binary card1963: Intermediate Atlas symbolic programming language (INTERASP)1963: Addendum1963: A primer for Fortran programming1964: Atlas Fortran manual: Part I1964: Part II1964: Using HARTRAN1965: System note 41966: Fortran on Atlas □ Atlas 2 at AWRE □ 1965: BAS subroutines1965: System notes1966: S3 Fortran □ Titan □ 1966: System note 11966: System note 21966: Fortran on Titan1966: Compile Master on Titan1966: System Note 31966: Differences between S3 dialect and Fortran II1966: Magnetic tape library subroutines1967: T3 Fortran reference manual
ACD C&A INF CCD CISD Archives Contact us Heritage archives Image license terms

Search

   
ACLApplicationsHartran :: Hartran and Fortran on Atlas
ACLApplicationsHartran :: Hartran and Fortran on Atlas
ACL ACD C&A INF CCD CISD Archives
Further reading

Overview1962: An outline of Fortran1962: Operating experience with Fortran1962: Implementation of Fortran on Atlas1962: Proposed target language (BAS)1962: BAS binary card1963: Intermediate Atlas symbolic programming language (INTERASP)1963: Addendum1963: A primer for Fortran programming1964: Atlas Fortran manual: Part I1964: Part II1964: Using HARTRAN1965: System note 41966: Fortran on Atlas
Atlas 2 at AWRE
1965: BAS subroutines1965: System notes1966: S3 Fortran
Titan
1966: System note 11966: System note 21966: Fortran on Titan1966: Compile Master on Titan1966: System Note 31966: Differences between S3 dialect and Fortran II1966: Magnetic tape library subroutines1967: T3 Fortran reference manual

An Outline of FORTRAN

I C Pyle

July 1962

Atomic Energy Research Establishment, Harwell, England

Proceedings of a Symposium held at the London School of Economics, Editor Peter Wegner

1. Introduction

The first point which I wish to emphasize is that a program written in FORTRAN consists of a collection of routines, which are physically disjoint. They are translated separately into an intermediate binary language, and at a later stage are combined by a loader to form an executable program.

This process can be illustrated diagrammaticaly thus:

Fortran Routine Fortran Compiler Binary Routine Binary Routine Loader Executable Program Other routines similarly

The routines have to be presented to the computer in some hard form which is usually punched cards. If there is a suitable input channel the computer could accept paper tape input. There is no inherent difference, because lines of information are assembled as they would be printed, and these line images are processed by the compiler.

Here is an example of a complete FORTRAN program, to compute and print sqrt(a12 + a22 + . . . + an2) where a1, a2 etc are provided as data. It consists of two routines (a main routine and a subroutine) which contain various types of statement: i.e. declarations and instructions including input/output statements with format specifications, and a DO loop to control the repetitive execution of a group of statements.

C     MAIN ROUTINE
      DIMENSION A (1000)
      READ INPUT TAPE 2, 100, N, (A (I), I = 1, N) 
100   FORMAT (I5/(7F10.0))
      CALL SUMSQ (A,N, TOTAL)
      S = SQRTF (TOTAL)
      WRITE OUTPUT TAPE 3, 103, N, S 
103   FORMAT (I10, F15.5)
      CALL EXIT
      END
      
      SUBROUTINE SUMSQ(VECTOR, NUMBER, SUM) 
      DIMENSION VECTOR (1000) 
      X =0.
      DO 5 I = 1, NUMBER 
      X = X + VECTOR (I) ** 2 
5     CONTINUE 
      SUM = X 
      RETURN 
      END

As will be seen from the example, a routine consists of a simple sequence of statements. (There are no compound statements.) Each statement begins on a new line, and may extend over several lines. A special mark (a character other than blank or '0' in column 6) indicates that the current line is a continuation. A routine may contain comments, which are to be printed with the routine but otherwise ignored. Each comment must be on one separate line, and indicated by a special mark (C in column 1). The first line in the example is a comment.

The operations in FORTRAN are designed principally to describe numerical calculations, but may be used for quite general work in a computer. Statements are either executable (instructions which specify operations to be carried out), or non-executable (declarations which specify the properties of names used).

Although some statements look like algebra, there is an important difference; they are dynamic, expressing the process of computation, rather than static, expressing relations. Thus the statement

      I = I + 1

is completely legitimate, meaning that the expression I + 1 is to be evaluated and assigned as the new value of the variable I. The equals sign means is to be given the value of rather than has the same value as.

The dialect of FORTRAN which is mainly described here is called FORTRAN II. This is the version which has been widely used up to the present. New dialects are now being introduced, principally FORTRAN IV and also Atlas FORTRAN. Some of the differences will be mentioned in passing.

2. Variables, Names and Values

The fundamental quantities in FORTRAN are called variables, which are identified by their names. Each variable can take any value within a certain domain, and the value may be changed during the computation. A statement involving variables is to be treated in the same way, regardless of the actual values which the variables currently have. Some instructions allow the current values of variables to be tested, and thus determine subsequent action.

Names, which identify variables and other objects in FORTRAN, consist of up to six characters (letters or digits), of which the first is a letter. The choice of names is left to the programmer, except for certain standard functions.

Thus in the above example, the variables are called

A, N TOTAL, S, VECTOR, NUMBER, SUM, X, I

The name SQRTF denotes a standard function (square root). Some others are described in Section 4.

It is possible for several names to identify the same object, and for the same name in different contexts to identify different objects. Each name has the same meaning throughout the routine in which it occurs: it cannot be used to identify more than one object in one routine. But in different routines, the same name may be used to identify different objects. The region throughout which the name identifies the same object (i.e. has the same meaning) is called the scope of the name.

When we speak of the object (variable, array, function, etc.) X we really mean the object whose name in this context is X. Similarly the value is X or there are N equations really refer to the current value of the variable whose name in this context is given.

The values which a variable can take all lie within a particular domain. The domains normally used in numerical work are REAL (floating point numbers having a finite accuracy in a large but finite range) and INTEGER (integers lying in a finite range, usually used for counting). Another domain of interest is COMPLEX (in which the real and imaginary parts are separately in the domain REAL). The finite accuracy and range of the REAL domain is sometimes inadequate, and extended multiple precision domains may be needed to improve the situation.

Non-numerical domains which are useful are LOGICAL (containing only two values .TRUE, and .FALSE.) and TEXT in which the values are characters (letters, digits etc.). It is sometimes possible to treat a sequence of logical variables or characters together as a single variable.

The mode of a variable is the domain in which its values lie. There is a convention that the name of a variable indicates its mode, according to the initial letter: I,J, K, L, M, or N for INTEGER, the other letters normally for REAL, but can be used for the other modes. Thus, in the above example

N, NUM, I   are INTEGER 
A, TOTAL, S are REAL

This convention must be adhered to in FORTRAN II, but can be overridden in the new dialects.

3. Arrays

An array is identified by its name, whose initial letter indicates the mode of the members (all of which should be of the same mode). For example, all the numbers at in the example are REAL, and they are grouped in the array A. Individual members of the array are specified by the array name followed by a list of subscripts, separated by commas, and enclosed in parentheses. The subscripts must have INTEGER values. In the dialects FORTRAN II and FORTRAN IV, the allowed forms of subscripts are typified by:

2, I, J+3, K-4, 
5*L, 6*M +7, 8*N - 9

The number of subscripts, and the range of values which they may take (lower and upper bounds) are fixed properties of the array. An array with one subscript represents a vector; one with two subscripts a matrix. Three dimensional arrays are also allowed. An isolated variable may be thought of as an array with no subscripts: it represents a scalar.

These properties are associated with the array name by specifying its dimensions. If we think of the array as a multi-dimensional cuboid, we give the ordered set of lengths in the different dimensions. The lower bound for subscript values is always 1; the specified lengths are the upper bounds. Thus in the example we have in the main routine

      DIMENSION A (1000)

which specifies that A is an array name, that one subscript is to be expected, and that the values of the subscript should lie in the range 1 to 1000. It is the programmer's responsibility to obey this rule: there is no dynamic checking.

Properties of several arrays may be declared in the same statement, e.g.

      DIMENSION B(5, 10, 20), RAD (50), ITEM (500, 3)

specifying that B, RAD, and ITEM are array names, using three, one and two subscripts respectively, with the given upper bounds. The declaration of the properties of an array must always precede any instruction which refers to an element of it.

4. Functions

A function is a subsidiary calculation which produces a value as its result. The result may depend on the current values of some variables (scalars or arrays), or on other functions or subroutines. These are its arguments. A function call is a reference which activates the subsidiary calculation, after making certain substitutions to specify the actual objects to be used as arguments. Although the principal action is to produce a result, there is no prohibition on other action occurring.

The primitive arithmetic functions of addition, subtraction, multiplication, division and exponentiation of REAL and INTEGER variables are written like algebra, with a special sign between the variables concerned. The signs used are +, -, * (crossed to avoid confusion with x), / (treated as inverse multiplication) and ** respectively. In FORTRAN II and FORTRAN IV, the variables which they combine must be of the same mode, except that a REAL variable can be exponentiated by an INTEGER variable. Mixed modes have to be prohibited because the primitive functions do not work with variables having values in different domains. In Atlas FORTRAN, more powerful primitive functions are available, and this rule is dropped.

Apart from the above arithmetic functions, functions are identified by their names, whose initial letter indicates the mode of the result. The modes of the arguments need not be the same as the mode of the result, but each of the quantities specified as an actual argument should be of the mode which the subsidiary calculation expects for that argument. The number of arguments is usually a fixed property of the function.

There are several types of function, of which the most important are standard functions, and private functions defined by the programmer. The names of these functions have the same meaning throughout a whole program; they are not limited to a routine.

Standard functions in FORTRAN II have an F after the stem of their name, and the result is presumed to be an INTEGER if and only if the name begins with the letter X. (This unusual convention is an historical accident.) The values of the arguments are supplied on entry to the subsidiary calculation. Some of the standard functions are:

ABSF (X)       absolute value.
FLOATF (I)     value in REAL domain corresponding to INTEGER argument
SQRTF (X)      square root 
EXPF (X)       exponential

The way in which a programmer defines his own functions will be described later. The name must not end in F, and the mode of the result is presumed to be an INTEGER if and only if the initial letter of the function name is I, J, K, L, M or N (the usual FORTRAN convention).

The information supplied on entry to the subsidiary calculation is effectively a simple name for each argument. It is not necessarily the name of a variable with a value, but may be an array or a function.

The following three examples of function calls refer to private functions which respectively carry out a straightforward computation, do a more sophisticated list processing operation, and output a number.

SUMI (VECT, N)
produce the sum of the first N members of the array VECT.
ISITIN (WORD, LIST)
search the array LIST (it defines its own length, L) for a word equal to WORD. Give the result I (> 0) if it is the Ith, - L - 1 (< 0) if it is not in the list.
QPRINT(X)
Output the value of X in a standard format, and produce the same value as result.

5. Constants

Numerical constants are written using the ordinary decimal notation. A scale factor (integral power of 10) may be included after the letter E. Constants in the domain INTEGER are written with digits alone. Those in the REAL domain have a decimal point or scale factor. Thus:

1, 2, 37, 1066, are INTEGER, 
.5, 2.718, 25., 1962.8, are REAL; 
3.14159, .314159E1, 314.159 E-2, 314159E-5  are different ways of writing the same constant.

A constant is treated like a variable, which is given the appropriate value before starting the calculation.

6. Expressions

Several kinds of statement may contain expressions, which are written like algebra, and cause the current values of the appropriate elements to be combined in the specified ways. An element in an expression may be a constant, a simple variable, an array variable, a subexpression or a function call, e.g. (respectively)

2.352, SCALAR, MATRIX (I,J), (U + V * W - X)
SQRTF (X(I) ** 2 + Y(J) ** 2)

The elements may be combined thus

U + V * W - X
(I-J)*L
S/T (I,J) + X(I) * Y(J)

A subexpression is written like an expression and enclosed in parentheses. A function call is written as the function name, followed by a list of arguments in parentheses; each argument may be an expression. Thus, subexpressions may themselves contain subexpressions, and arguments of function calls may contain function calls, and so on.

The value of a subexpression or argument expression is calculated in advance and then treated as the value of a variable which effectively replaces it. Thus each expression is reduced to an arithmetic combination of variables. These are treated in the conventional order, first exponentiation, then multiplication and division, and finally addition and subtraction.

The order of evaluation of subexpressions is illustrated by the following example:

A/B - ((C(I) ** D) ** E + COSF ( 2.0 * (F + G) ) ) F + G C(I) ** D 2.0 * X7 X5 ** E COSF X6 A/B X3 + X4 X1 - X2 result

In the above example, the expression is represented in the form of an upside down tree.

7. Arithmetic Statements

The fundamental instruction in a calculation assigns a new value of a variable. This is called an Arithmetic Statement, (although it need not involve any arithmetic). It causes a value to be obtained (in general by evaluating an expression), and then given to a specified variable. A scalar or a single member of an array may be changed in one statement.

As pointed out in the introduction, a variable may be involved in the expression and then have its value changed: no contradiction is implied. Here are some examples of arithmetic statements:

      X = 0.
      X = X + VECTOR(I) ** 2
      S = SQRTF (TOTAL)
      B(I,J) = A(I,J) + X(I) * Y(J)
      XZ = QPRINT(ZZ*YZ**2 - 1)
      D = ABC (E, ABC (F - G, H))

Note that an argument of a function may involve the function itself. No problem of recursion arises because the arguments are always worked out in advance. Thus the last example above is interpreted as:

      W1 = F - G
      W2 = ABC(W1,H)
      D = ABC(E, W2)

8. Flow of Control

The order in which the instructions are executed is important. We say that control flows (or is sent) from one instruction to another.

The instructions of a routine are normally obeyed in the order in which they are written, but some instructions explicitly specify which is to be obeyed next, allowing the written sequence to be broken. Statements in the routine may be identified by means of statement numbers, written as integers in the margin on the same line as the beginning of the statement (card columns 1 to 5). There is a dummy instruction

      CONTINUE

which allows a statement number to be defined at a particular point, but itself causes no action.

Control is sent unconditionally to a specified instruction by the unconditional GO TO statement, e.g.

      GO TO 50

Until another successor is explicitly defined, the specified instruction and those written after it are executed in order.

There are several ways of sending control to one of a number of statements.

In the computed GO TO statement, the successor is chosen according to the value of a variable: control is sent to the appropriate member of a list of possible successors, e.g.

      GO TO (5, 5, 7, 1, 21, 1), JUMP

If the variable JUMP currently has the value 4, control is sent to statement number 1. The variable acts rather like a subscript, and must be of mode INTEGER; its lower bound is 1, its upper bound is the number of successor specified. If the instruction is executed with the variable outside the allowed range, the program gets out of control: there is no check.

In the arithmetic IF statement, the successor depends on the sign of an expression: the expression is evaluated, and control passes to the first, second or third possible successor (there must be three) according as the value is negative, zero or positive, e.g.

      IF(X - Y)10, 11, 12

If the current value of X is less than that of Y, the result of evaluating the expression is negative, so control goes to statement number 10.

The form of this statement is rather unconventional: it is an ingenious notation to avoid the need for special relational operator symbols (< ≤, ≠, etc.) in a limited character set. All six relations can be obtained by putting the same statement numbers in two of the three possible successor positions.

The expression is written according to the usual rules: it may be a simple variable or even a constant. Thus to replace X by its absolute value we could write

      IF (X) 10, 15, 15 
10    X = - X 
15    CONTINUE

This will give the same effect as X = ABSF(X)

There are other statements which specify successors (assigned GO TO and special IFs for testing machine indicators) which are less important.

9. Loops

A group of instructions can be repeated a number of times by setting up a loop. The DO statement specifies the statement number of the last of the group of instructions to be repeated, and defines the values which the index of the loop is to take. Thus

      DO 5 I= 1, NUMBER 
      X = X + VECTOR(I)**2 
 5    CONTINUE

causes the instructions after the DO statement until statement number 5 (which is usually a CONTINUE, but may specify calculation) to be executed repeatedly while I takes the values 1,2,3 .... NUMBER.

The parameters (I and NUMBER) may be constants or variables. If increments of the loop index other than 1 are required, a third parameter is specified. The parameters must be positive and of mode INTEGER.

The loop is always begun. It may contain instructions which send control out of the loop, breaking off the repetitions. Whenever the end of the loop is reached, the index is incremented; if it is then less than or equal to the final value, control is sent back to the beginning of the loop, otherwise control flows out of the loop.

The loop may contain another DO statement and inner loop, which is executed repeatedly for each repetition of the outer loop. Several loops may specify the same statement as their last. For example, to search a matrix for the element with greatest absolute value, we would have

      Y = 0.
      DO 5 I = 1,M  
      DO 5 J = 1,N 
      IF (ABSF(A(I,J)- Y)5,5,4
 4    Y = ABSF(A(I,J))
      K = I 
      L = J
 5    CONTINUE 

10. Subroutine Calls

As mentioned in the introduction, a program consists of a number of logically separate sections called routines. The rules for writing complete routines are described in Section 11. The order in which routines occur has no relation to the order of execution: they always activate one another by explicit reference.

A routine is identified by its name, which has the same meaning throughout the program. A routine may have arguments, which may influence its action and may be influenced by it. Each routine defines a particular part of the calculation to be performed and is activated from another routine by an explicit subroutine call statement e.g.

                                     
      CALL SUMSQ (A, N, TOTAL)

This instruction causes the subroutine SUMSQ to be activated, with substitutions made as specified by the arguments: thus VECTOR in the subroutine is replaced by A and so on. Since SUM is replaced by TOTAL, this subroutine call causes the sum of squares of the first N members of the vector A to be calculated, and the value assigned to the variable TOTAL. On completion of the subroutine, the activating routine is resumed.

A calculation may therefore be organized by a main routine calling a sequence of subroutines in order thus:

      CALL ADD 1(SALARY, 15, TOTAL)
      CALL TEXT (8, 8H TOTAL =)
      CALL PRINT (TOTAL, 5, 3)
      CALL LINE                            

These subroutines respectively add together the first 15 elements of the array SALARY, putting the sum in TOTAL; output the sequence of 8 characters specified; output the current value of TOTAL; and print the output on a separate line.

There need not be any arguments in a subroutine call; an argument may be the name of a variable, array or routine, or an expression which may be just a constant. All arguments are effectively replaced by simple names before activating the subroutine. An expression is evaluated in advance, and its value given to a generated variable whose name effectively replaces it. An array may be identified by its name or its first element: an array element is given a simple name, which may be regarded as a scalar or an array name. A constant is similarly treated as a simple name. A constant of mode TEXT is written as a sequence of characters, preceded by the character count and the letter H.

Here is another subroutine call statement:

      CALL RUKU (SUBR, Y, F, G, H, X, N, DX)

This advances by one step (DX) the integration of the differential equations

dY(I)/dX = F(I) for I = 1,N

using the Runge-Kutta-Gill process. The argument SUBR denotes a subroutine which is called by RUKU to evaluate the derivatives F for the N equations, with independent variable X and dependent variables in the array Y. The arrays G and H are used as working space.

If a routine name (e.g. SUBR) is used as an argument, and is not used in a function call or subroutine call elsewhere in the same routine, then a declaration must be made to distinguish it from a scalar. The form of this declaration in FORTRAN II is

F     SUBR

(the F in column 1) but in new dialects of FORTRAN it is

      EXTERNAL SUBR

11. Complete Routines

In previous sections we have described how to write the statements which constitute the body of a routine (apart from input/output, which is described in Section 15). We now show how to build this body into a complete routine.

There are three types of routine, which are activated in different ways. The basic type is a subroutine, which just carries out a section of the program. This is activated by an explicit subroutine call in another routine. A function also carries out a section of the program, but in addition produces a scalar value as its result. The routine is activated when a reference to the function (a function call) occurs in an expression; the result of the function is subsequently used in the evaluation. The third type is a main routine which must always be present. This is activated by the loader to begin execution of the program.

The type of the routine, its name, and a list of dummy arguments are specified in a declaration which must be the first physical statement of the routine, e.g.

      SUBROUTINE ADD 1 (A, N, SUM) 
      FUNCTION SUM 1 (A, N)

A main routine is identified by a null declaration. In other words, if the first statement is not one of the above, then the routine is taken to be a main routine. The last physical statement of every routine must be the declaration

      END

Whenever a routine is activated, control begins at the first written instruction, and continues according to the standard rules until it comes to the instruction

      RETURN

This defines the logical end of the routine: when the instruction is encountered during execution, the routine which activated it is resumed.

Although routines are physically disjoint, there is no limit to the depth to which they may activate each other. However, a routine may not activate itself (either directly or indirectly) unless no return is expected.

12. Arguments

The dummy arguments written in the routine declaration may be used like other names throughout the routine. Each time the routine is activated, they will be treated as synonymous with the names provided in the calling instruction. They are effectively replaced, each time the routine is entered, by a prologue which is executed before obeying the first instruction.

There is no checking during this replacement: it is the programmer's responsibility to see that the actual arguments supplied are consistent with the uses made of the dummy arguments, in number, mode, and type. When an argument is an array name, the routine must declare the properties associated with the dummy name. These are normally the same as those of actual arrays used as arguments, which are consequently all of the same size and shape. However, the length in the last dimension may differ: in particular, vectors of different lengths may be used. Thus, for vectors, a length of 1 may be conventionally specified in the routine. Inside a function routine, the routine name is used like a scalar. The value of this scalar on returning is the result of the function. Here are some examples of complete routines:

      FUNCTION QPRINT (X)
      CALL LINE
      CALL PRINT (X, 0, 8)
      QPRINT = X
      RETURN
      END
      SUBROUTINE SET (I, J) 
      I = J
      RETURN 
      END
      SUBROUTINE ADD 1 (A, N, SUM) 
      DIMENSION A (I) 
      SUM = 0. 
      DO 6 I= 1, N 
 6    SUM = SUM + A (I) 
      RETURN 
      END

13. Input and Output Values

Since each reference to an argument in the routine requires action in the prologue to replace it, the programmer may take steps to reduce the number of references in the interest of speed. It is useful to distinguish arguments which are scalars, in which the value on entry to the routine or on exit from it (or both) may be significant.

If there is an output scalar which is specially important, the routine can be made a function, of which this is the result. There is then no corresponding argument. Otherwise, the values may be copied from the arguments into private variables at entry, or vice versa at exit. The body of the routine then uses the private variables, and no adjustment is needed during execution. This is worth doing if there are more than three references to the variable.

For example, we may convert ADD 1 into a function (because SUM is significant on output):

      FUNCTION SUM 1(A, N) 
      DIMENSION A (1) 
      SUM = 0. 
      DO 6 I = 1, N 
 6    SUM  = SUM  + A (I) 
      RETURN 
      END

or we could leave it as a subroutine but copy only the output value of SUM into the argument:

      SUBROUTINE ADD 2 (A, N, SUM 2) 
      DIMENSION A (1) 
      SUM = 0. 
      DO 6 I = 1,N 
 6    SUM = SUM + A (I) 
      SUM 2 = SUM 
      RETURN 
      END

If there were more references to N we could replace the second dummy argument by Nl and put

      N = N1

at the beginning. This makes N a normal variable, whose initial value is set to that of N1.

14. Common

The treatment of arguments is such that a routine can be called on different occasions to carry out a calculation using quite different sets of variables. In many circumstances, this flexibility is not needed: the routine may be activated several times, but always the same variables are concerned.

In this case the replacements effected by the prologue are clearly unnecessary; a better way of communicating values between routines is by use of common variables.

The normal variables of a routine are private, and are protected from interference by other routines, unless they are explicitly specified as arguments. But the declaration

      COMMON A1, B1, X1

makes the names A1, B1, X1, in this routine identify the first three common variables, which are accessible to all routines. If another routine contains

      COMMON A2, B2, X2

then these names in this routine will similarly identify the first three common variables, i.e. the same variables as the names A1, B1, X1 in the first routine. Note that the correspondence is by position in the COMMON declaration rather than by name.

An array name may occur in a COMMON declaration; it is equivalent to specifying as many scalars as there are elements in the array. Thus

      COMMON F1, G1, H1 
      DIMENSION G1 (5)

defines names usable in this routine for the first seven common variables. Another routine might use different names, and even different groupings, thus

      COMMON C2, E2
      DIMENSION C2 (3) E2 (4)

Then the names referring to the common variables are as follows

Common variable number In first routine In second routine
1 F1 C2(1)
2 G1(1) C2(2)
3 G1(2) C2(3)
4 G1(3) E2(1)
5 G1(4) E2(2)
6 G1(5) E2(3)
7 H1 E2(4)

Of course, the above example is not typical; one usually has identical COMMON and DIMENSION declarations in all routines, so the names are the same throughout.

For example, the array SALARY might be in common. We could then further improve the efficiency of ADD2:

      SUBROUTINE ADD 3 (N, SUM 3) 
      COMMON SALARY 
      DIMENSION SALARY (100) 
      SUM = 0. 
      DO 6 I = 1,N
 6    SUM = SUM + SALARY (I) 
      SUM 3 = SUM 
      RETURN 
      END

The same could be done with the function SUM 1.

15. Input/Output

Fortran contains powerful input/output facilities, which are implemented by hidden library routines controlled by the programmer's instructions. The controlling statements usually come in pairs, one specifying the variables whose values are to be input or output and the other specifying the external format of these values. For example, a simple input instruction and format specification would be

      READ INPUT TAPE 2, 200, N, M 
  200 FORMAT (2I5)

This will cause N and M to be given the respective values of two decimal integers on input tape number 2, each occupying five character positions. A typical line of input for this is

bbbb5bb100

where the letter b denotes a blank space.

To output the values, the statements would be

      WRITE OUTPUT TAPE 3, 300, N, M 
300   FORMAT (4HbbN= I5, 4H,bM= I5)

This would give the following output line bbN=bbbb5,bM=bb100

We could in fact have used the input format statement (number 200) to give output of the numbers alone, but it is good programming practice to put explanatory information with the numbers output.

There are really three parts to the information in an input/output statement: the equipment to be used, the external form of the information and the internal form of the information. The word(s) at the beginning specify the nature of the external medium, and of course whether it is input or output. For on-line equipment the words are

      READ  (card reader)
      PRINT (line printer)
      PUNCH (card punch)

Because input and output of cards and line printing are relatively slow processes, the usual method is now to use an auxiliary off-line computer to copy information between cards and tape or from tape to printer, and use magnetic tape input and output at the main computer. For these the instructions contain an integer (constant or variable) to specify the tape number, thus

      READ INPUT TAPE M 
      WRITE OUTPUT TAPE N

where M and N have conventional values for the installation.

For input and output of data and results, the external arrangement of the information is specified by a FORMAT statement, which is written separately, and referenced by its statement number. For auxiliary storage of variables which are only to be read back by the computer, the external arrangement of the information is irrelevant (it is in binary words), and instruction beginning

      READ TAPE I 
      WRITE TAPE J

are used.

The internal arrangement of the information is specified by a list of variable names, whose values are to be input or output. There can be any number of variables in such a list, either specified individually or in an implied loop: e.g.

      ,X,Y(5),Z(L)
      , (A(I), I = 1,4) equivalent to ,A(1) ,A(2) ,A(3) ,A(4)
      , (I,(C(I,J), J=1, N), B(I),I= 1, M)

16. Input/Output in the New Dialects

There are some changes in notation for the new dialects of FORTRAN, and generalizations of meaning appropriate to more advanced computers. The notational change is to substitute for the rather lengthy statement

      WRITE OUTPUT TAPE 3, 100 

the shorter statement

      WRITE (3, 100) 

and similarly

      READ (2, 101) 
for
      READ INPUT TAPE 2, 101 

also

      READ (5) 
for 
      READ TAPE 5 
      
      WRITE (6) 
for 
      WRITE TAPE 6

The semantic change is based on the advent of time-sharing computers, which can do their own off-line processing. The statements no longer specify actual input/output equipments, but identify streams of information which are separately input and output.

There is one principal input stream (containing the program followed by its data) which is read by the instruction

      READ

not followed immediately by a parenthesis. Similarly there is one principal output stream for printing, for which we use

      PRINT

An auxiliary output stream is reserved for information which is to be subsequently read mechanically; this is specified by

      PUNCH

All other input and output streams are numbered (the correspondence between the numbers used and the actual equipment used is set up by the operating system on the computer) and specified by the generalized

      READ(N, FMT) 
      WRITE (M, FMT)

instructions.

17. Formats

The rules for writing format specifications are quite distinct from the rest of FORTRAN. One thinks of an image of the external line scanned from left to right; the processing to be carried out during this scan is specified by code sequences in the format specification. A field is a group of adjacent characters treated together.

Thus I5 means that the next field consists of 5 characters which represent a decimal integer. For output, the next variable is taken from the list, and its current value is converted to decimal. For input, the characters are collected to form a binary integer, whose value is given to the next variable in the list. An integer before the code letter means that there are as many adjacent fields of the same form. Similarly, F6.1 means that the next field consists of 6 characters, which represent a real number in decimal form, with 1 digit after the decimal point.

Headings and other constant text can be output among the numbers by including a constant of mode TEXT in the specification. The letter H after an integer means copy as many following characters (spaces and commas included) from the format specification into the line image. Variable text can be handled using A-type conversion. The next variable in the list should be of mode TEXT: characters are copied from it to the line image for output, vice versa for input.

Items can be spaced out by using code X: 8X means space over the next 8 character positions (this produces spaces on output, ignores character on input). The end of a line is denoted by a / or the end of the format specification.

One level of parentheses can be used, preceded by an integer, to denote repetition of a group of fields. The whole specification is enclosed in parentheses.

If the lists comes to an end in the middle of a format specification, the rest of the specification is abandoned: the next reference to it will start at the beginning. If the list contains more variables than the format specifies, then the last part of the specification is repeated indefinitely (from the right-most left parenthesis with its associated count).

The following example is rather more complicated:

      WRITE OUTPUT TAPE 3, 102, IP, CASE, 
     X   (((PAGE (I, J, K), I = 1, 3), J = 1, 2), K = 1, NL) 
 102  FORMAT (5H1PAGE, I5, 10H FOR CASE , A6 / 
     X   2(8X,3F6.1,8X))

If the current values of the variables are as follows

IP = 7
CASE=4H ICP 
PAGE (1,1,1) = 111.0 
PAGE (1,1,2) = 112.0
etc.

and 
NL = 5

then the page of output produced by this would be

PAGE   7 FOR CASE ICP 
        111.0 211.0 311.0                121.0 221.0 321.0
        112.0 212.0 312.0                122.0 222.0 322.0
        113.0 213.0 313.0                123.0 223.0 323.0
        114.0 214.0 314.0                124.0 224.0 324.0
        115.0 215.0 315.0                125.0 225.0 325.0

The character at the beginning of each line is treated specially: 1 starts a new page, space is normal, for single spacing.

18. Conclusion

The word FORTRAN has at least four different meanings. I have been using it as the name of the source language in which routines may be written. It is also sometimes applied to the compiler which translates these routines into the intermediate binary language.

Third, it is used to mean the FORTRAN MONITOR SYSTEM (FMS) which includes the compiler and loader, and controls the processing and execution of jobs on the computer. Fourth, it is used for the underlying philosophy of independent treatment of routines, on which much of the total system is based.

The development of FORTRAN has covered a period of several years, and not all the present features were available in early systems. A brief summary of the stages it has gone through should spotlight the important features which programmers find convenient.

The original FORTRAN I did not allow subroutines: all the program had to be compiled together. The algebraic language was a great advance from machine language coding, but it forced programs to be monolithic and inflexible. Then FORTRAN II introduced the subroutine facilities, but still separated compilation from execution. This was a great improvement, and really marked the beginning of FORTRAN as a powerful system. Manufacturers other than IBM started providing FORTRAN compilers. Finally, the FORTRAN MONITOR. SYSTEM emerged, giving an even more marked improvement, as compilation and execution could be combined, and complete jobs prepared by the programmer away from the computer, to be run without any need for manual intervention.

⇑ Top of page
© Chilton Computing and UKRI Science and Technology Facilities Council webmaster@chilton-computing.org.uk
Our thanks to UKRI Science and Technology Facilities Council for hosting this site