I am learning how to use Boost Multiprecision Library. As an exercise, after following the following the Distribution Construction Example, I was able to successfully implement a function that calculates the Negative Binomial PDF with high-precision using the library's built-in high precision decimal floats representation cpp_def_float
:
#include <iostream>
#include <boost/math/distributions/negative_binomial.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
using namespace std;
using namespace boost;
typedef boost::multiprecision::cpp_dec_float_50 myPrecision;
template <class T1, class T2>
myPrecision negbinPDF(T1 passed_val, T2 passed_par1, T2 passed_par2)
{
myPrecision val = myPrecision(passed_val);
myPrecision par1 = myPrecision(passed_par1);
myPrecision par2 = myPrecision(passed_par2);
return math::pdf(math::negative_binomial_distribution<myPrecision>(par1, par2), val);
};
int main()
{
auto p = negbinPDF(1.23456789012345678901234567890, 8.0, 0.25);
cout << "The PDF is: " << p << endl;
}
It works as expected, printing the following output:
The PDF is: 0.0001263
However, I want to change the above code to use the GMP backend. As I understood from here, it would be just a matter of including the proper gmp.hpp
and using the proper GMP float type instead of the cpp_def_flota
. Like the following:
#include <iostream>
#include <boost/math/distributions/negative_binomial.hpp>
#include <boost/multiprecision/gmp.hpp>
using namespace std;
using namespace boost;
typedef boost::multiprecision::number<boost::multiprecision::gmp_float<50>> myPrecision;
// typedef boost::multiprecision::mpf_float_50 myPrecision; // this also raises the errors
template <class T1, class T2>
myPrecision negbinPDF(T1 passed_val, T2 passed_par1, T2 passed_par2)
{
myPrecision val = myPrecision(passed_val);
myPrecision par1 = myPrecision(passed_par1);
myPrecision par2 = myPrecision(passed_par2);
return math::pdf(math::negative_binomial_distribution<myPrecision>(par1, par2), val);
};
int main()
{
auto p = negbinPDF(1.23456789012345678901234567890, 8.0, 0.25);
cout << "The PDF is: " << p << endl;
}
Yet, this does not work, raising the following compiling errors (I display here only the few first; later I link to the full error log):
/tmp/cc6JpzDu.o: In function `boost::multiprecision::backends::detail::gmp_float_imp<50u>::~gmp_float_imp()':
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EED2Ev[_ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EED5Ev]+0x21): undefined reference to `__gmpf_clear'
/tmp/cc6JpzDu.o: In function `boost::multiprecision::backends::gmp_float<50u>::gmp_float()':
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends9gmp_floatILj50EEC2Ev[_ZN5boost14multiprecision8backends9gmp_floatILj50EEC5Ev]+0x31): undefined reference to `__gmpf_init2'
/tmp/cc6JpzDu.o: In function `boost::multiprecision::backends::detail::gmp_float_imp<50u>::str[abi:cxx11](long, std::_Ios_Fmtflags) const':
to_ask_at_SO.cpp:(.text._ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags[_ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags]+0xbe): undefined reference to `__gmp_get_memory_functions'
to_ask_at_SO.cpp:(.text._ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags[_ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags]+0x132): undefined reference to `__gmpf_get_str'
to_ask_at_SO.cpp:(.text._ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags[_ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags]+0x1b3): undefined reference to `__gmpf_get_str'
to_ask_at_SO.cpp:(.text._ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags[_ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags]+0x30f): undefined reference to `__gmpf_get_str'
to_ask_at_SO.cpp:(.text._ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags[_ZNK5boost14multiprecision8backends6detail13gmp_float_impILj50EE3strB5cxx11ElSt13_Ios_Fmtflags]+0x343): undefined reference to `__gmpf_get_str'
/tmp/cc6JpzDu.o: In function `boost::multiprecision::backends::detail::gmp_float_imp<50u>::operator=(double)':
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEaSEd[_ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEaSEd]+0x36): undefined reference to `__gmpf_init2'
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEaSEd[_ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEaSEd]+0x4f): undefined reference to `__gmpf_set_d'
/tmp/cc6JpzDu.o: In function `boost::multiprecision::backends::detail::gmp_float_imp<50u>::gmp_float_imp(boost::multiprecision::backends::detail::gmp_float_imp<50u> const&)':
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEC2ERKS4_[_ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEC5ERKS4_]+0x28): undefined reference to `__gmpf_init2'
to_ask_at_SO.cpp:(.text._ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEC2ERKS4_[_ZN5boost14multiprecision8backends6detail13gmp_float_impILj50EEC5ERKS4_]+0x48): undefined reference to `__gmpf_set'
The full error log can be seen here.
My question is just what am I doing wrong, how could I make this work using the GMP backend? If it helps, I am using Visual Code in a 64bits Ubuntu 18.04 installation.