A quick way to get up and running is to install the BH
package and use the Boost Multiprecision library, which provides several extended precision floating point types. For example, this code demos the float128
and mpf_float_100
types:
// [[Rcpp::depends(BH)]]
#include <Rcpp.h>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/mpfr.hpp>
namespace mp = boost::multiprecision;
// [[Rcpp::export]]
std::string qexp(double da = -1500.0, double db = -1501.0)
{
mp::float128 a(da), b(db);
mp::float128 res = mp::exp(a) / (mp::exp(a) + mp::exp(b));
return res.convert_to<std::string>();
}
// [[Rcpp::export]]
std::string mpfr_exp(double da = -1500.0, double db = -1501.0)
{
mp::mpf_float_100 a(da), b(db);
mp::mpf_float_100 res = mp::exp(a) / (mp::exp(a) + mp::exp(b));
return res.convert_to<std::string>();
}
The latter requires adding flags for linking to the libmpfr
and libgmp
before compiling; the former does not, as it is a wrapper around GCC's built in __float128
:
Sys.setenv("PKG_LIBS" = "-lmpfr -lgmp")
Rcpp::sourceCpp('/tmp/quadexp.cpp')
qexp()
# [1] "0.731058578630004879251159241821836351"
mpfr_exp()
# [1] "0.731058578630004879251159241821836274365144640165056519276365907919040453070204639387474532075981245292174466493140773"
Comparing to Rmpfr
,
library(Rmpfr)
a <- mpfr(-1500, 100)
b <- mpfr(-1501, 100)
exp(a) / (exp(a) + exp(b))
# 1 'mpfr' number of precision 100 bits
# [1] 7.3105857863000487925115924182206e-1