Streamlining Big Number Calculations in C using GMP
Published: 2023-07-29 11:01:29

Nowadays, technologies like Cryptography need computers to compute complex mathematical operations. These algorithms need the CPU to perform arithmetic operations on large numbers with high precision.

The amount of data a processor can execute at once depends on its number of virtual memory addresses. The maximum integer representation a 32-bit processor can work with is 4,294,967,295 (2^32 − 1), while for a 64-bit processor is 18,446,744,073,709,551,615 (2^64 − 1). These bit constraints affect C standard integer and float data types.

Most high-level languages, like Python, allows programmers to work with larger numbers. Allowing programmers to write programs for processing numbers larger than what the CPU can handle. It's possible to write programs for calculating big numbers in C, but it can get very complex and confusing.

GMP, GNU Multiple Precision Arithmetic Library, streamlines the complexity of working with big numbers in C. This article covers how you can use the GMP Library to perform basic mathematical operations on various kinds of numbers.

## Prerequisites

To follow this article, you need to have;

- A basic understanding of C,
- GCC installed - for compiling C programs,
- Basic understanding of GCC,
- Access to the internet - for installing GMP, and
- A text editor was installed.


## What is GMP?

GMP is a free library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating-point numbers. There is no practical limit to the precision except the ones implied by the available memory in the machine GMP runs on. GMP has a rich set of functions, and the functions have a regular interface. - gmplib.org

GMP allows you to calculate big numbers of many kinds with high precision. It represents numbers in its program as strings.


## Installing GMP

To install GMP library, you can follow this informative guide. It explains how you can download, configure and build the library on Window, Mac and Linux. 

## Performing Arithmetical Operations Using GMP

After installing the library, you need to include the GMP header file in your program to use the library for calculations. 

### Addition

For adding two integers, you need to declare and initialize the variables in a special way before calculations.

Include GMP library header. This allows you to access the types and macros declared in the header file.

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

Declare and initialize the variables for the result, and the numbers to add together.

```c
mpz_t res, num_a, num_b;
    
/* Initializing integers */
mpz_init(res), mpz_init(num_a), mpz_init(num_b);
```

Initializing the variables using `mpz_init` function tells GMP to allocate memory space to the variables. Then you can assign any large number to the initialized variables.

The lines below assigns `3479349783486297692763769376273723897236` to `num_a` and `9223372036854775807` to `num_b`. There is no limit to the amount of precision you get when using GMP for calculations.

```c
/* Assigning integers */
mpz_set_str(num_a, "3479349783486297692763769376273723897236", 10);
mpz_set_str(num_b, "9223372036854775807", 10);
```

The `mpz_set_str` function takes the first argument as the variable to assign a value. The second argument is the string representation of the integer you want to assign. The third argument represents the base of the integer (which, in this case, is the second argument). In the above example, the integers are in base 10, meaning decimal numbers. 

Now you can add the number together using the `mpz_add` function from the GMP library. The function sets `res` to `num_a + num_b`. Then you can use `gmp_printf` to print the values. It works like C standard library printf function. The only difference is that `gmp_printf` allows you to format larger numbers. The `%Zd` flag in the format string for `gmp_printf` is to format large integers.

```c
/* Addition */
mpz_add(res, num_a, num_b);
gmp_printf("Addition:\n%Zd + %Zd = %Zd\n\n", num_a, num_b, res);
```

Now you need to clear the variables. Clearing the variables frees the memory allocated for the variables.

```c
/* Clearing memory */
mpz_clear(res), mpz_clear(num_a), mpz_clear(num_b);
```

The full program should look like this.

```c
// main.c
    
#include <gmp.h>
    
int main(void)
{
    mpz_t res, num_a, num_b;
    
    /* Initializing integers */
    mpz_init(res), mpz_init(num_a), mpz_init(num_b);
    
    /* Assigning integers */
    mpz_set_str(num_a, "3479349783486297692763769376273723897236", 10);
    mpz_set_str(num_b, "9223372036854775807", 10);
    
    /* Addition */
    mpz_add(res, num_a, num_b);
    gmp_printf("Addition:\n%Zd + %Zd = %Zd\n\n", num_a, num_b, res);
    
    /* Clearing memory */
    mpz_clear(res), mpz_clear(num_a), mpz_clear(num_b);
    
    return (0);
}
```

You need to link the GMP library when compiling your program. You can only link the dynamic or static library if you have installed GMP on your machine. If you haven’t, go back to the installation section above.

Run the command below to build your program. The `-lgmp` flag tells gcc to search for the GMP library when linking. GCC will search the list of standard directories to find the library.

```bash
gcc main.c -o main -lgmp
```

If it could not find the gmp library on your machine. Try with the build flags below. The `-L~/gmp-6.2.1/.libs` flag tells gcc to also check the `~/gmp-6.2.1/.libs` directory if it could not find the library using the standard list. For you, this path is the location you installed GMP.

```bash
gcc main.c -o main -L~/gmp-6.2.1/.libs -lgmp -static
```

That covers how you can add large numbers in C and build your program.

### Subtraction

You can use the `mpz_sub` function from the GMP library to substract large numbers. Ensure you initialize the variables and assign their integers respectively.

This subtracts `num_b` from `num_a` and assigns the result to `res`.

```c
/* Subtraction */
mpz_sub(res, num_b, num_a);
gmp_printf("Substraction:\n%Zd - %Zd = %Zd\n\n", num_a, num_b, res);
```

Your full program might look like this.

```c
// main.c
    
#include <gmp.h>
    
int main(void)
{
    mpz_t res, num_a, num_b;
    
    /* Initializing integers */
    mpz_init(res), mpz_init(num_a), mpz_init(num_b);
    
    /* Assigning integers */
    mpz_set_str(num_a, "3434234245245245252452452452", 10);
    mpz_set_str(num_b, "9999943444444434344444444434232323232322", 10);
    
    /* Subtraction */
    mpz_sub(res, num_a, num_b);
    gmp_printf("Substraction:\n%Zd - %Zd = %Zd\n\n", num_a, num_b, res);
    
    /* Clearing memory */
    mpz_clear(res), mpz_clear(num_a), mpz_clear(num_b);
    
    return (0);
}
```

### Multiplication

For multiplying integers, use `mpz_mul` function from the GMP library.

This multiplies `num_a` and `num_b` and assigns result to `res`. 

```c
/* Multiplication */
mpz_mul(res, num_a, num_b);
gmp_printf("Multiplication:\n%Zd x %Zd = %Zd\n\n", num_a, num_b, res);
```

### Division

For division, things will look a little different. Instead of using the type `mpz_t` to declare integers as you have seen before, you will use `mpf_t` instead to declare floats.

To divide large numbers using GMP you need to declare and initialize floats and not integers.

```c
mpf_t div_res, div_a, div_b;
```

Then you initialize the variables using `mpf_init`.

```c
/* Initializing floats */
mpf_init(div_res), mpf_init(div_a), mpf_init(div_b);
```

Assign values you want to the variables. They can be as large as needed. The last argument to `mpf_set_str` tells GMP that the string is in a decimal format.

```c
/* Assign floats */
mpf_set_str(div_a, "7347973477376467734.34322335550000000000", 10);
mpf_set_str(div_b, "489384838948848.4783873847", 10);
```

Divide and print out the results using the functions below. The GMP function `mpf_div` divides `div_a` by `div_b` and assigns the result to `div_res`. Then prints out the formatted string.

```c
/* Division */
mpf_div(div_res, div_a, div_b);
gmp_printf("Division:\n%Ff / %Ff = %Ff\n\n", div_a, div_b, div_res);
```


Your final code should look like this.

```c
// main.c
    
#include <gmp.h>
    
int main(void)
{
    mpf_t div_res, div_a, div_b;
    
    /* Initializing floats */
    mpf_init(div_res), mpf_init(div_a), mpf_init(div_b);
    
    /* Assign floats */
    mpf_set_str(div_a, "7347973477376467734.34322335550000000000", 10);
    mpf_set_str(div_b, "489384838948848.4783873847", 10);
    
    /* Division */
    mpf_div(div_res, div_a, div_b);
    gmp_printf("Division:\n%Ff / %Ff = %Ff\n\n", div_a, div_b, div_res);
    
    /* Clearing memory */
    mpf_clear(div_res), mpf_clear(div_a), mpf_clear(div_b);
    
    return (0);
}
```

### Square root

Ensure you declare and initialize the float variables. Then calculate the square root of that variable using `mpf_sqrt` function. This function only accepts two arguments. The variable to square root and the variable to assign the result.

```c
/* Squre root */
mpf_sqrt(div_res, div_a);
gmp_printf("Square root:\nsqrt(%Ff) = %Ff\n", div_a, div_res);
```


## Conclusion

You can perform other arithmetical operations that are not covered in this article using GMP. Check out the resources section below for their documentation to learn more. It covers how you can perform more Arithmetical operations with Logical and Bitwise operations. Also you can calculate using C int types and rational numbers.

Use the resources provided below to learn more about working with big numbers in C using the GMP library. If you are looking for a challenge try writing a C function to add two large numbers.

Thanks for reading this article. 😊


## Resources

- Linking libraries using GCC Compiler - https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
- Installing GMP from the official website - https://gmplib.org/#DOWNLOAD
- Guide to installing GMP on any machine - http://rstudio-pubs-static.s3.amazonaws.com/493124_a46782f9253a4b8193595b6b2a037d58.html