- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
A colleague of mine noticed a bad behavior of IFX (and IFORT) for Fortran regarding negative exponents without parenthesis.
From our understanding, the Fortran standard does not allow this:
program negative_exponent
write(*,*) '10.0**-2 * 2=', 10.0**-2 * 2
end program negative_exponent
However, the above code compiles and runs using gfortran, nvfortran, ifort, and ifx.
On gfortran, it gives a warning about the syntax but then "does the right thing":
```
> gfortran negative_exponent.f90
negative_exponent.f90:2:37:
2 | write(*,*) '10.0**-2 * 2=', 10.0**-2 * 2
| 1
Warning: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
> a.out
10.0**-2 * 2= 1.99999996E-02
```
Using NVIDIA's nvfortran, there is no warning but the code gives the right answer:
```
> nvfortran negative_exponent.f90
> a.out
10.0**-2 * 2= 2.0000000E-02
```
However, on ifort or ifx, there is no warning and gives the wrong answer:
```
> ifx negative_exponent.f90
> a.out
10.0**-2 * 2= 9.9999997E-05
```
It seems to me that this code should ideally throw a compiler error since it is not allowed in Fortran (maybe have a flag to ignore the error?).
However, if it IS going to be allowed, it should give the right answer following standard math PEMDAS in compilation.
- Ron
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And what about?
rtCOP_e = 4.82e-6*te**-0.55*1.0e-6
real(8),parameter :: var1 = 4.82e-6
real(8),parameter :: var2 = -0.55
real(8),parameter :: var3 = 1.0/1000000.0
rtCOP_e = var1*var3*te**var2
I always define a PI function as
real(8) function pi()
pi=dacos(-1.d0)
end function
It ensures that trigonometrical results as (cos(pi()), sin(pi() ...) will be accurate
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Using pi() in an expression, without a prior type declaration, carries the risk of the function being treated as type real, default kind, which may be less precise than desired/expected.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not to mention that someone could (in about 5 minutes) use AI to easily make a python script that puts exponents in their fortran code according to how they assumed they worked/assumed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am not AI, but I wrote a Perl wrapper around ifort/ifx/gfortran that spots and reports the actual error, but not the correctly evaluated signed exponent. Here is the test file:
program exponent
implicit none
real:: a = 10.0, c = 2.0
integer:: b = 3
write(*,*) '10^+3+2/2=', a**+b+c/2
write(*,*) '10^-3-2*2=', a**-b-c*2
write(*,*) '10^+3*2=', a**+b*c
write(*,*) '10^-3*2=', a**-b*c
write(*,*) '10^+(2*2)/2=', a**+(b*2)/c
write(*,*) '10^-(2+1)/2=', a**-(b+1)/c
end program exponent
Bugs>ifort exponent.f90
ERROR: using signed exponent followed by * at line 8 in exponent.f90:
write(*,*) '10^+3*2=', a**+b*c
--------------------------^
ifort and ifx evaluate the * operator BEFORE the exponentiation!!!
gfortan and nvfortran evaluate the * operator AFTER the exponentiation!!!
Add parentheses to clarify the expression and make your code portable!!!
ERROR: using signed exponent followed by * at line 9 in exponent.f90:
write(*,*) '10^-3*2=', a**-b*c
--------------------------^
ifort and ifx evaluate the * operator BEFORE the exponentiation!!!
gfortan and nvfortran evaluate the * operator AFTER the exponentiation!!!
Add parentheses to clarify the expression and make your code portable!!!
ERROR: using signed exponent followed by / at line 10 in exponent.f90:
write(*,*) '10^+(2^2)/2=', a**+(b*2)/c
------------------------------^
ifort and ifx evaluate the / operator BEFORE the exponentiation!!!
gfortan and nvfortran evaluate the / operator AFTER the exponentiation!!!
Add parentheses to clarify the expression and make your code portable!!!
ERROR: using signed exponent followed by / at line 11 in exponent.f90:
write(*,*) '10^-(2+1)/2=', a**-(b+1)/c
------------------------------^
ifort and ifx evaluate the / operator BEFORE the exponentiation!!!
gfortan and nvfortran evaluate the / operator AFTER the exponentiation!!!
Add parentheses to clarify the expression and make your code portable!!!
negative_exponent.f90 contains 4 errors, so it cannot be compiled
Note that the correctly evaluated lines were not flagged.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No need for an AI. Searching for something like that \*\*[+-] is not very difficult would point out all problematic expressions. Then a regular expression search/replace could correct automatically almost all those problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I continue to disagree that the Intel results are wrong. If you accept the extension of consecutive operators, then you should follow the Fortran rules for operator precedence which make unary minus lower than multiplication. That another compiler chooses to ignore Fortran precedence rules in this case feels wrong to me, but again, it's non-standard so anything goes.
This supports my longstanding advice to do a test build with standards warnings enabled, just to see if you're using an extension you didn't expect. You should strive to use only standard-conforming code, unless there is no reasonable alternative, and then you should document it in the comments. I give no weight to "well, it has worked the way I want for years..."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Steve,
The fact that three reputable compilers disagree shows this isn’t obviously determined by Fortran precedence; it’s an ambiguity introduced by the extension.
Going back to your earlier question/point: Do the majority of Fortran programmers actually expect Intel’s precedence here? From the evidence in this thread (and the fact that gfortran, nvfortran, and NAG all either reject or interpret it differently), it seems more likely that most people would expect a**-b*c to mean (a**(-b))*c, i.e., what you’d get if you were following normal mathematical intuition. But, obviously, we only have half the data, and, as you point out, switching this might cause complaints (although I doubt it).
So I think the trade-off isn't between correctness and backward compatibility, but between continuing to surprise the majority of users (with results that differ by orders of magnitude), or inconveniencing the relatively few who might depend on the legacy parse, but who can be supported with an explicit switch.
I'm happy for us to disagree on this, of course (and discussing this as a who's right or wrong issue isn't the best approach IMO). But there is a compromise that seems to address both perspectives. Several people in this thread (caplanr, GaborToth) have already suggested the idea of a documented opt-in compatibility switch. Wouldn't that work for everyone?
-Pete
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Pete, it isn't "Intel's precedence", it's the Fortran language's precedence. These other compilers are pretending that unary minus (or plus) after another operator has the highest precedence, which is inconsistent for the behavior without consecutive operators.
The best solution is for people to code to the standard and use parentheses rather than rely on implementation-dependent interpretation. That compilers disagree on non-standard behavior is nothing new. TBH, I've come around to NAG's position that extensions are disabled by default, though I know many users would howl at this. NAG has options for many popular extensions, but you must ask for them. It's a very different world than it was in the late 1970s and 1980s.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is an interesting discussion. However, I am still bewildered as to why one would not code using paremtheses. I would want some code maintainer/converter/reviewer to know exactly what my intentions were when I coded it. I believe you should never assume anything.
Just saying.
Doc (not an Intel employee or contractor)
[AI is the same as snake-oil]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Doc, the fundamental cause of this problem is the way the Fortran language handles unary minus, especially when applied to a numeric literal. Most other programming languages treat something like -4 to be a fundamental entity ("primary" in Fortran-speak), but Fortran does not, and this leads to just this sort of situation. Instead, the minus is just an arithmetic operator and gets handled according to the language's rules for precedence and association.
Of course, this wouldn't be an issue if compilers back in the 70s and 80s hadn't added extensions willy-nilly, in an attempt to out-do competitors (or more often, copying extensions other compilers had.) DEC was as guilty of this as any of the vendors, if not more so. I imagine the consecutive operators thing just seemed reasonable at the time, but it does lead to errors, as this thread shows. There have been many occasions where I longed for a time machine to go back and try to talk sense into the developers. I did, while I was on the project, did manage to get the team to turn off some of the extensions that caused the most problems for users, such as free conversion between logical and numeric in list-directed input. That it still exists in expressions is problematic, too, but a lot of people have code depending on it so at best I fall back on my advice to do a test build with standards warnings enabled.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"DEC was as guilty of this as any of the vendors, if not more so. "
I remember that quite well. I was on a project (a proposal) for the FEDs back then, and discovered that the government benchmark could only run on DEC Fortran. There were four bidders: Dec, Prime, DG, and Wang. When I reported the issue, saying that the government had wired this proposal so only DEC could win, the government decided to pay Prime, DG, and Wang $500K each to withdraw their proposals, which they did. DEC got the contract and I suspect the delivery vans were driving around the beltway waiting for the ink to dry. The thing that made me angry was that the government specifically stated "Fortran Standard", yet the benchmark was written to use DEC's extentions.
This made the press in one of the government rags back then.
Doc (not an Intel employee or contractor)
[AI is the same as snake-oil]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@AlHill wrote:he thing that made me angry was that the government specifically stated "Fortran Standard", yet the benchmark was written to use DEC's extentions.
Indeed, I heard from many users that they considered certain DEC extensions as "standard" - STRUCTURE/RECORD for example, but I give props to DEC for introducing this one in 1985 as it was clear that "Fortran 88" wasn't going to happen, and it was a capability a LOT of users wanted.
But I have no sympathy for "syntactic sugar" extensions such as consecutive operators.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
SteveLionel: "But I have no sympathy for 'syntactic sugar' extensions such as 'consecutive operators'"
This reminded me of
Alan Perlis: " Syntactic sugar causes cancer of the semicolons."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve,
I appreciate your point about the precedence, but it's the effects that still concern me. After a bit of a rabbit hole search, there are quite a few threads on the topic, and it seems that the extension was motivated by legacy DEC compiler behaviour and optimisation strategies (reassociation for performance).
I agree that the best solution is for people to use parentheses. But, as a scientist first, and programmer second, I sometimes forget these things. (Don't tell anyone, but I still miss COMMON blocks).
I like your suggestion of disabling the extensions by default. That would seem to cover everything in that it's consistent with the Fortran standard, and both sides of the interpretation of what the statement means would have to explicitly declare it, either by adding in the parentheses or the extension.
Pete
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
He has worked in Fortran since 1969.
IBM 7090
IBM 1130
IBM 360
IBM 370
IBM 3090
VAX (VARIOUS MODELS)
CRAY 1
CRAY XMP
COMPAQ VISUAL FORTRAN
INTEL Visual Fortran XE 13 Compiler
INTEL ONEAPI
And the rule has always been to include enough parentheses to avoid any cofusion
DONALD H. KNUTH in the book "The art of computer programming" insists on the same
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've tried with Matlab, python and R just for fun:
Matlab: 10^-2*2 = 0.02
python: 10**-2*2 = 0.02
R: 10^-2*2 = 0.02
All of them produce the result almost all of us would expect.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is a good discussion. I will bring this issue to the team once again. We will consider the feedback from this post and give consideration to all arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It would seem to me, that the way Fortran handles unary minus is fine, when combined with the rest of the Fortran specification.
It is when compiler extensions are added that it becomes an issue.
Given the compiler extension to allow no parenthesis in exponents, how should 10**-2*2 be handled?
1) Do we assume the user is an expert in every detail of the Fortran standard and semantics - including how it treats unary minus - but is somehow unaware of a single part of the standard - needing parentheses in an exponent with a sign?
OR
2) Do we assume the user is a scientist that may not be familiar with every detail of the standard and forgets/doesn't-want-to use parenthesis, but who of course would expect PEMDAS to be adhered to in a programming language designed to be a FORmula TRANslation of mathematical equations?
IMO, the answer seems obvious. The extension was almost certainly made for the second individual above, and therefore the non-standard Fortran should follow standard math (like every other compiler that allows the extension).
Otherwise, the compiler should fail to compile and require the user to follow the Fortran standard.
If the desire to not need parentheses from users is so great, than the ISO Fortran team needs to get together and update/change the standard in 202Y. Either to not need them, or to change how unary sign is handled.
- Ron
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is one more point of view that should be given some consideration as part of the decision to leave the compiler as is or to alter its default behavior. If the expression under question is not standard-conforming, but has existed in widely used code for decades, it is likely that the author(s) made reasonable attempts to make the code standard-compliant at the time of creation, given the widely used Fortran machine/compiler combinations available to them and it is equally likely that their colleagues exercised and tested the code segment several times and found it worked as they expected; what would be a reasonable guess for the semantics that they regarded as acceptable?
The authors' guide of the Physics Review Letters journal states:
"Put in extra bracketing even where convention does not require it, if a likely misreading is thereby avoided. But leave them out where they would merely clutter the picture."
That strikes me as good advice even for Fortran source code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
People need to be actively warned when they are using nonstandard ambiguous code that could result in hidden numerical errors with possible severe consequences. You can not expect the entire user base to use the -strict flag or a code scanner.
I ask the Intel team to reconsider. Here is a specific refinement of the above suggestion #2 from GaborToth. Add two new flags to Intel fortran, plus default:
- (default) -- Consecutive operators generate a hard compile error, with informative message.
- -allow nonstandard_consecutive_operators -- Consecutive operators compile to Intel-specific interpretation, and informative warning is printed.
- -allow nonstandard_consecutive_operators_no_warning -- Consecutive operators compile to Intel-specific interpretation, and no warning is printed.
Documentation should be updated with an explicit warning that different compilers have completely different interpretations of this nonstandard construction, and will generate divergent numerical results.
This should provide the right degree of caution, while satisfying everyone's diverse needs. Since the Intel compiler is already detecting this specific condition, it should be easy to convert existing behavior into this precautionary approach.
I am generally enthusiastic about legacy support extensions in compilers, but this one is dangerous and scary. I would be glad to be warned that any of my legacy code is using a dangerous nonstandard construct, and to add a handful of extra parentheses.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page