Conversion between REAL_64 and REAL_32

by Manu (modified: 2009 Aug 21)

Recently one of our customer found a loss of precision in their floating point arithmetic computations involving REAL_32 and REAL_64. This loss can be seen in the code below:

make local x: REAL_32 y: REAL_64 z: REAL_64 do x := 0 y := 1.123456789012345 z := x + y end where at the end the value of z was not equal to the value of y. The explanation yields on the unfolded form of the x + y operation.

Indeed, the compiler interprets it as:

x.plus (y)

Where the signature of plus in class REAL_32 reads:

plus alias "+" (other: REAL_32): REAL_32

Because y is of type REAL_64 and there is a conversion from REAL_32 to REAL_64, the final code executed by the compiler is actually:

z := x.plus (y.truncated_to_real)

This is with the truncation to REAL_32 that we loose the precision.

The conversion from REAL_64 to REAL_32 was added when the conversion mechanism was put in place to replace the magic behind numerical operation in the original version of Eiffel. The reason for adding it was that we did not want to break existing code that allowed assignment of REAL_64 to REAL_32 entities.

A few years later, we now realize it was a bad move and in the next revision of EiffelStudio (i.e. 6.5) we are planning on removing that conversion. As a result some of your code might not compile. To give you an example, for EiffelStudio, over 6500 classes we had to change less than 60 classes.

To better find out how you feel about that removal, I've created a poll where you can express whether or not you agree to remove that conversion.

PS:

  • Note also that the breaking change could just appear in the experimental version of the libraries so you might be immune from that problem if you keep using the compatible version.
  • Updating your code to compile with that change will not break your code if you are compiling it with an older version of EiffelStudio which is a good thing.

Comments
  • Daniel Furrer (14 years ago 27/8/2009)

    another solution...

    would be to have an overloaded plus feature like this:

    plus alias "+" (other: REAL_64): REAL_64

    Were there many other situations where this problem occurred?

    One problem that I get now and which I find a bit annoying is that I have to make annotations for the type of literals like this:

    my_exp ({REAL_32} 0.5, {REAL_32} 1.0)

    So it seems that the lexer recognizes all real numbers as REAL_64. Maybe we could make it recognize them as REAL_32 (if the precision of the literal allows to do so without loss).

    • Manu (14 years ago 27/8/2009)

      For the manifest constant, I agree but currently the compiler unlike their integer counterpart, is only able to make them REAL_64 by default. We will try to implement something like that in the future.