blob: 021dc460e912f60f3f3f039b3b11454494c4c667 [file] [log] [blame]
#include <limits.h>
#include <stdint.h>
#include <math.h>
#include "gdtoa.h"
#if !(defined __x86_64) && !(defined __i386__)
#error "An architecture with extended precision long double required!"
#endif
/* IEEE extended precision floating point format, little endian byte ordering */
union ieee_ext
{
struct
{
uint32_t mt0:32;
uint32_t mt1:32;
uint32_t exp:15;
uint32_t sgn:1;
uint32_t etc:16;
} ieee;
long double d;
};
/*
__ldtoa: wrapper for long double conversion using gdtoa()
NOTE: This only works for IEEE extended precision long doubles.
Input:
ld - a pointer to the value to convert
The rest of the parameters are the analogous to the corresponding
parameters to gdtoa().
Returns:
This function returns a string that is to be free'd with freedtoa().
*/
char *
__ldtoa(long double *ld,
int mode,
int ndigits,
int *decpt,
int *sign,
char **rve)
{
FPI fpi =
{
64, /* nbits */
1 - 16383 - 63, /* emin */
32766 - 16383 - 63, /* emax */
1, /* rounding */
0 /* sudden_underflow */
};
union ieee_ext *l;
uint32_t bits[2];
int exp, kind;
char *ret;
l = (union ieee_ext *) ld;
*sign = l->ieee.sgn;
exp = l->ieee.exp;
bits[0] = l->ieee.mt0;
bits[1] = l->ieee.mt1;
if (isnan(*ld)) /* NaN */
kind = STRTOG_NaN;
else if (isinf(*ld)) /* Infinity */
kind = STRTOG_Infinite;
else if (exp == 0) /* Denormalized */
{
kind = STRTOG_Denormal;
exp = 1;
}
else /* Normalized or zero */
{
if (bits[0] | bits[1])
kind = STRTOG_Normal;
else
kind = STRTOG_Zero;
}
exp -= 16383 + 63;
ret = gdtoa(&fpi, exp, &bits[0], &kind, mode, ndigits, decpt, rve);
if (*decpt == -32768)
*decpt = INT_MAX;
return ret;
}