falcon: fix fpr_lt

Esse commit está contido em:
John M. Schanck 2020-09-18 22:18:08 -04:00 commit de Kris Kwiatkowski
commit c19e9513e8
2 arquivos alterados com 36 adições e 12 exclusões

Ver arquivo

@ -424,20 +424,32 @@ fpr fpr_sqrt(fpr x);
static inline int
fpr_lt(fpr x, fpr y) {
/*
* If x >= 0 or y >= 0, a signed comparison yields the proper
* result:
* If both x and y are positive, then a signed comparison yields
* the proper result:
* - For positive values, the order is preserved.
* - The sign bit is at the same place as in integers, so
* sign is preserved.
* Moreover, we can compute [x < y] as sgn(x-y) and the computation
* of x-y will not overflow.
*
* If the signs differ, then sgn(x) gives the proper result.
*
* If both x and y are negative, then the order is reversed.
* We cannot simply invert the comparison result in that case
* because it would not handle the edge case x = y properly.
* Hence [x < y] = sgn(y-x). We must compute this separately from
* sgn(x-y); simply inverting sgn(x-y) would not handle the edge
* case x = y properly.
*/
int cc0, cc1;
int64_t sx;
int64_t sy;
sx = *(int64_t *)&x;
sy = *(int64_t *)&y;
sy &= ~((sx ^ sy) >> 63); /* set sy=0 if signs differ */
cc0 = (int)((sx - sy) >> 63) & 1; /* Neither subtraction overflows when */
cc1 = (int)((sy - sx) >> 63) & 1; /* the signs are the same. */
cc0 = (int)((*(int64_t *)&x - * (int64_t *)&y) >> 63) & 1;
cc1 = (int)((*(int64_t *)&y - * (int64_t *)&x) >> 63) & 1;
return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63));
}

Ver arquivo

@ -424,20 +424,32 @@ fpr fpr_sqrt(fpr x);
static inline int
fpr_lt(fpr x, fpr y) {
/*
* If x >= 0 or y >= 0, a signed comparison yields the proper
* result:
* If both x and y are positive, then a signed comparison yields
* the proper result:
* - For positive values, the order is preserved.
* - The sign bit is at the same place as in integers, so
* sign is preserved.
* Moreover, we can compute [x < y] as sgn(x-y) and the computation
* of x-y will not overflow.
*
* If the signs differ, then sgn(x) gives the proper result.
*
* If both x and y are negative, then the order is reversed.
* We cannot simply invert the comparison result in that case
* because it would not handle the edge case x = y properly.
* Hence [x < y] = sgn(y-x). We must compute this separately from
* sgn(x-y); simply inverting sgn(x-y) would not handle the edge
* case x = y properly.
*/
int cc0, cc1;
int64_t sx;
int64_t sy;
sx = *(int64_t *)&x;
sy = *(int64_t *)&y;
sy &= ~((sx ^ sy) >> 63); /* set sy=0 if signs differ */
cc0 = (int)((sx - sy) >> 63) & 1; /* Neither subtraction overflows when */
cc1 = (int)((sy - sx) >> 63) & 1; /* the signs are the same. */
cc0 = (int)((*(int64_t *)&x - * (int64_t *)&y) >> 63) & 1;
cc1 = (int)((*(int64_t *)&y - * (int64_t *)&x) >> 63) & 1;
return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63));
}