Sunday, June 12, 2011

C++ BigIntegers: Installing a static GMP library with the C++ class extensions (gmpxx.h)


GMP Logo
So I was spending some time with GMP today, trying to install it on my Ubunty Natty (11.04). [1] I wanted to finally get BigInteger support for C/C++ in a hassle free manner. Naturally, I turned to my trusty Synaptic to get and install the libraries. A quick search for libgmp in the repository turned up some old versions of GMP and some modified packages. I was surprized! I was expecting libgmp to be in the Ubuntu repository. A quick Google confirmed that Ubuntu doesn't ship with GMP 5 (which was the latest at the time of this blog post). So I set down to install the library from source. So, first things first:

1) Get the gmp-5.0.2 library (or whatever's the latest now) from http://www.gmplib.org

2) Verify the file using gpg (Always a good practice)
    gpg --verify gmp-5.0.2.tar.bz2.sig gmp-5.0.2.tar.bz2

    You might get an error at this stage saying that the public key is not available. To fix that, issue
    gpg --search-keys <key_id>

    and select the SWOX key from the options you get. The KEY_ID is mentioned right below the download link on the gmplib download page. The gmp-5.0.2.tar.bz2.sig file can be downloaded from the downloads area of the site.

    Alternatively, you could check the SHA-1 or SHA-256 cryptographic checksum by extracting the .tar file from the .tar.bz2 or .tar.gz file and running sha1sum gmp-5.0.2.tar or sha256sum gmp-5.0.2.tar

3) Extract the files from the archive
    tar -xvjf gmp-5.0.2.tar.bz2

4) Follow the installation instructions: Now here's the catch.
     If you follow the standard installation instructions which ask you to follow the 3 step procedure: ./configure , make , sudo make install then you'll end up with only the C library built and installed. I did this and I spent quite a bit of time today messing around with GMP, trying to get it to install the C++ classes for enabling BigInteger support. Unfortunately, Google didn't help in fixing this problem. I couldn't find a thread which mentioned the installation of the C++ extensions. However, reading miscellaneous blog posts on issues with installing GMP, I figured out that the switch to install the C++ extensions is --enable-cxx and it has to be passed to ./configure. It seems obvious in hindsight but was really unobvious when I was figuring out the installation issues. So, here are the correct set of commands that you need to follow to get GMP to install with the C++ extensions.

   ./configure --enable-cxx
   make
   make check
   sudo make install

This will install GMP to your /usr/local/include and /usr/local/lib directories. I prefer this because you can easily remove the files and folders later with minimal system modifications should you so desire. Also, this is the recommended way for non-system installed packages (read install from source packages) to install themselves on a linux system.

5) Verify that GMP has installed correctly

   Create the following 2 programs to test out GMP:
   
test1.c:

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

   int main() {
      mpz_t a, b, c;
      mpz_inits(a, b, c, NULL);
      mpz_set_si(a, rand());
      mpz_set_si(b, rand());
      mpz_add(c, a, b);
      gmp_printf("%Zd + %Zd =  %Zd\n", a, b, c);
      // If you're not quitting, use mpz_clears(a, b, c, NULL)
      return EXIT_SUCCESS;
   }
Compile and test with: gcc test1.c -lgmp -static -o test1 && ./test1

test2.cc:
  
   #include <iostream>
   #include <cstdlib>
   #include <gmpxx.h>
   using namespace std;

   int main() {
       mpz_class a, b, c;
       a = rand();
       b = rand();
       c = a + b;
       cout << a << " + " << b << " = " << c << endl;
       return EXIT_SUCCESS;
   }

Compile and run with: g++ test2.cc -lgmpxx -lgmp -static -o test2 && ./test2

I've added the static flag to compile with the library included in the executable. If you want to use a shared library version of GMP, then omit the -static flag and make sure your LD_LIBRARY_FLAGS variable has /usr/local/lib present in it.


[1] GMP is the GNU Multi Precision computing library (Home page: http://www.gmplib.org) that provides unlimited precision computing support for C and C++. (Actually, the maximum limit of precision is 41 billion digits but by the time you get to that... hmm... you'll probably run out of space). Their code is very optimized and if you *ever* need BigInteger support in C or C++ - that's the way to go.