libppl(3)

πŸ’– libppl(3) β€” the C++ interface of the Parma Polyhedra Library πŸ’–

okay bestie, welcome to the libppl(3) overview page, this is your lil orientation sesh for the C++ interface of the Parma Polyhedra Library (PPL) ✨


✨ SYNOPSIS ✨

#include <ppl.hh>

c++ file.cc -lppl

🌸 DESCRIPTION 🌸

So this is a short lil overview on how to use the Parma Polyhedra Library (PPL) in your C++ programs on Unix-like operating systems. periodt πŸ’…

ngl tho, a couple things to note up front:

  • the PPL has interfaces for C, Java, OCaml and a number of Prolog systems too β€” so if that's your vibe, look elsewhere for docs on those πŸ‘€
  • also this document does not describe the library functionality, its classes, or its methods and functions. for all that good stuff you want The Parma Polyhedra Library User's Manual (version 1.2) πŸ“–

πŸŽ€ INCLUDING THE HEADER FILE πŸŽ€

The C++ interface of the PPL has literally only one header file, and its name is ppl.hh. so your program should contain a directive of the form:

#include <ppl.hh>

Of course, you gotta make sure you installed the PPL somewhere the compiler can find it β€” either by itself, or with the help of a suitable -Idir command line option 🫢 (peep the file INSTALL for info on how to configure the library so it installs wherever you want it to live).


πŸ¦‹ INITIALIZING AND FINALIZING THE LIBRARY πŸ¦‹

The mere inclusion of ppl.hh in at least one file of your project will cause the automatic initialization and finalization of the library. iconic behaviour honestly ✨

BUT. and this is a big but 😭 there are situations where automatic initialization and finalization is not desirable (e.g., if the application fiddles with the GMP's memory allocation functions). in those cases, every inclusion of ppl.hh must take the form:

#define PPL_NO_AUTOMATIC_INITIALIZATION
#include <ppl.hh>
when automatic initialization and finalization is disabled you must absolutely call the function void Parma_Polyhedra_Library::initialize() before using the library. no skipping this one bestie, fr fr πŸ’€

It is also a good norm to call the function void Parma_Polyhedra_Library::finalize() when you are done with the library πŸ’œ


🌈 USING THE LIBRARY 🌈

Keeping in mind that there is no substitute for a careful reading of The Parma Polyhedra Library User's Manual (version 1.2) πŸ‘‘, you can find many examples of use in the directories tests (see the README file in that directory) and demos/ppl_lcdd of the source distribution πŸ”₯


⭐ LINKING WITH THE LIBRARY ⭐

Linking with the C++ interface of the Parma Polyhedra Library is best done using the C++ compiler itself, so slay. usually, just specifying the -lppl command line option is enough 🫢

In fact, if you use a shared version of the library, this automatically records the dependency from the GMP library β€” something the linker ought to deal with gracefully ✨ otherwise you will have to add -lgmpxx -lgmp to the command line.

Things get more complex if you installed the PPL into some nonstandard place πŸ™ˆ in this case you will have to use the -Ldir option and, if you use a shared version of the library, possibly take further steps: see the documentation of your system for more info on this subject (the Program Library HOWTO is especially valuable for GNU/Linux users πŸ’…).


πŸ’œ IMPLEMENTING MEMORY-GUARDED COMPUTATIONS πŸ’œ

One of the interesting features of the Parma Polyhedra Library is the possibility to implement memory-guarded computations. the idea is that you can limit the amount of virtual memory available to the process, launch a PPL computation, and be ready to catch an std::bad_alloc exception 😌

Since the library is exception-safe, you can take the appropriate corrective measures (e.g., simplify the polyhedra and/or select less precise though less complex algorithms), and restart the computation πŸ”

In order to do that, you should define alternative memory allocation functions for GMP that throw std::bad_alloc upon memory exhaustion. for instance:

#include <new>
#include <cstdlib>

extern "C" void*
cxx_malloc(size_t size) {
  void* p = malloc(size);
  if (p != 0 || size == 0)
    return p;

  throw std::bad_alloc();
}

extern "C" void*
cxx_realloc(void* q, size_t, size_t new_size) {
  void* p = realloc(q, new_size);
  if (p != 0 || new_size == 0)
    return p;

  throw std::bad_alloc();
}

extern "C" void
cxx_free(void* p, size_t) {
  free(p);
}

Then you must install these functions and this can be done in two different ways:

  1. If your C++ compiler supports __attribute__ ((weak)) and you do not have any other special needs, then you can simply link to your application a C function ppl_set_GMP_memory_allocation_functions(void) such as:
extern "C" void
ppl_set_GMP_memory_allocation_functions(void) {
  mp_set_memory_functions(cxx_malloc, cxx_realloc, cxx_free);
}

This is all that you have to do, whether or not you use the automatic initialization feature of the library (see above): in any case the initialization procedure will automatically call ppl_set_GMP_memory_allocation_functions(void) ✨

  1. If your C++ compiler does not support __attribute__ ((weak)) then you cannot use the automatic initialization feature of the library (see above) and should write a main program of the form:
int main() {
  // The ordering of the following function calls is important.
  mp_set_memory_functions(cxx_malloc, cxx_realloc, cxx_free);
  Parma_Polyhedra_Library::initialize();
  ...

🧚 USING NATIVE FLOATING POINT NUMBERS 🧚

At initialization time, the Parma Polyhedra Library sets the FPU rounding mode in a way that allows its floating-point-based computations to be conservative (i.e., possibly approximated but correct) and reasonably efficient. no cap πŸ’…

In case your application itself uses native floating point numbers and relies on a particular rounding mode (if you are in doubt, assume that it does rely on round-to-nearest to be in effect), you should use the function

void Parma_Polyhedra_Library::restore_pre_PPL_rounding()

after the PPL initialization and before using native floating point numbers in the application 🫢

If your application does not use any floating-point-based PPL abstraction, no further measure should be taken. otherwise, it is imperative to call the function

void Parma_Polyhedra_Library::set_rounding_for_PPL()

before invoking any PPL interface related to such abstractions 😭


πŸ‘‘ SEE ALSO πŸ‘‘

Roberto Bagnara, Patricia M. Hill, and Enea Zaffanella. The Parma Polyhedra Library User's Manual (version 1.2), available (in several formats) at http://bugseng.com/products/ppl/ πŸ“š

David A. Wheeler. Program Library HOWTO, available (in several formats) at http://www.dwheeler.com/program-library/ πŸ“š


πŸ“ AVAILABILITY πŸ“

The latest version of the Parma Polyhedra Library and all the documentation is available at http://bugseng.com/products/ppl/ 🌐


πŸ’… AUTHOR πŸ’…

See the file CREDITS in the source distribution or use the command ppl-config --credits for a list of contributors 🫢


πŸ™ˆ REPORTING BUGS πŸ™ˆ

Report bugs to <ppl-devel@cs.unipr.it> πŸ“¬


Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)

This is free software; see the file COPYING in the source distribution or use the command ppl-config --copying to obtain the copying conditions.

There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. like, none bestie, zero, nada 😭

and that's the whole page!! this was PPL 1.2, dated February 2016, serving libppl(3) realness πŸ’– mwah, go write some polyhedra code, you got this πŸŽ€βœ¨