Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Comparing DOUBLE value, even though variable declared as REAL

baymu83
Beginner
1,625 Views
Hello everyone!

First the important things: Compiler IVF XE 12.0.2.154

My problem is as follows:

During an iteration I have to compare an intermediate result of that iteration to a value calculated prior to the iteration. Both values are defined as REAL and the default REAL kind of the compiler is set to 4 Bytes.

IF (Y .LE. ASBS) THEN ...

Y ... intermediate result
ASBS ... value calculated prior to the iteration

Everything works fine, until the REAL value of Y is equal to the REAL value of ASBS. In this case the program should execute the statements in the if-block, but instead of doing so simply skips the block. (See the pictures attached)

A more thorough examination of the two values, using them both declared as DOUBLE PRECISION, reveals that indeed ASBS is a little smaller than Y.

To make sure this was no display problem of the debugger I printed out both results on the screen as well, but the output showed the same values as were displayed by the debugger.

My question now is: Why does the compiler behave like that and how can I change that behaviour?

Many thanks in advance.
0 Kudos
6 Replies
mecej4
Honored Contributor III
1,625 Views
It is not the compiler behavior that needs to change; it is your expectation of how floating point arithmetic should operate.

You are comparing two REAL*4 variables, whose decimal representations as shown in the debugger agree to seven significant digits. However, if you looked at their internal representations, it is possible that you would have found one of them to be Z'40F78FF7' and the other Z'40F78FF8'; although the difference between these numbers cannot be seen with seven significant decimal digits, there is a difference. A test of equality must fail unless all bits match (32 bits for REAL*4, 64 for REAL*8, etc.)

You need to alter your program so that your comparisons for equality between floating point values are more realistic. This is a topic that is well covered in textbooks. Many compilers routinely issue warning messages when they encounter comparisons for equality (.EQ., .LE., .GE.) between floating point numbers.
0 Kudos
anthonyrichards
New Contributor III
1,625 Views
Yes, you should use

TOL=1.0e-07 ! or some reasonable value for REAL*4 numbers
IF(abs(Y-ASBS).LE.TOL) then
0 Kudos
Arjen_Markus
Honored Contributor II
1,625 Views
You can also use the functions epsilon(), nearest() or rrspacing()to find a number that
is very close but still different.

A more sophisticated method is to use a fuzzy comparison method - see http://ftp.cac.psu.edu/pub/ger/fortran/hdk/eps.f90

Regards,

Arjen
0 Kudos
baymu83
Beginner
1,625 Views
Thanks for your kind reminder on the issue of floating point arithmetics. I was aware of that problem in general, but didnt think it was an issue here.

I did some research on my problem and found the core of it to be some place different.

The code I work on is some research code originally created in the 90s using CVF 6. Of course the code was updated when new research results had been available, but the compiler stayed the same.

Now weve reached a point at which it is impossible to use the CVF 6 any longer, because of the introduction of Fortran 2003 features, which are not supported by CVF 6.

So we migrated from CVF 6 to IVF 11. Everything looked fine in the first place, but now as more and more special test-cases are created, there are some differences in the output.

Some test-cases work fine, when using the CVF-compiled version, but fail when the IVF-compiled version is used. I also did the changes suggested by Steve Lionel in his migration-paper (Floating Point Model -> source, Enable Enhanced Instruction Set -> No enhanced instruction set), which made the results slightly worse. The variation in the result is up to 100 %, which is not acceptable.

I've also searched the board for similar problems and found this related topic:

http://software.intel.com/en-us/forums/showthread.php?t=66793&o=d&s=lr&wapkw=%28%2Bfortran+openmp%29

What I could not figure out is whether the "X87"-Instruction-Set (CVF 6) is the same as the "IA-32"-Instruction-Set (IVF 11), or just similar to it.

From my experience I would say they are just similar, so my question is:

Is there any way to make the IVF 11 use the "X87"-Instruction-Set?




0 Kudos
mecej4
Honored Contributor III
1,625 Views
>The variation in the result is up to 100 %, which is not acceptable.

That is an indication of the presence of bugs in the code, which need to be removed. Such bugs often come alive only with one compiler or the other, but their detection should trigger a search-and-destroy mission, not a search for compiler options to hide them -- in other words, sweep-under-the-rug options.

IA32 refers to the instruction set that debuted on the 386 chip, which did not have a built in FPU. Later chips such as the 486DX, Pentium, etc., had a built in FPU, and the term IA32 is sometimes used to include x87 instructions as well. You can ask the IFort 11.1 compiler to produce X87 instructions for real arithmetic using the /architecture:IA32 option; however, as I stated above, this should be regarded as a stop-gap measure.
0 Kudos
TimP
Honored Contributor III
1,625 Views
Unless you used the fltconsistency option with CVF, and similar options such as /arch:IA32 /fp:source, with ifort, you could expect difficulty in matching numerics. I agree with mecej4 that the x87 selection to attempt automatic promotion of single precision expressions to double has to be considered a stop-gap. If your application depends on mixed single and double precision, you should write it into the source code explicitly. No compiler could apply the implicit promotions with full consistency; ifort might find more of them than CVF did.
0 Kudos
Reply