[英]No matching function for call to 'as' in Rcpp
I'm trying to write an R wrapper for the FINUFFT routines for calculating the FFT of an unevenly sampled series. 我正在尝试为FINUFFT例程编写一个R包装器,用于计算不均匀采样系列的FFT。 I have virtually no experience with C/C++, so I'm working from an example that compares the traditional Fourier transform to the NUFFT. 我几乎没有使用C / C ++的经验,所以我的工作是将传统的傅立叶变换与NUFFT进行比较。 The example code follows. 示例代码如下。
// this is all you must include for the finufft lib...
#include "finufft.h"
#include <complex>
// also needed for this example...
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
/* Simple example of calling the FINUFFT library from C++, using plain
arrays of C++ complex numbers, with a math test. Barnett 3/10/17
Double-precision version (see example1d1f for single-precision)
Compile with:
g++ -fopenmp example1d1.cpp -I ../src ../lib-static/libfinufft.a -o example1d1 -lfftw3 -lfftw3_omp -lm
or if you have built a single-core version:
g++ example1d1.cpp -I ../src ../lib-static/libfinufft.a -o example1d1 -lfftw3 -lm
Usage: ./example1d1
*/
{
int M = 1e6; // number of nonuniform points
int N = 1e6; // number of modes
double acc = 1e-9; // desired accuracy
nufft_opts opts; finufft_default_opts(&opts);
complex<double> I = complex<double>(0.0,1.0); // the imaginary unit
// generate some random nonuniform points (x) and complex strengths (c):
double *x = (double *)malloc(sizeof(double)*M);
complex<double>* c = (complex<double>*)malloc(sizeof(complex<double>)*M);
for (int j=0; j<M; ++j) {
x[j] = M_PI*(2*((double)rand()/RAND_MAX)-1); // uniform random in [-pi,pi)
c[j] = 2*((double)rand()/RAND_MAX)-1 + I*(2*((double)rand()/RAND_MAX)-1);
}
// allocate output array for the Fourier modes:
complex<double>* F = (complex<double>*)malloc(sizeof(complex<double>)*N);
// call the NUFFT (with iflag=+1): note N and M are typecast to BIGINT
int ier = finufft1d1(M,x,c,+1,acc,N,F,opts);
int n = 142519; // check the answer just for this mode...
complex<double> Ftest = complex<double>(0,0);
for (int j=0; j<M; ++j)
Ftest += c[j] * exp(I*(double)n*x[j]);
int nout = n+N/2; // index in output array for freq mode n
double Fmax = 0.0; // compute inf norm of F
for (int m=0; m<N; ++m) {
double aF = abs(F[m]);
if (aF>Fmax) Fmax=aF;
}
double err = abs(F[nout] - Ftest)/Fmax;
printf("1D type-1 NUFFT done. ier=%d, err in F[%d] rel to max(F) is %.3g\n",ier,n,err);
free(x); free(c); free(F);
return ier;
}
Much of this I don't need, such as generating the test series and comparing to the traditional FFT. 我不需要大部分内容,例如生成测试系列和与传统FFT进行比较。 Further, I want to return the values of the transform, not just an error code indicating success. 此外,我想返回转换的值,而不仅仅是指示成功的错误代码。 Below is my code. 以下是我的代码。
#include "finufft.h"
#include <complex>
#include <Rcpp.h>
#include <stdlib.h>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
ComplexVector finufft(int M, NumericVector x, ComplexVector c, int N) {
// From example code for finufft, sets precision and default options
double acc = 1e-9;
nufft_opts opts; finufft_default_opts(&opts);
// allocate output array for the finufft routine:
complex<double>* F = (complex<double>*)malloc(sizeof(complex<double>*)*N);
// Change vector inputs from R types to C++ types
double* xd = as< double* >(x);
complex<double>* cd = as< complex<double>* >(c);
// call the NUFFT (with iflag=-1): note N and M are typecast to BIGINT
int ier = finufft1d1(M,xd,cd,-1,acc,N,F,opts);
ComplexVector Fd = as<ComplexVector>(*F);
return Fd;
}
When I try to source this in Rstudio, I get the error "no matching function for call to 'as(std::complex<double>*&)'", pointing to the line declaring Fd
towards the end. 当我尝试在Rstudio中获取它时,我得到错误“没有匹配函数来调用'as(std :: complex <double> *&)'”,指向最后声明Fd
的行。 I believe the error indicates that either the function 'as' isn't defined (which I know is false), or the argument to 'as' isn't the correct type. 我相信错误表明函数'as'没有定义(我知道它是假的),或者'as'的参数不是正确的类型。 The examples here include one using 'as' to convert to a NumericVector, so unless there's some complication with complex values I don't see why it should be a problem here. 这里的示例包括使用'as'转换为NumericVector的示例,因此除非复杂值有一些复杂性,否则我不明白为什么它应该是一个问题。
I know there are potential problems using two namespaces, but I don't believe that's the issue here. 我知道使用两个命名空间可能存在问题,但我不认为这是问题所在。 My best guess is that there's an issue with how I'm trying to use pointers, but I lack the experience to identify it and I can't find any similar examples online to guide me. 我最好的猜测是,我试图使用指针有一个问题,但我缺乏识别它的经验,我在网上找不到任何类似的例子来指导我。
Rcpp::as<T>
converts from an R data type ( SEXP
) to a C++ data type, eg Rcpp::ComplexVector
. Rcpp::as<T>
从R数据类型( SEXP
)转换为C ++数据类型,例如Rcpp::ComplexVector
。 This does not fit your situation, where you try to convert from a C-style array to C++. 这不适合您的情况,您尝试从C风格的数组转换为C ++。 Fortunately Rcpp::Vector
, which is the basis for Rcpp::ComplexVector
, has a constructor for this task: Vector (InputIterator first, InputIterator last)
. 幸运的是, Rcpp::Vector
是Rcpp::ComplexVector
的基础,它有一个用于此任务的构造函数: Vector (InputIterator first, InputIterator last)
。 For the other direction (going from C++ to C-style array) you can use vector.begin()
or &vector[0]
. 对于另一个方向(从C ++到C风格的数组),您可以使用vector.begin()
或&vector[0]
。
However, one needs a reinterpret_cast
to convert between Rcomplex*
and std::complex<double>*
. 但是,需要reinterpret_cast
来在Rcomplex*
和std::complex<double>*
之间进行转换。 That should cause no problems, though, since Rcomplex
(aka complex double
in C) and std::complex<doulbe>
are compatible . 但是,这应该没有问题,因为Rcomplex
(在C中也称为complex double
Rcomplex
)和std::complex<doulbe>
是兼容的 。
A minimal example: 一个最小的例子:
#include <Rcpp.h>
#include <complex>
using namespace Rcpp;
// [[Rcpp::export]]
ComplexVector foo(ComplexVector v) {
std::complex<double>* F = reinterpret_cast<std::complex<double>*>(v.begin());
int N = v.length();
// do something with F
ComplexVector Fd(reinterpret_cast<Rcomplex*>(F),
reinterpret_cast<Rcomplex*>(F + N));
return Fd;
}
/*** R
set.seed(42)
foo(runif(4)*(1+1i))
*/
Result: 结果:
> Rcpp::sourceCpp('56675308/code.cpp')
> set.seed(42)
> foo(runif(4)*(1+1i))
[1] 0.9148060+0.9148060i 0.9370754+0.9370754i 0.2861395+0.2861395i 0.8304476+0.8304476i
BTW, you can move these reinterpret_cast
s out of sight by using std::vector<std::complex<double>>
as argument and return types for your function. 顺便说一下,你可以通过使用std::vector<std::complex<double>>
作为参数并返回函数的类型来将这些reinterpret_cast
移到视线之外。 Rcpp does the rest for you. Rcpp为您完成剩下的工作。 This also helps getting rid of the naked malloc
: 这也有助于摆脱裸体malloc
:
#include <Rcpp.h>
// dummy function with reduced signature
int finufft1d1(int M, double *xd, std::complex<double> *cd, int N, std::complex<double> *Fd) {
return 0;
}
// [[Rcpp::export]]
std::vector<std::complex<double>> finufft(int M,
std::vector<double> x,
std::vector<std::complex<double>> c,
int N) {
// allocate output array for the finufft routine:
std::vector<std::complex<double>> F(N);
// Change vector inputs from R types to C++ types
double* xd = x.data();
std::complex<double>* cd = c.data();
std::complex<double>* Fd = F.data();
int ier = finufft1d1(M, xd, cd, N, Fd);
return F;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.