falcon: fix fpr_lt
Bu işleme şunda yer alıyor:
ebeveyn
ff16fec435
işleme
c19e9513e8
@ -424,20 +424,32 @@ fpr fpr_sqrt(fpr x);
|
|||||||
static inline int
|
static inline int
|
||||||
fpr_lt(fpr x, fpr y) {
|
fpr_lt(fpr x, fpr y) {
|
||||||
/*
|
/*
|
||||||
* If x >= 0 or y >= 0, a signed comparison yields the proper
|
* If both x and y are positive, then a signed comparison yields
|
||||||
* result:
|
* the proper result:
|
||||||
* - For positive values, the order is preserved.
|
* - For positive values, the order is preserved.
|
||||||
* - The sign bit is at the same place as in integers, so
|
* - The sign bit is at the same place as in integers, so
|
||||||
* sign is preserved.
|
* 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.
|
* If both x and y are negative, then the order is reversed.
|
||||||
* We cannot simply invert the comparison result in that case
|
* Hence [x < y] = sgn(y-x). We must compute this separately from
|
||||||
* because it would not handle the edge case x = y properly.
|
* sgn(x-y); simply inverting sgn(x-y) would not handle the edge
|
||||||
|
* case x = y properly.
|
||||||
*/
|
*/
|
||||||
int cc0, cc1;
|
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));
|
return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,20 +424,32 @@ fpr fpr_sqrt(fpr x);
|
|||||||
static inline int
|
static inline int
|
||||||
fpr_lt(fpr x, fpr y) {
|
fpr_lt(fpr x, fpr y) {
|
||||||
/*
|
/*
|
||||||
* If x >= 0 or y >= 0, a signed comparison yields the proper
|
* If both x and y are positive, then a signed comparison yields
|
||||||
* result:
|
* the proper result:
|
||||||
* - For positive values, the order is preserved.
|
* - For positive values, the order is preserved.
|
||||||
* - The sign bit is at the same place as in integers, so
|
* - The sign bit is at the same place as in integers, so
|
||||||
* sign is preserved.
|
* 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.
|
* If both x and y are negative, then the order is reversed.
|
||||||
* We cannot simply invert the comparison result in that case
|
* Hence [x < y] = sgn(y-x). We must compute this separately from
|
||||||
* because it would not handle the edge case x = y properly.
|
* sgn(x-y); simply inverting sgn(x-y) would not handle the edge
|
||||||
|
* case x = y properly.
|
||||||
*/
|
*/
|
||||||
int cc0, cc1;
|
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));
|
return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Yükleniyor…
Yeni konuda referans
Bir kullanıcı engelle