I'm trying to learn how to use the boost multi precision package with Rcpp. My main problem seems to be with wrapping and returning. If any would could comment on the below code it could be appreciated.
The error I get is "cannot convert const boost::multiprecision::number
// [[Rcpp::depends(BH)]]
#include <Rcpp.h>
#include <boost/multiprecision/cpp_dec_float.hpp>
using boost::multiprecision::cpp_dec_float_100;
// [[Rcpp::export]]
SEXP getBig(int a, int b) {
cpp_dec_float_100 seventh = cpp_dec_float_100(1) / 7;
return Rcpp::wrap(seventh);
}
In order to call Rcpp::wrap(someObject), we need someone to write the actual implementations of wrap() for the type of someObject. Rcpp supplies this for many types, and add-on packages can do so too as we explain on in the "Extending Rcpp" vignette.
Here it would be your job to either create such wrappers for cpp_dec_float_100, or to convert from that type to a type known by Rcpp.
Related
I was prepossessing data in C++ using the Armadillo library. The program end product is a ucube, which is a cube filled with unsigned integers. After its run, I want to load the ucube to R to perform some final statistical tests. To do so, I made a C++ function that load the ucube returning an array.
But it does not work!
I got the following warning: "warning: Cube::load(): incorrect header in B.bin" and the program returns a 0x0x0 array.
Trying to find why, I made a toy C++ program, which works fine. It is able to load the cubes without any problem.
#include <iostream>
#include <armadillo>
using namespace arma;
void read_cubes(char const* A, char const* B){
cube C;
ucube D;
C.load(A, arma_binary);
D.load(B, arma_binary);
}
int main(int argc, char** argv){
cube A = randu<cube>(5,5,5);
ucube B = randi<ucube>(5,5,5, distr_param(1, 10));
A.save(argv[1], arma_binary);
B.save(argv[2], arma_binary);
read_cubes(argv[1], argv[2]);
}
But I do not know why, doing the same steps in R does not work. To illustrate, please run the toy program as ./a.out A.bin B.bin. It will yield the Cube<double> A.bin and the Cube<uword> B.bin, which I will mention later.
The problem
If I source the following C++ code with Rcpp::sourceCpp and I try to read the Cube<double> A.bin with read_cube("A.bin") it works, but if I do the same for the Cube<uword> B.bin with read_ucube("B.bin") it does not (I get the warning).
#include <RcppArmadillo.h>
#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::cube read_cube(char const* x){
arma::cube A;
A.load(x, arma::arma_binary);
return A;
}
// [[Rcpp::export]]
arma::ucube read_ucube(char const* x){
arma::ucube B;
B.load(x, arma::arma_binary);
return B;
}
Of course I could cast the Cube<uword> to a Cube<double> before ending the C++ program, but I would like to know why this happen and if it is possible to load a Cube<uword> in RcppArmadillo. Because it should be possible, right?
Unfortunately R still only supports 32 bit integers, so RcppArmadillo forces Armadillo to use 32 bit integers. This is done by defining ARMA_32BIT_WORD before including the armadillo header. See RcppArmadillo's configuration here.
You can apply the same "trick" with your Armadillo programs like so:
#define ARMA_32BIT_WORD
#include <armadillo>
One of the effects is that ucube (Cube<uword>) will use 32 bit unsigned integers.
After doing the above trick, recompile your Armadillo programs and save the ucubes again. They can then be loaded in RcppArmadillo.
#include <iostream>
#include <math.h>
/*
Boost Lib: https://www.boost.org
added compiler options:
-fext-numeric-literals
*/
#include <boost/multiprecision/float128.hpp>
using namespace boost::multiprecision;
int main(){
float128 x = 34235235.00090912892709;
float128 z = std::exp(x);
std::cout<< z;
return 0;
}
Gives the following error:
error: no matching function for call to ‘exp(boost::multiprecision::float128&)’
Boost should be able to use any C++ std lib function; where is my mistake?
Boost should be able to use any C++ std lib function
That's exactly your mistake. You can cast the float128 type to a double and pass that to std::exp, but as you probably use the multiprecision library for a reason, this might not be a good idea. Instead, call the function provided by boost itself:
const auto z = boost::multiprecision::exp(x);
You might want to omit boost::multiprecision:: and rely upon ADL or the using directive in your example. For this to work, it might be necessary to add the -lquadmath and/or -fext-numeric-literals linker flag (thanks to #JHBonarius for pointing that out).
I have a C++ code that uses endl, vector, complex, and cout occasionally without any namespace qualification. When compiling with GCC 4.9, I get errors like this one:
bfm.h:454:4: error: 'complex' does not name a type
complex<double> inner(Fermion_t x,Fermion_t y);
^
In the very same file, there are lines with an std:: qualifier:
std::complex<Float> dot(Fermion_t x_t, Fermion_t y_t,int sx,int sy);
Throughout the codebase, I saw the following template specializations used
std::complex<double>
std::complex<cFloat>
complex<Float>
complex<double>
complex<T>
complex<S>.
Neither for the regular express struct\s+complex nor class\s+complex I managed to find something in the codebase or the codebase of the base library. Therefore I assume that it indeed is the standard library complex type.
There are a couple of using namespace std scattered around in various header files, but not all of them.
I tried compiling this codebase with GCC 4.9 and Clang 3.7. Both give similar errors about the missing type. Is there some possibility that this has worked with an older version of GCC? I have tried to insert std:: at all the needed points but I have the impression that I do something wrong if I cannot just compile the source checkout that is meant for this type of computer.
you can use selective using... declarations or type aliasing to bring in only the std:: members you need. Like:
using std::complex;
using std::cout;
using std::endl;
cout << "Hello world" << endl; // works
complex<float> x; // works
fstream y; // compile error, no namespace qualification, no using declaration
std::fstream z; // OK
Ah, yes, maybe not that evident, so perhaps worth mentioning. You now that std::endl? Well, it's a stream manipulator, a function in fact.
Which means one can bring in the current block function members from other namespaces as well.
Like:
#include <cmath>
#include <cstdlib>
inline void dummy(float x) {
float y=fabs(x); // Na'a.., fabs is imported into std namespace by <cmath>
using std::itoa; // same is itoa, but we'll be using it
char buff[128];
itoa(42, buff, 10); // OK
}
I need to write some code for a MFC project, but I don't know how to get required code to work when using MFC.
I prototyped my function first just using the STL types, and boost.
STL Prototype
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find.hpp>
void ProtoTest()
{
std::string sText("123Hello4");
boost::iterator_range<std::string::iterator> nc_result = find_token(sText, boost::algorithm::is_alpha(), boost::algorithm ::token_compress_on);
}
Result = "Hello"
I eventually managed to get it working with MFC, however I had to supply two typedefs. I would like to do it in one, however there isn't much documentation on using the MFC port provided in boost.
#include "stdafx.h"
#include <boost\range\atl.hpp>
void Test()
{
typedef boost::range_iterator<CString>::type CString_it;
typedef boost::iterator_range<CString_it> CString_range;
CString strText("123Hello4");
CString_range r;
r = find_token(text, boost::algorithm::is_alpha(), boost::algorithm ::token_compress_on);
}
Again Result = "Hello"
Is there a single typedef I can use to hold the result of find_token, rather than needing two typdefs to achieve it.
You could just combine them
typedef boost::iterator_range<boost::range_iterator<CString>::type> CString_range;
But I don't know if that is an advantage.
I am trying to pass data around the numpy and boost::ublas layers. I
have written an ultra thin wrapper because swig cannot parse ublas'
header correctly. The code is shown below
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <sstream>
#include <string>
using std::copy;
using namespace boost;
typedef boost::numeric::ublas::matrix<double> dm;
typedef boost::numeric::ublas::vector<double> dv;
class dvector : public dv{
public:
dvector(const int rhs):dv(rhs){;};
dvector();
dvector(const int size, double* ptr):dv(size){
copy(ptr, ptr+sizeof(double)*size, &(dv::data()[0]));
}
~dvector(){}
};
with the SWIG interface that looks something like
%apply(int DIM1, double* INPLACE_ARRAY1) {(const int size, double* ptr)}
class dvector{
public:
dvector(const int rhs);
dvector();
dvector(const int size, double* ptr);
%newobject toString;
char* toString();
~dvector();
};
I have compiled them successfully via gcc 4.3 and vc++9.0. However
when I simply run
a = dvector(array([1.,2.,3.]))
it gives me a segfault. This is the first time I use swigh with numpy
and not have fully understanding between the data conversion and
memory buffer passing. Does anyone see something obvious I have
missed? I have tried to trace through with a debugger but it crashed within the assmeblys of python.exe. I have no clue if this is a swig problem or of my simple wrapper. Anything is appreciated.
You may be interested in looking at the pyublas module. It does the conversion between numpy arrays and ublas data types seamlessly and without copying.
You may want to replace
copy(ptr, ptr+sizeof(double)*size, &(dv::data()[0]));
by
copy(ptr, ptr+size, &(dv::data()[0]));
Remember that in C/C++ adding or subtracting from a pointer moves it by a multiple of the size of the datatype it points to.
Best,