extract-dbl.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:7k
- /* __gmp_extract_double -- convert from double to array of mp_limb_t.
- Copyright 1996, 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc.
- This file is part of the GNU MP Library.
- The GNU MP Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
- The GNU MP Library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
- #include "gmp.h"
- #include "gmp-impl.h"
- #ifdef XDEBUG
- #undef _GMP_IEEE_FLOATS
- #endif
- #ifndef _GMP_IEEE_FLOATS
- #define _GMP_IEEE_FLOATS 0
- #endif
- #define BITS_IN_MANTISSA 53
- /* Extract a non-negative double in d. */
- int
- __gmp_extract_double (mp_ptr rp, double d)
- {
- long exp;
- unsigned sc;
- #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 GMP_LIMB_BITS >= 32.
- 4. This lits is incomplete and misspelled.
- */
- 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
- /* Work around alpha-specific bug in GCC 2.8.x. */
- volatile
- #endif
- union ieee_double_extract x;
- x.d = d;
- exp = x.s.exp;
- #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)
- {
- /* Denormalized number. Don't try to be clever about this,
- since it is not an important case to make fast. */
- 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)
- {
- /* Denormalized number. Don't try to be clever about this,
- since it is not an important case to make fast. */
- 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; /* Remove IEEE bias. */
- }
- #else
- {
- /* Unknown (or known to be non-IEEE) double format. */
- 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 /* IEEE */
- sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS;
- /* We add something here to get rounding right. */
- 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;
- }