Classes with Armadillo data - c++

Initially, I was importing some data from R directly into a C++ function like so:
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
List gibbs(List dat) {
int N = dat["N"];
arma::vec y = dat["y"];
...
}
Eventually, I needed more than just N and y (the input_data list has many separate vectors and matrices I need to import). So, I thought it would be a good idea to create a class Data to store all the input variables and automatically do some pre-processing in the constructor. Something like
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
class Data {
public:
int N;
arma::vec y;
// other data
Data(List input_data) {
N = input_data["N"];
y = input_data["y"];
// pre-processing steps
}
};
However, this doesn't work. It gives the following error:
object_LocLev.cpp:12:7: error: use of overloaded operator '=' is ambiguous (with operand types 'arma::vec' (aka 'Col<double>') and 'Rcpp::Vector<19>::NameProxy' (aka 'generic_name_proxy<19>'))
y = input_data["y"];
~ ^ ~~~~~~~~~~~~~~~
My question is why does this error appear? Is there a better way of assigning y?

Related

Rcpp: confusion about the base operation of assignment

Recently, I am trying to work on the Rcpp package to improve efficiency of computation in my work. However,I am not deep knowledged about C++, there are some strange behavoirs I can not understand. The below example show a simple tasks about derving weight of NumericVector, there are several questions:
When I use WAP=rev(WAP), it results in an incorrect output, I have to introduce a new variable to store the result so that I get the right output. I do not know why, should it NEVER use a 'x=f(x)' operation in C++ and Rcpp (must copy by clone instead) ?
About the CharacterVector method="eq", exactly I want to use a char or string type, however, it does not work with strncmp function (now I have to use method[0]), but I do not know how to look up the API of Rcpp functions in Rstudio?
I wonder whether there is a R-style grep, tolower function for conditions in Rcpp, I do not know which document I should refer to except for Rcpp suger, so that I can find the availiable base functions. Otherwise, I am thinking about calling R functions with Rcpp::function R_grep("grep"), but I do know whether this is the best way and recommended.
Any suggestions would be greatly appreciated.
#include <Rcpp.h>
#include <string>
#include <math.h>
#include <algorithm>
using namespace std;
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector cppweight(int N, CharacterVector method="eq", const bool reverse=false, const bool test=false){
NumericVector W(N);
NumericVector WAP(N);
NumericVector revWAP(N);
//method=tolower(method); //function not exists
if(strncmp(method[0],"eq",2)==0){
W=rep(1,N)/1.0*N;//convert int to float by multiplying 1.0
WAP=W/sum(W);
Rcout<< sum(W) << "\n";
} else if(strncmp(method[0],"ln",2)==0){
W=rev(seq(1,N))/1.0*N;
WAP=W/sum(W);
}
if(reverse){
if(test){
WAP=rev(WAP);//Why this result in incorrect result
revWAP=WAP;
}else{
revWAP=rev(WAP);
}
}else{
revWAP=WAP;
}
return(round(revWAP,3));
}
/*** R
cppweight(6,"ln",reverse=F,test=F)
cppweight(6,"ln",reverse=T,test=F)
cppweight(6,"ln",reverse=T,test=T)
*/

Rcpp: ambiguous overload for 'operator=' Matrix and List

The following Rcpp code is the minimal reproducible example for a much larger code that generates the identical compilation error. It seems that I cannot asign a numeric matrix to a list and the list then again to another matrix.
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
List return_a(NumericMatrix a, NumericMatrix b){
//the function only returns the input matrix a
List result(1);
result(0) = a;
return(result);
}
//[[Rcpp::export]]
List wrapper_cpp(NumericMatrix a, NumericMatrix b){
//the function is a dummy wrapper for much more code
List Step1(1);
List results(1);
Step1 = return_a(a,b);
a = Step1(0);
results(0) = a;
return(results);
}
The code above gives the following compilation error that I shortened:
error: ambiguous overload for 'operator=' (operand types are 'Rcpp::NumericMatrix {aka Rcpp::Matrix<14>}' and 'Rcpp::Vector<19>::Proxy ...
a = Step1(0);
My real function is much more complex. I need to manipulate matrices in several loops and in each step the matrices are returned by each function within a list. I then need to extract these lists to manipulate the matrices further. How can this be done?
Besides the error that #Ralf already mentioned, you were simply trying too much. Sometimes we need an intermediate step as the template magic is ... finicky. The following works.
Code
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
List return_a(NumericMatrix a, NumericMatrix b){
//the function only returns the input matrix a
List result(1);
result(0) = a;
return(result);
}
//[[Rcpp::export]]
List wrapper_cpp(NumericMatrix a, NumericMatrix b){
//the function is a dummy wrapper for much more code
List results(1);
List Step1 = return_a(a,b);
NumericMatrix tmp = Step1(0);
results(0) = tmp;
return(results);
}
Output
R> Rcpp::sourceCpp("~/git/stackoverflow/54771818/answer.cpp")
R> wrapper_cpp(matrix(1:4,2,2), matrix(4:1,2,2))
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
R>

Eigen binaryExpr with eigen type output

I'm having a problem while trying to use binaryExpr. It is the first use I'm making of it so I have been following the Eigen documentation
For my use I need a functor with Eigen type inputs and outputs but this does not want to compile and I do not understand why. I've looked up the explanation in the code but I didn't think this would apply here because I use floats and an array of floats
// We require Lhs and Rhs to have "compatible" scalar types.
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
// add together a float matrix and a double matrix.
Here is a short example of the use I would need that gets me the same compilation error:
#include <eigen3/Eigen/Dense>
using namespace std;
using namespace Eigen;
struct myBinaryFunctor {
EIGEN_EMPTY_STRUCT_CTOR(myBinaryFunctor)
typedef Vector2f result_type;
Vector2f operator()(const Matrix<float,9,1>& a,const float& f) const
{
float x = a.head(4).sum()*f;
float y = a.tail(5).sum()/f;
return Vector2f(x,y);
}
};
int main()
{
constexpr int n = 3;
Matrix<Matrix<float,9,1>,n,n> Ma;
Matrix<float,n,n> F;
Matrix<Vector2f,n,n> R;
for(size_t i = 0, sizeMa = Ma.size(); i<sizeMa; i++)
{
Ma(i).setOnes();
}
F.setConstant(n,n,2);
R = Ma.binaryExpr(F,myBinaryFunctor());
return 0;
}
The compilation output is :
/usr/local/include/eigen3/Eigen/src/Core/CwiseBinaryOp.h:107: erreur : static assertion failed: YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY
EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
^
If you have a solution that could make this work this would be a huge help for me :) If not I would still enjoy an explanation to understand what is happening. Thanks a lot.
Adding:
namespace Eigen {
template<>
struct ScalarBinaryOpTraits<Matrix<float,9,1>,float,myBinaryFunctor> {
typedef Vector2f ReturnType;
};
}
will do the job. This is because implicit scalar conversion are explicitly disallowed within Eigen, so you must explicit say that two different scalar types are compatible. For instance adding a VectorXd to a VectorXf is disallowed.
Nonetheless, it seems to me that your abusing Eigen's features here.

Error using complex vector

I need to access a specific element of a vector of complex data in C++.
Here is what I have:
vector< complex<float> > x; // Create vector of complex numbers
x.push_back(complex<float>(1, 2)); // Place 1 + j2 in vector
x.push_back(complex<float>(2, 1)); // Place 2 + j1 in vector
// Attempt at accessing the zero-th elements real part
float temp1 = x.at(0).real;
float temp2 = x[0].real;
This gives the following error in Visual Studio 2015:
Severity Code Description Project File Line Suppression State
Error C3867 'std::_Complex_base::real': non - standard syntax; use '&' to create a pointer to member opencv_dft c : \users\josh\VS_project\main.cpp 101
You forgot the parentheses in the calls to real(). You need:
float temp1 = x.at(0).real();
float temp2 = x[0].real();
real() is a member function, not a data member.
No need for casting in statement x.push_back(complex(float){1, 2})-though doesn't hurt to cast. Also don't forget using namespace std for statements using vector and complex.
Also don't forget ()s in x.at(0).real so it is x.at(0).real();.
Here is how I wrote a program using vectors and complex numbers.
#include <iostream>
#include <complex>
#include <vector>
using namespace std;
void main() {
complex<float> a = { 1,2 };
a = { 1,4 };
vector<complex<float>> av;
av.push_back({ 1,2 });
cout << av.at(0).real();
}

How can I initialize a SparseVector in Eigen

How can I initialize a SparseVector in Eigen ? The following code:
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
using namespace Eigen;
SparseVector<float> vec(3);
main()
{
vec(0)=1.0;
}
gives me the following error
error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
vec(0)=1.0;
by the way, vec[0]=1.0 doesn't work either.
Looking at the documentation I noticed Scalar& coeffRef(Index i), and it says:
Returns a reference to the coefficient value at given index i. This operation involes a log(rho*size) binary search. If the coefficient does not exist yet, then a sorted insertion into a sequential buffer is performed. (This insertion might be very costly if the number of nonzeros above i is large.)
So the following should work:
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
using namespace Eigen;
SparseVector<float> vec(3);
main()
{
vec.coeffRef(0)=1.0;
}
Not sure why they did it that way instead of using array overloading. Perhaps when it becomes IS_STABLE then they'll do it in a more typical C++ way?