GMP provides methods for initializing and assigning an mpz_t.
A call to mpz_init_set(a, b) will assign to a the content of b. However, I assume, this performs a deep copy on b.
On my project I need to work with arrays of mpz_t that are as long as 5,000,000 (we are talking about 640MB of memory) and the framework I'm using performs various assignment operations on such types (I didn't develop the framework and rewriting it in not an option). Recently, I realized that after most of the assignments the value of b is cleared so it seems unnatural to deep copy a value that can already be used like it is. However, the interface of the framework doesn't allow to do that (uses wrappers around mpz_t's) and it would take a lot of effort to change that (I can still change some basic things).
I have already tried a solution based on a pointer to mpz_class but surprisingly that doesn't give a performance boost at all. In fact it slows down the execution (didn't test on huge arrays though).
My question is: Can I shallow copy an mpz_t? Example given below
class somewrapper
{
mpz_t v;
somewrapper(mpz_t x) //constructor: probably performing deep copy here as well
{
// the following line performs a deep copy(?) on x
// but x is not used. why not shallow copy it?
mpz_init_set(v, x);
}
somefunction() { }
}
Consider that mpz_t
is a struct defined in gmp.h
:
typedef struct
{
int _mp_alloc; /* Number of *limbs* allocated and pointed to by the _mp_d field. */
int _mp_size; /* abs(_mp_size) is the number of limbs the last field points to. If _mp_size is negative this is a negative number. */
mp_limb_t *_mp_d; /* Pointer to the limbs. */
} __mpz_struct;
// ...
typedef __mpz_struct mpz_t[1];
where the GMP developers cast the type as an array of size one because this simplifies passing the type to functions just as if it was a pointer (see here for a fine explanation)
So you can make a shallow copy of an mpz_t
like this:
class somewrapper
{
mpz_t v;
somewrapper(mpz_t x) //constructor: for sure passing the reference
{
// the following line performs a shallow copy
v->_mp_alloc = x->_mp_alloc;
v->_mp_size = x->_mp_size;
v->_mp_d = x->_mp_d;
}
somefunction() { }
}
but note that if you delete the original mpz
before deleting the shallow copy, say using mpz_clear
, then the juice in mp_limb_t *_mp_d
will be gone, and the pointer in the shallow copy will no longer be valid so accessing it may cause trouble.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With