One of the Fortran benchmark codes that DanRRight wrote about recently contains two code segments with the following pattern:
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ITERATION SCHEME FOR CIRCULATION (GAM)
!
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
DO j = 2 , N - 1
IF ( ABS((g_new(j) - g_old(j))/g_new(j)) .GT. g_tol ) GOTO 70
GOTO 80
ENDDO
...
70 <replace g_old by g_new and continue iterations unless iteration limit has been reached>
...
80 <iterative process has converged. Proceed with next part of calculation>
It took me a while to recognise that the body of the DO loop can only be executed zero or one times! If N < 3, the loop is not executed at all. Otherwise, the IF condition is tested. Regardless of the result of the test, the loop is exited (to 70 if TRUE, to 80 if FALSE). I could replace the DO .. line by 'j = 2' and remove the ENDDO line, and the program would behave the same as it does now.
If it is not too much trouble to implement, it would be nice to have the compiler detect this pattern and issue a warning that this is a not a normal DO loop.
The fake DO loop hides what I think is a major error in the program. What the original programmer meant (and wrote in old Fortran 77 style) was
IF (ANY (ABS((g_new - g_old)/g_new) .GT. g_tol) ) THEN
GO TO 70 ! continue iterations
ELSE
GOTO 80 ! iterations have converged; proceed to next part
ENDIF
I suspect that the GOTO 80 should have come after the ENDDO, but got misplaced by a code polisher/reformatter.
Why do I have that suspicion? Normally, when solving a set of simultaneous equations (linear or nonlinear) by an iterative method, the algorithm is along the lines of
g = g_old # use old array g_old as the trial solution for the fixed point iteration g = F(g)
iter := 0;
do
iter := iter+1; if (iter >= max_iter) exit B # failed to converge
g_new := F(g)
delta := ||g_new-g_|| # norm of change in array g
if (delta <= g_tol) exit A # converged
g := g + \omega * (g_new - g) # \omega is the relaxation parameter
end do