diff options
author | tege <tege@gmplib.org> | 2001-01-02 09:05:11 +0100 |
---|---|---|
committer | tege <tege@gmplib.org> | 2001-01-02 09:05:11 +0100 |
commit | 3cda1e9cd20d980654d20732a3e0c59362e921a2 (patch) | |
tree | 7494483a3496827f798e1a2e7593e5cf15de1ecb /extract-dbl.c | |
parent | 82a1764f441b2b7c1fb0cc28d635e8584b8f8b9c (diff) | |
download | gmp-3cda1e9cd20d980654d20732a3e0c59362e921a2.tar.gz |
Generalize to handle smaller limb sizes.
Diffstat (limited to 'extract-dbl.c')
-rw-r--r-- | extract-dbl.c | 71 |
1 files changed, 50 insertions, 21 deletions
diff --git a/extract-dbl.c b/extract-dbl.c index 5b64a88f1..cca9e6f0e 100644 --- a/extract-dbl.c +++ b/extract-dbl.c @@ -1,6 +1,6 @@ /* __gmp_extract_double -- convert from double to array of mp_limb_t. -Copyright 1996, 1999, 2000 Free Software Foundation, Inc. +Copyright 1996, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU MP Library. @@ -30,20 +30,22 @@ 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 manh, manl; +#else +#define BITS_PER_PART BITS_PER_LONGINT + unsigned long int manh, manl; +#endif /* BUGS @@ -55,11 +57,7 @@ __gmp_extract_double (rp, d) 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 +70,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 +85,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 +103,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,22 +142,26 @@ __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 */ + + /* 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 % BITS_PER_MP_LIMB; /* We add something here to get rounding right. */ exp = (exp + 2048) / BITS_PER_MP_LIMB - 2048 / BITS_PER_MP_LIMB + 1; -#if BITS_PER_MP_LIMB == 64 +#if LIMBS_PER_DOUBLE == 2 if (sc != 0) { rp[1] = manl >> (BITS_PER_MP_LIMB - sc); @@ -167,7 +173,8 @@ __gmp_extract_double (rp, d) rp[0] = 0; exp--; } -#else +#endif +#if LIMBS_PER_DOUBLE == 3 if (sc != 0) { rp[2] = manh >> (BITS_PER_MP_LIMB - sc); @@ -182,6 +189,28 @@ __gmp_extract_double (rp, d) exp--; } #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 BITS_PER_MP_LIMB == 16. + The ASSERT_ALWAYS should catch the problematic cases. */ + ASSERT_ALWAYS ((manl << sc) == 0); + manl = (manh << sc) | (manl >> (BITS_PER_MP_LIMB - sc)); + manh = manh >> (BITS_PER_MP_LIMB - sc); + } + { + int i; + for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--) + { + rp[i] = manh >> (BITS_PER_LONGINT - BITS_PER_MP_LIMB); + manh = ((manh << BITS_PER_MP_LIMB) + | (manl >> (BITS_PER_LONGINT - BITS_PER_MP_LIMB))); + manl = manl << BITS_PER_MP_LIMB; + } + } +#endif return exp; } |