Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Fortran Power Operator (**) Precedence Error

K__Jin
Beginner
9,430 Views

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 17.0.6.270 [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?

0 Kudos
9 Replies
K__Jin
Beginner
9,431 Views

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.

0 Kudos
Steve_Lionel
Honored Contributor III
9,432 Views
D:\Projects>ifort /stand t.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, 
Version 19.0.0.117 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))

0 Kudos
K__Jin
Beginner
9,432 Views

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)

0 Kudos
mecej4
Honored Contributor III
9,432 Views

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

  0.8000000       12.80000

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.

0 Kudos
Steve_Lionel
Honored Contributor III
9,432 Views

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

0 Kudos
K__Jin
Beginner
9,432 Views

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.

0 Kudos
mecej4
Honored Contributor III
9,432 Views

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

 

0 Kudos
K__Jin
Beginner
9,433 Views

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.

0 Kudos
mecej4
Honored Contributor III
9,433 Views

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)

0 Kudos
Reply