(Rcpp, armadillo) convert arma::vec to arma::mat - r

I have a matrix X, which is vectorized by arma::vectorise function. After some computation on the converted vector x, I want to reshape it into arma::mat. I tried to use .reshape function in Armadillo, but it gives me this error.
Rcpp code
// [[Rcpp::export]]
arma::mat vec2mat(arma::vec x, int nrow, int ncol){
return x.reshape(nrow, ncol);
}
Error message
no viable conversion from returned value of type 'void' to function return type 'arma::mat' (aka 'Mat<doubld>')
Would anyone help me to find a good way to handle this? I'm not sure what type I should use for function return type in this case. If you know another way to convert vector to matrix, then it would be also great :)
Thanks in advance!

You overlooked / ignored details in the Armadillo documentation: reshape() is a member function of an already existing matrix whereas you try to force it with an assignment. And the compiler tells you no mas. So listen to the compiler.
Working code
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat vec2mat(arma::vec x, int nrow, int ncol) {
arma::mat y(x);
y.reshape(nrow, ncol);
return y;
}
Demo
> Rcpp::sourceCpp("56606499/answer.cpp") ## filename I used
> vec2mat(sqrt(1:10), 2, 5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1.000000 1.732051 2.236068 2.645751 3.000000
[2,] 1.414214 2.000000 2.449490 2.828427 3.162278
>

Related

Is there any way in which to make an Infix function using sourceCpp()

I was wondering whether it is possible to make an infix function, e.g. A %o% B with Rcpp.
I know that this is possible using the inline package, but have yet been able to find a method for doing this when using sourceCpp().
I have made the following infix implementation of %o% / outer() when arguments are sure to be vectors using RcppEigen and inline:
`%op%` <- cxxfunction(signature(v1="NumericVector",
v2="NumericVector"),
plugin = "RcppEigen",
body = c("
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
"))
This can easily be implemented in to be imported using sourceCpp(), however not as an infix function.
My current attempt is as follows:
#include <Rcpp.h>
using namespace Rcpp;
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
NumericMatrix outerProd(NumericVector v1, NumericVector v2) {
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
}
So to summarize my question.. Is it possible to make an infix function available through sourceCpp?
Is it possible to make an infix function available through sourceCpp?
Yes.
As always, one should read the Rcpp vignettes!
In particular here, if you look in Section 1.6 of the Rcpp attributes vignette, you'd see you can modify the name of a function using the name parameter for Rcpp::export.
For example, we could do:
#include <Rcpp.h>
// [[Rcpp::export(name = `%+%`)]]
Rcpp::NumericVector add(Rcpp::NumericVector x, Rcpp::NumericVector y) {
return x + y;
}
/*** R
1:3 %+% 4:6
*/
Then we'd get:
Rcpp::sourceCpp("~/infix-test.cpp")
> 1:3 %+% 4:6
[1] 5 7 9
So, you still have to name C++ functions valid C++ names in the code, but you can export it to R through the name parameter of Rcpp::export without having to do anything further on the R side.
John Chambers states three principles on page four of the (highly recommended) "Extending R" book:
Everything that exists in R is an object.
Everything that happens in R is a function call.
Interfaces to other software are part of R.
So per point two, you can of course use sourceCpp() to create your a compiled function and hang that at any odd infix operator you like.
Code Example
library(Rcpp)
cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
`%+%` <- function(a,b) cc(a,b)
cc("Hello", "World")
"hello" %+% "world"
Output
R> library(Rcpp)
R> cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
R> `%+%` <- function(a,b) cc(a,b)
R>
R> cc("Hello", "World")
[1] "HelloWorld"
R>
R> "hello" %+% "world"
[1] "helloworld"
R>
Summary
Rcpp is really just one cog in the machinery.
Edit
It also works with your initial function, with some minor simplification. For
`%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
as.numeric(1:3) %op% as.numeric(3:1)
we get
R> `%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
R> as.numeric(1:3) %op% as.numeric(3:1)
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 4 2
[3,] 9 6 3
R>
(modulo some line noise from the compiler).

rcpp: how to apply gamma function to a scalar?

I guess the function gamma only works for a vector as the input. Is there a way to apply it to a scalar, say,gamma(3)`?
Actually, I would get the correct output if I include gamma(3) as part of my code, but there's a warning message....
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List fool(NumericVector vec){
double res = 0;
res = sum(gamma(vec)) + gamma(3);
List result;result["num"] = res;
return result;
}
Here is the warning messgae:
exp.cpp:7:27: warning: 'gamma' is deprecated: first deprecated in OS X 10.9 [-Wdeprecated-declarations]
res = sum(gamma(vec)) + gamma(3);
^
/usr/include/math.h:720:15: note: 'gamma' has been explicitly marked deprecated here
extern double gamma(double) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_9, __IPHONE_NA, __IPHONE_NA);
^
1 warning generated.
Thanks for posting code. You fell victim of being careless with namespaces. There is a (vectorized) gamma() in the Rcpp namespace -- the first argument and there is (was) a scalar gamma() (preferred: tgamma()) in the C math library. And it is better to be explicit.
Corrected code below:
#include <Rcpp.h>
// [[Rcpp::export]]
double fool(Rcpp::NumericVector vec){
double res =
Rcpp::sum(Rcpp::gamma(vec)) + // Rcpp sugar sum() and gamma() on vector
::tgamma(3.0); // math library tgamma of double
return res;
}
/*** R
v <- 1:5
fool(v)
sum(gamma(v)) + gamma(3)
*/
Output
R> sourceCpp("/tmp/shuang.cpp")
R> v <- 1:5
R> fool(v)
[1] 36
R> sum(gamma(v)) + gamma(3)
[1] 36
R>

Using RcppArmadillo each_col with lambda function?

According to the Armadillo website, you can pass in a lambda function into .each_col, such as
X.each_col( [](vec& a){ a.print(); } );
The following Rcpp seems to have an error though, reporting "Expected Expression"
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
arma::vec colCumSum(const arma::mat& X) {
return X.each_col( [](const arma::vec& b){ b.cumsum(); } );
}
You actually have to tell R to use C++11 in order to have lambda support. The magic line is [[Rcpp::plugins("cpp11")]] which makes it all work:
But once I do that I get issues on the cumsum(). You also had too many const in there.
So here is a simpler version which does work with another lambda from the documentation -- which just prints. I also turned to ivec and imat for consistency:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins("cpp11")]]
// [[Rcpp::export]]
arma::ivec colCumSum(arma::imat& X) {
X.each_col( [](arma::ivec& a){ a.print(); } );
return X.col(0);
}
/*** R
M <- matrix(1:16, 4, 4)
colCumSum(M)
*/
When you source this, it builds and runs. You will need to work out the lambda use case for the reduction that cumsum() does.
> sourceCpp("/tmp/foo.cpp")
> M <- matrix(1:16, 4, 4)
> colCumSum(M)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
>

A simple RcppArmadillo index issue

I'm coding with RcppArmadillo and got stuck with a very basic question. Suppose I have a vector "v", and I want to take its first 10 elements, like in R: v[1:10]. Since 1:10 doesn't work in RcppArmadillo, I tried v.elem(seq_len(10)), but it didn't work. Any hint?
Assuming you're taking about an arma::vec, this should work:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec f(const arma::vec & v, int first, int last) {
arma::vec out = v.subvec(first, last);
return out;
}
/*** R
f(11:20, 3, 6)
*/
Note that this uses zero-based indexing (11 is the 0th element of the vector). Coerce to NumericVector as desired.
When source'ed into R, the code is compiled, linked, loaded and the embedded example is executed:
R> sourceCpp("/tmp/armaEx.cpp")
R> f(11:20, 3, 6)
[,1]
[1,] 14
[2,] 15
[3,] 16
[4,] 17
R>
So it all really is _just one call to subvec(). See the Armadillo documentation for more.

Convert RcppArmadillo vector to Rcpp vector

I am trying to convert RcppArmadillo vector (e.g. arma::colvec) to a Rcpp vector (NumericVector). I know I can first convert arma::colvec to SEXP and then convert SEXP to NumericVector (e.g. as<NumericVector>(wrap(temp)), assuming temp is an arma::colvec object). But what is a good way to do that?
I want to do that simply because I am unsure if it is okay to pass arma::colvec object as a parameter to an Rcpp::Function object.
I was trying to Evaluate a Rcpp::Function with argument arma::vec, it seems that it takes the argument in four forms without compilation errors. That is, if f is a Rcpp::Function and a is a arma::vec, then
f(a)
f(wrap(a))
f(as<NumericVector>(wrap(a)))
f(NumericVector(a.begin(),a.end()))
produce no compilation and runtime errors, at least apparently.
For this reason, I have conducted a little test for the four versions of arguments. Since I suspect that somethings will go wrong in garbage collection, I test them again gctorture.
gctorture(on=FALSE)
Rcpp::sourceCpp(code = '
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double foo1(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(a, b));
}
return sum;
}
// [[Rcpp::export]]
double foo2(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(wrap(a),wrap(b)));
}
return sum;
}
// [[Rcpp::export]]
double foo3(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(as<NumericVector>(wrap(a)),as<NumericVector>(wrap(b))));
}
return sum;
}
// [[Rcpp::export]]
double foo4(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(NumericVector(a.begin(),a.end()),NumericVector(b.begin(),b.end())));
}
return sum;
}
')
# note that when gctorture is on, the program will be very slow as it
# tries to perfrom GC for every allocation.
# gctorture(on=TRUE)
f = function(x,y) {
mean(x) + mean(y)
}
# all three functions should return 700
foo1(c(1,2,3), c(4,5,6), f) # error
foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
foo3(c(1,2,3), c(4,5,6), f) # correct answer
foo4(c(1,2,3), c(4,5,6), f) # correct answer
As a result, the first method produces an error, the second method produces a wrong answer and only the third and the fourth method return the correct answer.
> # they should return 700
> foo1(c(1,2,3), c(4,5,6), f) # error
Error: invalid multibyte string at '<80><a1><e2>'
> foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
[1] 712
> foo3(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
> foo4(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
Note that, if gctorture is set FALSE, then all functions will return a correct result.
> foo1(c(1,2,3), c(4,5,6), f) # error
[1] 700
> foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
[1] 700
> foo3(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
> foo4(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
It means that method 1 and method 2 are subjected to break when garbage is collected during runtime and we don't know when it happens. Thus, it is dangerous to not wrap the parameter properly.
Edit: as of 2017-12-05, all four conversions produce the correct result.
f(a)
f(wrap(a))
f(as<NumericVector>(wrap(a)))
f(NumericVector(a.begin(),a.end()))
and this is the benchmark
> microbenchmark(foo1(c(1,2,3), c(4,5,6), f), foo2(c(1,2,3), c(4,5,6), f), foo
3(c(1,2,3), c(4,5,6), f), foo4(c(1,2,3), c(4,5,6), f))
Unit: milliseconds
expr min lq mean median uq
foo1(c(1, 2, 3), c(4, 5, 6), f) 2.575459 2.694297 2.905398 2.734009 2.921552
foo2(c(1, 2, 3), c(4, 5, 6), f) 2.574565 2.677380 2.880511 2.731615 2.847573
foo3(c(1, 2, 3), c(4, 5, 6), f) 2.582574 2.701779 2.862598 2.753256 2.875745
foo4(c(1, 2, 3), c(4, 5, 6), f) 2.378309 2.469361 2.675188 2.538140 2.695720
max neval
4.186352 100
5.336418 100
4.611379 100
3.734019 100
And f(NumericVector(a.begin(),a.end())) is marginally faster than other methods.
This should works with arma::vec, arma::rowvec and arma::colvec:
template <typename T>
Rcpp::NumericVector arma2vec(const T& x) {
return Rcpp::NumericVector(x.begin(), x.end());
}
I had the same question. I used wrap to do the conversion at the core of several layers of for loops and it was very slow. I think the wrap function is to blame for dragging the speed down so I wish to know if there is an elegant way to do this.
As for Raymond's question, you might want to try including the namespace like: Rcpp::as<Rcpp::NumericVector>(wrap(A)) instead or include a line using namespace Rcpp; at the beginning of your code.

Resources