Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!uwm.edu!ux1.cso.uiuc.edu!ux1.cso.uiuc.edu!auriga!jadoube!levine From: levine@jadoube.mcs.anl.gov Newsgroups: comp.lang.fortran Subject: WHERE statement Message-ID: <10400001@jadoube> Date: 26 Oct 89 16:31:32 GMT Lines: 122 Nf-ID: #N:jadoube:10400001:000:4925 Nf-From: jadoube.mcs.anl.gov!levine Oct 25 16:11:00 1989 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