mpz_t variables represent integers using sign and magnitude, in space
dynamically allocated and reallocated. The fields are as follows.
The number of limbs, or the negative of that when representing a negative
integer. Zero is represented by
_mp_size set to zero, in which case
_mp_d data is undefined.
A pointer to an array of limbs which is the magnitude. These are stored
“little endian” as per the
mpn functions, so
_mp_d is the
least significant limb and
_mp_d[ABS(_mp_size)-1] is the most
_mp_size is non-zero, the most significant limb
Currently there’s always at least one readable limb, so for instance
mpz_get_ui can fetch
_mp_d unconditionally (though its value
is undefined if
_mp_size is zero).
_mp_alloc is the number of limbs currently allocated at
_mp_alloc >= ABS(_mp_size). When an
is about to (or might be about to) increase
_mp_size, it checks
_mp_alloc to see whether there’s enough space, and reallocates if not.
MPZ_REALLOC is generally used for this.
mpz_t variables initialised with the
mpz_roinit_n function or
MPZ_ROINIT_N macro have
_mp_alloc = 0 but can have a
_mp_size. They can only be used as read-only constants. See
Special Functions for details.
The various bitwise logical functions like
mpz_and behave as if
negative values were two’s complement. But sign and magnitude is always used
internally, and necessary adjustments are made during the calculations.
Sometimes this isn’t pretty, but sign and magnitude are best for other
Some internal temporary variables are set up with
MPZ_TMP_INIT and these
_mp_d space obtained from
TMP_ALLOC rather than the memory
allocation functions. Care is taken to ensure that these are big enough that
no reallocation is necessary (since it would have unpredictable consequences).
is usually a
long. This is done to make the fields just 32 bits on
some 64 bits systems, thereby saving a few bytes of data space but still
providing plenty of range.