blob: f248c95a447fde4c3e20ca6d3fecd3e566343e2b [file] [log] [blame]
/* APPLE LOCAL file 5316398 improved float/double -> int64 functions */
#include <stdint.h>
int64_t
__fixsfdi (float x)
{
union { float f; uint32_t u; } u = {x};
uint32_t fabsx = u.u & 0x7fffffffU;
uint32_t exp = fabsx >> 23;
int64_t result = 0;
/* for small ints, overflow and NaN, the int32_t converter works fine
if( |x| < 0x1.0p31f || |x| >= 1.0p64f || isnan(x) ) unsigned
compare */
if (exp - (127U + 31U) >= (63U - 31U))
{
if (exp > (127 + 31))
{
if (x == -0x1.0p63f)
return 0x8000000000000000LL;
uint32_t r = (int32_t) x;
result = (int64_t) r << 32;
r = (r << 1) | (r & 1);
result |= r;
return result;
}
/* small number. Regular int32_t conversion will work fine here. */
result = (int32_t) x;
return result;
}
/* 0x1.0p31 <= |x| <0x1.0p64, x is always an integer in this range */
/* convert float to fixed */
result = (fabsx & 0x007fffffU) | 0x00800000;
/* signMask = x < 0.0f ? -1LL : 0 */
int64_t signMask = (int64_t) u.u << 32;
signMask >>= 63;
/* Calculate shift value to move fixed point to right place */
int32_t leftShift = exp - (127 + 23);
/* move the fixed point into place */
result <<= leftShift;
/* Fix sign */
result ^= signMask;
result -= signMask;
return result;
}