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

Operation ordering for negative exponents

Robin_T_
Novice
1,436 Views

Hello,

I stumbled upon some strange behavior today.

program power_test

	implicit none
	
	print *, 5.d0 * 3.d0 ** 2
	print *, 3.d0 ** 2 * 5.d0
	print *, 5.d0 * 3.d0 ** -2
	print *, 3.d0 ** -2 * 5.d0

end program power_test
ifort -m64 -fpp -fopenmp -O3 -g -traceback -C -c power_test.f90
ifort power_test.o -m64 -fpp -fopenmp -O3 -g -traceback -C -o power_test.x		

gives

   45.0000000000000     
  45.0000000000000     
  0.555555555555556     
  1.693508780843029E-005

So, when the exponent is positive, everything works as expected, but when it is negative, the multiplication is evaluated first, and then the power, but only if the multiplication comes after the power. Is this intended and if yes why?

0 Kudos
1 Solution
Juergen_R_R
Valued Contributor I
1,436 Views

 

E.g. enforce the f2003 standard with the following:

$ ifort2018 -e03 foo.f90 
foo.f90(7): error #8810: Consecutive operators are an extension to the Fortran 2003 standard.
  print *, 5.d0 * 3.d0 ** -2
--------------------------^
foo.f90(8): error #8810: Consecutive operators are an extension to the Fortran 2003 standard.
  print *, 3.d0 ** -(2 * 5.d0)
-------------------^

And you get warnings. ;)

Actually not just warnings, indeed errors. BTW, that is equivalent to -f std2003 -warn stderrors

 

View solution in original post

0 Kudos
11 Replies
Juergen_R_R
Valued Contributor I
1,435 Views

gfortran (8.0.1) e.g. gives the following warning:

  print *, 3.d0 ** -2 * 5.d0
                   1
Warning: Extension: Unary operator following arithmetic operator (use parentheses) at (1)

So, in other words, the behaviour of what happens when you put a unary minus operator after the arithmetic operator ** for exponentiation is not defined by the standard and is left to the processor (compiler). In order to guarantee a result that you expect you have to set parentheses.

 

0 Kudos
mecej4
Honored Contributor III
1,435 Views

Lines 7 and 8 of the code in the initial post each contain two consecutive numeric operators. This is not permitted in standard Fortran -- for example, there is Note 7.37 in the Fortran-95 standard, which states:

These formation rules do not permit expressions containing two consecutive numeric operators, such as A ∗∗ –B or A + –B. However, expressions such as A ∗∗ (–B) and A + (–B) are permitted.
Do not expect the compiler to guess and do what you want; use parentheses to make your intentions explicit. Use compiler options to enforce standards conformance and to catch errors of this type; make the code right and, only then, make it fast, if you wish.
0 Kudos
Robin_T_
Novice
1,436 Views

Use compiler options to enforce standards conformance and to catch errors of this type

Can you specify which compiler options I would need for that? I was completely unaware that this is not permitted as the compiler does not throw any warning.

0 Kudos
Juergen_R_R
Valued Contributor I
1,437 Views

 

E.g. enforce the f2003 standard with the following:

$ ifort2018 -e03 foo.f90 
foo.f90(7): error #8810: Consecutive operators are an extension to the Fortran 2003 standard.
  print *, 5.d0 * 3.d0 ** -2
--------------------------^
foo.f90(8): error #8810: Consecutive operators are an extension to the Fortran 2003 standard.
  print *, 3.d0 ** -(2 * 5.d0)
-------------------^

And you get warnings. ;)

Actually not just warnings, indeed errors. BTW, that is equivalent to -f std2003 -warn stderrors

 

0 Kudos
TimP
Honored Contributor III
1,436 Views

Some compilers, back 20 years ago when the standard didn't require a warning about extensions, would accept that expression, maybe with expected result.  It was never permitted by Fortran standard, so was always inadvisable.  It might be reasonable to expect that ifort would at least warn about anything which isn't permitted by any standard, but it's hard to move off the dime in such situations.

0 Kudos
mecej4
Honored Contributor III
1,436 Views

Tim P. wrote:
 Some compilers, back 20 years ago when the standard didn't require a warning about extensions, would accept that expression, maybe with expected result.  It was never permitted by Fortran standard, so was always inadvisable.  It might be reasonable to expect that ifort would at least warn about anything which isn't permitted by any standard, but it's hard to move off the dime in such situations.

That is why it is usually a good idea for less-experienced users to place /standard-semantics in the ifort.cfg files in the appropriate compiler bin directories.

Secondly, when the compiler allows syntax that is not standard, such as 2**-3, what rules does it follow? In other words, where is the documentation of the extension to the standard? Or are we supposed to look it up in a VAX Fortran manual?

0 Kudos
IanH
Honored Contributor II
1,436 Views

mecej4 wrote:
Secondly, when the compiler allows syntax that is not standard, such as 2**-3, what rules does it follow? In other words, where is the documentation of the extension to the standard? Or are we supposed to look it up in a VAX Fortran manual?

It is documented in the Intel Fortran manual under Language Reference > Expressions and Assignment Statements > Expressions > Numeric Expressions.

0 Kudos
mecej4
Honored Contributor III
1,436 Views

Thanks for the link, Ian.

The wording there is essentially the same as that in the VAX, DEC and HP/VMS Fortran manuals. Note that no rules are spelled out on how to evaluate these extended expressions. All that I can see is "However, Intel Fortran allows two consecutive operators if the second operator is a plus or minus." That tells me that the second operator is allowed if it is '+' or '-', but not what it is supposed to mean or do. We can look at the examples below that in the manual, but those are just examples and do not specify the meanings of all the possible combinations of two operators (the second of which is restricted to '+' or '-'). Just before the second example, we can see this non sequitur: "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". What does "evaluate the operator" mean?

I have never seen any code that needs this illogical and confusing feature. I feel that this extension should be not be part of the default behavior of the compiler.

Here are a couple of examples of the havoc that this extension can do.  Take the expression a/c*b, which is equal to (a*b)/c. The mere addition of an unnecessary unary + to c resulted in b being moved from the numerator to the denominator, causing a/+c*b to be regarded the same as a/(c*b).

print *,1.0/2*2, 1.0/+2*2

1.000000      0.2500000

print *,1.0/2/2, 1.0/+2/2

0.2500000       1.000000

real :: a=2.0, b=3.0, c=4.0
print *, a/-c*b, a/+c*b, a/c*b, a/c*-b, a/c*+b

-0.1666667      0.1666667       1.500000      -1.500000       1.500000

Gfortran accepts such expressions with warnings, but does not always interpret them in the same way as Ifort:

   1.00000000       1.00000000                                                                                                              
  0.250000000      0.250000000                                                                                                              
  -1.50000000       1.50000000       1.50000000      -1.50000000       1.50000000 

[Please note: I am not blaming Ian for any of this!]

0 Kudos
Robin_T_
Novice
1,436 Views

mecej4,

the Gfortran behvior is what I would expect intuitively and from my experience with other programming languages. It is also more consequent as it maintains the ordering (power before multiplication) for double operators. This was the original reason for my post.

0 Kudos
Robin_T_
Novice
1,436 Views

mecej4 wrote:

Robin, I agree.

If you do not mind, please share the history of the code that uses this extension. Is is code that was first written several decades ago and, if so, what machine was it developed for?

I have little objection to well-documented extensions, as long as they are provided only when requested or with warnings when availed of without a request.

 

I was writing this code just now and stumbled upon it on debugging. As mentioned previously, I had no clue about this syntax rule, as I have never read the Language specifications you provided earlier. Since I also did not know about the -e03 compiler option, I had no idea it was not standard.

0 Kudos
mecej4
Honored Contributor III
1,436 Views

Robin, I agree.

If you do not mind, please share the history of the code that uses this extension. Is this code that was first written several decades ago and, if so, what machine was it developed for?

I have little objection to well-documented extensions, as long as they are provided only when requested or with warnings when availed of without a request.

Gfortran provides a page that documents the extensions: https://gcc.gnu.org/onlinedocs/gfortran/Extensions-implemented-in-GNU-Fortran.html#Extensions-implemented-in-GNU-Fortran; the link "Unary operators:" leads to this compact, but badly worded, explanation: 

As an extension, GNU Fortran allows unary plus and unary minus operators to appear as the second operand of binary arithmetic operators without the need for parenthesis.
0 Kudos
Reply