GMP Integers and Math

Continuing from last week’s Lesson, just as you can’t use the equal sign to assign an mpz_t huge integer value, you can’t use the standard arithmetic operators to do math — huge math. Nope, you must use special GMP library functions to do the math.

Addition is where math teaching begins, probably because a 5-year-old quickly understands the concept of “more.” The function is mpz_add(), which has three arguments:

  • The result
  • Value 1
  • Value 2

All arguments are initialized mpz_t values, which makes this function the equivalent of:

The result = Value 1 + Value 2;

Here’s some code:

2022_10_15-Lesson-a.c

#include <gmp.h>

int main()
{
    mpz_t a,b,x;

    /* initialize */
    mpz_init(a);
    mpz_init(b);
    mpz_init(x);

    /* set values */
    mpz_set_ui(a,3000000000);    /* three billion */
    mpz_set_ui(b,5000000000);    /* five billion */

    /* add the values */
    mpz_add(x,a,b);
    /* output */
    gmp_printf("%Zd + %Zd = %Zd\n",a,b,x);

    return(0);
}

Variables a, b, and x are declared at Line 5. These values are initialized at Lines 8 through 10, which sets their values to zero and allows them to be used in further functions. If you attempt to use an uninitialized value, the program may barf as the pointers in the mpz_t structure are uninitialized.

Values for variables a and b are assigned at Lines 13 and 14.

The math happens at Line 17 with the mpz_add() function. Values a and b are added, with the result stored in variable x. Line 19 uses the gmp_printf() function to output the results:

3000000000 + 5000000000 = 8000000000

(Remember to add the -lgmp switch when compiling at the command line to link in the GMP library.)

Now you know that three billion plus five billion equals eight billion. Of course, with the GMP library you can use much larger values: Modify the code on your own and wear out the zero key on the keyboard to see how humongous the values get.

Multiplication is handled by the mzp_addmul() function. Its arguments are the same as for mpz_add(), though the second and third arguments are multiplied and stored in the first argument.

To update the existing code, I added the following lines before the return statement:

    /* multiply */
    mpz_addmul(x,a,b);
    /* output */
    gmp_printf("%Zd * %Zd = %Zd\n",a,b,x);

The mpz_addmul() function performs multiplication, storing the result in re-used variable x. The gmp_printf() statement outputs the results.

Here’s a sample run, which also includes output from the original code:

3000000000 + 5000000000 = 8000000000
3000000000 * 5000000000 = 15000000008000000000

While three billion times five billion is equal to 15 quintillion, I hope you spied the digit 8 in the result. This value is left over from the first calculation, stored in variable x. Unlike standard integer datatypes, you must always initialize a mpz_t variable before it’s used. In this code, variable x — already assigned the value eight billion — is re-used. Therefore the bits in the value aren’t reset for the new calculation.

To fix the problem, you must add an mpz_init() function before the mpz_addmul() function:

mpz_init(x);

Once re-initialized (to zero), the output is correct:

3000000000 + 5000000000 = 8000000000
3000000000 * 5000000000 = 15000000000000000000

Click here to see the full, correct code on GitHub.

You can explore the rest of the math functions on your own, as they’re referenced in the online manual (API). Have fun with the ha-yuge integers.

Leave a Reply