|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Tue Feb 20, 2018 5:24 pm Post subject: |
|
|
As mecej4 notes the value of the do loop variable after the loop is carefully defined. I often find the most natural way to code something makes use of this value.
The following code attempts to find the first instance when the test is true. Here n may be 0, in which case the code prints "Not found". And if the test is always false the code also prints "Not found".
Code: |
! Simple search
do i=1, n
if (test) exit
end do
! Use the result
if (i > n) then
print *, 'Not found'
else
print *, 'Found at pass ', i
end if
|
Without this facility in the language you have to write code like this using another variable:
Code: |
! Simple search (without using index variable after loop).
j = n + 1
do i=1, n
if (test) then
j = i
exit
end if
end do
! Use the result
if (j > n) then
print *, 'Not found'
else
print *, 'Found at pass', j
end if
|
_________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Feb 20, 2018 6:36 pm Post subject: |
|
|
Another common situation where one needs the last used value of the index variable of a DO loop: nested loops where the inner loop may terminate either by satisfying the loop criterion or by a conditional EXIT statement, and the work to be done in the outer loop is along the lines of:
Code: | IF (INNER LOOP RAN FULL COUNT) THEN
BLOCK A1
ELSE ! shortened run of inner loop
BLOCK A2
ENDIF
|
We could maintain a separate logical variable to keep track of the matter, but often the terminal value of the inner loop index is sufficient. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Tue Feb 20, 2018 8:07 pm Post subject: |
|
|
davidb,
It just shows that one is never too old to learn something. In Fortran 66 the DO loop index was definitely undefined after normal completion exit, and I definitely remember various machines producing a zero, as well as the final count. It seems that the Fortran 77 standard imposed the requirement that it should be the final count + 1, which is a good thing to know, but something I never used, because assuming its value is meaningless is rather safe.
Sadly my copy of McCracken was never returned from a loan, so I can't check the original advice. Presumably one needs to know if one uses EXIT and CYCLE, or the exiting GOTO from my old-fashioned approach is the next statement after the DO loop. I'd better find out how the test works for other forms of loop in order to complete my education.
I'd always avoided decrementing, but I found a decrementing loop on the web that works:
Code: | program decrement
do i = 10, 1, -2
write(*,*) 'inner i =', i
end do
write(*,*) 'exit i =', i
end |
'exit i' is zero, but the final i through the loop was 2 (having been 10,8,6,4, and 2 in the loop). On balance, I think I'll carry on pretending I don't know what the final value is - it's my safe space.
Eddie |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Feb 20, 2018 8:27 pm Post subject: |
|
|
I recollect somewhat vaguely that the reason that the DO index became undefined was because some of the mainframes, such as CDC 6xxx, on which early Fortran ran. had 18-bit index registers and 60-bit registers for integers and reals, and it was quite a bit of work to do general arithmetic on index register contents. See http://www.60bits.net/msu/mycomp/cdc6000/65frame.htm .
Some of the early Fortrans limited you to use expressions of the form c*K+d for subscripts, where c and d were constants known at compile time and K was a DO index variable. |
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Tue Feb 20, 2018 10:43 pm Post subject: |
|
|
The rules for calculating i on normal exit.
Given
m1 is the initial value of i.
m2 is a final value of i (not necessarily achieved).
m3 is the optional increment value (cannot be zero, default is 1).
An iteration count (=number of loop passes) is calculated using
Code: |
count = max(int((m2 - m1 + m3)/m3), 0)
|
Note that count is 0 if:
m3 > 0 and m1 > m2
or
m3 < 0 and m1 < m2
The do loop is equivalent to:
Code: |
i = m1
count = max(int((m2 - m1 + m3)/m3), 0)
c = count
10 if (c .eq. 0) goto 20
<body of loop>
c = c - 1
i = i + m3
goto 10
20 continue
|
On exit i has the value m1 + count*m3 when statement label 20 is reached.
Compilers don't need to generate exactly this code but it must be equivalent. Long ago I used the Hewlett-Packard F77 compiler, which could vectorise the loop, but then made sure the final value was correctly set up using:
Code: |
call vectorize routine
i = m1 + m3*max(int((m2 - m1 + m3)/m3), 0)
|
example 1
count = max(int((n - 1 + 1)/1), 0) = n
On exit i = n + 1
example 2
count = max(int((0 - 1 + 1)/1), 0) = 0
on exit i = 1
example 3
Code: |
do i=1, 6, 2
end do
|
count = max(int((6 - 1 + 2)/2), 0) = 3
on exit i = 7
example 4
Code: |
do i=1, 5, 3
end do
|
count = max(int(5 - 1 + 3)/3), 0) = 2
on exit i = 7 _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Tue Feb 20, 2018 11:53 pm Post subject: |
|
|
david,
So what you are saying is if I test i, and it lies in between the loop limits (inclusive) then it was a forced EXIT, but if i is something else, the loop was run to completion with no forced exit?
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Wed Feb 21, 2018 12:15 am Post subject: |
|
|
Eddie,
With F90, the DO index is defined on exit.
I use this feature extensively, to test the type of exit.
Searching a list for an item is a typical use.
Code: | DO I = 1, num_known
if ( possible == list(I) ) exit
END DO
if ( I > num_known ) then ! add new item
list(I) = possible
num_known = I
end if |
|
|
Back to top |
|
|
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Wed Feb 21, 2018 11:54 am Post subject: Re: |
|
|
LitusSaxonicum wrote: | david,
So what you are saying is if I test i, and it lies in between the loop limits (inclusive) then it was a forced EXIT, but if i is something else, the loop was run to completion with no forced exit?
Eddie |
Almost. If i is something else, the loop was run to completion or was not entered at all.
Have a look at John's search/append new item example above this for a typical use case. His code will still work properly when num_known = 0. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Wed Feb 21, 2018 3:47 pm Post subject: |
|
|
Well, this is all very interesting, and I’m happy to be educated (sincerely), but it comprises what I call ‘Cotton-Eyed Joe’ programming style:
Where did you come from, how do I know?
Where did you come from, Cotton-Eyed Joe?*
Whereas my style is to know without needing to ask, on the grounds that there was only one route in, decided in advance, and signposted in traditional redneck style by a bunch of GO TOs.
A great example of Cotton-Eyed Joe programming is in a Clearwin+ %gr callback, where the first thing you have to ask is: “Where did you come from?” via -
Code: |
COTTON_EYED_JOE_string = clearwin_string@ ('CALLBACK_REASON') |
It’s a paradigm that I don’t like or use much – only when I have to (like there).
If it hadn't been for Cotton-Eyed Joe
It'd been working a long time ago.**
The alternate paradigm is exemplified by a set of callback functions for buttons on a form: you know within each callback function where it came from – although you can Cotton-Eyed Joe it by testing the WINIO@ return code instead.
Eddie
*Yes, I know I changed the words. I don’t need to ask where he’ll go. It’s there in the GO TO!
**I changed these too, on the grounds that the originals didn’t apply. 50 years and 4 days ago, if you must ask. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|