Conversion of Rcpp::NumericMatrix to Eigen::MatrixXd - rcpp

I am facing a very similar issue to these questions:
convert Rcpp::NumericVector to Eigen::VectorXd
Converting between NumericVector/Matrix and VectorXd/MatrixXd in Rcpp(Eigen) to perform Cholesky solve
I am writing an R-package, that uses the RcppEigen library for Matrix arithmetic. My problem is that the project is not compiling because of an error in the conversion of the Rcpp::NumericMatrix input to an Eigen::MatrixXd.
The file looks like this:
#include <map>
#include <Rcpp.h>
...
using namespace Eigen;
...
// [[Rcpp::export]]
Rcpp::List my_function(Rcpp::NumericMatrix input_matrix)
{
...
Map<MatrixXd> GATE_matrixx(Rcpp::as<Map<MatrixXd> >(GATE_matrix));
...
}
This gives me the following error:
Myfile.cpp:40:65: required from here
C:/Users/User/AppData/Local/Programs/R/R-4.2.2/library/Rcpp/include/Rcpp/internal/Exporter.h:31:31:error:
matching function for call to 'Eigen::Map<Eigen::Matrix<double, -1,
-1> >::Map(SEXPREC*&) 31 | Exporter( SEXP x ) : t(x) | ^ In file included from
C:/Users/User/AppData/Local/Programs/R/R-4.2.2/library/RcppEigen/include/Eigen/Core:19
from
C:/Users/User/AppData/Local/Programs/R/R-4.2.2/library/RcppEigen/include/Eigen/SparseCore:11
from
C:/Users/User/AppData/Local/Programs/R/R-4.2.2/library/RcppEigen/include/Eigen/Sparse:26
from Myfile.cpp:8
I have also tried to change the line to:
MatrixXd input_matrix_eigen(Rcpp::as\<MatrixXd\>(input_matrix));
This gives me the equivalent error :
Myfile.cpp:40:54: required from here
C:/Users/User/AppData/Local/Programs/R/R
4.2.2/library/RcppEigen/include/Eigen/src/Core/Matrix.h:332:31:error: matching function for call to 'Eigen::Matrix<double, -1,
-1>::_init1<SEXPREC*>(SEXPREC* const&)
Do you have any ideas?
If more information is required to evaluate the issue, just let me know.

If you use the command
RcppEigen::RcppEigen.package.skeleton("demoPackage")
an example package demoPackage is created for you which you can install the usual way. It contains example functions to create amd return a matrix:
// [[Rcpp::export]]
Eigen::MatrixXd rcppeigen_hello_world() {
Eigen::MatrixXd m1 = Eigen::MatrixXd::Identity(3, 3);
// Eigen::MatrixXd m2 = Eigen::MatrixXd::Random(3, 3);
// Do not use Random() here to not promote use of a non-R RNG
Eigen::MatrixXd m2 = Eigen::MatrixXd::Zero(3, 3);
for (auto i=0; i<m2.rows(); i++)
for (auto j=0; j<m2.cols(); j++)
m2(i,j) = R::rnorm(0, 1);
return m1 + 3 * (m1 + m2);
}
If you set the same seed as I do you should get the same matrix
> set.seed(42)
> demoPackage::rcppeigen_hello_world()
[,1] [,2] [,3]
[1,] 8.11288 -1.694095 1.089385
[2,] 1.89859 5.212805 -0.318374
[3,] 4.53457 -0.283977 10.055271
>

Related

Ignore missing values while finding min in Rcpp

I am trying to find the minimum of 2 values from 2 vectors in Rcpp. But the following does not compile:
#include <cmath>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector timesTwo(int time_length, double BXadd,
NumericVector vn_complete, NumericVector vn1_complete) {
// Empty vectors
NumericVector BX (time_length);
for(int t = 0; t < time_length; t++) {
BX[t] = BXadd * sqrt(std::min(na_omit(vn_complete[t], vn1_complete[t])));
}
return BX;
// return vn_complete[0];
}
Error 1 occurred building shared library.
It works if I don't use na_omit.
R code for running the function:
Rcpp::sourceCpp("test.cpp")
timesTwo(5, 2, 5:9, 1:5)
What follows below is a slightly non-sensical answer (as it only works with vectors not containing NA) but it has all the component your code has, and it compiles.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector foo(int time_length, double BXadd,
NumericVector vn_complete, NumericVector vn1_complete) {
// Empty vectors
NumericVector BX (time_length);
vn_complete = na_omit(vn_complete);
vn1_complete = na_omit(vn1_complete);
for(int t = 0; t < time_length; t++) {
double a = vn_complete[t];
double b = vn1_complete[t];
BX[t] = BXadd * std::sqrt(std::min(a,b));
}
return BX;
}
// Edited version with new function added
// [[Rcpp::export]]
NumericVector foo2(double BXadd, NumericVector vn_complete,
NumericVector vn1_complete) {
return BXadd * sqrt(pmin(vn_complete, vn1_complete));
}
/*** R
foo(5, 2, 5:9, 1:5)
foo2(5, 2, 5:9, 1:5)
*/
For a real solution you will have to think harder about what the removal of NA is supposed to do as it will alter the lenth of your vectors too. So this still needs work.
Lastly, your whole function can be written in R as
2 * sqrt(pmin(5:9, 1:5))
and I think you could write that same expression using Rcpp sugar too as we have pmin() and sqrt():
// [[Rcpp::export]]
NumericVector foo2(double BXadd, NumericVector vn_complete,
NumericVector vn1_complete) {
return BXadd * sqrt(pmin(vn_complete, vn1_complete));
}

In Rcpp How to create a NumericMatrix by a NumbericaVector?

In Rcpp How to create a NumericMatrix by a NumbericaVector?
Something like
// vector_1 has 16 element
NumericMatrix mat = NumericMatrix(vector_1, nrow = 4);
Thanks.
Edit: I knew we had something better. See below for update.
Looks like we do not have a matching convenience constructor for this. But you can just drop in a helper function -- the following is minimally viable (one should check that n + k == length(vector)) and taken from one of the unit tests:
// [[Rcpp::export]]
Rcpp::NumericMatrix vec2mat(Rcpp::NumericVector vec, int n, int k) {
Rcpp::NumericMatrix mat = Rcpp::no_init(n, k);
for (auto i = 0; i < n * k; i++) mat[i] = vec[i];
return mat;
}
Another constructor takes the explicit dimensions and then copies the payload for you (via memcpy()), removing the need for the loop:
// [[Rcpp::export]]
Rcpp::NumericMatrix vec2mat2(Rcpp::NumericVector s, int n, int k) {
Rcpp::NumericMatrix mat(n, k, s.begin());
return mat;
}
Full example below:
> Rcpp::sourceCpp("~/git/stackoverflow/66720922/answer.cpp")
> v <- (1:9) * 1.0 # numeric
> vec2mat(v, 3, 3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> vec2mat2(v, 3, 3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
>
Full source code below.
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericMatrix vec2mat(Rcpp::NumericVector vec, int n, int k) {
Rcpp::NumericMatrix mat = Rcpp::no_init(n, k);
for (auto i = 0; i < n * k; i++) mat[i] = vec[i];
return mat;
}
// [[Rcpp::export]]
Rcpp::NumericMatrix vec2mat2(Rcpp::NumericVector s, int n, int k) {
Rcpp::NumericMatrix mat(n, k, s.begin());
return mat;
}
/*** R
v <- (1:9) * 1.0 # numeric
vec2mat(v, 3, 3)
vec2mat2(v, 3, 3)
*/
Depending on what you want to do with the matrix object (linear algrebra?) you may want to consider RcppArmadillo (or RcppEigen) as those packages also have plenty of vector/matrix converters.

Apply lambda function to `arma::cube` in `RcppArmadillo`

I tried to use RcppArmadillo to compute the Frobenious norm across each slice of an array(arma::cube). The example code in file cxxFuns.cpp is presented below.
// [[Rcpp::depends(RcppArmadillo)]]
#include "RcppArmadillo.h"
// [[Rcpp::export]]
arma::vec array_norm (arma::cube & x) {
arma::vec out = x.each_slice([](arma::mat& x0) {return arma::norm(x0, "fro") ;}) ;
return out ;
}
After the cpp file is compiled successfully, the function array_norm throws an exception:
set.seed(2020)
Rcpp::sourceCpp('cxxFuns.cpp')
x <- array(rnorm(3*4*5), 3:5)
array_norm(x)
#> error: copy into matrix: can't interpret cube with dimensions 3x4x5 as a vector
#> Error in array_norm(x) :
#> copy into matrix: can't interpret cube with dimensions 3x4x5 as a vector
Created on 2020-12-02 by the reprex package (v0.3.0)
That actually an error message from Armadillo because something is not right with your logic yet -- the result is not a vector. You can see that by changing to this (self-contained, a very nice Rcpp trick) code:
Code
// [[Rcpp::depends(RcppArmadillo)]]
#include "RcppArmadillo.h"
// [[Rcpp::export]]
bool array_norm (arma::cube & x) {
auto out = x.each_slice([](arma::mat& x0) {return arma::norm(x0, "fro") ;}) ;
out.print("out");
return true;
}
/*** R
set.seed(2020)
x <- array(rnorm(3*4*5), 3:5)
array_norm2(x)
*/
Output
> Rcpp::sourceCpp("~/git/stackoverflow/65104769/answer.cpp")
> set.seed(2020)
> x <- array(rnorm(3*4*5), 3:5)
> array_norm2(x)
out
[cube slice 0]
0.3770 -1.1304 0.9391 0.1174
0.3015 -2.7965 -0.2294 -0.8531
-1.0980 0.7206 1.7591 0.9093
[cube slice 1]
1.1964 1.8000 -2.2890 1.0982
-0.3716 1.7040 0.0583 0.3182
-0.1233 -3.0388 2.1744 -0.0731
[cube slice 2]
0.8343 0.9367 -0.8125 2.4354
0.1988 -0.1474 -0.7437 0.3881
1.2978 0.1104 1.0953 0.2906
[cube slice 3]
-0.2856 0.4472 -0.3010 0.2531
0.0760 0.9085 -0.7260 -0.3707
-0.5603 -0.5051 -1.1801 0.0222
[cube slice 4]
0.6600 0.6014 0.1188 -1.3283
0.4888 -0.6738 0.1212 -0.5669
-0.1888 0.4761 -0.1860 0.5788
[1] TRUE

RcppArrayFire passing a matrix row as af::array input

In this simple example I would like to subset a matrix by row and pass it to another cpp function; the example demonstrates this works by passing an input array to the other function first.
#include "RcppArrayFire.h"
using namespace Rcpp;
af::array theta_check_cpp( af::array theta){
if(*theta(1).host<double>() >= 1){
theta(1) = 0;
}
return theta;
}
// [[Rcpp::export]]
af::array theta_check(RcppArrayFire::typed_array<f64> theta){
const int theta_size = theta.dims()[0];
af::array X(2, theta_size);
X(0, af::seq(theta_size)) = theta_check_cpp( theta );
X(1, af::seq(theta_size)) = theta;
// return X;
Rcpp::Rcout << " works till here";
return theta_check_cpp( X.row(1) );
}
/*** R
theta <- c( 2, 2, 2)
theta_check(theta)
*/
The constructor you are using to create X has an argument ty for the data type, which defaults to f32. Therefore X uses 32 bit floats and you cannot extract a 64 bit host pointer from that. Either use
af::array X(2, theta_size, f64);
to create an array using 64 bit doubles, or extract a 32 bit host pointer via
if(*theta(1).host<float>() >= 1){
...

Compute density using Rcpp sugar function [duplicate]

From R, I'm trying to run sourceCpp on this file:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace arma;
using namespace Rcpp;
// [[Rcpp::export]]
vec dnormLog(vec x, vec means, vec sds) {
int n = x.size();
vec res(n);
for(int i = 0; i < n; i++) {
res[i] = log(dnorm(x[i], means[i], sds[i]));
}
return res;
}
See this answer to see where I got the function from. This throws the error:
no matching function for call to 'dnorm4'
Which is the exact error I was hoping to prevent by using the loop, since the referenced answer mentions that dnorm is only vectorized with respect to its first argument. I fear the answer is obvious, but I've tried adding R:: before the dnorm, tried using NumericVector instead of vec, without using log() in front. No luck. However, adding R:: before dnorm does produce a separate error:
too few arguments to function call, expected 4, have 3; did you mean '::dnorm4'?
Which is not fixed by replacing dnorm above with R::dnorm4.
There are two nice teachable moments here:
Pay attention to namespaces. If in doubt, don't go global.
Check the headers for the actual definitions. You missed the fourth argument in the scalar version R::dnorm().
Here is a repaired version, included is a second variant you may find interesting:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec dnormLog(arma::vec x, arma::vec means, arma::vec sds) {
int n = x.size();
arma::vec res(n);
for(int i = 0; i < n; i++) {
res[i] = std::log(R::dnorm(x[i], means[i], sds[i], FALSE));
}
return res;
}
// [[Rcpp::export]]
arma::vec dnormLog2(arma::vec x, arma::vec means, arma::vec sds) {
int n = x.size();
arma::vec res(n);
for(int i = 0; i < n; i++) {
res[i] = R::dnorm(x[i], means[i], sds[i], TRUE);
}
return res;
}
/*** R
dnormLog( c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
dnormLog2(c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
*/
When we source this, both return the same result because the R API allows us to ask for logarithms to be taken.
R> sourceCpp("/tmp/dnorm.cpp")
R> dnormLog( c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
[,1]
[1,] -0.923939
[2,] -0.938939
[3,] -0.963939
R> dnormLog2(c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
[,1]
[1,] -0.923939
[2,] -0.938939
[3,] -0.963939
R>

Resources