Loops: Repetitive Execution

The idea of a loop is that we have a block of code we want to execute more than once. Sometimes we know exactly how many times we want it to be executed, and sometimes we simply want to repeat the same steps until something happens.

FORTRAN provides several kinds of loop structures.


DO WHILE loop

The format for a DO WHILE loop is the following:

         DO WHILE (logical expression)
           (one or more statements)
         END DO

The expression is evaluated, and if it is .TRUE., the body of the loop is executed. After the body is executed, the expression is evaluated again, and so on. When the expression is evaluated and found to be .FALSE., control branches to the statement immediately following the END DO statement.

It is important that something in the body of the loop should have some effect on the logical expression, or else there is a danger that the loop will not end. This is called an "infinite loop" or an "endless loop", and if it occurs, someone outside the program (the user, the operating system) will have to intervene to stop it.

Example: The following code will print out 5, 4, 3, 2 and 1 on consecutive lines.

         M = 5
         DO WHILE (M > 0)
           PRINT *, M
           M = M - 1
         END DO

If the variable controlling a loop is REAL, it is probably not wise to rely on testing for "equal", due to round-off dangers in working with floating-point values. Instead test for "less than or equal" or "greater than or equal".


General DO loops

A more flexible kind of loop looks like this:

         DO
           (assorted statements)
           IF (some condition) THEN
             EXIT
           (assorted statements)           
         END DO

The idea here is that we have a block of statements between DO and END DO, and we want that block of statements to be executed repeatedly. As we do not want it to go on forever, at some point we check some condition (the IF statement) and if the condition is .TRUE., we execute the EXIT statement, which ends the execution of the loop, so the program will continue with the next line after END DO.

The IF statement and the EXIT could be anywhere in the body of the loop. If the IF statement is at the very top, we have the equivalent of a DO WHILE loop.


Counted DO loop

Most DO loops are counted loops. The format for it looks like this:

         DO VAR = expr1, expr2, increment
           (one or more statements)
         END DO

Here VAR is a REAL or INTEGER variable, and expr1 and expr2 are constants, variables or numeric expressions of the same type as VAR. The increment value is optional; its default value is 1.

This is more or less equivalent to a DO WHILE loop. If the increment value is positive, it is equivalent to:

         VAR = expr1
         DO WHILE (VAR .LE. expr2)
           (one or more statements)
           VAR = VAR + increment
         END DO

If the increment value is negative, it is equivalent to:

         VAR = expr1
         DO WHILE (VAR .GE. expr2)
           (one or more statements)
           VAR = VAR + increment
         END DO

If the increment is 0, then the loop will theoretically run forever; it is possible the compiler will catch this error.

Example: The following code is equivalent to the last example.

         DO M = 6, 0, -1
           PRINT *, M
         END DO


Nested loops

We can have loop structures inside other loop structures. For instance, we could have

         DO A = 5, 17, 3
           (one or more statements)
           DO WHILE (B > 42)
             (one or more statements)
           END DO
           (one or more statements)
         END DO

As usual with nested constructs, it is advisable to use indentation to make the layout of the code on the page reflect the logical structure.

We can nest loop constructs up to 25 levels deep.

We can also have IF statements inside loops and loops in the body of a THEN or ELSE block.


Implied DO loops in input/output

Often when we are doing input or output and an array is involved, we need a loop. For instance, we may want to print the elements of an array in neat columns.

An example of this might be:

         READ *, (A(I), I = 1, 6)

where A is an array of (at least) 6 values.

This is equivalent to

         READ (*,*)  A(1), A(2), A(3), A(4), A(5), A(6)

We can have nested implied DO loops as well, perhaps for dealing with two-dimensional arrays. For example:

         READ (*, 100) ((B(I,J), I = 1, 2), J = 1, 3)
100      FORMAT(2(I6, 3X))

where B is a 2 x 3 array of type INTEGER.

This will read the 6 INTEGER values in the order B(1,1), B(2,1), B(1,2), B(2,2), B(1,3), B(2,3).