Ending a Do loop

Really silly question but this feels untidy to me and I’d like the opinion of others.

I have a few do loops where the original coder has used goto statements to jump out where necessary; such as this…

   do j = 1, 9
       [do something here]
       if <some condition> goto 20
   end do
20 continue
   [more code]

Obviously I want to remove these goto statements so do I either do a minimal change…

   do j = 1, 9
       [do something here]
       if <some condition> j = 99
   end do
   [more code]

Or should I restructure the whole loop?

   j = 1
   do while j < 10
       [do something here]
       j = j + 1
       if <some condition> j = 99
   end do
   [more code]

I feel the latter is neater but would just appreciate the thoughts of others (in case my thinking is wrong).

Maybe,


...
if < condition > exit
...
1 Like

You are looking for exit and probably also cycle:

   do j = 1, 9
       [do something here]
       if (<some condition>) exit
   end do

There is no need for labels in this situation. Jumping out of a loop with a goto might also trigger warnings in some compilers if I recall correctly.

For more details check the section on Operators and flow control - Fortran Programming Language or Introduction to Fortran — Advanced Quantum Chemistry Methods.

1 Like

And this is EXACTLY why I raised the question; thank you.

When you propose 2 solutions, there is always the 3rd way. :laughing:

I hadn’t come across exit before; solves a LOT of issues in this (lengthy) code.

Again, thank you (to both of you).

1 Like

If no exit occurs, then j = 9+1 on termination of loop, so you can still test for exit occuring :slight_smile:

   do j = 1, 9
       [do something here]
       if (<some condition>) exit
   end do
   if (J <= 9) then !  exit occurred
    ...
1 Like

I strongly advise never to use an un-tagged EXIT statement. We write tools to detect software errors. The number of errors associated with un-tagged EXIT and LEAVE statements is alarming. Tag the loop and tag the EXIT and the danger is removed.

Best wishes,

John

3 Likes

Thanks, I will try to follow this advice going forward. Is LEAVE an extension, and if so, what compiler has it? I don’t recognize it.

1 Like

Thanks!
Reading something more about EXIT statement in ISO/IEC JTC 1/SC 22/WG 5/N2146

" EXIT [ construct-name ]
 If a construct-name appears on an EXIT statement, the EXIT statement
 shall be within that construct; otherwise, it shall be within at least
 one do-construct. "

Is there a specific option (flag) in the Fortran compilers that warns about possible errors in this case?

I think it would be interesting to mention this in fortran-lang Best Practices

John, What do you imply by “tagging” ?
Are you requiring setting an error_code associated with the EXIT ?

When I have an optional EXIT, or to test if a “DO scan” was unsuccessfull, I will often use the “If (do_index <= do_limit ) then” (for +ve step) test to identify that the Do loop did not run to completion.
I am not convinced that this approach is alarming ?

Are you able to expand on your findings ?

I think he means that one should write

do i=1,n
   jloop: do j=1,n
      if (x(i,j) == 0) exit jloop
   end do jloop
end do

and not

do i=1,n
   do j=1,n
      if (x(i,j) == 0) exit
   end do
end do

even though the two codes are equivalent. It should be explicit what loop the programmer intends to exit. I think one reason is that if you put an additional loop inside the loop over j, the effect of exit will change, even if that was not intended.

1 Like

@Beliavsky is exactly right. An EXIT statement with no construct identifier is a GO SOMEPLACE statement. The errors occur when additional dimensions are added to arrays which require existing code to be enclosed in additional loops.

LEAVE was a precursor to EXIT. It was implemented in Gould-SEL extended FORTRAN 77. The Gould-SEL systems were the preferred machines for high performance simulation and instrument control from about 1978 to 1990. They were used in flight simulators, power-plant simulators and for control of instruments like tracking radars. The codes live on in emulation, even now. The optional argument to LEAVE was (is?) the end label of a DO loop.

1 Like

I assume the same advice would apply to CYCLE.

I have considered the design of “EXIT label” and “CYCLE label” poor for another reason.
The options for the value of label are extremely limited.
In the example above there are no options available for label.

I think the syntax could have been made more flexible so that the following could be allowed to include the DO do-variable.

do i=1,n
   do j=1,n
      if (x(i,j) == 0) exit i
   end do
end do

Givel the very limited label options, it should not be too difficult for a compiler to identify what “i” means.

Perhaps I’ve misunderstood your point, but typically I’d do something like:

outer: do i=1,n
   do j=1,n
      if (x(i,j) == 0) exit outer
   end do
end do outer

iloop: do i=1,n
   do j=1,n
      if (x(i,j) == 0) exit iloop
   end do
end do iloop

It does kind of break the visual symmetry of the nested constructs and syntax highlighting appears to be broken. Still for other types of loops like

repeat: do
!...
if (condition) exit repeat
end do repeat

the labeling works perfectly.

Still the idea of using the do loop variable as the exit label is enticing.

I like this proposal a lot! We should propose it.

2 Likes

'Twas proposed. 'Twas rejected in posts on comp.lang.fortran. But I like it.

John

2 Likes