In IEEE-754, you can compare the floating-point values as sign-magnitude integer values. So I'm using it here. The integer comparison is similar to the one I used in this answer, but unsigned version. Below is the raw version before converting to branchless
Here minus operator is not used either like the other question, but you can shorten the code by converting back to using minus.
int isGreaterI(uint64_t x, uint64_t y)
{
if ((x ^ y) >> 63) // never happens as we only pass absolute values as below
{
return (x >> 63) & 1;
}
else
{
uint64_t xm = ~x + 1ULL;
uint64_t diff = y + xm;
return diff >> 63;
}
}
int isGreaterF(double a, double b)
{
uint64_t ai = *((uint64_t*)(&a));
uint64_t bi = *((uint64_t*)(&b));
int result;
if ((ai ^ bi) >> 63) // different signs
{
result = bi >> 63; // bi < 0, ai > 0
}
else
{
uint64_t sign = ai >> 63;
result = isGreaterI(ai, bi);
if (sign)
result = !result;
}
return result;
}
After muxing the branches' results in the if
blocks to remove conditionals and removing unneccessary branches we have the below final version
int isGreaterMagnitude(uint64_t x, uint64_t y)
{
uint64_t xm = ~x + 1ULL;
uint64_t diff = y + xm;
return diff >> 63;
}
int isGreaterF(double a, double b)
{
uint64_t ai = *((uint64_t*)(&a));
uint64_t bi = *((uint64_t*)(&b));
uint64_t mask = ((ai ^ bi) >> 63) + (~0ULL); // mask = 0 if a and b have different signs
uint64_t r1 = bi >> 63;
uint64_t sign = (int64_t)ai >> 63;
uint64_t r2 = isGreaterMagnitude(ai, bi);
r2 = (r2 & ~sign) | ((1 - r2) & sign);
return (r1 & ~mask) | (r2 & mask);
}