有什么方法可以使用sourceCpp()制作Infix函数

时间:2019-11-15 13:07:51

标签: r rcpp

我想知道是否可以制作一个infix函数,例如A %o% B与Rcpp。

我知道可以使用inline包来做到这一点,但是在使用sourceCpp()时仍然无法找到一种方法。

当使用%o%outer()确定参数是矢量时,我对RcppEigen / 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);
                           "))

可以很容易地实现它,以使用sourceCpp()进行导入,但是不能作为infix函数。

我当前的尝试如下:

#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);
}

所以总结我的问题。是否可以通过sourceCpp使中缀函数可用?

2 个答案:

答案 0 :(得分:4)

  

是否可以通过sourceCpp使中缀函数可用?

一如既往,您应该阅读Rcpp vignettes! 特别是在这里,如果您查看the Rcpp attributes vignette的1.6节,就会发现可以使用Rcpp::export的name参数来修改函数的名称。 例如,我们可以这样做:

#include <Rcpp.h>

// [[Rcpp::export(name = `%+%`)]]
Rcpp::NumericVector add(Rcpp::NumericVector x, Rcpp::NumericVector y) {
  return x + y;
}

/*** R
1:3 %+% 4:6
*/

那么我们会得到:

Rcpp::sourceCpp("~/infix-test.cpp")

> 1:3 %+% 4:6
[1] 5 7 9

因此,您仍然必须在代码中命名有效的C ++名称的C ++函数,但是您可以通过Rcpp::export的名称参数将其导出到R,而无需在R端做任何进一步的事情。

答案 1 :(得分:3)

约翰·钱伯斯(John Chambers)在(强烈推荐的)“扩展R”书的第四页上陈述了三个原则:

  • R中存在的所有对象都是对象。
  • R中发生的一切都是函数调用。
  • 与其他软件的接口是R的一部分。

因此,对于第二点,您当然可以使用sourceCpp()创建您的已编译函数,并将其挂在您喜欢的任何奇数中缀运算符上。

代码示例

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"

输出

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> 

摘要

Rcpp实际上只是机械中的一枚齿轮。

编辑

它还可以与您的初始功能一起使用,但略有简化。对于

`%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)

我们得到

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> 

(对来自编译器的一些线路噪声进行模运算)。