_fixunssfdi.c   [plain text]


/* 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;
}