forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Program aborts with spurious error report
Goto page Previous  1, 2
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Tue Feb 20, 2018 5:24 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1884

PostPosted: Tue Feb 20, 2018 6:36 pm    Post subject: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Tue Feb 20, 2018 8:07 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1884

PostPosted: Tue Feb 20, 2018 8:27 pm    Post subject: Reply with quote

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
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Tue Feb 20, 2018 10:43 pm    Post subject: Reply with quote

The rules for calculating i on normal exit.

Given

Code:

do i=m1,m2,m3

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
Code:

do i=1, n
end do

count = max(int((n - 1 + 1)/1), 0) = n
On exit i = n + 1

example 2
Code:

do i=1, 0
end do

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Tue Feb 20, 2018 11:53 pm    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2551
Location: Sydney

PostPosted: Wed Feb 21, 2018 12:15 am    Post subject: Reply with quote

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
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed Feb 21, 2018 11:54 am    Post subject: Re: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Wed Feb 21, 2018 3:47 pm    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
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