IF ( (im == 0) .OR. ( im > 0 .AND. m(im) /= tbi ) ) THEN
...
END IF ! im
This code gets executed with im = 0, and I get an error when running
with subscript checking on, because it executes the statement m(im) /= tbi.
This seems unnecessary and wasteful to me, and actually complicates the
code if one wants to avoid errors with checking. As far as I know, C
(and C++) do not have this problem. Why is this a problem in Fortran?
I am running Absoft F90 8.0 on RH 9.0, but I have also seen this
behavior on other machines.
Andreas
IF (im == 0) THEN
...
ELSE
IF (im > 0) THEN
IF (m(im)...)
Jan
Hmm. Interesting. I see this as a feature! :o) (I have no C or C++ experience). If "im"
is to be used as an array index, I'd sure want to know if it _ever_ went out of bounds
(even if I wasn't going to use it in that situation.)
Since you're evaluating both logical expressions (im == 0 and (im > 0 .AND. m(im) /= tbi))
in the same construct, you don't distinguish between the two so why test for both? If you
use "im" in such a way that a value of 0 is a necessary valid value (for whatever other
use), what about declaring "m" like so:
real, dimension(0:N) :: m
and then always setting m(0) to some non-tbi value,
m(0) = -tbi
and then simply do
if ( m(im) /= tbi ) then
...
end if
?
The intent seems clearer to me (based solely on the snippet provided).
cheers,
paulv
--
Paul van Delst
CIMSS @ NOAA/NCEP/EMC
Ph: (301)763-8000 x7748
Fax:(301)763-8545
> Why does Fortran evaluate entire logical statements, even if part of
> it already made checking the remainder superfluous? For example,
>
>
> IF ( (im == 0) .OR. ( im > 0 .AND. m(im) /= tbi ) ) THEN
> ...
> END IF ! im
>
> This code gets executed with im = 0, and I get an error when running
> with subscript checking on, because it executes the statement m(im) /=
> tbi.
Your code is illegal if it depends on such short-circuiting.
Compilers may do it if they choose as an optimization, but code
is not allowed to depend on it.
This question is frequently discussed, so I will not go into
detail. In general, the Fortran standard goes to a lot of trouble
to allow compilers to optimize expressions as best fits the
particular environment. Note that the order of evaluation of
subexpressions is *NOT* specified by the standard; they might
even be evaluated in parallel in general.
The compiler is given the freedom to reorder things (with some limits,
particular involving parens) for optimization or other purposes.
Code that depends on a specific order of evaluation or on
eliding specific parts of the expression is specifically
forbidden by the standard.
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Fortran doesn't require that both parts of the test be executed. It also
doesn't require that both parts not be executed. Further, the language
doesn't state in which order the operands of the expression are
evaluated (in most modern hardware, where piplining is employed,
it is more efficient to evaluate things that are independent in parallel).
And, since logical OR is a commutative operator, the language allows
the expression to be evaluated right to left. (The same for logical AND.)
> This seems unnecessary and wasteful to me, and actually complicates the
> code if one wants to avoid errors with checking. As far as I know, C
> (and C++) do not have this problem. Why is this a problem in Fortran?
It depends on what you consider wasteful, I suppose. For most logical
expressions full evaluation is more efficient since it allows better use
of pipelined instructions. And, you don't have to insert conditional
jumps at lots of points within the code that evaluates the expressions
(such a jump is often almost as expensive it's not taken as it is if the
jump is taken). Of course, the code does get more complex if you
really want to force the shortcutting of the operators. Different decisions
by different language designers.
--
J. Giles
> Why does Fortran evaluate entire logical statements, even if part of
> it already made checking the remainder superfluous? For example,
>
> IF ( (im == 0) .OR. ( im > 0 .AND. m(im) /= tbi ) ) THEN
> ...
> END IF ! im
>
> This code gets executed with im = 0, and I get an error when running
> with subscript checking on, because it executes the statement m(im) /=
> tbi.
>
Fortran provides absolutely no guidance on the order in which the
various components of a
compound logical expression need be evaluated, only that the correct
logical result be found.
There is specifically no guarantee that the compiler do things in a
"left to right" sequence
following the source code. It is left to the programmer to explicitly
preclude the case of a
null subscript,
DO WHILE (im >= 0)
IF (im > 0) THEN
IF (m(im) == tbi) EXIT
END IF
... condition is satisfied ...
EXIT
END DO
I suggest a DO construct because of the convenience of using EXIT to
break out.
Andreas
> DO WHILE (im >= 0)
> IF (im > 0) THEN
> IF (m(im) == tbi) EXIT
> END IF
> ... condition is satisfied ...
> EXIT
> END DO
>
> I suggest a DO construct because of the convenience of using EXIT to
> break out.
Admitedly a matter of personal style and preference rather than
of something concrete, but I personally advise against the use of
DO constrcuts for things like this. DO is fundamentally a looping
construct and I recommend that its use be restricted to places
where you want a loop. When you use it for something that really
has nothing to do with loops:
1. I find it confusing to read as a human. My mind sees the initial
DO WHILE here and assumes that we are starting a loop. I have
to read down through it to figure out that this particular
loop can never actually loop.
You are basically using DO WHILE as a strangely spelled
synonym for "IF" in order to take advantage of some of the
syntax options offered by "IF".
I agree that it would be nice if EXIT could work with IF blocks,
but I don't find this a good substitute. Frankly, I think a good
old GOTO is clearer than this. GOTO has its problems, and I very
seldom use it any more, but its problems aren't automatically
solved by avoiding that particular spelling. In my mind, using a
DO WHILE to emulate an IF is worse than just using a GOTO.
(I wouldn't use a GOTO for this one either. Odds are that
I'd use an extra logical variable.)
2. I think it very error prone. It is going to be awfully easy
to forget that EXIT at the end, in which case you have an
infinite loop.
Personal styles differ, I realize. That's one that I personally
really don't like.
P.S. While I'm ementioning personal styles, another of mine is
that I never use EXIT without a construct label. Otherwise I find
it confusing to the reader. Yes, I know that it always refers to DO
constructs - never to SELECT or IF constructs or to the whole
procedure, but I don't find that intuitively obvious. The only
reason I know it is that I've just plain memorized it.
I too wish that EXIT worked with IF blocks. But it doesn't (and why not?
--was this ever a subject for discussion in the language committee?), and
I have long felt (with, I think, much good company) that GOTOs are to be
avoided at all costs; I use them as sparingly as possible, and only for
error
breakouts when there simply is no alternative. It is certainly a valid
criticism
of my constuct to note that omitting the final EXIT would screw things up
(and that omission would not produce an error message, in contrast to a
missing ENDIF), but I also submit that my sample is nonetheless clear and
efficient.
DO WHILE is to me quite different from a simple DO loop: it _is_ a more
powerful version of IF which I do not hesitate to employ for that purpose,
and I do not feel I am perverting the language -- or the code's human
readability
-- by doing so, but rather taking full advantage of the statement's
natural syntax.
But in this case, the main motivation, as stated, is the appropriateness
(and
cleanness) of being able to use EXIT to break out; I would not have chosen
this if there were an EXITIF statement for IF blocks.
It does, but it is spelled GOTO.
> --was this ever a subject for discussion in the language committee?), and
> I have long felt (with, I think, much good company) that GOTOs are to be
> avoided at all costs; I use them as sparingly as possible, and only for
> error
> breakouts when there simply is no alternative.
I don't think "GOTOs should be avoided at all costs."
GOTOs should be avoided when there are clearer and specific
constructs.
In this case, there isn't.
> I am grateful for the thoughtful comments, but do not necessarily agree.
That's fine. I'll leave it at that. (I'm unrepentant, but I don't
like arguing about points of style choice. I'll point out my style
choices and summarize my reasons once, but not argue about them.)
I also prefer xemacs over either gnu emacs or vi. :-)
To answer a question you asked, though
> I too wish that EXIT worked with IF blocks. But it doesn't (and why not?
> --was this ever a subject for discussion in the language committee?),
Yes, it certainly has been discussed. Why it wasn't allowed in the first
place, I don't know. I wasn't there. One might suspect that it just
wasn't thought of because it was introduced while working on DO loops
and nobody noticed that the same thing might be nice elsewhere, but that
is purely speculation on my part.
As for why it isn't added now....well one issue is certainly
compatibility with existing standard-conforming code. If the same
EXIT that now means to exit a DO loop changes meaning, then that would
be a very big problem. Having the standard change the interpretation
of code that curretly is unambiguously specified would be incredibly
bad; I can't see that flying at all. So if something were done,
it would have to be done in a compatible way. I'm sure that is
possible, but it does complicate life...and likely add confusion.
For example, the code you showed had exactly one of the kinds of constructs
that would be problematical. You had (abbreviated to the essentials)
DO...
IF (...) ...
... EXIT
END IF
END DO
That EXIT unambiguously means to EXIT the DO loop, not the IF
block. No way that I can see the standard changing so that it
means to exit the IF block. That would break your code; probably
wouldn't generate a warning message or anything - just wouldn't
work right. And it would do the same to other people's code.
(Wouldn't break mine because of my style of always using a construct
name on my EXITs).
Any solution to this seems likely to have issues of one kind or other.
i usually just put a comment after the exit, eg. exit ! i loop
C would enforce sequential short-cut evaluation only with a particular
translation of your code into C. In this context, a Fortran compiler is
free to translate .OR. as | or || would be translated in C, and .AND. as &
or &&. As the other posters have pointed out, if your code requires a
specific interpretation, write it so that the compiler has no choice.
--
Tim Prince
Note that if tbi is zero, m(0) would be equal to tbi :)
But I like the general idea: that way you turn code into data.
Regards,
Arjen
> > This seems unnecessary and wasteful to me, and actually complicates the
> > code if one wants to avoid errors with checking. As far as I know, C
> > (and C++) do not have this problem. Why is this a problem in Fortran?
>
> It depends on what you consider wasteful, I suppose. For most logical
> expressions full evaluation is more efficient since it allows better use
> of pipelined instructions. And, you don't have to insert conditional
> jumps at lots of points within the code that evaluates the expressions
> (such a jump is often almost as expensive it's not taken as it is if the
> jump is taken). Of course, the code does get more complex if you
> really want to force the shortcutting of the operators. Different decisions
> by different language designers.
>
Now, that figures! I never realised that this is the (or a) reason!
Thanks for this enlightenment (I mean it)
Regards,
Arjen
Oh yeah... <ehem>. (Insert d'oh/forehead-slap here).
But, (trying to save face somewhat here... :o), hopefully there are some other constraints
(physical or otherwise) on tbi in the OP's code.
Huh. How about that...that's what I usually use as construct names!
i_loop: DO i = 1, N
....
IF ( ... ) EXIT i_loop
....
END DO i_loop
I find *not* using construct names (or comments) with exit statements very confusing. When
I see "exit" I still think of it as akin to stop or return (e.g. exit this
program/routine). Sticking a construct name (or comment) in there makes my intent clear (a
necessary thing for people such as myself who can't remember what they were doing 30
minutes ago let alone what the code they wrote yesterday is supposed to do...:o)
> Tom Micevski wrote:
> >
> > Richard Maine wrote:
> > > P.S. While I'm ementioning personal styles, another of mine is
> > > that I never use EXIT without a construct label.
> >
> > i usually just put a comment after the exit, eg. exit ! i loop
>
> Huh. How about that...that's what I usually use as construct names!
>
> i_loop: DO i = 1, N
> ....
> IF ( ... ) EXIT i_loop
> ....
> END DO i_loop
Me too. Heck, insert the standard joke about the compiler checking
the validity of comments. Well, in this case, by doing little more
that removing the comment characters, you can make it so.
> I find *not* using construct names (or comments) with exit
> statements very confusing. When I see "exit" I still think of it as
> akin to stop or return (e.g. exit this program/routine).
Me too. I've had enough exposure that I am more used to it by now,
but I recall that confusion from my earlier f90 days, so I try to have
pity on others who might not be quite as immersed in f90 as I am.
There is probably some other language that uses "exit" in that
sense, which still sticks in my mind, though I couldn't off-hand
nam ethe language. Well, if nothing else, there is the old
"call exit" used in many old Fortrans.
I do a lot of coding in IDL (for visualisation of Fortran output!) and there you have
IDL BREAK == Fortran EXIT
IDL CONTINUE == Fortran CYCLE
IDL EXIT == exit IDL and return to operating system.
IDL is very Fortran-like in it's syntax and when I switch between the two I can get very
weird things happening:
In IDL, rather than EXITing loops, my IDL session quits (obvious error)
In Fortran, rather than CYCLE the loop, it just CONTINUEs (not so obvious)
Me too.
I wanted to add a smarter comment than that but I forgot what it was :-)).
--
Jugoslav
___________
www.geocities.com/jdujic
[...]
>>I find *not* using construct names (or comments) with exit
>>statements very confusing. When I see "exit" I still think of it as
>>akin to stop or return (e.g. exit this program/routine).
[...]
> There is probably some other language that uses "exit" in that
> sense, which still sticks in my mind, though I couldn't off-hand
> nam ethe language. Well, if nothing else, there is the old
> "call exit" used in many old Fortrans.
Well, there is that obsolete C language and its progeny -- nothing that
a modern programmer would need to be concerned about :^).
John Bollinger
jobo...@indiana.edu