- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page