有什么方法可以使用 sourceCpp() 创建中缀函数

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

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

我知道使用 inline 包可以做到这一点,但是在使用 sourceCpp().

时我还没有找到这样做的方法

当参数肯定是使用RcppEigeninline的向量时,我已经实现了%o%/outer()的以下中缀实现:

`%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() 导入,但不能作为中缀函数。

我目前的尝试如下:

#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 提供中缀函数?

John Chambers 在(强烈推荐)"Extending 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> 

(模数来自编译器的一些线路噪声)。

Is it possible to make an infix function available through sourceCpp?

.

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

#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 端做任何进一步的操作。