Bitwise logic gmpxx.h problems

Torbjorn Granlund tg at swox.com
Tue Jul 29 00:37:47 CEST 2008


Marc Glisse <marc.glisse at normalesup.org> writes:

  __gmp_expr<T, T> temp(expr.val);
  Op::eval(p, temp.__get_mp());
  
  I believe it could be safely replaced by:
  
  expr.val.eval(p);
  Op::eval(p,p);
  
This is greek to me, but if you say the latter is better, I believe
you.  :-)

  It would also be interesting to make statistics about how often a typical 
  gmpxx program calls mpz_set(x,y) with x==y.
  
That's bad, and should really be avoided.

If you or somebody else C++ speaker can improve gmpxx.h, then that
would be a nice contribution to GMP.

  Begin most useless rant paragraphs:
  
  I was surprised to see that the allocation policy choice in gmp is at the 
  level of the malloc/realloc/free functions. This means that if for 
  instance I want a policy like "never allocate less than two limbs" for 
  mpz_t, the best I can do is apparently to have the malloc replacement 
  allocate more than asked and the realloc replacement do nothing if the new 
  size asked is still smaller than already allocated. It would have been 
  nicer if I could have made the mpz_t aware of the size actually allocated 
  to it. Looks like one of the "bright ideas" in the tasks.
  
The mpz->_mp_alloc field is "aware" of the allocation.  Or what do you
mean?

  > // Max allocations for plain types when converted to mpz_t
  > // FIXME: how do we get the proper max "double" exponent?
  
  I would say DBL_MAX_EXP (from <float.h>) in C and 
  std::numeric_limits<double>::max_exponent (from <limits>) in C++ if I 
  understand the question.

OK, I'll use the terse C++'y std::numeric_limits<double>::max_exponent.
  
  > #define __GMP_DBL_LIMBS (2 + (1025 - 1) / GMP_NUMB_BITS)
  
  I had never realized double could only represent such small integers that 
  they can be allocated on the stack (I thought this trick would be used 
  only for signed/unsigned long, and for initialization of a mpf by a 
  double).
  
I suppose the only IEEE double value that does not fit on an integer
on the stack is Inf.  :-)

  > #define __GMP_ULI_LIMBS (1 + (8 * sizeof (long) - 1) / GMP_NUMB_BITS)
  >
  > #define __GMPXX_LOGOP_UI(OP)						\
  
  The name of the macro does not reflect the fact that it is for mpz only 
  (not mpq, which could get a similar macro later).
  
I'll leave it with a non-optimal name for now, we can clean it up when
we apply these macros more widely.

  >  mpz_t temp;								\
  >  mp_limb_t limbs[__GMP_ULI_LIMBS];					\
  >  temp->_mp_d = limbs;							\
  >  temp->_mp_alloc = __GMP_ULI_LIMBS;					\
  >  mpz_set_ui (temp, l);						\
  >  mpz_##OP (z, w, temp)
  
  I thought you could leave the OP part out of the macro, make the macro 
  only provide a temp for use by the calling code. If I want to reuse this 
  one for sub(unsigned,mpz) I need to call sub(mpz,unsigned) and then neg. 
  For division it does not work. Though if the permutation of the arguments 
  is the only issue it would be pretty easy to provide a second macro for 
  this.
  
OK, I made removed OP.

  The original macros I thought of were:
  (leaving out the trailing \, they are inconvenient in the mail)
  
  #define MPZ_INIT2_STACK(temp,N)
  mp_limb_t limbs[N];
  temp->_mp_d=limbs;
  temp->_mp_alloc=N
  
  #define MPZ_CLEAR_STACK(temp) /* do nothing */
  
  with versions:
  
  #define MPZ_INIT_SET_UI_STACK(temp,l)
  MPZ_INIT2_STACK(temp,__GMP_ULI_LIMBS);
  mpz_set_ui(temp,l)
  
  modelled after the regular mpz_init2 and mpz_init_set_ui. I even left the 
  mpz_t declaration out of it so a #define MPZ_INIT2_STACK mpz_init2 (and 
  similarly for mpz_clear) would work.
  
  I don't know what is best. Anyway I believe these macros are not 
  interfaces so they can be changed in the next release.
  
I tend to spend less design effort on internal interfaces than
external ones...

  Aren't you missing the macro change to make operators like &= work? I 
  think it was just a PP->P and ZZ->Z to make it mimic operator+=.
  
No, I am not missing those.  They're already in.
  
  While I am writing an email, I might as well add a clean-up. In gmp.h, 
  there is:
  
  #define __need_size_t  /* tell gcc stddef.h we only want size_t */
  #if defined (__cplusplus)
  #include <cstddef>     /* for size_t */
  #else
  #include <stddef.h>    /* for size_t */
  #endif
  #undef __need_size_t
  
  It should be changed to:
  
  #if defined (__cplusplus)
  #include <cstddef>     /* for size_t */
  #else
  #define __need_size_t  /* tell gcc stddef.h we only want size_t */
  #include <stddef.h>    /* for size_t */
  #undef __need_size_t
  #endif
  
I suppose that __need_size_t stuff should be removed altogether.

I put the current gmpxx.h at <http://gmplib.org/devel/gmpxx.h>.

-- 
Torbjörn


More information about the gmp-bugs mailing list