Search code examples
rrcpp

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?


Solution

  • 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.