float compares on x86 (i.e. 32 bit) bug?
Matthias Kretz
kretz@fias.uni-frankfurt.de
Tue Apr 13 12:22:00 GMT 2010
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.
Comments?
--
Matthias Kretz
Phone: +49 6221 1871682
sip:062211871682@sipgate.de
Email: kretz@fias.uni-frankfurt.de
More information about the Gcc-help
mailing list