Search code examples
fortranfortran77

Fortran 77 Do Loop block clarification


Both NUM and ARRAY double precision variables, not sure how the if block will execute. When will it stop? What is it actually doing?, If we go to 8, then are we exiting the do loop?

Thanks

DO 7 I = 1,28                                                   
IF (NUM - ARRAY(I)) 8,7,7                                    
7 CONTINUE                                                         
I=29                                                             
8 NUM = ARRAY(I) 
....
....
....
....

Solution

  • As previously stated the conditional in the loop is an arithmetic if statement.

    We know (and that's explicitly stated in the previous answer here) that if num is less than array(i) the label 8 is chosen, otherwise label 7 is chosen. It's also stated in that other answer that these have the effect of exiting the loop or cycling it. To be precise, I'll continue.

    A DO construct has a range. A nonblock DO construct like the one in the question has range consisting of the statements between and including the do statement and the DO termination statement (in this case 7 continue). The DO termination statement is a valid target for a jump from within the range of the construct.

    When the DO termination statement is jumped to, execution remains within the scope of the construct. That termination statement is executed (in this case, continue, doing nothing) and the loop iteration condition is again tested. That is, the loop cycles.

    From within a DO construct, a jump to a statement outside the range of the construct terminates execution of the construct: like an exit.

    This example, then, has the equivalent form using an IF construct (with go tos - bear with me)

    DO 7 I = 1,28
    IF (NUM < ARRAY(I)) THEN
      GO TO 8
    ELSE
      GO TO 7
    END IF
    7 CONTINUE
    I=29
    8 NUM = ARRAY(I)
    

    Now, because the statement labelled 7 is a continue statement, we can write this as

    DO 7 I = 1,28
    IF (NUM < ARRAY(I)) THEN
      GO TO 8
    ELSE
      CYCLE
    END IF
    7 CONTINUE
    I=29
    8 NUM = ARRAY(I)
    

    That's still pretty ugly (and not just because of all the upper case). Fortunately, we can make this prettier. The i=29 statement will be executed only when the loop terminates without the statement labelled 8 being jumped to. Now, the loop index i has control I = 1,28 so when the loop terminates naturally the index already has the value 29. That assignment does nothing (in modern Fortran) so we can remove it. Which leaves us with

    DO 7 I = 1,28
    IF (NUM < ARRAY(I)) THEN
      GO TO 8
    ELSE
      CYCLE
    END IF
    7 CONTINUE
    8 NUM = ARRAY(I)
    

    When we also note that the IF construct is immediately followed by the end of the loop (and so we don't need to explicitly cycle) we have

    DO 7 I = 1,28
    IF (NUM < ARRAY(I)) EXIT
    7 CONTINUE
    NUM = ARRAY(I)
    

    or (more nicely)

    DO I = 1,28
      IF (NUM < ARRAY(I)) EXIT
    END DO
    NUM = ARRAY(I)
    

    All this example is doing is finding the value of the earliest element in array(1:28) which is larger than num, or array(29) if none is.