#ifndef D2I_H
#define D2I_H
#ifndef __arm__
#error header valid for __arm__ only
#endif
#include <stdint.h>
#ifndef FLAGS_BEHAVIOR
#define FLAGS_BEHAVIOR
typedef enum
{
kCorrectFlags = -1, kLazyFlags = 0, kNoFlags = 1 }Flags_Behavior;
#endif
static inline int32_t d2i_cheesy( double x, Flags_Behavior behavior ) __attribute__ ((always_inline));
static inline int32_t d2i_cheesy( double x, Flags_Behavior behavior )
{
double rounded;
int32_t result;
union{ double d; uint64_t u; }u;
switch( behavior )
{
case kCorrectFlags:
result = (int32_t) x;
rounded = (float) result;
if( x != rounded )
{
#if defined( AVOID_PIC )
u.d = x;
u.u = (u.u & 0x8000000000000000ULL) | 0x3fe0000000000000ULL; result = (int32_t) (x + u.d);
#else
{
static const double half[2] = { 0.5, -0.5 };
result = (int32_t)( x + half[ x < 0.0 ] );
}
#endif
}
return result;
case kLazyFlags:
#if defined( AVOID_PIC )
u.d = x;
u.u = (u.u & 0x8000000000000000ULL) | 0x3fe0000000000000ULL; result = (int32_t) (x + u.d);
#else
{
static const double half[2] = { 0.5, -0.5 };
result = (int32_t)( x + half[ x < 0.0 ] );
}
#endif
return result;
case kNoFlags:
{
u.d = x;
uint64_t fabsx = u.u & 0x7fffffffffffffffULL;
int32_t exp = (int32_t)(fabsx >> 52);
result = 0;
if( exp >= 1022U )
{ int32_t leftShift = exp - (1023+52);
int32_t rightShift = -leftShift;
int32_t mask = leftShift >> 31;
int32_t signX = (int32_t)((u.u ^ fabsx) >> 32);
leftShift &= ~mask;
rightShift &= mask;
signX >>= 31;
int64_t r = ( u.u & 0x000fffffffffffffULL) | 0x0010000000000000ULL;
r += 0x0008000000000000ULL >> (exp - 1022);
r >>= rightShift;
r <<= leftShift;
result = (int32_t) r;
result ^= signX;
result -= signX;
}
return result;
}
break;
}
return 0;
}
static inline long lrint_private( double x ) __attribute__ ((always_inline));
static inline long lrint_private( double x )
{
register float temp;
register long result;
__asm__ __volatile__ ( "ftosid %0, %P1" : "=w" (temp) : "w" (x) );
__asm__ __volatile__ ( "fmrs %0, %1" : "=r" (result) : "w" (temp) );
return result;
}
#endif