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

Exiting from nested DO Loops

WSinc
New Contributor I
1,567 Views
Suppose we have a situation where I am scanning a 2 dimensional array:

DO i=1,100
DO j=1,100

! I want to stop scanning if I meet some criterion - -
! I want to jump out of BOTH levels
! normally, I would have to use a GO TO:
if( A(I,J).lt.100)GO TO 40
! an exit does NOT jump out of both levels.
END DO
END DO

40 ! place I am jumping to

Apparently our current Fortran does not have anything like EXIT 40, where you can tell it WHERE to exit to.
I know we're not supposed to use GO TOs if possible, but what's the alternative here?
0 Kudos
7 Replies
TimP
Honored Contributor III
1,567 Views
Quoting - billsincl
Suppose we have a situation where I am scanning a 2 dimensional array:

DO i=1,100
DO j=1,100

! I want to stop scanning if I meet some criterion - -
! I want to jump out of BOTH levels

Use f90 syntax, with named loops.
loop1: do....
loop2: do..
if() exit loop1
enddo loop2
enddo loop1

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,567 Views


The above works, except you have to be aware that should the inner loop have !$OMP PARALLEL DO then you cannot exit the outer loop from within the inner parallel loop. For that consider using a shared flag

error = .false.
loop1: do....
!$OMP PARALLEL DO SHARED(error)
loop2: do..
if(.not. error) error = (error detection expression)
if(error)exit
enddo loop2
!$OMP ENDPARALLEL DO
if(error) exit
...
enddo loop1



>> if(.not. error) error = (error detection expression)

The above protectes agains one thread setting error to .true. and another thread setting error to .false.

All threads exit inner loop when any thread detects error, thenouter loop thread exits outer loop

Jim Dempsey

0 Kudos
WSinc
New Contributor I
1,567 Views


The above works, except you have to be aware that should the inner loop have !$OMP PARALLEL DO then you cannot exit the outer loop from within the inner parallel loop. For that consider using a shared flag

error = .false.
loop1: do....
!$OMP PARALLEL DO SHARED(error)
loop2: do..
if(.not. error) error = (error detection expression)
if(error)exit
enddo loop2
!$OMP ENDPARALLEL DO
if(error) exit
...
enddo loop1



>> if(.not. error) error = (error detection expression)

The above protectes agains one thread setting error to .true. and another thread setting error to .false.

All threads exit inner loop when any thread detects error, thenouter loop thread exits outer loop

Jim Dempsey

Maybe that works too, but what a Godawful mess - -
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,567 Views

Think of it as structure exception handling.

Jim
0 Kudos
rase
New Contributor I
1,567 Views
I agree, that's a mess. The goto instruction is not a religious dogma, and the use of goto does not condemn you to hell for eternity. Why not use it when the alternatives are not convincing?
0 Kudos
eos_pengwern
Beginner
1,567 Views

Quite; judicious use of GOTOs can substantially reduce the length of complicated control structures where thereare several levels of IF-THEN and DO-ENDDO structures to break out of.

The downside of GOTOs, as far as I know,is that they can make the flow of a program difficult to follow. If this is addressed, for example by:
- never jumping more than ~20 lines of code
- at the 'destination', putting a comment to explain where the program may have jumped from

...then there seems no reason not to use them if they're the best tool for the job.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,567 Views

>>The downside of GOTOs, as far as I know,is that they can make the flow of a program difficult to follow.

And the upside of GOTO is they can make the flow of a program easy to follow.

Like all statements it can be abused, as well as be used effectively.

As mentioned earlier in this thread, you can use alternate means such as "exit LoopName", "cycle LoopName", while at other times the clearest way to express the flow is with use of "GOTO nnn" or "GOTO SomeName". I recommend using the name tag method as opposed to numeric tag, and choose an appropriate name.

Most of the "tweets" on problems with goto evolved around earlier implementations of C were GOTOcould go anywhere without regard to the consequences of scoping rules. And in the process trash the stack, not initialize local scoped variables etc... Fortran doesn't have nested scopes ({...}) so most of the arguments with respect to C do not hold for use in Fortran.

Those problems are fixed now in C++ and all the reasons of substance for banning use of goto are moot. This leaves style as the only arguing point. You cannot goto to enter a scope, gotos that exit a scope also cleanup implicitly (call dtor's, pop scope local variables etc...)

>> Quite; judicious use of GOTOs can substantially reduce the length of complicated control structures where thereare several levels of IF-THEN and DO-ENDDO structures to break out of.

Yes, In Fortran, as well as C++, avoidance of GOTO may require you to intoduce convolutions into an otherwise simple routine.

Jim Dempsey
0 Kudos
Reply