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
>
Related
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).
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>
I want to create a sequence of integer numbers for indexing within a matrix. The R pendant would be:
indexRow <- max(0,1):min(2,12)
matrix1[indexRow, ]
This is what i have tried in Rcpp to create the sequence of integers:
#include <Rcpp.h>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
NumericVector test(NumericVector x) {
IntegerVector indexRow = Rcpp::seq_along(max(0, 1), min(1, 12));
}
However I get the Error message:
no matching function for call to 'seq_along(const int&, const int&)'
How can I create a sequence of integers in Rcpp?
Here is a possible Rcpp implementation :
library(Rcpp)
cppFunction(plugins='cpp11','NumericVector myseq(int &first, int &last) {
NumericVector y(abs(last - first) + 1);
if (first < last)
std::iota(y.begin(), y.end(), first);
else {
std::iota(y.begin(), y.end(), last);
std::reverse(y.begin(), y.end());
}
return y;
}')
#> myseq(max(0,1), min(13,17))
#[1] 1 2 3 4 5 6 7 8 9 10 11 12 13
This code generates a function myseq which takes two arguments: The first and the last number in an integer series. It is similar to R's seq function called with two integer arguments seq(first, last).
A documentation on the C++11 function std::iota is given here.
seq_along takes in a vector, what you want to use is seq combined with min and max, both take vectors. seq returns an IntegerVector. Here is an example.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector test(IntegerVector a, IntegerVector b) {
IntegerVector vec = seq(max(a), min(b));
return vec;
}
In R you use
> test(c(0,1), c(2,12))
[1] 1 2
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.
I want to compute a function of the form:
$m_{jl}(x) = x + \gamma[j]*zeta[j,l] + sum_{k \neq j} zeta[j,k]$
using Rcpp. My problem is about the sum_{k \neq j} zeta[j,k]$.. I would like to be able to do something zeta[j,-j]. Is it possible? I tried zeta(j,-)-zeta(j,j), but the Rcpp does not like zeta(j,-).
You can use sugar functions:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double myFun(NumericMatrix x) {
return sum(x)-sum(diag(x));
}
R:
A <- matrix(1:9,3)
sum(A)-sum(diag(A))
#[1] 26
myFun(A)
#[1] 26
I suspect this could be made faster with RcppEigen.