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

Niels Möller nisse at
Sat Mar 10 23:15:37 UTC 2018

"Marco Bodrato" <bodrato at> writes:

> double
> mpz_get_d (const mpz_t u)
> {
>   static unsigned int c = 0;
>   int m;

I'd prefer more descriptive names for c and m.

>   if (c == 0)
>     c = gmp_tests_dbl_mant_bits ();
This is *almost* thread-safe. If two threads race in calling this
function for the first time, it should still work provided that access
to c is atomic (it doesn't matter if gmp_tests_dbl_mant_bits is called
twice, producing the same result). That's probably the case on most
platforms, but not entirely kosher. It would break if the first thread
writes c, and the second threads reads a non-zero value of c with a mix
of the old value (zero) and the new value.

I know recent c++ defines the meaning of a static initializer like

  static unsigned int c = gmp_tests_dbl_mant_bits ();

so that the initializer is evaluated exactly once, after the first entry
to the function, but before any thread uses the value (likely generating
code using pthread_once). Has anything like that made it into recent C

If we could use float.h constants, we wouldn't need to worry.

>   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;
>       }
>     }

Maybe rearrange loop so that 

   if (m < 0)
     l &= GMP_LIMB_MAX << -m;
   x += l;

is done after the loop, and not repeated prior to the loop?


Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.

More information about the gmp-devel mailing list