#include "lint.h"
#include <sys/types.h>
#include <sys/isa_defs.h>
#include "base_conversion.h"
#define TBL_DECADE_OFFSET 50
#define TBL_DECADE_MAX 117
static const double tbl_decade[TBL_DECADE_MAX + 1] = {
0.0,
1.00000000000000012631e-49, 1.00000000000000012631e-48,
1.00000000000000009593e-47, 1.00000000000000002300e-46,
1.00000000000000013968e-45, 1.00000000000000007745e-44,
1.00000000000000007745e-43, 1.00000000000000003762e-42,
1.00000000000000000576e-41, 1.00000000000000013321e-40,
1.00000000000000009243e-39, 1.00000000000000009243e-38,
1.00000000000000006632e-37, 1.00000000000000010809e-36,
1.00000000000000000786e-35, 1.00000000000000014150e-34,
1.00000000000000005597e-33, 1.00000000000000005597e-32,
1.00000000000000008334e-31, 1.00000000000000008334e-30,
1.00000000000000008334e-29, 1.00000000000000008334e-28,
1.00000000000000003849e-27, 1.00000000000000003849e-26,
1.00000000000000003849e-25, 1.00000000000000010737e-24,
1.00000000000000010737e-23, 1.00000000000000004860e-22,
1.00000000000000009562e-21, 1.00000000000000009562e-20,
1.00000000000000009562e-19, 1.00000000000000007154e-18,
1.00000000000000007154e-17, 1.00000000000000010236e-16,
1.00000000000000007771e-15, 1.00000000000000015659e-14,
1.00000000000000003037e-13, 1.00000000000000018184e-12,
1.00000000000000010106e-11, 1.00000000000000003643e-10,
1.00000000000000006228e-09, 1.00000000000000002092e-08,
1.00000000000000008710e-07, 1.00000000000000016651e-06,
1.00000000000000008180e-05, 1.00000000000000004792e-04,
1.00000000000000002082e-03, 1.00000000000000002082e-02,
1.00000000000000005551e-01, 1.00000000000000000000e+00,
1.00000000000000000000e+01, 1.00000000000000000000e+02,
1.00000000000000000000e+03, 1.00000000000000000000e+04,
1.00000000000000000000e+05, 1.00000000000000000000e+06,
1.00000000000000000000e+07, 1.00000000000000000000e+08,
1.00000000000000000000e+09, 1.00000000000000000000e+10,
1.00000000000000000000e+11, 1.00000000000000000000e+12,
1.00000000000000000000e+13, 1.00000000000000000000e+14,
1.00000000000000000000e+15, 1.00000000000000000000e+16,
1.00000000000000000000e+17, 1.00000000000000000000e+18,
1.00000000000000000000e+19, 1.00000000000000000000e+20,
1.00000000000000000000e+21, 1.00000000000000000000e+22,
1.00000000000000008389e+23, 1.00000000000000011744e+24,
1.00000000000000009060e+25, 1.00000000000000004765e+26,
1.00000000000000001329e+27, 1.00000000000000017821e+28,
1.00000000000000009025e+29, 1.00000000000000001988e+30,
1.00000000000000007618e+31, 1.00000000000000005366e+32,
1.00000000000000008969e+33, 1.00000000000000006087e+34,
1.00000000000000015310e+35, 1.00000000000000004242e+36,
1.00000000000000007194e+37, 1.00000000000000016638e+38,
1.00000000000000009082e+39, 1.00000000000000003038e+40,
1.00000000000000000620e+41, 1.00000000000000004489e+42,
1.00000000000000001394e+43, 1.00000000000000008821e+44,
1.00000000000000008821e+45, 1.00000000000000011990e+46,
1.00000000000000004385e+47, 1.00000000000000004385e+48,
1.00000000000000007630e+49, 1.00000000000000007630e+50,
1.00000000000000015937e+51, 1.00000000000000012614e+52,
1.00000000000000020590e+53, 1.00000000000000007829e+54,
1.00000000000000001024e+55, 1.00000000000000009190e+56,
1.00000000000000004835e+57, 1.00000000000000008319e+58,
1.00000000000000008319e+59, 1.00000000000000012779e+60,
1.00000000000000009211e+61, 1.00000000000000003502e+62,
1.00000000000000005786e+63, 1.00000000000000002132e+64,
1.00000000000000010901e+65, 1.00000000000000013239e+66,
1.00000000000000013239e+67
};
#define tenm4 tbl_decade[TBL_DECADE_OFFSET - 4]
#define ten4 tbl_decade[TBL_DECADE_OFFSET + 4]
#define tenm12 tbl_decade[TBL_DECADE_OFFSET - 12]
#define ten12 tbl_decade[TBL_DECADE_OFFSET + 12]
#define one tbl_decade[TBL_DECADE_OFFSET]
static int
__double_to_digits(double x, char *s, int n)
{
double y;
int d[5], i, j;
char *ss, tmp[4];
y = (int)(x * tenm12);
x -= y * ten12;
if (x < 0.0) {
y -= one;
x += ten12;
}
d[0] = (int)(y * tenm4);
d[1] = (int)(y - d[0] * ten4);
y = (int)(x * tenm4);
d[4] = (int)(x - y * ten4);
d[2] = (int)(y * tenm4);
d[3] = (int)(y - d[2] * ten4);
ss = s;
if (n > 20) {
for (j = 0; j < n - 20; j++)
*ss++ = '0';
i = 0;
} else {
for (i = 0; d[i] == 0 && n <= ((4 - i) << 2); i++)
;
__four_digits_quick(d[i], tmp);
for (j = 0; j < 4 && tmp[j] == '0' &&
n <= ((4 - i) << 2) + 3 - j; j++)
;
while (j < 4)
*ss++ = tmp[j++];
i++;
}
while (i < 5) {
__four_digits_quick(d[i], ss);
ss += 4;
i++;
}
*ss = '\0';
return (ss - s);
}
static union {
unsigned int i[2];
double d;
} C[] = {
#ifdef _LITTLE_ENDIAN
{ 0x00000000, 0x43300000 },
{ 0x00000000, 0x3ca00000 },
{ 0x00000000, 0x3fe00000 },
{ 0xffffffff, 0x3fdfffff },
#else
{ 0x43300000, 0x00000000 },
{ 0x3ca00000, 0x00000000 },
{ 0x3fe00000, 0x00000000 },
{ 0x3fdfffff, 0xffffffff },
#endif
};
#define two52 C[0].d
#define twom53 C[1].d
#define half C[2].d
#define halfdec C[3].d
static double
__arint_set_n(double *x, int nrx, int *pe)
{
int hx;
double rx, rmx;
#ifdef _LITTLE_ENDIAN
hx = *(1+(int *)x);
#else
hx = *(int *)x;
#endif
if (hx >= 0x43300000) {
if (nrx == 0)
*pe = 0;
else if (nrx == 1 && hx < 0x43400000)
*pe = 1;
else
*pe = 2;
return (*x);
} else if (hx < 0x3fe00000) {
if (nrx > 1 && hx == 0x3fdfffff)
*pe = (*x == halfdec)? 2 : 1;
else
*pe = 1;
return (0.0);
}
rx = (*x + two52) - two52;
if (nrx == 0) {
*pe = (rx == *x)? 0 : 1;
} else {
rmx = rx - *x;
if (rmx < 0.0)
rmx = -rmx;
*pe = (nrx * twom53 * *x < half - rmx)? 1 : 2;
}
return (rx);
}
int
__fast_double_to_decimal(double *dd, decimal_mode *pm, decimal_record *pd,
fp_exception_field_type *ps)
{
int i, is, esum, eround, hd;
double dds;
__ieee_flags_type fb;
if (pm->rd != fp_nearest)
return (1);
if (pm->df == fixed_form) {
if (pm->ndigits < 0 || pm->ndigits > __TBL_TENS_MAX)
return (1);
__get_ieee_flags(&fb);
dds = __dabs(dd);
esum = 0;
if (pm->ndigits) {
if (pm->ndigits > __TBL_TENS_EXACT) {
dds *= __tbl_tens[pm->ndigits];
esum = 2;
} else {
dds = __mul_set(dds, __tbl_tens[pm->ndigits],
&eround);
esum = eround;
}
}
if (dds > 2147483647999999744.0) {
__set_ieee_flags(&fb);
return (1);
}
dds = __arint_set_n(&dds, esum, &eround);
if (eround == 2) {
__set_ieee_flags(&fb);
return (1);
}
if (dds == 0.0) {
is = (pm->ndigits > 0)? pm->ndigits : 1;
for (i = 0; i < is; i++)
pd->ds[i] = '0';
pd->ds[is] = '\0';
eround++;
} else {
is = __double_to_digits(dds, pd->ds, pm->ndigits);
}
pd->ndigits = is;
pd->exponent = -pm->ndigits;
} else {
if (pm->ndigits < 1 || pm->ndigits > 18)
return (1);
__get_ieee_flags(&fb);
dds = __dabs(dd);
#ifdef _LITTLE_ENDIAN
hd = *(1+(int *)dd);
#else
hd = *(int *)dd;
#endif
hd = (hd >> 20) & 0x7ff;
if (hd >= 0x400) {
if (hd > 0x4e0)
i = TBL_DECADE_MAX;
else
i = TBL_DECADE_MAX - ((0x4e0 - hd) >> 2);
} else {
if (hd < 0x358)
i = 0;
else
i = TBL_DECADE_OFFSET - ((0x3ff - hd) >> 2);
}
while (dds < tbl_decade[i])
i--;
i = pm->ndigits - 1 - (i - TBL_DECADE_OFFSET);
esum = 0;
if (i > 0) {
if (i > __TBL_TENS_EXACT) {
if (i > __TBL_TENS_MAX) {
__set_ieee_flags(&fb);
return (1);
}
dds *= __tbl_tens[i];
esum = 2;
} else {
dds = __mul_set(dds, __tbl_tens[i], &eround);
esum = eround;
}
} else if (i < 0) {
if (-i > __TBL_TENS_EXACT) {
if (-i > __TBL_TENS_MAX) {
__set_ieee_flags(&fb);
return (1);
}
dds /= __tbl_tens[-i];
esum = 2;
} else {
dds = __div_set(dds, __tbl_tens[-i], &eround);
esum = eround;
}
}
dds = __arint_set_n(&dds, esum, &eround);
if (eround == 2) {
__set_ieee_flags(&fb);
return (1);
}
is = __double_to_digits(dds, pd->ds, 1);
if (is > pm->ndigits) {
pd->ds[--is] = '\0';
i--;
}
pd->ndigits = is;
pd->exponent = -i;
}
*ps = (eround == 0)? 0 : (1 << fp_inexact);
__set_ieee_flags(&fb);
return (0);
}