#include <sys/types.h>
#include <machine/endian.h>
#include <math.h>
#if BYTE_ORDER == BIG_ENDIAN
typedef union
{
double value;
struct
{
u_int32_t msw;
u_int32_t lsw;
} parts;
} ieee_double_shape_type;
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
typedef union
{
double value;
struct
{
u_int32_t lsw;
u_int32_t msw;
} parts;
} ieee_double_shape_type;
#endif
#define EXTRACT_WORDS(ix0,ix1,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
#define GET_HIGH_WORD(i,d) \
do { \
ieee_double_shape_type gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
#define INSERT_WORDS(d,ix0,ix1) \
do { \
ieee_double_shape_type iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
static const double one = 1.0;
double
modf(double x, double *iptr)
{
int32_t i0,i1,j0;
u_int32_t i;
EXTRACT_WORDS(i0,i1,x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) {
INSERT_WORDS(*iptr,i0&0x80000000,0);
return x;
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) {
u_int32_t high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0);
return x;
} else {
INSERT_WORDS(*iptr,i0&(~i),0);
return x - *iptr;
}
}
} else if (j0>51) {
u_int32_t high;
if (j0 == 0x400) {
*iptr = x;
return 0.0 / x;
}
*iptr = x*one;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0);
return x;
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) {
u_int32_t high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0);
return x;
} else {
INSERT_WORDS(*iptr,i0,i1&(~i));
return x - *iptr;
}
}
}