[comp.lang.fortran] Questions about IF

br0w+@andrew.cmu.edu (Bruno W. Repetto) (06/23/91)

Suppose there is this IF command:

  IF(<expression-1>.AND.<expression-2>.AND. ... .AND.<expression-n>)statement

(The intent is to execute 'statement' ONLY IF all expressions 'expression-i',
for i=1 to n, evaluate to .TRUE.)

My questions are about the STANDARD for executing such a command:
1) Are the expressions evaluated from "left to right"?
2) Supposing 1) above is true, if expressions 1 to i evaluate to .TRUE., and
   expression i+1 evaluates to .FALSE., are the subsequent expressions
   evaluated (if any remain), or is the execution of the IF command concluded
   right then?

I know that at least Microsoft FORTRAN (v5.0) and Sun f77 (v1.3.1) "do it
right", i.e., they evaluate the expressions from left to right.  The execution
of the command is concluded as soon as one of the expressions evaluate to
.FALSE.; otherwise, 'statement' is executed.

Thanks.  Bruno.  br0w+@andrew.cmu.edu

burley@albert.gnu.ai.mit.edu (Craig Burley) (06/24/91)

In article <scNB_TG00WBMQ0ykwM@andrew.cmu.edu> br0w+@andrew.cmu.edu (Bruno W. Repetto) writes:

   Suppose there is this IF command:

     IF(<expression-1>.AND.<expression-2>.AND. ... .AND.<expression-n>)statement

   1) Are the expressions evaluated from "left to right"?

The standard doesn't mandate any particular order, even if the expressions
have side effects -- if there are order dependencies in the side effects, then
the program (probably) is not standard-conforming.

   2) Supposing 1) above is true, if expressions 1 to i evaluate to .TRUE., and
      expression i+1 evaluates to .FALSE., are the subsequent expressions
      evaluated (if any remain), or is the execution of the IF command concluded
      right then?

(First of all, 1) above is NOT true, but the answer might explain things
further.)

Again, it's entirely up to the compiler.  A program that depends on expressions
i+2 through the rest being evaluated even if i+1 evaluates .FALSE. is not
standard-conforming -- for that matter, so is a program that depends on any
of the expressions 1 through i being evaluated if i+1 evaluates .FALSE. (i.e.
they evaluate to .TRUE.).  In other words, if the compiler can somehow "divine"
that testing expression i+1 first is a good idea (i.e. it has no side effects
and is fairly simple), it can do it and skip the rest, so in

    IF (LFUNC1(X).AND.LFUNC2(Y).AND..FALSE.) STOP

a standard-conforming compiler may make the entire statement effectively
disappear even though LFUNC1 and LFUNC2 might perform important side effects;
if they do (including modifying their arguments), the program is
(potentially) not standard-conforming.

The upshot of all this is that a great deal of flexibility is extended to
the Fortran compiler writer by the standard, at the "expense" of the
Fortran programmer, as compared to, say, the C language.  This is one of the
many reasons for preferring Fortran over C or vice versa, depending on the
task at hand.
--

James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

JRowe@exua.exeter.ac.uk (John Rowe) (06/24/91)

In article <scNB_TG00WBMQ0ykwM@andrew.cmu.edu> br0w+@andrew.cmu.edu (Bruno W. Repetto) writes:


>     IF(<expression-1>.AND.<expression-2>.AND. ... .AND.<expression-n>)statement

> My questions are about the STANDARD for executing such a command:
> 1) Are the expressions evaluated from "left to right"?

I doubt it. The 77 standard says (section 6.6.7) "the processor may
evaluate any other expression that is logically equivalent, provided
that the integrity of parentheses is not violated." I assume that
allows it to reverse the ordering.

> 2) Supposing 1) above is true, if expressions 1 to i evaluate to .TRUE., and
>    expression i+1 evaluates to .FALSE., are the subsequent expressions
>    evaluated (if any remain), or is the execution of the IF command concluded
>    right then?

 The compiler has the choice. The standard says (6.6.1) "It is not
necessary", it doesn't say "shall not".

Basically FORTRAN is about you specifying a FORmula and the compiler
TRANslating in the fastest way it can. Things like an expression, one
part of which is only evaluated if another part is true/false are
totally alien, unlike say in C.

John

seymour@milton.u.washington.edu (Richard Seymour) (06/25/91)

In article <scNB_TG00WBMQ0ykwM@andrew.cmu.edu> br0w+@andrew.cmu.edu (Bruno W. Repetto) writes:
>Suppose there is this IF command:
>  IF(<expression-1>.AND.<expression-2>.AND. ... .AND.<expression-n>)statement
>My questions are about the STANDARD for executing such a command:
>1) Are the expressions evaluated from "left to right"?
>2)...   expression i+1 evaluates to .FALSE., are the subsequent expressions
>   evaluated (if any remain), or is the execution of the IF command concluded
>   right then?

DEC VAX/VMS Fortran manual babbles on about this at lenght.  if you want
ALL of the subexpressions evaluated, and you want the order (left-right)
which you entered, use the compiler switch /NOOPTimize
otherwise, all bets are off... the compiler reserves the right to cease
 chewing thru them if one proves .false., to re-order them for speed,
to migrate some of them outside for pre-evaluation outside of a DO loop,
and to completely ignore the line if the compiler knows the outcome
(the if(foo.and.boo.and..FALSE.)  case.)
and at times i've seen the /noopt case still shuffle the order (common
subexpression evaluation)
(the   if((a+1.gt.24).and.(a+1.lt.30)) case.. the "a+1" may happen only once.)
--dick

jlg@cochiti.lanl.gov (Jim Giles) (06/25/91)

Actually, the standard does require that no optimization 
violate parenthesis.  So you can force the order of
evaluation any way you want:

      If (expr1 .and. (expr2.and.expr3)) then
         ...

This does the second '.and.' first.  The other question was about
short-circuiting: the standard _allows_ short-circuiting but does
not _require_ it.

J. Giles

rchrd@well.sf.ca.us (Richard Friedman) (06/25/91)

Another compiler-dependent problem with IF statements has to do
with optimizations.  Supposing the IF is within a loop and
the compiler has smartly removed loop independent computations
outside the loop, but some of the items in the IF expression
should not be computed if earlier expressions are false because
they will cause out of bounds array references:

   IF(SW1 .and. BAR(I+N)-BAR(I) .eq. 0)...

Suppose I and N are not defined if SW1 is false (say its some
sort of processing option).  If the IF were in a loop, the 
compiler might want to precompute the BAR()-BAR(), or atleast
maybe just prefetch them.  This could generate referencing
errors if SW1 is false.  And, it could be order dependent
(left-right r/t right-left), which raises portability issues.
Gotta be careful outthere.
-- 
/\=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=/\
\/Richard Friedman (415)540-5216  |     rchrd@well.sf.ca.us  \/
/\Pacific-Sierra Rsrch (Berkeley) | or well!rchrd@apple.com  /\
\/=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\/

silvert@cs.dal.ca (Bill Silvert) (06/25/91)

In article <26384@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
>Actually, the standard does require that no optimization 
>violate parenthesis.  So you can force the order of
>evaluation any way you want:
>
>      If (expr1 .and. (expr2.and.expr3)) then
>         ...
>
>This does the second '.and.' first.  The other question was about
>short-circuiting: the standard _allows_ short-circuiting but does
>not _require_ it.

Sorry, this doesn't make sense to me.  All the parentheses guarantee is
that expr1 will not be evaluated second.  Both the sequences 1-2-3 and
3-2-1 are consistent with the given parentheses.
-- 
William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography
P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2.  Tel. (902)426-1577
UUCP=..!{uunet|watmath}!dalcs!biome!silvert
BITNET=silvert%biome%dalcs@dalac	InterNet=silvert%biome@cs.dal.ca

burley@pogo.gnu.ai.mit.edu (Craig Burley) (06/25/91)

In article <25663@well.sf.ca.us> rchrd@well.sf.ca.us (Richard Friedman) writes:

   Another compiler-dependent problem with IF statements has to do
   with optimizations.  Supposing the IF is within a loop and
   the compiler has smartly removed loop independent computations
   outside the loop, but some of the items in the IF expression
   should not be computed if earlier expressions are false because
   they will cause out of bounds array references:

      IF(SW1 .and. BAR(I+N)-BAR(I) .eq. 0)...

   Suppose I and N are not defined if SW1 is false (say its some
   sort of processing option).  If the IF were in a loop, the 
   compiler might want to precompute the BAR()-BAR(), or atleast
   maybe just prefetch them.  This could generate referencing
   errors if SW1 is false.  And, it could be order dependent
   (left-right r/t right-left), which raises portability issues.
   Gotta be careful outthere.

Yes, but it should be made clear the problem is really with the program, not
the compiler.  The IF statement should really be two IFs:

      IF (SW1) THEN
          IF (BAR(I+N)-BAR(I) .eq. 0)...
      END IF

(or equivalent).  This is one of the many reasons I like coding in C; the
kind of tasks I write programs for, I often need to represent these kinds of
conditionals, and the C construct, "if (sw1 && ...)", does exactly what I want.
On the other hand, C provides no proper equivalent for Fortran's .AND. and
.OR., which is unfortunate since it would be handy at times.  (It provides
bitwise AND and OR, but the compiler must evaluate both operands, it does not
have the option of short-circuiting; so either you must code using left-to-
right short-circuiting, where you have to decide which operand takes longer
to evaluate for yourself, or you don't get short-circuiting at all.)
--

James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

burley@pogo.gnu.ai.mit.edu (Craig Burley) (06/25/91)

In article <1991Jun25.124806.15349@cs.dal.ca> silvert@cs.dal.ca (Bill Silvert) writes:

   In article <26384@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
   >Actually, the standard does require that no optimization 
   >violate parenthesis.  So you can force the order of
   >evaluation any way you want:
   >
   >      If (expr1 .and. (expr2.and.expr3)) then
   >         ...
   >
   >This does the second '.and.' first.  The other question was about
   >short-circuiting: the standard _allows_ short-circuiting but does
   >not _require_ it.

   Sorry, this doesn't make sense to me.  All the parentheses guarantee is
   that expr1 will not be evaluated second.  Both the sequences 1-2-3 and
   3-2-1 are consistent with the given parentheses.

As I understand the standard, ANY sequence of evaluation of expr1, expr2, and
expr3 is valid.  What the parentheses do is ensure that the second .and. is
evaluated as written.

In other words, the system (compiler) may evalute expr3 first, expr1 second,
and expr2 third.  Then it must evaluate (expr2.and.expr3) (the exprns already
having been evaluated, so they now represent the results of those evaluations),
because the result is needed in evaluating expr1.and.result (or anything
logically equivalent, according to the standard).

The upshot is, in my opinion, there is basically no need for parentheses
in logical or relational expressions in Fortran except to enforce or override
precedence.  (There's no need for them at all in character expressions, since
only one character operator, //, exists.)  In arithmetic expressions,
parentheses are useful to ensure an order of operator (_not_ operand)
evaluation that might prevent overflow compared to some other order.  For
example, in A+(B+C), A, B, and C may be evaluated in any order, but the
parentheses ensure that B and C are added together and the result added to
A, instead of possibly adding A and B together or A and C, and this might
reduce the possibility of overflow (or underflow).

In summary: parentheses in Fortran do not restrict the order of evaluation
of operands, just the way in which operators are applied to their operands.
(This is my opinion; if you think otherwise, please point me to the applicable
spot in the standard.  I'm using Section 6.6.3 page 6-17, "Integrity of
Parentheses", as a guide, and the wording is a bit ambiguous, but the
sentence beginning "For example" seems to indicate that what is at issue
is the evaluation of operators, not operands.  6.6.2 seems to back this
up, implying that a processor (compiler) may evaluate the function
references in the expression "F1(X)*(F2(X)*F3(X))" in any order.)
--

James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

jlg@cochiti.lanl.gov (Jim Giles) (06/26/91)

In article <1991Jun25.124806.15349@cs.dal.ca>, silvert@cs.dal.ca (Bill Silvert) writes:
|> In article <26384@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
|> >Actually, the standard does require that no optimization 
|> >violate parenthesis.  So you can force the order of
|> >evaluation any way you want:
|> >
|> >      If (expr1 .and. (expr2.and.expr3)) then
|> >         ...
|> >
|> >This does the second '.and.' first.  The other question was about
|> >short-circuiting: the standard _allows_ short-circuiting but does
|> >not _require_ it.
|> 
|> Sorry, this doesn't make sense to me.  All the parentheses guarantee is
|> that expr1 will not be evaluated second.  Both the sequences 1-2-3 and
|> 3-2-1 are consistent with the given parentheses.

You misunderstand the parenthesis rule.  The objects I've called
`expr1', `expr2', and `expr3' can be evaluated in _any_ order.
The parenthesis force the 'and' between `expr2' and `expr3' to 
be evaluated before the other 'and'.  That's all.

J. Giles

anda@cs.umn.edu (Andrew A. Anda) (06/26/91)

May one force the first expression to be evaluated in the the
following statement to be expr2 by parenthesis embedding in the
following manner?

if(expr1.and.(expr2))then
...

&y&a
-- 
Andrew Allen Anda, (University of Minnesota: anda@cs.umn.edu)
Computer Science Dept., 4-192 EE/CSci Bldg.,
200 Union St. S.E.,
Mpls., MN 55455

JRowe@exua.exeter.ac.uk (John Rowe) (06/26/91)

In article <26384@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:

>   Actually, the standard does require that no optimization 
>   violate parenthesis.  So you can force the order of
>   evaluation any way you want:

>	 If (expr1 .and. (expr2.and.expr3)) then
>	    ...

>   This does the second '.and.' first.

But can it choose to evaluate:

	 If ((expr2.and.expr3) .and. expr1) then

I didn't see anything that said it couldn't.

John

silvert@cs.dal.ca (Bill Silvert) (06/26/91)

In article <26462@beta.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
>You misunderstand the parenthesis rule.  The objects I've called
>`expr1', `expr2', and `expr3' can be evaluated in _any_ order.
>The parenthesis force the 'and' between `expr2' and `expr3' to 
>be evaluated before the other 'and'.  That's all.

What's the point?  The original posting asked about the order in which
the expressions were evaluated, since that can have side effects.  What
difference does it make in what order the AND's are evaluated?

Bill
-- 
William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography
P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2.  Tel. (902)426-1577
UUCP=..!{uunet|watmath}!dalcs!biome!silvert
BITNET=silvert%biome%dalcs@dalac	InterNet=silvert%biome@cs.dal.ca

burley@pogo.gnu.ai.mit.edu (Craig Burley) (06/26/91)

In article <1991Jun26.055007.8060@cs.umn.edu> anda@cs.umn.edu (Andrew A. Anda) writes:

   May one force the first expression to be evaluated in the the
   following statement to be expr2 by parenthesis embedding in the
   following manner?

   if(expr1.and.(expr2))then

No.  The parens only ensure that the first .and. will not be combined in
ways different than specified with any operators in expr2.  But evaluation
of operands (expr1, expr2, and any operands within them) can still happen
in any order.
--

James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

jlg@cochiti.lanl.gov (Jim Giles) (06/27/91)

In article <1991Jun26.130917.20736@cs.dal.ca>, silvert@cs.dal.ca (Bill Silvert) writes:
|> [...]
|> What's the point?  The original posting asked about the order in which
|> the expressions were evaluated, since that can have side effects.  What
|> difference does it make in what order the AND's are evaluated?

Well, AND is commutative and associative, so it shouldn't make any
difference.  But, Fortran _allows_ short-circuit evaluation of logicals,
so if you're on one of those machines that does that, the order of the
ANDs usually turns out to be the order of the expressions as well.
It could be nice to know you can enforce that.

J. Giles

userAKDU@mts.ucs.UAlberta.CA (Al Dunbar) (06/29/91)

In article <JROWE.91Jun26111343@exua.exua.exeter.ac.uk>, JRowe@exua.exeter.ac.uk (John Rowe) writes:
>In article <26384@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
> 
>>   Actually, the standard does require that no optimization 
>>   violate parenthesis.  So you can force the order of
>>   evaluation any way you want:
> 
>>        If (expr1 .and. (expr2.and.expr3)) then
>>           ...
> 
>>   This does the second '.and.' first.
> 
>But can it choose to evaluate:
> 
>         If ((expr2.and.expr3) .and. expr1) then
> 
>I didn't see anything that said it couldn't.
> 
 
Exactly. This does not violate parenthesis. Assuming no side
effects, the results of both of the above would be the same.
 
 -------------------+-------------------------------------------
 Al Dunbar          | 
 Edmonton, Alberta  |  Disclaimer: "not much better than
 CANADA             |                  datclaimer"    
 -------------------+-------------------------------------------