#include "gmp.h"
#include "gmp-impl.h"
#ifdef XDEBUG
#undef _GMP_IEEE_FLOATS
#endif
#ifndef _GMP_IEEE_FLOATS
#define _GMP_IEEE_FLOATS 0
#endif
int
__gmp_extract_double (mp_ptr rp, double d)
{
long exp;
unsigned sc;
#ifdef _LONG_LONG_LIMB
#define BITS_PER_PART 64
unsigned long long int manl;
#else
#define BITS_PER_PART GMP_LIMB_BITS
unsigned long int manh, manl;
#endif
ASSERT (d >= 0.0);
if (d == 0.0)
{
MPN_ZERO (rp, LIMBS_PER_DOUBLE);
return 0;
}
#if _GMP_IEEE_FLOATS
{
#if defined (__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 8
volatile
#endif
union ieee_double_extract x;
x.d = d;
exp = x.s.exp;
#if BITS_PER_PART == 64
manl = (((mp_limb_t) 1 << 63)
| ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
if (exp == 0)
{
exp = 1;
do
{
manl = manl << 1;
exp--;
}
while ((manl & GMP_LIMB_HIGHBIT) == 0);
}
#endif
#if BITS_PER_PART == 32
manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
manl = x.s.manl << 11;
if (exp == 0)
{
exp = 1;
do
{
manh = (manh << 1) | (manl >> 31);
manl = manl << 1;
exp--;
}
while ((manh & GMP_LIMB_HIGHBIT) == 0);
}
#endif
#if BITS_PER_PART != 32 && BITS_PER_PART != 64
You need to generalize the code above to handle this.
#endif
exp -= 1022;
}
#else
{
exp = 0;
if (d >= 1.0)
{
ASSERT_ALWAYS (d * 0.5 != d);
while (d >= 32768.0)
{
d *= (1.0 / 65536.0);
exp += 16;
}
while (d >= 1.0)
{
d *= 0.5;
exp += 1;
}
}
else if (d < 0.5)
{
while (d < (1.0 / 65536.0))
{
d *= 65536.0;
exp -= 16;
}
while (d < 0.5)
{
d *= 2.0;
exp -= 1;
}
}
d *= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
#if BITS_PER_PART == 64
manl = d;
#endif
#if BITS_PER_PART == 32
manh = d;
manl = (d - manh) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
#endif
}
#endif
sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS;
exp = (exp + 64 * GMP_NUMB_BITS) / GMP_NUMB_BITS - 64 * GMP_NUMB_BITS / GMP_NUMB_BITS + 1;
#if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 2
#if GMP_NAIL_BITS == 0
if (sc != 0)
{
rp[1] = manl >> (GMP_LIMB_BITS - sc);
rp[0] = manl << sc;
}
else
{
rp[1] = manl;
rp[0] = 0;
exp--;
}
#else
if (sc > GMP_NAIL_BITS)
{
rp[1] = manl >> (GMP_LIMB_BITS - sc);
rp[0] = (manl << (sc - GMP_NAIL_BITS)) & GMP_NUMB_MASK;
}
else
{
if (sc == 0)
{
rp[1] = manl >> GMP_NAIL_BITS;
rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
exp--;
}
else
{
rp[1] = manl >> (GMP_LIMB_BITS - sc);
rp[0] = (manl >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
}
}
#endif
#endif
#if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 3
if (sc > GMP_NAIL_BITS)
{
rp[2] = manl >> (GMP_LIMB_BITS - sc);
rp[1] = (manl << sc - GMP_NAIL_BITS) & GMP_NUMB_MASK;
if (sc >= 2 * GMP_NAIL_BITS)
rp[0] = 0;
else
rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
}
else
{
if (sc == 0)
{
rp[2] = manl >> GMP_NAIL_BITS;
rp[1] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
rp[0] = 0;
exp--;
}
else
{
rp[2] = manl >> (GMP_LIMB_BITS - sc);
rp[1] = (manl >> GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
}
}
#endif
#if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE == 3
#if GMP_NAIL_BITS == 0
if (sc != 0)
{
rp[2] = manh >> (GMP_LIMB_BITS - sc);
rp[1] = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
rp[0] = manl << sc;
}
else
{
rp[2] = manh;
rp[1] = manl;
rp[0] = 0;
exp--;
}
#else
if (sc > GMP_NAIL_BITS)
{
rp[2] = (manh >> (GMP_LIMB_BITS - sc));
rp[1] = ((manh << (sc - GMP_NAIL_BITS)) |
(manl >> (GMP_LIMB_BITS - sc + GMP_NAIL_BITS))) & GMP_NUMB_MASK;
if (sc >= 2 * GMP_NAIL_BITS)
rp[0] = (manl << sc - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
else
rp[0] = manl >> (2 * GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
}
else
{
if (sc == 0)
{
rp[2] = manh >> GMP_NAIL_BITS;
rp[1] = ((manh << GMP_NUMB_BITS - GMP_NAIL_BITS) | (manl >> 2 * GMP_NAIL_BITS)) & GMP_NUMB_MASK;
rp[0] = (manl << GMP_NUMB_BITS - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
exp--;
}
else
{
rp[2] = (manh >> (GMP_LIMB_BITS - sc));
rp[1] = (manh >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
rp[0] = ((manh << (GMP_NUMB_BITS - GMP_NAIL_BITS + sc))
| (manl >> (GMP_LIMB_BITS - (GMP_NUMB_BITS - GMP_NAIL_BITS + sc)))) & GMP_NUMB_MASK;
}
}
#endif
#endif
#if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE > 3
if (sc == 0)
{
int i;
for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--)
{
rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
manh = ((manh << GMP_NUMB_BITS)
| (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
manl = manl << GMP_NUMB_BITS;
}
exp--;
}
else
{
int i;
rp[LIMBS_PER_DOUBLE - 1] = (manh >> (GMP_LIMB_BITS - sc));
manh = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
manl = (manl << sc);
for (i = LIMBS_PER_DOUBLE - 2; i >= 0; i--)
{
rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
manh = ((manh << GMP_NUMB_BITS)
| (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
manl = manl << GMP_NUMB_BITS;
}
}
#endif
return exp;
}