float compares on x86 (i.e. 32 bit) bug?

Andrew Haley aph@redhat.com
Tue Apr 13 12:39:00 GMT 2010


On 04/13/2010 01:22 PM, Matthias Kretz wrote:
> Hi,
> 
> I was wondering why the following code failed:
> 
> int main() {
>   const float_v x = ...;
>   const float_v y = ...;
>   float_v r = Vc::sqrt(x * x + y * y);
> 
>   for (int i = 0; i < Count; ++i) {
>     const float a = r[0];
>     const float b = std::sqrt(x[0] * x[0] + y[0] * y[0]);
>     if (a != b) {
>       std::cout << a << " != " << b << ": " << a - b << std::endl;
>       return 1;
>     }
>   }
>   return 0;
> }
> 
> Output is:
> 1.41421 != 1.41421: 0
> 
> float_v is a class from my Vc library (http://gitorious.org/vc/) that wraps 
> __m128. Vc::sqrt thus uses the SSE sqrt with single precision. std::sqrt OTOH 
> is implemented as fsqrt and the comparison "a != b" is implemented with 
> fucomip using the result from fsqrt directly and the result from Vc::sqrt 
> loaded from memory. After fucomip the following flags are set:
> (gdb) p $eflags
> $6 = [ CF IF ]
> 
> Obviously I expected ZF to be set. Here's the problem:
> st6 1.41421353816986083984375            (raw 0x3fffb504f30000000000)
> st7 1.4142135623730950487637880730318329 (raw 0x3fffb504f333f9de6484)
> 
> Looking at the binary representation the single precision values are equal. 
> Just st7 (the result from fsqrt) is not stored as single.
> 
> So now I understand why it failed. Am I right in my understanding that this is 
> a bug? According to the C++ code the comparison should not have returned false 
> because std::sqrt returns a single precision value.

Isn't this http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 ?

We won't know until you give us a real test case, one that we can compile
and run.

Andrew.



More information about the Gcc-help mailing list