Ejemplo n.º 1
0
double
mpf_get_d_2exp (signed long *exp2, mpf_srcptr src)
{
  mp_size_t size, abs_size;
  mp_srcptr ptr;
  int cnt;
  signed long exp;

  size = SIZ(src);
  if (UNLIKELY (size == 0))
    {
      *exp2 = 0;
      return 0.0;
    }

  ptr = PTR(src);
  abs_size = ABS (size);
  count_leading_zeros (cnt, ptr[abs_size - 1]);
  cnt -= GMP_NAIL_BITS;

  exp = EXP(src) * GMP_NUMB_BITS - cnt;
  *exp2 = exp;

  return mpn_get_d (ptr, abs_size, size,
                    (long) - (abs_size * GMP_NUMB_BITS - cnt));
}
Ejemplo n.º 2
0
/* ARM gcc 2.95.4 was seen generating bad code for ulong->double
   conversions, resulting in for instance 0x81c25113 incorrectly converted.
   This test exercises that value, to see mpn_get_d has avoided the
   problem.  */
void
check_0x81c25113 (void)
{
#if GMP_NUMB_BITS >= 32
  double     want = 2176995603.0;
  double     got;
  mp_limb_t  np[4];
  mp_size_t  nsize;
  long       exp;

  if (tests_dbl_mant_bits() < 32)
    return;

  for (nsize = 1; nsize <= numberof (np); nsize++)
    {
      refmpn_zero (np, nsize-1);
      np[nsize-1] = CNST_LIMB(0x81c25113);
      exp = - (nsize-1) * GMP_NUMB_BITS;
      got = mpn_get_d (np, nsize, (mp_size_t) 0, exp);
      if (got != want)
        {
          printf  ("mpn_get_d wrong on 2176995603 (0x81c25113)\n");
          printf  ("  nsize  %ld\n", (long) nsize);
          printf  ("  exp    %ld\n", exp);
          d_trace ("  got    ", got);
          d_trace ("  want   ", want);
          abort ();
        }
    }
#endif
}
Ejemplo n.º 3
0
double
mpz_get_d (mpz_srcptr z)
{
    mp_size_t size;

    size = SIZ (z);
    if (UNLIKELY (size == 0))
        return 0.0;

    return mpn_get_d (PTR (z), ABS (size), size, 0L);
}
Ejemplo n.º 4
0
/* Check values 2^n approaching exponent overflow.
   Some systems might trap on overflow, so watch out for SIGFPE.  */
void
check_ieee_overflow (void)
{
  static long exp;
  mp_limb_t  n = 1;
  long       i;
  mp_size_t  sign;
  double     want, got;

  if (! _GMP_IEEE_FLOATS)
    return;

  if (tests_setjmp_sigfpe() == 0)
    {
      exp = 1010;
      want = 1.0;
      for (i = 0; i < exp; i++)
        want *= 2.0;

      for ( ; exp < 1050; exp++)
        {
          for (sign = 0; sign >= -1; sign--)
            {
              got = mpn_get_d (&n, (mp_size_t) 1, sign, exp);
              if (got != want)
                {
                  printf  ("mpn_get_d wrong on overflow\n");
                  printf  ("  n=1\n");
                  printf  ("  exp   %ld\n", exp);
                  printf  ("  sign  %ld\n", (long) sign);
                  d_trace ("  got   ", got);
                  d_trace ("  want  ", want);
                  abort ();
                }
              want = -want;
            }
          want *= 2.0;
          FORCE_DOUBLE (want);
        }
    }
  else
    {
      printf ("Warning, IEEE overflow tests skipped due to SIGFPE (exp=%ld)\n", exp);
    }
  tests_sigfpe_done ();
}
Ejemplo n.º 5
0
/* Check values 2^n approaching and into IEEE denorm range.
   Some systems might not support denorms, or might have traps setup, so
   watch out for SIGFPE.  */
void
check_ieee_denorm (void)
{
  static long exp;
  mp_limb_t  n = 1;
  long       i;
  mp_size_t  sign;
  double     want, got;

  if (! _GMP_IEEE_FLOATS)
    return;

  if (tests_setjmp_sigfpe() == 0)
    {
      exp = -1020;
      want = 1.0;
      for (i = 0; i > exp; i--)
        want *= 0.5;

      for ( ; exp > -1500 && want != 0.0; exp--)
        {
          for (sign = 0; sign >= -1; sign--)
            {
              got = mpn_get_d (&n, (mp_size_t) 1, sign, exp);
              if (got != want)
                {
                  printf  ("mpn_get_d wrong on denorm\n");
                  printf  ("  n=1\n");
                  printf  ("  exp   %ld\n", exp);
                  printf  ("  sign  %ld\n", (long) sign);
                  d_trace ("  got   ", got);
                  d_trace ("  want  ", want);
                  abort ();
                }
              want = -want;
            }
          want *= 0.5;
          FORCE_DOUBLE (want);
        }
    }
  else
    {
      printf ("Warning, IEEE denorm tests skipped due to SIGFPE (exp=%ld)\n", exp);
    }
  tests_sigfpe_done ();
}
Ejemplo n.º 6
0
/* Expect large values to result in +/-inf, on IEEE systems. */
void
check_inf (void)
{
  static const long exp_table[] = {
    999999L, LONG_MAX,
  };
  static const mp_limb_t  np[4] = { 1, 1, 1, 1 };
  long       exp;
  mp_size_t  nsize, sign, got_sign;
  double     got;
  int        exp_i;

  if (! _GMP_IEEE_FLOATS)
    return;

  for (nsize = 1; nsize <= numberof (np); nsize++)
    {
      for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
        {
          exp = exp_table[exp_i];

          for (sign = 0; sign >= -1; sign--)
            {
              got = mpn_get_d (np, nsize, sign, exp);
              got_sign = (got >= 0 ? 0 : -1);
              if (! tests_isinf (got))
                {
                  printf  ("mpn_get_d wrong, didn't get infinity\n");
                bad:
                  printf  ("  nsize    %ld\n", (long) nsize);
                  printf  ("  exp      %ld\n", exp);
                  printf  ("  sign     %ld\n", (long) sign);
                  d_trace ("  got      ", got);
                  printf  ("  got sign %ld\n", (long) got_sign);
                  abort ();
                }
              if (got_sign != sign)
                {
                  printf  ("mpn_get_d wrong sign on infinity\n");
                  goto bad;
                }
            }
        }
    }
}
Ejemplo n.º 7
0
/* Expect large negative exponents to underflow to 0.0.
   Some systems might have hardware traps for such an underflow (though
   usually it's not the default), so watch out for SIGFPE. */
void
check_underflow (void)
{
  static const long exp_table[] = {
    -999999L, LONG_MIN,
  };
  static const mp_limb_t  np[1] = { 1 };

  static long exp;
  mp_size_t  nsize, sign;
  double     got;
  int        exp_i;

  nsize = numberof (np);

  if (tests_setjmp_sigfpe() == 0)
    {
      for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
        {
          exp = exp_table[exp_i];

          for (sign = 0; sign >= -1; sign--)
            {
              got = mpn_get_d (np, nsize, sign, exp);
              if (got != 0.0)
                {
                  printf  ("mpn_get_d wrong, didn't get 0.0 on underflow\n");
                  printf  ("  nsize    %ld\n", (long) nsize);
                  printf  ("  exp      %ld\n", exp);
                  printf  ("  sign     %ld\n", (long) sign);
                  d_trace ("  got      ", got);
                  abort ();
                }
            }
        }
    }
  else
    {
      printf ("Warning, underflow to zero tests skipped due to SIGFPE (exp=%ld)\n", exp);
    }
  tests_sigfpe_done ();
}
Ejemplo n.º 8
0
/* Exercise values 2^n+1, while such a value fits the mantissa of a double. */
void
check_twobit (void)
{
  int        i, mant_bits;
  double     got, want;
  mp_size_t  nsize, sign;
  mp_ptr     np;

  mant_bits = tests_dbl_mant_bits ();
  if (mant_bits == 0)
    return;

  np = refmpn_malloc_limbs (BITS_TO_LIMBS (mant_bits));
  want = 3.0;
  for (i = 1; i < mant_bits; i++)
    {
      nsize = BITS_TO_LIMBS (i+1);
      refmpn_zero (np, nsize);
      np[i/GMP_NUMB_BITS] = CNST_LIMB(1) << (i % GMP_NUMB_BITS);
      np[0] |= 1;

      for (sign = 0; sign >= -1; sign--)
        {
          got = mpn_get_d (np, nsize, sign, 0);
          if (got != want)
            {
              printf    ("mpn_get_d wrong on 2^%d + 1\n", i);
              printf    ("   sign     %ld\n", (long) sign);
              mpn_trace ("   n        ", np, nsize);
              printf    ("   nsize    %ld\n", (long) nsize);
              d_trace   ("   want     ", want);
              d_trace   ("   got      ", got);
              abort();
            }
          want = -want;
        }

      want = 2.0 * want - 1.0;
    }

  free (np);
}
Ejemplo n.º 9
0
double
mpz_get_d_2exp (mpir_si *exp2, mpz_srcptr src)
{
  mp_size_t size, abs_size;
  mp_srcptr ptr;
  int cnt;
  mpir_si exp;

  size = SIZ(src);
  if (UNLIKELY (size == 0))
    {
      *exp2 = 0;
      return 0.0;
    }

  ptr = PTR(src);
  abs_size = ABS(size);
  count_leading_zeros (cnt, ptr[abs_size - 1]);
  exp = abs_size * GMP_NUMB_BITS - (cnt - GMP_NAIL_BITS);
  *exp2 = exp;
  return mpn_get_d (ptr, abs_size, size, -exp);
}
Ejemplo n.º 10
0
/* Exercise various 2^n values, with various exponents and positive and
   negative.  */
void
check_onebit (void)
{
  static const int bit_table[] = {
    0, 1, 2, 3,
    GMP_NUMB_BITS - 2, GMP_NUMB_BITS - 1,
    GMP_NUMB_BITS,
    GMP_NUMB_BITS + 1, GMP_NUMB_BITS + 2,
    2 * GMP_NUMB_BITS - 2, 2 * GMP_NUMB_BITS - 1,
    2 * GMP_NUMB_BITS,
    2 * GMP_NUMB_BITS + 1, 2 * GMP_NUMB_BITS + 2,
    3 * GMP_NUMB_BITS - 2, 3 * GMP_NUMB_BITS - 1,
    3 * GMP_NUMB_BITS,
    3 * GMP_NUMB_BITS + 1, 3 * GMP_NUMB_BITS + 2,
    4 * GMP_NUMB_BITS - 2, 4 * GMP_NUMB_BITS - 1,
    4 * GMP_NUMB_BITS,
    4 * GMP_NUMB_BITS + 1, 4 * GMP_NUMB_BITS + 2,
    5 * GMP_NUMB_BITS - 2, 5 * GMP_NUMB_BITS - 1,
    5 * GMP_NUMB_BITS,
    5 * GMP_NUMB_BITS + 1, 5 * GMP_NUMB_BITS + 2,
    6 * GMP_NUMB_BITS - 2, 6 * GMP_NUMB_BITS - 1,
    6 * GMP_NUMB_BITS,
    6 * GMP_NUMB_BITS + 1, 6 * GMP_NUMB_BITS + 2,
  };
  static const int exp_table[] = {
    0, -100, -10, -1, 1, 10, 100,
  };

  /* FIXME: It'd be better to base this on the float format. */
  int     limit = 511;

  int        bit_i, exp_i, i;
  double     got, want;
  mp_size_t  nsize, sign;
  long       bit, exp, want_bit;
  mp_limb_t  np[20];

  for (bit_i = 0; bit_i < numberof (bit_table); bit_i++)
    {
      bit = bit_table[bit_i];

      nsize = BITS_TO_LIMBS (bit+1);
      refmpn_zero (np, nsize);
      np[bit/GMP_NUMB_BITS] = CNST_LIMB(1) << (bit % GMP_NUMB_BITS);

      for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
        {
          exp = exp_table[exp_i];

          want_bit = bit + exp;
          if (want_bit > limit || want_bit < -limit)
            continue;

          want = 1.0;
          for (i = 0; i < want_bit; i++)
            want *= 2.0;
          for (i = 0; i > want_bit; i--)
            want *= 0.5;

          for (sign = 0; sign >= -1; sign--, want = -want)
            {
              got = mpn_get_d (np, nsize, sign, exp);
              if (got != want)
                {
                  printf    ("mpn_get_d wrong on 2^n\n");
                  printf    ("   bit      %ld\n", bit);
                  printf    ("   exp      %ld\n", exp);
                  printf    ("   want_bit %ld\n", want_bit);
                  printf    ("   sign     %ld\n", (long) sign);
                  mpn_trace ("   n        ", np, nsize);
                  printf    ("   nsize    %ld\n", (long) nsize);
                  d_trace   ("   want     ", want);
                  d_trace   ("   got      ", got);
                  abort();
                }
            }
        }
    }
}
Ejemplo n.º 11
0
void
check_rand (void)
{
  gmp_randstate_t rands;
  int            rep, i;
  unsigned long  mant_bits;
  long           exp, exp_min, exp_max;
  double         got, want, d;
  mp_size_t      nalloc, nsize, sign;
  mp_limb_t      nhigh_mask;
  mp_ptr         np;
  
  gmp_randinit_default(rands);
  
  mant_bits = tests_dbl_mant_bits ();
  if (mant_bits == 0)
    return;

  /* Allow for vax D format with exponent 127 to -128 only.
     FIXME: Do something to probe for a valid exponent range.  */
  exp_min = -100 - mant_bits;
  exp_max =  100 - mant_bits;

  /* space for mant_bits */
  nalloc = BITS_TO_LIMBS (mant_bits);
  np = refmpn_malloc_limbs (nalloc);
  nhigh_mask = MP_LIMB_T_MAX
    >> (GMP_NAIL_BITS + nalloc * GMP_NUMB_BITS - mant_bits);

  for (rep = 0; rep < 200; rep++)
    {
      /* random exp_min to exp_max, inclusive */
      exp = exp_min + (long) gmp_urandomm_ui (rands, exp_max - exp_min + 1);

      /* mant_bits worth of random at np */
      if (rep & 1)
        mpn_randomb (np, rands, nalloc);
      else
        mpn_rrandom (np, rands,nalloc);
      nsize = nalloc;
      np[nsize-1] &= nhigh_mask;
      MPN_NORMALIZE (np, nsize);
      if (nsize == 0)
        continue;

      sign = (mp_size_t) gmp_urandomb_ui (rands, 1L) - 1;

      /* want = {np,nsize}, converting one bit at a time */
      want = 0.0;
      for (i = 0, d = 1.0; i < mant_bits; i++, d *= 2.0)
        if (np[i/GMP_NUMB_BITS] & (CNST_LIMB(1) << (i%GMP_NUMB_BITS)))
          want += d;
      if (sign < 0)
        want = -want;

      /* want = want * 2^exp */
      for (i = 0; i < exp; i++)
        want *= 2.0;
      for (i = 0; i > exp; i--)
        want *= 0.5;

      got = mpn_get_d (np, nsize, sign, exp);

      if (got != want)
        {
          printf    ("mpn_get_d wrong on random data\n");
          printf    ("   sign     %ld\n", (long) sign);
          mpn_trace ("   n        ", np, nsize);
          printf    ("   nsize    %ld\n", (long) nsize);
          printf    ("   exp      %ld\n", exp);
          d_trace   ("   want     ", want);
          d_trace   ("   got      ", got);
          abort();
        }
    }

  free (np);
  gmp_randclear(rands);
}
Ejemplo n.º 12
0
double
mpq_get_d (mpq_srcptr src)
{
  double res;
  mp_srcptr np, dp;
  mp_ptr remp, tp;
  mp_size_t nsize = SIZ(NUM(src));
  mp_size_t dsize = SIZ(DEN(src));
  mp_size_t qsize, prospective_qsize, zeros, chop, tsize;
  mp_size_t sign_quotient = nsize;
  long exp;
#define N_QLIMBS (1 + (sizeof (double) + GMP_LIMB_BYTES-1) / GMP_LIMB_BYTES)
  mp_limb_t qarr[N_QLIMBS + 1];
  mp_ptr qp = qarr;
  TMP_DECL;

  ASSERT (dsize > 0);    /* canonical src */

  /* mpn_get_d below requires a non-zero operand */
  if (UNLIKELY (nsize == 0))
    return 0.0;

  TMP_MARK;
  nsize = ABS (nsize);
  dsize = ABS (dsize);
  np = PTR(NUM(src));
  dp = PTR(DEN(src));

  prospective_qsize = nsize - dsize + 1;   /* from using given n,d */
  qsize = N_QLIMBS + 1;                    /* desired qsize */

  zeros = qsize - prospective_qsize;       /* padding n to get qsize */
  exp = (long) -zeros * GMP_NUMB_BITS;     /* relative to low of qp */

  chop = MAX (-zeros, 0);                  /* negative zeros means shorten n */
  np += chop;
  nsize -= chop;
  zeros += chop;                           /* now zeros >= 0 */

  tsize = nsize + zeros;                   /* size for possible copy of n */

  if (WANT_TMP_DEBUG)
    {
      /* separate blocks, for malloc debugging */
      remp = TMP_ALLOC_LIMBS (dsize);
      tp = (zeros > 0 ? TMP_ALLOC_LIMBS (tsize) : NULL);
    }
  else
    {
      /* one block with conditionalized size, for efficiency */
      remp = TMP_ALLOC_LIMBS (dsize + (zeros > 0 ? tsize : 0));
      tp = remp + dsize;
    }

  /* zero extend n into temporary space, if necessary */
  if (zeros > 0)
    {
      MPN_ZERO (tp, zeros);
      MPN_COPY (tp+zeros, np, nsize);
      np = tp;
      nsize = tsize;
    }

  ASSERT (qsize == nsize - dsize + 1);
  mpn_tdiv_qr (qp, remp, (mp_size_t) 0, np, nsize, dp, dsize);

  /* strip possible zero high limb */
  qsize -= (qp[qsize-1] == 0);

  res = mpn_get_d (qp, qsize, sign_quotient, exp);
  TMP_FREE;
  return res;
}