Rcpp: 如何将复数从R传递到cpp

5

我希望使用Rcpp将复数从R传递到我的cpp代码。我尝试以类似于传递double和integer的方式来传递复数:

#include <complex>
#include <Rcpp.h>

using namespace Rcpp;

RcppExport SEXP mandelC(SEXP s_c) {
    std::complex<double> c = ComplexVector(s_c)[0];
}

然而,这段代码无法编译并且会报错:
g++ -I/usr/share/R/include -DNDEBUG -I/usr/share/R/include -fopenmp  -I/home/siim/lib/R/Rcpp/include     -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c a.cpp -o a.o
a.cpp: In function ‘SEXPREC* mandelC(SEXP)’:
a.cpp:7:50: error: conversion from ‘Rcpp::traits::storage_type<15>::type {aka Rcomplex}’ to non-scalar type ‘std::complex<double>’ requested
std::complex<double> c = ComplexVector(s_c)[0];
                                              ^

很明显,我做了些错误的事情但是我一直没有找到任何例子。有人能指点我正确的方向吗?
1个回答

9
您缺少一些非常简单的东西:
R> cppFunction("ComplexVector doubleMe(ComplexVector x) { return x+x; }")
R> doubleMe(1+1i)
[1] 2+2i
R> doubleMe(c(1+1i, 2+2i))
[1] 2+2i 4+4i
R> 

请记住,在R中,一切都是向量,标量并不存在:它们是长度为1的向量。因此,对于单个complex数字,您仍需要传递一个长度为1的ComplexVector
请查看Baptiste创建的两个包,这些包通过RcppArmadillo进行复杂数学计算--这"证明"了一些RcppArmadillo接口的工作方式。 编辑:如果您确实需要一个标量,也可以获得它:
R> cppFunction("std::complex<double> doubleMeScalar(std::complex<double> x) { 
+                                                   return x+x; }")
R> doubleMeScalar(1+1i)
[1] 2+2i
R> 

好的,所以你建议不传递一般的SEXP,而是传递ComplexVector,并使用ComplexVector进行数学计算,而不是std :: complex?有没有一种简单的方法从ComplexVector中获取单个(标量)std :: complex? - Ott Toomet
亲爱的Miller先生,也就是“@Hack-R”,您已经被标记并暂停了两次;我要求您在未经事先同意的情况下停止编辑帖子。谢谢。 - Dirk Eddelbuettel
@OttToomet:给自己一个好处,快速阅读Rcpp属性文档。你不可能写出比我展示的更简洁的代码 - 我们利用了Rcpp在幕后为我们转换事物的事实。_内部_它总是一个SEXP传输。但我发现纯C接口太麻烦了,你似乎也迷失在其中。Rcpp保持了许多本应该相当简单的东西...就是这样:相当简单。 - Dirk Eddelbuettel
1
PS 如果您使用 verbose=TRUE 调用 cppFunction(),则会看到一些生成的代码,就像在使用 compileAttributes() 生成绑定的包中一样。 - Dirk Eddelbuettel
谢谢,这很有帮助。我已经能够解决单个标量的问题。特别是我想使用std::norm()函数,但我还没有弄清如何在Rcpp::ComplexVector中使用它。 - Ott Toomet
1
很高兴知道它有所帮助。请随意接受和/或点赞,如您所愿。 - Dirk Eddelbuettel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接