Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28386 Discussions

Changing the loop range inside the loop

DataScientist
Valued Contributor I
1,006 Views

Is this code standard-conforming?

program hello
    integer :: n = 10, i
    do i = 1, n
        Print *, i
        if (i == 5) n = 6
    end do
end program Hello

 

Note that the value of n changes inside the loop. So is this loop supposed to end at 6 or 10? Both GFortran and Intel ifort end the loop at 10. But is this the standard behavior or compiler-dependent?

 

0 Kudos
1 Solution
IanH
Honored Contributor II
952 Views

I think the previous two responses have misread the assignment as being to the loop index variable.

As stated in the latter post, the iteration count for this form of do loop is determined prior to the start of the first iteration.  Subsequent changes to variables used in determining the iteration count (start, finish or step) do not affect the iteration count of the loop.

(You are not permitted to modify the loop index variable i, but the code shown does not do that.)

The code, and the observed result, conform to the standard (the last value printed will be 10, noting the value of i after the loop terminates will be 11).

If the termination criteria for your loop is dynamic, perhaps use an EXIT statement or the DO WHILE (...) form of do loop.

View solution in original post

8 Replies
mecej4
Honored Contributor III
976 Views

The Fortran standard forbids changing of the loop index variable by the program code inside the loop.

The only permitted change is the automatic incrementing (by m3, if specified; decrementing if m3 is negative; by 1 otherwise) that occurs after each repetition of the loop DO <var> = m1, m2, m3 .

The compiler may take any action, and without notifying you of the violation.

andrew_4619
Honored Contributor II
969 Views

further to mecej4's comments, the loop counters are setup prior to the execution of the loop for the first time. But ultimately your program is not conforming IMO.

IanH
Honored Contributor II
953 Views

I think the previous two responses have misread the assignment as being to the loop index variable.

As stated in the latter post, the iteration count for this form of do loop is determined prior to the start of the first iteration.  Subsequent changes to variables used in determining the iteration count (start, finish or step) do not affect the iteration count of the loop.

(You are not permitted to modify the loop index variable i, but the code shown does not do that.)

The code, and the observed result, conform to the standard (the last value printed will be 10, noting the value of i after the loop terminates will be 11).

If the termination criteria for your loop is dynamic, perhaps use an EXIT statement or the DO WHILE (...) form of do loop.

andrew_4619
Honored Contributor II
947 Views

You hit the nail head on as usual Ian

jimdempseyatthecove
Honored Contributor III
937 Views

IanH,

In the sketch given, along with the question, implied (IMHO) a termination to be performed after the next iteration (as opposed to exiting at the IF statement.

The better approach would be using a DO WHILE or DO ... WHILE loop or

doExit = n
do i=1,n
 if(i > doExit) exit
 ...
 if(i=5) doExit = 6
 ...
end do

Jim Dempsey

Steve_Lionel
Honored Contributor III
930 Views

The standard describes the execution of a counted DO loop as determining the number of iterations at the start, so changes to the end value within the loop have no effect. I know that the DEC-heritage compilers look to see if the index variable might change within the loop, and change to a tested loop to accommodate. Such a loop would be nonstandard, as specified. 

Changing the end value within the loop should not affect execution. I agree that a test with EXIT would be the right approach if that behavior is desired.

DataScientist
Valued Contributor I
917 Views

Thank you all for your responses. I believe @IanH and @Steve_Lionel have the correct answer and the standard behavior is the desired outcome in this code. It is hard to find the answer on the web or in textbooks.

0 Kudos
JohnNichols
Valued Contributor III
908 Views

web or in textbooks

Interesting observation -- but the forum is probably better than most text books on Fortran as it is faster. 

If you are looking for say the first non zero value in a array then if you use your method to minimize the time of the loop use exit, if you want the code to be more readable use do while 

Both work.  

Fortran is very old and its beauty is you can keep running programs.  C# can change so fast code from 6 months ago may not run. 

Of course the perfect language is LISP but you need to enjoy a lot of pain as you learn. 

0 Kudos
Reply