The "problem" is that a == b
. The sign doesn't matter because mantissa (sign put aside) is purely 0. I get 0x80000000
vs 0
So fmax
just checks if a < b
or b < a
(depending on the implementation), and both are false, so either answer is a potential match.
On my gcc version I get fmax(0.0,-0.0)
at 0.0
, but fmax(-0.0,0.0)
is -0.0
.
My attempt at a full workaround, using memcmp
to compare data binary wise in the case of a 0 result.
Even better as suggested, using signbit
which tests if number has negative bit set (regardless of the value):
#include <stdio.h>
#include <math.h>
#include <string.h>
float my_fmax(float a,float b)
{
float result = fmax(a,b);
if ((result==0) && (a==b))
{
/* equal values and both zero
the only case of potential wrong selection of the negative
value. Only in that case, we tamper with the result of fmax,
and just return a unless a has negative bit set */
result = signbit(a) ? b : a;
}
return result;
}
int main () {
float a = -0.0, b = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = b = -0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = 1.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = -1.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
b = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
}
result (I think I covered all the cases):
fmax(-0.000000, 0.000000) = 0.000000
fmax(0.000000, 0.000000) = 0.000000
fmax(-0.000000, -0.000000) = -0.000000
fmax(1.000000, -0.000000) = 1.000000
fmax(-1.000000, -0.000000) = -0.000000
fmax(-1.000000, 0.000000) = 0.000000