=================================================================== RCS file: /home/cvs/OpenXM_contrib/gmp/Attic/extract-dbl.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -p -r1.1.1.1 -r1.1.1.2 --- OpenXM_contrib/gmp/Attic/extract-dbl.c 2000/09/09 14:12:16 1.1.1.1 +++ OpenXM_contrib/gmp/Attic/extract-dbl.c 2003/08/25 16:06:00 1.1.1.2 @@ -1,6 +1,6 @@ /* __gmp_extract_double -- convert from double to array of mp_limb_t. -Copyright (C) 1996, 1999, 2000 Free Software Foundation, Inc. +Copyright 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. @@ -30,36 +30,36 @@ MA 02111-1307, USA. */ #define _GMP_IEEE_FLOATS 0 #endif +#define BITS_IN_MANTISSA 53 + /* Extract a non-negative double in d. */ int -#if __STDC__ __gmp_extract_double (mp_ptr rp, double d) -#else -__gmp_extract_double (rp, d) - mp_ptr rp; - double d; -#endif { long exp; unsigned sc; - mp_limb_t manh, manl; +#ifdef _LONG_LONG_LIMB +#define BITS_PER_PART 64 /* somewhat bogus */ + unsigned long long int manl; +#else +#define BITS_PER_PART GMP_LIMB_BITS + unsigned long int manh, manl; +#endif /* BUGS 1. Should handle Inf and NaN in IEEE specific code. 2. Handle Inf and NaN also in default code, to avoid hangs. - 3. Generalize to handle all BITS_PER_MP_LIMB >= 32. + 3. Generalize to handle all GMP_LIMB_BITS >= 32. 4. This lits is incomplete and misspelled. */ + ASSERT (d >= 0.0); + if (d == 0.0) { - rp[0] = 0; - rp[1] = 0; -#if BITS_PER_MP_LIMB == 32 - rp[2] = 0; -#endif + MPN_ZERO (rp, LIMBS_PER_DOUBLE); return 0; } @@ -72,7 +72,7 @@ __gmp_extract_double (rp, d) union ieee_double_extract x; x.d = d; exp = x.s.exp; -#if BITS_PER_MP_LIMB == 64 +#if BITS_PER_PART == 64 /* generalize this to BITS_PER_PART > BITS_IN_MANTISSA */ manl = (((mp_limb_t) 1 << 63) | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11)); if (exp == 0) @@ -87,7 +87,8 @@ __gmp_extract_double (rp, d) } while ((mp_limb_signed_t) manl >= 0); } -#else +#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) @@ -104,6 +105,9 @@ __gmp_extract_double (rp, d) while ((mp_limb_signed_t) manh >= 0); } #endif +#if BITS_PER_PART != 32 && BITS_PER_PART != 64 + You need to generalize the code above to handle this. +#endif exp -= 1022; /* Remove IEEE bias. */ } #else @@ -140,25 +144,30 @@ __gmp_extract_double (rp, d) } } - d *= MP_BASE_AS_DOUBLE; -#if BITS_PER_MP_LIMB == 64 + d *= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2))); +#if BITS_PER_PART == 64 manl = d; #else manh = d; - manl = (d - manh) * MP_BASE_AS_DOUBLE; + manl = (d - manh) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2))); #endif } -#endif +#endif /* IEEE */ - sc = (unsigned) exp % BITS_PER_MP_LIMB; + /* Up until here, we have ignored the actual limb size. Remains + to split manh,,manl into an array of LIMBS_PER_DOUBLE limbs. + */ + sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS; + /* We add something here to get rounding right. */ - exp = (exp + 2048) / BITS_PER_MP_LIMB - 2048 / BITS_PER_MP_LIMB + 1; + exp = (exp + 64 * GMP_NUMB_BITS) / GMP_NUMB_BITS - 64 * GMP_NUMB_BITS / GMP_NUMB_BITS + 1; -#if BITS_PER_MP_LIMB == 64 +#if LIMBS_PER_DOUBLE == 2 +#if GMP_NAIL_BITS == 0 if (sc != 0) { - rp[1] = manl >> (BITS_PER_MP_LIMB - sc); + rp[1] = manl >> (GMP_LIMB_BITS - sc); rp[0] = manl << sc; } else @@ -168,10 +177,34 @@ __gmp_extract_double (rp, d) 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 LIMBS_PER_DOUBLE == 3 +#if GMP_NAIL_BITS == 0 if (sc != 0) { - rp[2] = manh >> (BITS_PER_MP_LIMB - sc); - rp[1] = (manl >> (BITS_PER_MP_LIMB - sc)) | (manh << sc); + rp[2] = manh >> (GMP_LIMB_BITS - sc); + rp[1] = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc)); rp[0] = manl << sc; } else @@ -181,6 +214,58 @@ __gmp_extract_double (rp, d) 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] = 0; + 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 LIMBS_PER_DOUBLE > 3 + /* Insert code for splitting manh,,manl into LIMBS_PER_DOUBLE + mp_limb_t's at rp. */ + if (sc != 0) + { + /* This is not perfect, and would fail for GMP_LIMB_BITS == 16. + The ASSERT_ALWAYS should catch the problematic cases. */ + ASSERT_ALWAYS ((manl << sc) == 0); + manl = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc)); + manh = manh >> (GMP_LIMB_BITS - sc); + } + { + int i; + for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--) + { + rp[i] = manh >> (BITS_PER_LONGINT - GMP_LIMB_BITS); + manh = ((manh << GMP_LIMB_BITS) + | (manl >> (BITS_PER_LONGINT - GMP_LIMB_BITS))); + manl = manl << GMP_LIMB_BITS; + } + } #endif return exp;