I am new to Intel's ifort compiler. I have a program and it is working
fine under IBM xlf compiler. Recently we forced to switch to use
Intel's ifort compiler and same program now has problem.
For example
if (A .GT. 0 .and. Array(A) .LE. 100) then
......
endif
When code compiled by ifort, if A is < 0 then program will give me
segmentation fault. When I use the -C option, it found out the above
code A will return a negative number (supposed to be) but since the
ifort also evaluate the 2nd half of the statement so the program abort.
Does any one know a compiler option will ask ifort to stop evaluate 2nd
statement once the first one is false?
Thanks very much.
-Charles
There is no such option. You have a bug in your code which you should
fix. The Fortran language allows a logical expression to be evaluated
in any order and to any completeness which is logically equivalent.
That the code worked in one particular compiler (and version of that
compiler) does not mean the code would work with other compilers or
other versions (or even the same version with different compilation
options.)
The correct code here would be:
if (A .GT. 0) then
if (Array(A) .LE. 100) then
...
For further reading, see an article I wrote in 1999 that touches on
this topic at
http://softwareforums.intel.com/ISN/Community/en-US/forums/permalink/116158/116163/ShowThread.aspx#116163
Steve Lionel
Developer Products Division
Intel Corporation
Nashua, NH
User communities for Intel Software Development Products
http://softwareforums.intel.com/
Intel Fortran Support
http://developer.intel.com/software/products/support/
My Fortran blog
http://www.intel.com/software/drfortran
> Hello,
>
> I am new to Intel's ifort compiler. I have a program and it is working
> fine under IBM xlf compiler. Recently we forced to switch to use
> Intel's ifort compiler and same program now has problem.
>
> For example
>
> if (A .GT. 0 .and. Array(A) .LE. 100) then
> ......
> endif
>
> When code compiled by ifort, if A is < 0 then program will give me
> segmentation fault. When I use the -C option, it found out the above
> code A will return a negative number (supposed to be) but since the
> ifort also evaluate the 2nd half of the statement so the program abort.
Fortran does not have shortcut evaluation of logical connectives.
Do you have any reason, beyond just hope, to believe that this program
actually worked correctly in the past? It may have referenced an out of
bound element without segment faulting and so continued running. There
is not guarantee that it did what you hoped as it is simpley and purely
a nonstandard program. Most would just say buggy or wrong!
If there was such an option, it would not be a good idea to use it.
Counting on a compiler switch to make this code work is IMO a bad idea,
since the language does not require this behavior but does permit it.
Why not use a nested IF instead?
>if (A .GT. 0 .and. Array(A) .LE. 100) then
>Does any one know a compiler option will ask ifort to stop evaluate 2nd
>statement once the first one is false?
In general, you'll have to change your source code to
if (a .gt. 0) then
if (array(a) .le. 100) then
Fortran doesn't do short-circuit evaluation. Maybe you could rely
on that feature in f2c, but that's not really state of the art
any more :-)
>For example
>
>if (A .GT. 0 .and. Array(A) .LE. 100) then
> ......
>endif
This is called "short circuiting" in C. Fortran doesn't short-circuit;
the compiler is free to evaluate the right condition first if it
thinks that might be faster.
Some Fortran compilers do short-circuit. PathScale's compiler does
short-circuit by default, or you can use the
-LANG:short_circuit_conditionals=OFF flag if you want to find out
if your code depends on short-circuiting.
The standard-conforming way to express this code is:
if (A .GT. 0) then
if (Array(A) .LE. 100) then
......
endif
endif
-- greg
(employed by, not speaking for, QLogic/PathScale)
> Does any one know a compiler option will ask ifort to stop evaluate 2nd
> statement once the first one is false?
Others have pointed out why the code should be fixed instead of looking
for a compiler switch to support the nonstandard coding practice.
Let me just note that part of your confusion might arrise from
misunderstanding the terminology involved. You refer to the "2nd
statement". There is no second statement here. This is all a single
statement. What you appear to be calling "statements" are just parts of
an expression. If you change to the nested IF form as suggested by other
posters, then there will be 2 statements.
--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
That works fine for .AND., but it is a little harder for .OR.
if(something) then
.....
else if(somethingelse) then
.....
endif
where you duplicate the code to be executed in the ..... part.
For arrays tests, the .AND. case is more common, but it would
be nice to be able to do .OR., too.
Also, the .AND. case gets a little ugly if you have many conditions.
-- glen
> That works fine for .AND., but it is a little harder for .OR.
There have been proposals floated to the standards committee for
something like and_then and or_else operators, but those have not
passed.
Steve Lionel wrote:
<snip>
> There have been proposals floated to the standards committee for
> something like and_then and or_else operators, but those have not
> passed.
There were several reasons for that, IIRC.
What is the precedence of .andthen. and .orelse. ?
If they go where .and. and .or. go, as some prefer,
then it potentially breaks existing code,
as applications programmers may already have user-defined operators
with these names.
Isn't this a slippery slope? Basically, this proposal asks
for a way to delay argument evaluation. Why not other procedures?
If used without a _great_ deal of skill, this is anti-optimization.
Various different ideas were floated, but none got a critical amount
of support to continue along the standards development path.
Other ideas were thought to be more important, given time and people.
<snip>
--
Cheers!
Dan Nagle
Purple Sage Computing Solutions, Inc.
A temporary might be of interest. The shortcut of (A.and.B) is:
T = A; If(T) T = B
This can be extended for as many operands as you might have.
The shortcut for (A.or.B) is:
T = A; if(.not.T) T = B
Again, this pattern can be repeated as many times as needed for
multiple operands. So the OPs code (repeated below) can be
replaced:
if (A .GT. 0 .and. Array(A) .LE. 100) then
......
endif
becomes:
T = A > 0; If(T) T = Array(A) <= 100
if(T) then
...
endif
A non-strict logical intrinic function might be notationally
more convenient. A Dan Nagle points out, such things
have been considered and the committee thinks they're
rather too complex.
--
J. Giles
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
User-defined operators can't do the same thing, though, because the
operator necessarily evaluates both of its arguments. Short-circuiting
can only be done by the language. (Of course, that's also an argument
against it, as if the built-in operators are then extended to a
user-defined type, they have different semantics in terms of argument
evaluation than the built-in operators -- this is a potential gotcha in
C++.)
Sorry for not making it clear, but if there are more than two
operands you have to use the block form of the IF. So the
shortcut form of (A.and.B.and.C) is:
T = A; If(T) then; T = B; If(T) then; T = C; endif; endif
Of course this means that in general if you have N operands
you'll end with n- endif's. The same applies to the shortcut
version of .or.
Again, non-strict versions of AND and OR might be preferable.
On the other hand, Fortran has gone 50+ years without shortcut
logical operators. It may not really need them.
But user-defined operators can have the same _name_,
which potentially breaks old code.
> though, because the
> operator necessarily evaluates both of its arguments. Short-circuiting
> can only be done by the language.
Until users start asking why they can't have delayed argument
evaluation in their procedures. Then it gets very messy
very quickly.
> (Of course, that's also an argument
> against it, as if the built-in operators are then extended to a
> user-defined type, they have different semantics in terms of argument
> evaluation than the built-in operators -- this is a potential gotcha in
> C++.)
>Until users start asking why they can't have delayed argument
>evaluation in their procedures. Then it gets very messy
>very quickly.
Actually, there are ISV codes that require delayed argument evaulation... not
in the general sense, but for the case that the address passed in for your
variable isn't valid, "but my code doesn't use that variable except inside
this if statement, so it's not a bug in my user code!"
So we grew this option:
-LANG:formal_deref_unsafe=(ON|OFF)
Tell the compiler whether it is unsafe to speculate a dereference of a formal parameter in
Fortran. The default is OFF, which is better for performance.
-- greg
(employed by, not speaking for, QLogic/PathScale.)
Yes, that's true. I think it's highly unlikely, since there's nothing
to differentiate the behavior of such an operator from .and. or .or.,
though. Dunno where the committee draws the line on such things, but I
don't think new standard operators have been defined within the last
thirty years, have they?
Be that as it may, I'd guess that something in the nature of an
intrinsic module would be the likely route to implement such a beast
without stepping on users' toes, no?
>> though, because the operator necessarily evaluates both of its
>> arguments. Short-circuiting can only be done by the language.
>
> Until users start asking why they can't have delayed argument
> evaluation in their procedures. Then it gets very messy
> very quickly.
:eek:
Greg Lindahl wrote:
<snip>
> Actually, there are ISV codes that require delayed argument evaulation... not
> in the general sense, but for the case that the address passed in for your
> variable isn't valid, "but my code doesn't use that variable except inside
> this if statement, so it's not a bug in my user code!"
But it is not standard-conforming, because it's the reference
to the procedure that causes the actual arguments to be evaluated.
I'm perfectly happy that you support your customers' needs.
And I've heard vendors tell of far worse that they support.
<snip>
>But it is not standard-conforming, because it's the reference
>to the procedure that causes the actual arguments to be evaluated.
You're right. Most compilers won't dereference arguments until they're
actually used... but we tend to hoist such references because of the
SSAPRE algorithm.
-- greg
Compilers are allowed to use copy-in/copy-out, also known as call
by value result. OS/360 Fortran did it for scalars because it was
faster and/or generated smaller code, not for arrays.
Now it is usually done for possibly discontiguous arrays calling
routines with an assumed size dummy variable.
That should be enough reasons not to rely on it.
-- glen