#ifdef HEXFLOAT
#include <stdio.h>
#include <math.h>
#include <limits.h>
#define EXPBIAS 1023
#define EXPMIN -1022
#define EXPSPECIAL 2047
#define FRACTHEX 13
union hexdouble {
double d;
struct {
#if defined(__ppc__)
unsigned int sign:1;
unsigned int exp:11;
unsigned long long fract:52;
#elif defined(__i386__)
unsigned long long fract:52;
unsigned int exp:11;
unsigned int sign:1;
#else
#error Unsupported architecture
#endif
} s;
};
#if !__TYPE_LONGDOUBLE_IS_DOUBLE
#ifdef __i386__
#define LEXPBIAS 16383
#define LEXPMIN -16382
#define LEXPSPECIAL 32767
#define LFRACTHEX 16
union hexlongdouble {
long double d;
struct {
unsigned long long fract:63;
unsigned int i:1;
unsigned int exp:15;
unsigned int sign:1;
} s;
};
#endif
#endif
int
__hdtoa(double d, const char *xdigs, int prec, char *cp,
int *expt, int *signflag, char **dtoaend)
{
union hexdouble u;
char buf[FRACTHEX];
char *hp;
int i;
long long fract;
u.d = d;
*signflag = u.s.sign;
fract = u.s.fract;
switch (u.s.exp) {
case EXPSPECIAL:
*expt = INT_MAX;
*cp = (fract ? 'N' : 'I');
return 0;
case 0:
*cp++ = '0';
*expt = (fract ? EXPMIN : 0);
break;
default:
*cp++ = '1';
*expt = u.s.exp - EXPBIAS;
break;
}
if (prec < 0)
prec = FRACTHEX;
if (prec > 0) {
int dig = (prec > FRACTHEX ? FRACTHEX : prec);
int zero = prec - dig;
int shift = FRACTHEX - dig;
if (shift > 0)
fract >>= (shift << 2);
for (hp = buf + dig, i = dig; i > 0; i--) {
*--hp = xdigs[fract & 0xf];
fract >>= 4;
}
strncpy(cp, hp, dig);
cp += dig;
while(zero-- > 0)
*cp++ = '0';
}
*dtoaend = cp;
return prec;
}
#if !__TYPE_LONGDOUBLE_IS_DOUBLE
#ifdef __i386__
int
__hldtoa(long double d, const char *xdigs, int prec, char *cp,
int *expt, int *signflag, char **dtoaend)
{
union hexlongdouble u;
char buf[LFRACTHEX];
char *hp;
int i;
unsigned long long fract;
u.d = d;
*signflag = u.s.sign;
fract = (u.s.fract << 1);
switch (u.s.exp) {
case LEXPSPECIAL:
*expt = INT_MAX;
*cp = (fract ? 'N' : 'I');
return 0;
default:
*cp++ = u.s.i ? '1' : '0';
*expt = u.s.exp - LEXPBIAS;
break;
}
if (prec < 0)
prec = LFRACTHEX;
if (prec > 0) {
int dig = (prec > LFRACTHEX ? LFRACTHEX : prec);
int zero = prec - dig;
int shift = LFRACTHEX - dig;
if (shift > 0)
fract >>= (shift << 2);
for (hp = buf + dig, i = dig; i > 0; i--) {
*--hp = xdigs[fract & 0xf];
fract >>= 4;
}
strncpy(cp, hp, dig);
cp += dig;
while(zero-- > 0)
*cp++ = '0';
}
*dtoaend = cp;
return prec;
}
#endif
#endif
#endif