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