[comp.lang.fortran] WHERE statement

levine@jadoube.mcs.anl.gov (10/26/89)

I've recently ported an existing Fortan 77 program to Fortran 8x and found
what I consider significant limitations in the WHERE statement.  The problems
I've encountered stem from the WHERE statement being just a masked assignment
statement, and not a parallel IF statement.  So only array assignment 
statements are allowed in WHERE blocks.  In particular other (nested) WHERE
statements are not allowed nor are subroutine calls.

At least for the example below, the 8x code seems awkward to write, and the
amount of it required greater than the necessary 77 code.  The code fragments
are from a cellular automata program that implements a 2-d hexagonal lattice
on an N by N array.

The things in the 77 code that I think make the 8x port difficult are:
1) Nested IF statements 
2) Dealing with boundary conditions in the same loop as dealing with the bulk.
3) The problem geometry( mapping a hexagon into a rectangle).

The problems I see with the WHERE statement are the following:

1. The inability to nest WHERE statements leads to having to AND together
   all the logical expressions making the code a) larger b) difficult to 
   read and c) more inefficient (all the repeated mask computations
   [maybe with some ugly kludge these can be precomputed but the code gets
   even uglier]).  I consider the inability to nest WHERE statements a
   very serious limitation.

2. Also not allowed in WHERE statements are subroutine calls.  It seems
   natural to want to make a subroutine call to make a calculation in some
   cases but not others.  Short of inlining the subroutine, or passing the
   mask to the subroutine there doesn't seem to be a sensible way to do this.

3. There is no ELSEWHERE IF structure.  By analogy with the IF statement

   IF                  WHERE
    :                   
   ELSEIF              ! nothing analagous (i.e., ELSEWHERE IF) exists
    :                  
   ELSE                ELSEWHERE
    :                   :
   ENDIF               ENDIF


4. The conformability requirement.  I may be out in left field with this one
   but as a dumb programmer it sure looks to me like there could be a 
   natural mapping of A(1:N-1) into the logical expression L(1:N).  Its
   been pointed out to me that in the more general case the mapping of
   A(ilower:iupper) into L(1:N) is not defined, and gets even worse if you
   add a stride as in L(1:N:ISTRIDE) but would it make sense
   to say that if the bounds were constants or used the same variable
   +- a constant that a mapping could be defined?

I'd be interested in other peoples comments on the WHERE statment, it
seems very limited and inflexible to me.   --dave (opinions my own)

 David Levine       		       levine@mcs.anl.gov
 Mathematics and Computer Science      {alliant,sequent,rogue}!anlams!levine
 9700 Cass Avenue South                (312) 972-6735
 Argonne National Laboratory            
 Argonne, Illinois 60439

-------------------Original Fortran 77 code fragment------------------------
Below is the Fortan 77 code.  It only contains one of 6 similar IF tests.
[i1 is used to determine the neighbor cell in the row above (below).  ]
[It varies for even and odd rows because a hexagonal lattice is being ]
[ mapped into a rectangular grid.                                     ]

      DO 10 i = 1, n
         DO 20 j = 1, n
           IF ( state(i,j) .eq. 1 ) THEN
                      :
              IF ( sortie(i,j) .gt. 0 )  THEN
                      :
                IF ((p6 .gt. 0) .and. (p1 .lt. 0) .and. (d1 .gt. 0)) THEN
                   tx(i,j) = x(i,j) - bp
                   ty(i,j) = y(i,j) - ap
                   outne(i,j) = 1
                   IF (( i1 .lt. n) .or. ( j .lt. n )) THEN
                      insw(i1+1,j+1) = 1  
                   ENDIF
                ENDIF
                      :
              ENDIF
                      :
           ENDIF
20       CONTINUE
10    CONTINUE

-----------Manually Converted Fortran 8x code fragment------------------------

The code above was turned into the following Fortran 8x code.

 WHERE (state .EQ. 1)  
  :
 ENDWHERE
    :
    WHERE ((state .EQ. 1)  .AND. (sortie .gt. 0))
    :
    ENDWHERE
       :
       WHERE ((state .EQ. 1)   .AND.
    +         (p6.GT.0)        .AND.
    +         (p1.LT.0)        .AND.
    +         (d1.GT.0))
         tx = x - bp
         ty = y - ap
         outne = 1
       ENDWHERE
       WHERE ((state(2:n:2,1:n) .EQ. 1)  .AND.
    +         (p6(2:n:2,1:n).GT.0)       .AND.
    +         (p1(2:n:2,1:n).LT.0)       .AND.
    +         (d1(2:n:2,1:n).GT.0))
         insw(1:n-1:2,1:n) = 1
       ENDWHERE
       WHERE ((state(3:n-1:2,1:n-1) .EQ. 1)  .AND.
    +         (sortie(3:n-1:2,1:n-1).GT.0)   .AND.
    +         (p6(3:n-1:2,1:n-1).GT.0)       .AND.
    +         (p1(3:n-1:2,1:n-1).LT.0)       .AND.
    +         (d1(3:n-1:2,1:n-1).GT.0))
         insw(2:n-2:2,2:n) = 1
       ENDWHERE

fisher@Alliant.COM (Larry Fisher) (10/27/89)

I have one question in regard to the "conversion" of a DO loop with nested
IFs to a Fortran 8X WHERE block:  Why do the conversion?

Working with the Alliant Fortran compiler, I have the option of using
WHERE blocks when porting and tuning code.  However, I find that it is
rarely worth the time to do the conversion for a number of reasons.

First, I assume that the reason for using WHERE is to get (force) the
DO/nested IF structure to be mapped to vector hardware instructions.  As
a practical matter on today's vector processors, vectorized IF
statements are worthwhile only if the conditionally-executed (cond-ex)
statements are "frequently" executed.  I quote the word frequently
because the definition varies by machine and by computational complexity
of the cond-ex code.  Keeping the explanation brief, the implementation
of vector IFs causes the cond-ex code to be executed *regardless* of
whether or not the result will be used.  The only part of the cond-ex
code that is conditional is the storage into destination
(left-hand-side) variables based on a mask; a mask that is the result of
the IF statement's condition expression.

Second, I (IMHO) view WHERE blocks to be a notational shorthand that is
to be used where appropriate.  The DO/nested IF example recently shown
in this group is not one I would consider appropriate for a WHERE block.
As was pointed out by the original poster, forcing the readable F78 code
into a much-less-comprehensible F8x WHERE block doesn't make sense,
never mind the fact that no equivalent to ELSEIF exists.  Finally, It
doesn't appear to me that the existing algorithm implemented in F78 is
one that, without changes, will run effectively on vector hardware.

Certainly we could discuss automatic mapping of DO/IF constructs to
WHERE blocks by a Fortran compiler, as is done, where appropriate, by
Alliant's FX/Fortran compiler, but that's just one of a number of other
considerations tied to the above comments.

"Opinions..."
-- 
Larry Fisher			Domain:	fisher@alliant.com
Alliant Computer Systems	UUCP:	{mit-eddie|linus}!alliant!fisher
Littleton, MA 01460		Phone:	(508) 486-1449

mcdonald@uxe.cso.uiuc.edu (10/27/89)

>At least for the example below, the 8x code seems awkward to write, and the
>amount of it required greater than the necessary 77 code.  The code fragments
>are from a cellular automata program that implements a 2-d hexagonal lattice
>on an N by N array.

I simply don't understand this. Sine F8x is a superset of F77, how
can F8x code be "more awkward to write" or the amount "greater than
the necessart 77 code" - they are both impossible. Perhaps you could
find an unsuited F8x construct, and write worse code using that construct -
but you could use the older, more suitable constructs, and have 
"less awkward" and smaller code.

Dpug McDonald