blob: 08ffc6a6e26dea242d3fcedbea0d22779b929a9b [file] [log] [blame]
/* APPLE LOCAL file 5316398 improved float/double -> int64 functions */
#include <stdint.h>
uint64_t
__fixunssfdi (float x)
{
union { float f; uint32_t u; } u = {x};
uint32_t hi, lo;
/* early out for common small positive numbers. */
if (__builtin_expect (u.u < 0x4f800000U, 1))
return (uint64_t) ((uint32_t) x);
/* larger non-overflowing cases are all exact, so we just need to do
the conversion in integer code */
/* if( 0x1.0p32f <= x < 0x1.0p63f ) */
if (__builtin_expect (u.u < 0x5f800000U, 1))
{
uint32_t bits = (u.u & 0x007fffffU) | 0x00800000U;
uint32_t shift = (u.u >> 23) - (127 + 23);
if (shift < 32)
{
hi = bits >> (32 - shift);
lo = bits << shift;
}
else
{
hi = bits << (shift - 32);
lo = 0;
}
return ((uint64_t) hi << 32) | lo;
}
/* Overflow or NaN: convert value to unsigned int, set invalid as
necessary */
hi = x;
/* extend to 64-bits. */
lo = (hi << 1) | (hi & 1);
return ((uint64_t) hi << 32) | lo;
}