I am filing a potential bug about the Intel Fortran Compiler. When a negative value is used as a power, the power operation precedence might be wrong.
For example, I tested the following code on a Windows 10 x64 machine with Intel(R) Visual Fortran Compiler 126.96.36.1990 [IA-32].
program testpower implicit none double precision :: s, a s = 2**-0.5*2 write(*,*) '2**-0.5*2 = ', s s = 2**(-0.5)*2 write(*,*) '2**(-0.5)*2 = ', s end program
The program produces the following output (no errors or warnings during compilation):
2**-0.5*2 = 0.500000000000000
2**(-0.5)*2 = 1.41421341896057
For the first case, it gives a result as if it was 2**(-0.5*2).
This error happens if there is a "-" sign after the power operand. Or, maybe a parenthesis is required in this situation?
BTW, I also tested that s=2**+0.5*2 produces s=2.0. So, looks like we will have a problem if we have a sign after the **. I tested with gfotran and it gave an error message about missing parenthesis.
D:\Projects>ifort /stand t.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 188.8.131.52 Build 20180804 Copyright (C) 1985-2018 Intel Corporation. All rights reserved. t.f90(5): warning #8810: Consecutive operators are an extension to the Fortran 2008 standard. s = 2**-0.5*2 -------^
It's not a bug. The Intel documentation says:
Ordinarily, the exponentiation operator would be evaluated first in the following example. However, because Intel Fortran allows the combination of the exponentiation and minus operators, the exponentiation operator is not evaluated until the minus operator is evaluated:
A**-B*C is evaluated as A**(-(B*C))
Thanks Steve. I see the warning message after adding "/stand", and also find the explanation from Intel Fortran Reference. For completeness, I am just adding another example about consecutive operators (from Intel Fortran Reference):
When consecutive operators are used with constants, the unary plus or minus before the constant is treated the same as any other operator. This can produce unexpected results. In the following example, the multiplication operator is evaluated first, since it takes precedence over the minus operator:
X/-15.0*Y is evaluated as X/-(15.0*Y)
It is unfortunate that this extension is enabled by default (i.e., if /stand is not specified). Consider this bizarre case:
program strange real x,y,z x=3.2 y=4.0 print *,x/+1.0*y,x/1.0*y end
In the first expression, the mere presence of the normally superfluous but harmless '+' sign has the unfortunate effect of moving the y from the numerator to the denominator. The output of the program is
Even if you specify /stand, all that you are rewarded with is just a warning, which implies that we have to go hunting for a compiler option that has the effect of "when I say /stand, I really mean /stand -- do not produce an OBJ file for non-standard code". In a large program with many files, it is easy to lose sight of a warning if it comes in the midst of hundreds of other warnings.
It's the general case of consecutive operators being allowed, otherwise you couldn't do something like a*-b. This extension goes back 40 years or more.
The option you want is /warn:stderrors
Thanks mecej4 and Steve for your input on this topic. I agree that the extension on consecutive operators is convenient in some cases. I also understand mecej4's point on this, because it may give unexpected results. Also, I do see lots of warnings in my program after using "/stand". I will just add parenthesis to avoid consecutive operations.
Few compilers support this extension. I was surprised to see Gfortran doing so, but its interpretation of the semantics is quite different. For the program in #5, it says
S:\LANG>gfortran strange.f90 strange.f90:5:11: print *,x/+1.0*y,x/1.0*y 1 Warning: Extension: Unary operator following arithmetic operator (use parentheses) at (1) S:\LANG>a 12.8000002 12.8000002
Seems like gfortran thinks unary operators have higher precedence than binary operators (at least for this case, it calculates the unary '-' operator, then division and multiplication from left to right) and I think this implementation (for this example) is more intuitive to me. But, how about -3**2? In this case, I am expecting a result of -9. I tested with gfortran and Intel, both gave -9 as expected. But, in this case if gfortran strictly obeyed the rule of unary operator has high precedence of binary operator, then we should get 9. But, looks like here gfortran thinks the "-" sign is not an unary operator but a binary minus operator and treat the expression as something like 0-3**2 which gives -9 (this is just my guess). So, my guess is that gfortran only interpret the "+/-" sign as an unary operator in the case of consecutive operation.
Sorry, in comment #2 I made a mistake by saying gfortran gave an error message. It was a warning message like mecej4 showed in the above comment. Thanks.
Jin, Kai wrote:
... But, how about -3**2? In this case, I am expecting a result of -9. I tested with gfortran and Intel, both gave -9 as expected. But, in this case if gfortran strictly obeyed the rule of unary operator has high precedence of binary operator, then we should get 9.
This case does not require any extensions to standard Fortran. The standard precedence rules (Table 7.1 of Fortran 2008) tell us how to interpret the expression. In fact, the example in the 2008 standard that is given after that table is:
For example, in the expression
-A ** 2
the exponentiation operator (**) has precedence over the negation operator (-); therefore, the operands of
the exponentiation operator are combined to form an expression that is used as the operand of the negation
operator. The interpretation of the above expression is the same as the interpretation of the expression
- (A ** 2)