Hello Piranha!

Your first Piranha program

After following the installation instructions, you should be able to compile and run your first C++ Piranha program:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Include the standard I/O header.
#include <iostream>

// Include the global Piranha header.
#include <piranha/piranha.hpp>

// Import the names from the Piranha namespace.
using namespace piranha;

int main()
{
    // Piranha initialisation.
    init();
    // Print the rational number 4/3 to screen.
    std::cout << rational{4, 3} << '\n';
}

Note

The C++ code snippets shown in the tutorial are imported verbatim from the Piranha source tree. You should take care of adjusting the include path of the piranha.hpp header to the correct location on your system before attempting to compile the C++ code samples. On Unix systems, if you installed Piranha in a standard PREFIX, the correct way of including the Piranha header is #include <piranha/piranha.hpp>.

This program will just print to screen the rational number \(\frac{4}{3}\), represented in Piranha by a class called (unsurprisingly) rational. In Unix-like environments, you can compile this simple program with GCC via the command:

$ g++ -std=c++11 hello_piranha.cpp -lmpfr -lgmp

Note however that, since Piranha is a multi-threaded library, it will be likely necessary to link to additional platform-specific threading libraries and/or enable threading-related compiler switches for the compilation to be successful. For instance, on a modern GNU/Linux distribution, the correct switches are:

$ g++ -std=c++11 hello_piranha.cpp -lmpfr -lgmp -lpthread -pthread

A couple of things to note:

  • we pass the -std=c++11 flag to specify that we want to use the C++11 version of the C++ standard for the compilation. Piranha is written in C++11, and this flag is necessary as long as GCC does not default to C++11 mode;
  • we specify via the -lmpfr -lgmp flags that the executable needs to be linked to the GMP and MPFR libraries (if you do not do this, the program will still compile but the final linking will fail due to undefined references);
  • for this simple example, it is not necessary to link to any other library. If, however, Piranha’s serialization capabilities are used, then it will be necessary to link the executable to the Boost Serialization library and to the bzip2 library;
  • Piranha itself is header-only, so there is no -lpiranha to link to.

We also need to point out that for non-debug builds, the NDEBUG macro should be defined:

$ g++ -O2 -DNDEBUG -std=c++11 hello_piranha.cpp -lmpfr -lgmp -lpthread -pthread

If NDEBUG is not defined, a noticeable runtime overhead due to Piranha’s self-checking mechanism will be introduced.

If you installed Piranha in a custom PREFIX, you will need to specify on the command line where the Piranha headers are located via the -I switch. E.g.,

$ g++ -I/home/username/.local/include -std=c++11 hello_piranha.cpp -lmpfr -lgmp -lpthread -pthread

If the GMP and/or MPFR libraries are not installed in a standard path, you can use the -L switch to tell GCC where to look for them:

$ g++ -std=c++11 hello_piranha.cpp -L/custom/library/path -lmpfr -lgmp -lpthread -pthread

After a successful compilation, the executable a.out can be run:

$ ./a.out
4/3

The environment class

As you can see from the C++ code, before starting to use the library we create an environment object called env. The constructor of this object will setup the Piranha runtime environment, performing the registration of cleanup functions to be automatically called when the program finishes, checking that the required libraries were configured correctly, etc.

The creation of an environment object is not mandatory strictly speaking, but it is strongly encouraged and it might become mandatory in the future.

Your first Pyranha program

The Python counterpart of the C++ code is:

1
2
3
4
5
6
7
# Import the standard Fraction class.
from fractions import Fraction
# Import the pyranha module.
import pyranha

# Print the rational 4/3 to screen.
print(Fraction(4, 3))

Two important differencese with respect to the C++ code should be evident.

First of all, in Python we do not need to create any environment object: importing the pyranha module will automatically take care of creating the environment object for us.

Secondly, in Python we do not use the rational class from Piranha, but we use the standard Fraction class from fractions module. Indeed, Pyranha includes code to convert automatically the numerical types implemented in C++ to corresponding types in Python. This means that, for instance, Piranha functions that in C++ return rational will return Fraction in Python, and C++ functions accepting a rational parameter will accept Fraction parameter when called from Python.

The fundamental numerical types implemented in Piranha and their Python counterparts are the subject of the next tutorial chapter.