mini-gmp mpz_{get,set}_d not fully compatible with GMP

Marco Bodrato bodrato at mail.dm.unipi.it
Sat Mar 10 22:41:09 UTC 2018


Ciao,

Il Mar, 6 Marzo 2018 11:58 pm, Marc Glisse ha scritto:
> It is also possible to determine it at runtime (comparing 2^n+{0,1,2} for
> instance should work whether we round up, down or to the nearest;
> tests/misc.c compares 2^n+1-2^n to 1, which also looks good), doing it

Well, stealing the tests_dbl_mant_bits code from tests-misc.c, I wrote the
following code for mini-gmp. It seams to work...

Comments?

-----8<----------8<----
static unsigned int
gmp_tests_dbl_mant_bits (void)
{
  unsigned int n;
  volatile double x, y, d;

  n = 1;
  x = d = 1.0;
  do {
    x *= 2.0;
    y = x + d;
    d = y - x;
  } while (d == 1.0 && ++n < sizeof(double) * CHAR_BIT);

  return n;
}

double
mpz_get_d (const mpz_t u)
{
  static unsigned int c = 0;
  int m;
  mp_limb_t l;
  mp_size_t un;
  double x;
  double B = 2.0 * (double) GMP_LIMB_HIGHBIT;

  un = GMP_ABS (u->_mp_size);

  if (un == 0)
    return 0.0;

  if (c == 0)
    c = gmp_tests_dbl_mant_bits ();

  l = u->_mp_d[--un];
  gmp_clz (m, l);
  m = m + c - GMP_LIMB_BITS;
  if (m < 0)
    l &= GMP_LIMB_MAX << -m;

  for (x = l; --un >= 0;)
    {
      x = B*x;
      if (m > 0) {
	l = u->_mp_d[un];
	m -= GMP_LIMB_BITS;
	if (m < 0)
	  l &= GMP_LIMB_MAX << -m;
	x += l;
      }
    }

  if (u->_mp_size < 0)
    x = -x;

  return x;
}
-----8<----------8<----


Ĝis,
m

-- 
http://bodrato.it/



More information about the gmp-devel mailing list