Study for Wednesday's exam, and read the Web notes introducing Arrays.
DO, CYCLE, EXIT
You've been introduced to a Fortran 90 form of the DO loop (DO WHILE). There are some other forms, that you also need to learn. In addition, there are two related Fortran 90 statements that can make some DO constructs simpler, the CYCLE and EXIT statements.
The earliest form of the DO loop is still commonly used. The loop begins with a DO statement that specifies the label of a statement ending the loop, and gives the name of a single loop index. The loop index starts with a specified value, and is incremented by a specified amount on each successive pass through the loop, until it exceeds a specified maximum value (or drops below a limit for negative increments). Here is one example:
do 100 ii=istart,ilast,istep isum = isum + ii 100 continueIn this example, I'm assuming that values have been established for istart, ilast, istep, and isum earlier in the program. The number 100 after "do" gives the label number ending the loop. I didn't have to use a CONTINUE statement here. The following coding would have been equivalent.
do 100 ii=istart,ilast,istep 100 isum = isum + iiThe use of the CONTINUE gives me room to add other statements later with minimal problems. In this instance "continue" means "continue looping" rather than continue to the next statement below.
Flow through the loop starts by comparing the initial value of "ii" ("istart") with the bounding value "ilast". If "istep" is positive and "ii" is greater than "ilast", nothing in the loop is executed and the program continues to the next statement after the one with the loop-end label. If "istep" is negative, and "ii" is less than "ilast", the loop contents are also skipped. Otherwise statements below the DO are executed through whatever statement contains the end label (here 100). Then the program adds the appropriate increment to the loop index. If the new value does not exceed the bounding value of "ilast" another pass is made through the statements within the loop. If the index has a value greater than "ilast" for positive "istep" or less than "ilast" for negative "istep", then the program proceeds with the next statement after the end of the loop.
The current Fortran standard permits consistent use of INTEGER or REAL data types for the index, its bounds, and increment. However, you will recall that the machine's floating point arithmetic makes it difficult to know whether 3.1 added 3 times to 1.0 will produce a number greater than, less than, or exactly equal to 10.3. In any case the appropriate use of a DO is for operations related to counting, and the dominant use is in applications involving array variables (covered later). It is likely that DO loop control will be restricted to INTEGER types in a future standard. Do not use REAL variables in this context. I haven't for over 25 years, and have gotten along quite well.
When providing bounds and increments, in a DO statement, you have the option to use INTEGER constants. For example, a loop to calculate 10 factorial could be written:
nfac=1 do 100 n=2,10,1 nfac=nfac*n 100 continue print *,'n=',n,', 10 factorial = ',nfacThe value printed for n would be 11, because of the way the index is incremented, but the last value of n used within the loop was 10, so the correct value of 10 factorial is printed.
Since most DO loops operate with an increment of 1, Fortran lets you abbreviate the above DO statement as:
do 100 n=2,10Whenever the increment is missing, a value of one is assumed. Of course this factorial example lacks foresight. What you really want to do is program for a general factorial calculation.
nfac=1 do 100 i=2,n nfac=nfac*i 100 continue print *, n,' factorial = ',nfacThe value of n would be established with a READ, or some assignment earlier in the program.
Fortran 90 also allows one more abbreviation to the above DO loop. The statement label is no longer mandatory, and a DO, END DO structure can be used.
nfac=1 do i=2,n nfac=nfac*i end do print *, n,' factorial = ',nfacIt is worth running through some examples on your own so that you are confident about when the contents of a loop are executed, and what the value of the index is after the loop completes normally. Try entering the following program:
program testdo integer i,i1,i2,istep parameter (i1=2, i2=6, istep=3) do i=i1,i2,istep print *, 'Value of i within the loop is: ',i enddo print *, 'Value of i after the loop completes is:',i stop end
Do several more trials, changing the parameter statement to the following, and observing the results.
parameter (i1=2, i2=6, istep=-1) parameter (i1=10, i2=6, istep=-1) parameter (i1=10, i2=6, istep=-3) parameter (i1=10, i2=6, istep=1)
This indexed DO structure works rather nicely with our Newton iteration example. Notice that it is possible to include GO TO (or other branching) statements within the DO loop to exit the loop when certain conditions are met. However, you may not have any branching statement external to the loop with a branch to a label contained within a DO loop (including the end of loop label).
If you belong to the school of thought, that GO TOs should be avoided at all cost, then the Fortran CYCLE and EXIT statements are for you. Even if you aren't, they can clean up your program in many cases. CYCLE says don't do any more of the statements below this one in the DO loop and cycle back to the beginning of the loop to start the pass with the next value of the index. EXIT says leave the DO loop, branching to execute the next statement after the end of the loop.
An old DO structure with GO TO's and labels like:
x=1 do 100 i=1,10 x=2*x+i if (x.gt.200) go to 200 if (x.lt.100) go to 100 print *, ' x.ge.100' 100 continue 200 print * , ' x = ',xwith Fortran 90 can become:
x=1 do i=1,10 x=2*x+i if (x.gt.200) exit if (x.lt.100) cycle print *, ' x.ge.100' end do print * , ' x = ',xThe simple DO is another one of the structures that Fortran 90 lets you name. In the previous example, I might choose to provide the construct name "xtest" as follows:
x=1 xtest: do i=1,10 x=2*x+i if (x.gt.200) exit if (x.lt.100) cycle print *, ' x.ge.100' end do xtest print * , ' x = ',x
x=1 do x=2*x+1 if (x.gt.200) exit if (x.lt.100) cycle print *, ' x.ge.100' end do print * , ' x = ',x
Check you knowledge of this material, but first be sure your Web Browser works correctly.
Written and Maintained by John Mahaffy : email@example.com