| Index: gcc/gmp/mpn/generic/get_d.c
|
| diff --git a/gcc/gmp/mpn/generic/get_d.c b/gcc/gmp/mpn/generic/get_d.c
|
| deleted file mode 100644
|
| index ea8a880e329e2eac97665c3c5ad0e197601c250f..0000000000000000000000000000000000000000
|
| --- a/gcc/gmp/mpn/generic/get_d.c
|
| +++ /dev/null
|
| @@ -1,493 +0,0 @@
|
| -/* mpn_get_d -- limbs to double conversion.
|
| -
|
| - THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
|
| - CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
|
| - FUTURE GNU MP RELEASES.
|
| -
|
| -Copyright 2003, 2004 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"
|
| -#include "longlong.h"
|
| -
|
| -#ifndef _GMP_IEEE_FLOATS
|
| -#define _GMP_IEEE_FLOATS 0
|
| -#endif
|
| -
|
| -#if ! _GMP_IEEE_FLOATS
|
| -/* dummy definition, just to let dead code compile */
|
| -union ieee_double_extract {
|
| - struct {
|
| - int manh, manl, sig, exp;
|
| - } s;
|
| - double d;
|
| -};
|
| -#endif
|
| -
|
| -/* To force use of the generic C code for testing, put
|
| - "#define _GMP_IEEE_FLOATS 0" at this point. */
|
| -
|
| -
|
| -
|
| -/* In alpha gcc prior to 3.4, signed DI comparisons involving constants are
|
| - rearranged from "x < n" to "x+(-n) < 0", which is of course hopelessly
|
| - wrong if that addition overflows.
|
| -
|
| - The workaround here avoids this bug by ensuring n is not a literal
|
| - constant. Note that this is alpha specific. The offending transformation
|
| - is/was in alpha.c alpha_emit_conditional_branch() under "We want to use
|
| - cmpcc/bcc".
|
| -
|
| - Bizarrely, it turns out this happens also with Cray cc on
|
| - alphaev5-cray-unicosmk2.0.6.X, and has the same solution. Don't know why
|
| - or how. */
|
| -
|
| -#if HAVE_HOST_CPU_FAMILY_alpha \
|
| - && ((defined (__GNUC__) && ! __GMP_GNUC_PREREQ(3,4)) \
|
| - || defined (_CRAY))
|
| -static volatile const long CONST_1024 = 1024;
|
| -static volatile const long CONST_NEG_1023 = -1023;
|
| -static volatile const long CONST_NEG_1022_SUB_53 = -1022 - 53;
|
| -#else
|
| -#define CONST_1024 (1024)
|
| -#define CONST_NEG_1023 (-1023)
|
| -#define CONST_NEG_1022_SUB_53 (-1022 - 53)
|
| -#endif
|
| -
|
| -
|
| -
|
| -/* Return the value {ptr,size}*2^exp, and negative if sign<0.
|
| - Must have size>=1, and a non-zero high limb ptr[size-1].
|
| -
|
| - {ptr,size} is truncated towards zero. This is consistent with other gmp
|
| - conversions, like mpz_set_f or mpz_set_q, and is easy to implement and
|
| - test.
|
| -
|
| - In the past conversions had attempted (imperfectly) to let the hardware
|
| - float rounding mode take effect, but that gets tricky since multiple
|
| - roundings need to be avoided, or taken into account, and denorms mean the
|
| - effective precision of the mantissa is not constant. (For reference,
|
| - mpz_get_d on IEEE systems was ok, except it operated on the absolute
|
| - value. mpf_get_d and mpq_get_d suffered from multiple roundings and from
|
| - not always using enough bits to get the rounding right.)
|
| -
|
| - It's felt that GMP is not primarily concerned with hardware floats, and
|
| - really isn't enhanced by getting involved with hardware rounding modes
|
| - (which could even be some weird unknown style), so something unambiguous
|
| - and straightforward is best.
|
| -
|
| -
|
| - The IEEE code below is the usual case, it knows either a 32-bit or 64-bit
|
| - limb and is done with shifts and masks. The 64-bit case in particular
|
| - should come out nice and compact.
|
| -
|
| - The generic code works one bit at a time, which will be quite slow, but
|
| - should support any binary-based "double" and be safe against any rounding
|
| - mode. Note in particular it works on IEEE systems too.
|
| -
|
| -
|
| - Traps:
|
| -
|
| - Hardware traps for overflow to infinity, underflow to zero, or
|
| - unsupported denorms may or may not be taken. The IEEE code works bitwise
|
| - and so probably won't trigger them, the generic code works by float
|
| - operations and so probably will. This difference might be thought less
|
| - than ideal, but again its felt straightforward code is better than trying
|
| - to get intimate with hardware exceptions (of perhaps unknown nature).
|
| -
|
| -
|
| - Not done:
|
| -
|
| - mpz_get_d in the past handled size==1 with a cast limb->double. This
|
| - might still be worthwhile there (for up to the mantissa many bits), but
|
| - for mpn_get_d here, the cost of applying "exp" to the resulting exponent
|
| - would probably use up any benefit a cast may have over bit twiddling.
|
| - Also, if the exponent is pushed into denorm range then bit twiddling is
|
| - the only option, to ensure the desired truncation is obtained.
|
| -
|
| -
|
| - Other:
|
| -
|
| - For reference, note that HPPA 8000, 8200, 8500 and 8600 trap FCNV,UDW,DBL
|
| - to the kernel for values >= 2^63. This makes it slow, and worse the
|
| - Linux kernel (what versions?) apparently uses untested code in its trap
|
| - handling routines, and gets the sign wrong. We don't use such a limb to
|
| - double cast, neither in the IEEE or generic code. */
|
| -
|
| -
|
| -double
|
| -mpn_get_d (mp_srcptr up, mp_size_t size, mp_size_t sign, long exp)
|
| -{
|
| - ASSERT (size >= 0);
|
| - ASSERT_MPN (up, size);
|
| - ASSERT (size == 0 || up[size-1] != 0);
|
| -
|
| - if (size == 0)
|
| - return 0.0;
|
| -
|
| - /* Adjust exp to a radix point just above {up,size}, guarding against
|
| - overflow. After this exp can of course be reduced to anywhere within
|
| - the {up,size} region without underflow. */
|
| - if (UNLIKELY ((unsigned long) (GMP_NUMB_BITS * size)
|
| - > (unsigned long) (LONG_MAX - exp)))
|
| - {
|
| - if (_GMP_IEEE_FLOATS)
|
| - goto ieee_infinity;
|
| -
|
| - /* generic */
|
| - exp = LONG_MAX;
|
| - }
|
| - else
|
| - {
|
| - exp += GMP_NUMB_BITS * size;
|
| - }
|
| -
|
| -
|
| -#if 1
|
| -{
|
| - int lshift, nbits;
|
| - union ieee_double_extract u;
|
| - mp_limb_t x, mhi, mlo;
|
| -#if GMP_LIMB_BITS == 64
|
| - mp_limb_t m;
|
| - up += size;
|
| - m = *--up;
|
| - count_leading_zeros (lshift, m);
|
| -
|
| - exp -= (lshift - GMP_NAIL_BITS) + 1;
|
| - m <<= lshift;
|
| -
|
| - nbits = GMP_LIMB_BITS - lshift;
|
| -
|
| - if (nbits < 53 && size > 1)
|
| - {
|
| - x = *--up;
|
| - x <<= GMP_NAIL_BITS;
|
| - x >>= nbits;
|
| - m |= x;
|
| - nbits += GMP_NUMB_BITS;
|
| -
|
| - if (LIMBS_PER_DOUBLE >= 3 && nbits < 53 && size > 2)
|
| - {
|
| - x = *--up;
|
| - x <<= GMP_NAIL_BITS;
|
| - x >>= nbits;
|
| - m |= x;
|
| - nbits += GMP_NUMB_BITS;
|
| - }
|
| - }
|
| - mhi = m >> (32 + 11);
|
| - mlo = m >> 11;
|
| -#endif
|
| -#if GMP_LIMB_BITS == 32
|
| - up += size;
|
| - x = *--up, size--;
|
| - count_leading_zeros (lshift, x);
|
| -
|
| - exp -= (lshift - GMP_NAIL_BITS) + 1;
|
| - x <<= lshift;
|
| - mhi = x >> 11;
|
| -
|
| - if (lshift < 11) /* FIXME: never true if NUMB < 20 bits */
|
| - {
|
| - /* All 20 bits in mhi */
|
| - mlo = x << 21;
|
| - /* >= 1 bit in mlo */
|
| - nbits = GMP_LIMB_BITS - lshift - 21;
|
| - }
|
| - else
|
| - {
|
| - if (size != 0)
|
| - {
|
| - nbits = GMP_LIMB_BITS - lshift;
|
| -
|
| - x = *--up, size--;
|
| - x <<= GMP_NAIL_BITS;
|
| - mhi |= x >> nbits >> 11;
|
| -
|
| - mlo = x << GMP_LIMB_BITS - nbits - 11;
|
| - nbits = nbits + 11 - GMP_NAIL_BITS;
|
| - }
|
| - else
|
| - {
|
| - mlo = 0;
|
| - goto done;
|
| - }
|
| - }
|
| -
|
| - if (LIMBS_PER_DOUBLE >= 2 && nbits < 32 && size != 0)
|
| - {
|
| - x = *--up, size--;
|
| - x <<= GMP_NAIL_BITS;
|
| - x >>= nbits;
|
| - mlo |= x;
|
| - nbits += GMP_NUMB_BITS;
|
| -
|
| - if (LIMBS_PER_DOUBLE >= 3 && nbits < 32 && size != 0)
|
| - {
|
| - x = *--up, size--;
|
| - x <<= GMP_NAIL_BITS;
|
| - x >>= nbits;
|
| - mlo |= x;
|
| - nbits += GMP_NUMB_BITS;
|
| -
|
| - if (LIMBS_PER_DOUBLE >= 4 && nbits < 32 && size != 0)
|
| - {
|
| - x = *--up;
|
| - x <<= GMP_NAIL_BITS;
|
| - x >>= nbits;
|
| - mlo |= x;
|
| - nbits += GMP_NUMB_BITS;
|
| - }
|
| - }
|
| - }
|
| -
|
| - done:;
|
| -
|
| -#endif
|
| - {
|
| - if (UNLIKELY (exp >= CONST_1024))
|
| - {
|
| - /* overflow, return infinity */
|
| - ieee_infinity:
|
| - mhi = 0;
|
| - mlo = 0;
|
| - exp = 1024;
|
| - }
|
| - else if (UNLIKELY (exp <= CONST_NEG_1023))
|
| - {
|
| - int rshift = GMP_LIMB_BITS - lshift;
|
| -
|
| - if (LIKELY (exp <= CONST_NEG_1022_SUB_53))
|
| - return 0.0; /* denorm underflows to zero */
|
| -
|
| - rshift = -1022 - exp;
|
| - ASSERT (rshift > 0 && rshift < 53);
|
| - if (GMP_LIMB_BITS == 64)
|
| - {
|
| - mlo = (mlo >> rshift) | (mhi << lshift);
|
| - mhi >>= rshift;
|
| - }
|
| - else
|
| - {
|
| - if (rshift >= 32)
|
| - {
|
| - mlo = mhi;
|
| - mhi = 0;
|
| - rshift -= 32;
|
| - }
|
| - lshift = GMP_LIMB_BITS - rshift;
|
| - mlo = (mlo >> rshift) | (rshift == 0 ? 0 : mhi << lshift);
|
| - mhi >>= rshift;
|
| - }
|
| - exp = -1023;
|
| - }
|
| - }
|
| - u.s.manh = mhi;
|
| - u.s.manl = mlo;
|
| - u.s.exp = exp + 1023;
|
| - u.s.sig = (sign < 0);
|
| - return u.d;
|
| -}
|
| -#else
|
| -
|
| -
|
| -#define ONE_LIMB (GMP_LIMB_BITS == 64 && 2*GMP_NUMB_BITS >= 53)
|
| -#define TWO_LIMBS (GMP_LIMB_BITS == 32 && 3*GMP_NUMB_BITS >= 53)
|
| -
|
| - if (_GMP_IEEE_FLOATS && (ONE_LIMB || TWO_LIMBS))
|
| - {
|
| - union ieee_double_extract u;
|
| - mp_limb_t m0, m1, m2, rmask;
|
| - int lshift, rshift;
|
| -
|
| - m0 = up[size-1]; /* high limb */
|
| - m1 = (size >= 2 ? up[size-2] : 0); /* second highest limb */
|
| - count_leading_zeros (lshift, m0);
|
| -
|
| - /* relative to just under high non-zero bit */
|
| - exp -= (lshift - GMP_NAIL_BITS) + 1;
|
| -
|
| - if (ONE_LIMB)
|
| - {
|
| - /* lshift to have high of m0 non-zero, and collapse nails */
|
| - rshift = GMP_LIMB_BITS - lshift;
|
| - m1 <<= GMP_NAIL_BITS;
|
| - rmask = GMP_NAIL_BITS == 0 && lshift == 0 ? 0 : MP_LIMB_T_MAX;
|
| - m0 = (m0 << lshift) | ((m1 >> rshift) & rmask);
|
| -
|
| - /* rshift back to have bit 53 of m0 the high non-zero */
|
| - m0 >>= 11;
|
| - }
|
| - else /* TWO_LIMBS */
|
| - {
|
| - m2 = (size >= 3 ? up[size-3] : 0); /* third highest limb */
|
| -
|
| - /* collapse nails from m1 and m2 */
|
| -#if GMP_NAIL_BITS != 0
|
| - m1 = (m1 << GMP_NAIL_BITS) | (m2 >> (GMP_NUMB_BITS-GMP_NAIL_BITS));
|
| - m2 <<= 2*GMP_NAIL_BITS;
|
| -#endif
|
| -
|
| - /* lshift to have high of m0:m1 non-zero, collapse nails from m0 */
|
| - rshift = GMP_LIMB_BITS - lshift;
|
| - rmask = (GMP_NAIL_BITS == 0 && lshift == 0 ? 0 : MP_LIMB_T_MAX);
|
| - m0 = (m0 << lshift) | ((m1 >> rshift) & rmask);
|
| - m1 = (m1 << lshift) | ((m2 >> rshift) & rmask);
|
| -
|
| - /* rshift back to have bit 53 of m0:m1 the high non-zero */
|
| - m1 = (m1 >> 11) | (m0 << (GMP_LIMB_BITS-11));
|
| - m0 >>= 11;
|
| - }
|
| -
|
| - if (UNLIKELY (exp >= CONST_1024))
|
| - {
|
| - /* overflow, return infinity */
|
| - ieee_infinity:
|
| - m0 = 0;
|
| - m1 = 0;
|
| - exp = 1024;
|
| - }
|
| - else if (UNLIKELY (exp <= CONST_NEG_1023))
|
| - {
|
| - if (LIKELY (exp <= CONST_NEG_1022_SUB_53))
|
| - return 0.0; /* denorm underflows to zero */
|
| -
|
| - rshift = -1022 - exp;
|
| - ASSERT (rshift > 0 && rshift < 53);
|
| - if (ONE_LIMB)
|
| - {
|
| - m0 >>= rshift;
|
| - }
|
| - else /* TWO_LIMBS */
|
| - {
|
| - if (rshift >= 32)
|
| - {
|
| - m1 = m0;
|
| - m0 = 0;
|
| - rshift -= 32;
|
| - }
|
| - lshift = GMP_LIMB_BITS - rshift;
|
| - m1 = (m1 >> rshift) | (rshift == 0 ? 0 : m0 << lshift);
|
| - m0 >>= rshift;
|
| - }
|
| - exp = -1023;
|
| - }
|
| -
|
| - if (ONE_LIMB)
|
| - {
|
| -#if GMP_LIMB_BITS > 32 /* avoid compiler warning about big shift */
|
| - u.s.manh = m0 >> 32;
|
| -#endif
|
| - u.s.manl = m0;
|
| - }
|
| - else /* TWO_LIMBS */
|
| - {
|
| - u.s.manh = m0;
|
| - u.s.manl = m1;
|
| - }
|
| -
|
| - u.s.exp = exp + 1023;
|
| - u.s.sig = (sign < 0);
|
| - return u.d;
|
| - }
|
| - else
|
| - {
|
| - /* Non-IEEE or strange limb size, do something generic. */
|
| -
|
| - mp_size_t i;
|
| - mp_limb_t limb, bit;
|
| - int shift;
|
| - double base, factor, prev_factor, d, new_d, diff;
|
| -
|
| - /* "limb" is "up[i]" the limb being examined, "bit" is a mask for the
|
| - bit being examined, initially the highest non-zero bit. */
|
| - i = size-1;
|
| - limb = up[i];
|
| - count_leading_zeros (shift, limb);
|
| - bit = GMP_LIMB_HIGHBIT >> shift;
|
| -
|
| - /* relative to just under high non-zero bit */
|
| - exp -= (shift - GMP_NAIL_BITS) + 1;
|
| -
|
| - /* Power up "factor" to 2^exp, being the value of the "bit" in "limb"
|
| - being examined. */
|
| - base = (exp >= 0 ? 2.0 : 0.5);
|
| - exp = ABS (exp);
|
| - factor = 1.0;
|
| - for (;;)
|
| - {
|
| - if (exp & 1)
|
| - {
|
| - prev_factor = factor;
|
| - factor *= base;
|
| - FORCE_DOUBLE (factor);
|
| - if (factor == 0.0)
|
| - return 0.0; /* underflow */
|
| - if (factor == prev_factor)
|
| - {
|
| - d = factor; /* overflow, apparent infinity */
|
| - goto generic_done;
|
| - }
|
| - }
|
| - exp >>= 1;
|
| - if (exp == 0)
|
| - break;
|
| - base *= base;
|
| - }
|
| -
|
| - /* Add a "factor" for each non-zero bit, working from high to low.
|
| - Stop if any rounding occurs, hence implementing a truncation.
|
| -
|
| - Note no attention is paid to DBL_MANT_DIG, since the effective
|
| - number of bits in the mantissa isn't constant when in denorm range.
|
| - We also encountered an ARM system with apparently somewhat doubtful
|
| - software floats where DBL_MANT_DIG claimed 53 bits but only 32
|
| - actually worked. */
|
| -
|
| - d = factor; /* high bit */
|
| - for (;;)
|
| - {
|
| - factor *= 0.5; /* next bit */
|
| - bit >>= 1;
|
| - if (bit == 0)
|
| - {
|
| - /* next limb, if any */
|
| - i--;
|
| - if (i < 0)
|
| - break;
|
| - limb = up[i];
|
| - bit = GMP_NUMB_HIGHBIT;
|
| - }
|
| -
|
| - if (bit & limb)
|
| - {
|
| - new_d = d + factor;
|
| - FORCE_DOUBLE (new_d);
|
| - diff = new_d - d;
|
| - if (diff != factor)
|
| - break; /* rounding occured, stop now */
|
| - d = new_d;
|
| - }
|
| - }
|
| -
|
| - generic_done:
|
| - return (sign >= 0 ? d : -d);
|
| - }
|
| -#endif
|
| -}
|
|
|