16.1 Integer Internals

mpz_t variables represent integers using sign and magnitude, in space dynamically allocated and reallocated. The fields are as follows.

_mp_size

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 the _mp_d data is undefined.

_mp_d

A pointer to an array of limbs which is the magnitude. These are stored “little endian” as per the mpn functions, so _mp_d[0] is the least significant limb and _mp_d[ABS(_mp_size)-1] is the most significant. Whenever _mp_size is non-zero, the most significant limb is non-zero.

Currently there’s always at least one readable limb, so for instance mpz_get_ui can fetch _mp_d[0] unconditionally (though its value is undefined if _mp_size is zero).

_mp_alloc

_mp_alloc is the number of limbs currently allocated at _mp_d, and normally _mp_alloc >= ABS(_mp_size). When an mpz routine 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 the MPZ_ROINIT_N macro have _mp_alloc = 0 but can have a non-zero _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 routines.

Some internal temporary variables are set up with MPZ_TMP_INIT and these have _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).

_mp_size and _mp_alloc are int, although mp_size_t 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.