As a general rule, all GMP functions expect output arguments before input arguments. This notation is based on an analogy with the assignment operator. (The BSD MP compatibility functions disobey this rule, having the output argument(s) last.)
GMP lets you use the same variable for both input and output in one call. For
example, the main function for integer multiplication, mpz_mul
, can be
used to square x
and put the result back in x
with
mpz_mul (x, x, x);
Before you can assign to a GMP variable, you need to initialize it by calling one of the special initialization functions. When you're done with a variable, you need to clear it out, using one of the functions for that purpose. Which function to use depends on the type of variable. See the chapters on integer functions, rational number functions, and floating-point functions for details.
A variable should only be initialized once, or at least cleared out between each initialization. After a variable has been initialized, it may be assigned to any number of times.
For efficiency reasons, avoid initializing and clearing out a GMP variable in a loop. Instead, initialize it before entering the loop, and clear it out after the loop has exited.
GMP variables are small, containing only a couple of sizes, and pointers to allocated data. Once you have initialized a GMP variable, you don't need to worry about space allocation. All functions in GMP automatically allocate additional space when a variable does not already have enough. They do not, however, reduce the space when a smaller value is stored. Most of the time this policy is best, since it avoids frequent re-allocation.
When a variable of type mpz_t
is used as a function parameter, it's
effectively a call-by-reference, meaning anything the function does to it will
be be done to the original in the caller. When a function is going to return
an mpz_t
result, it should provide a separate parameter or parameters
that it sets, like the GMP library functions do. A return
of an
mpz_t
doesn't return the object, only a pointer to it, and this is
almost certainly not what you want. All this applies to mpq_t
and
mpf_t
too.
Here's an example function accepting an mpz_t
parameter, doing a
certain calculation, and returning a result.
void myfunction (mpz_t result, mpz_t param, unsigned long n) { unsigned long i; mpz_mul_ui (result, param, n); for (i = 1; i < n; i++) mpz_add_ui (result, result, i*7); } int main (void) { mpz_t r, n; mpz_init (r); mpz_init_set_str (n, "123456", 0); myfunction (r, n, 20L); mpz_out_str (stdout, 10, r); printf ("\n"); return 0; }
This example will work if result
and param
are the same
variable, just like the library functions. But sometimes this is tricky to
arrange, and an application might not want to bother for its own subroutines.
mpz_t
is actually implemented as a one-element array of a certain
structure type. This is why using it to declare a variable gives an object
with the fields GMP needs, but then using it as a parameter passes a pointer
to the object. Note that the actual contents of an mpz_t
are for
internal use only and you should not access them directly if you want your
code to be compatible with future GMP releases.
Go to the first, previous, next, last section, table of contents.