I am getting different behavior between Portland and Intel fortran compilers when evaluating a simple expression with an exponent followed by a multiply. I am pretty sure that pgf90 (and gfortran) are working correctly based on my understanding of operator precedence, but I would like a second opinion since these things can get a bit tricky.
Here is my code simplified down to a very basic form. When run with ifort the expression of the form d1=a**-2*b
gets interpretted as d1=a**(-2*b)
by ifort by as d1=(a**-2)*b
by pgf90 and gfortran. If I remove the negative sign from the exponent, all three compilers interpret this as d1=(a**2)*b
. If I change *b to +b I also get good behavior from all three.
program badvals
implicit none
real :: a, b, c1, c2, d1, d2
a = 2.
b = 4.
! Works with addition following the exponent.
c1 = a**-2+b
c2 = a**(-2)+b
! Ifort differs with multiplication following negative exponent.
d1 = a**-2*b
d2 = a**(-2)*b
print*, "c1, d1 = ",c1, d1
print*, "c2, d2 = ",c1, d2
print*, "c2-c1, d2-d1 = ",c2-c1, d2-d1
end program badvals
!Program output for ifort v13.0.1.117: (either -O0 or -fast):
! c1, d1 = 4.250000 3.9062500E-03
! c2, d2 = 4.250000 1.000000
! c2-c1, d2-d1 = 0.0000000E+00 0.9960938
!Program output for pgf90 v12.10-0: (either -O0 or -fast):
! c1, d1 = 4.250000 1.000000
! c2, d2 = 4.250000 1.000000
! c2-c1, d2-d1 = 0.000000 0.000000
!Program output for gfortran v4.1.2: (either -O0 or -O3):
! c1, d1 = 4.250000 1.000000
! c2, d2 = 4.250000 1.000000
! c2-c1, d2-d1 = 0.000000 0.000000
Is there a history behind these differences so that they should be considered a "feature"? Or, is this an outright bug on Intel's part?
Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator. For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.
The ifort-compiled executable runs five times faster than the > gfortran-compiled executable on my Intel Xeon CPU.
In addition to addition +, subtraction -, multiplication * and division /, Fortran has an exponential operator **. Thus, raising X to the Y-th power is written as X**Y. For example, the square of 5 is 5**2, and the square root of 5 is 5**0.5. The exponential operator has the highest priority.
Searching the web, I find that statement that two consecutive operators are not allowed. Therefore interpreting rather than rejecting this expression is an extension to the language. That extension has been implemented differently by different compiler vendors.
Indeed, when I use gfortran with restrictive compiler options, it rejects this code example:
badvals.f90:9.11:
c1 = a**-2+b
1
Error: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
badvals.f90:13.11:
d1 = a**-2*b
1
Error: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
Similarly, ifort with restrictive compiler options provides the following:
badvals.f90(9): warning #7026: Non-standard extension
c1 = a**-2+b
----------^
badvals.f90(13): warning #7026: Non-standard extension
d1 = a**-2*b
----------^
So: 1) using the warning and error options of the compiler can be very helpful, 2) its more of an extension than a bug, 3) even if this expression were allowed by the language, gfortran's advice is good -- use parentheses for clarity even if not required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With