February 7, 2016 | Article | No Comments

GMP (GNU Multi Precision) Library is one of vital library in GNU infrastructure. It is a popular library which gives flexibility to operate abritrary precision integers, rationals, and floating point numbers. There are also MPFR (Multi Precision Floating-point Reliably) and MPC (Multi Precision Complex) which are extension to to GMP capability for precision in computation.

In this article we will try to code using GMP, with C, on Linux 64-bit.

## Installation

Check whether our box has GMP library.

`locate libgmp.a`

If GMP is installed already, we will get entry. If not, proceed to GMP site to download and install the library. Just do usual Linux installation procedure.

## Getting Start

Before we start, let’s talking about the arbritrary precision. Do we need it? or why do we need it?

Program constitute of two element: algorithm and data. Data is represented by variable, which has size on memory. The size is fix, according to the word size of processor register. To simplify it, computer process numbers in multiple of 2: 8, 16, 32, or 64 bits at a time. For example, if we declare an int variable x, it will have 32 bit size.

Let’s discover by writing little code.

```#include <stdio.h>
#include <limits.h>

void printbin(int x)
{
if (x==0)
return;
else
{
printbin(x>>1);
if (x&1)
printf("1");
else
printf("0");

}
}

int main() {
int k, x, i;
char c;

/* 1. Print machine native size and the max/min integer */
printf("sizeof(int) = %d bits\n", sizeof(int) * 8);
printf("max(int)    = %d\n", INT_MAX);
printf("min(int)    = %d\n", INT_MIN);

/* 2. Try to overflow */
k = INT_MAX;
printf("%d + 1 = %d\n", k, k+1);

/* 3. See the representation of variable */
printf("Enter x: ");
scanf("%d", &x);
printf("x in binary = ");
printbin(x);
printf("\n");

return 0;
}```

sizeof(int) gives the number of bytes for integer and INT_MAX is a macro defined in limits.h which inform the largest possible integer. INT_MIN is just the opposite of it.

This is the result in my box. See the range, -2147483648 (min) to 2147483647 is the valid value of 32-bits integer. If we increment x which hold maximum value it will overflow to negative.

## Enter GMP!

Now let’s dive to the GMP. GMP allows us to use integers whose sizes can grow dynamically to the required precision. Imagine it as BigNum, close to. It can support 128, 256, or 1024 bits. There is no need for us to specify this, the library does to dirt. GMP will dynamically allocate memory to accommodate extra bits of precision as we need.

Let’s try it with simple code.

```#include <gmp.h>
#include <stdio.h>

int main()
{
char inputStr;

/* type for GMP integers.
We don't care about the internal representation
*/
mpz_t n;
int flag;

scanf("%1024s" , inputStr);

/* 1. Initialize the number */
mpz_init(n);
mpz_set_ui(n,0);

/* 2. Parse the input string as a base 10 number */
flag = mpz_set_str(n,inputStr, 10);
if (flag == 0)
{
printf("Fail");
return -1;
}

printf ("n = ");
mpz_out_str(stdout,10,n);
printf ("\n");

/* 3. Add one to the number */
mpz_add_ui(n,n,1); /* n = n + 1 */

/* 4. Print the result */
printf (" n +1 = ");
mpz_out_str(stdout,10,n);
printf ("\n");

/* 5. Square n+1 */
mpz_mul(n,n,n); /* n = n * n */
printf (" (n +1)^2 = ");
mpz_out_str(stdout,10,n);
printf ("\n");

/* 6. Clean up the mpz_t handles or else we will leak memory */
mpz_clear(n);

return 0;
}```

Remember to include library libgmp.a so GCC won’t complaint. Here is the result: The complete information is always on GMP manual. But we love simplicity. So here we go.

At minimum we need this skeleton to use GMP.

```#include <gmp.h>

/* ... */

mpz_t n;
mpz_init(n);

/* ... */

mpz_set_ui(n,0);

/* ... */

mpz_clear(n);```

Now let’s make something out of it. Say, factorial program?

```#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>

/* Use iterative solution here. */
void factorial(int n)
{
int i;
mpz_t p;

mpz_init_set_ui(p, 1);      /* p = 1 */
for (i=1; i<= n; i++)
mpz_mul_ui(p, p, i);    /* p = p * 1 */

printf("%d! = ", n);
mpz_out_str(stdout, 10, p);
printf("\n");
mpz_clear(p);
}

int main()
{
int n;

do {
printf("N = ");
scanf("%d", &n);

if (n <= 1)
{
printf("N should be > 1\n");
printf("Leaving...\n");
break;
}

factorial(n);
} while (1);
return 0;
}```

Try it! 