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" -------------------+-------------------------------------------