gpt4 book ai didi

c++ - Rcpp 中没有调用 'as' 的匹配函数

转载 作者:太空狗 更新时间:2023-10-29 20:33:10 25 4
gpt4 key购买 nike

我正在尝试为 FINUFFT 编写一个 R 包装器用于计算不均匀采样序列的 FFT 的例程。我几乎没有使用 C/C++ 的经验,所以我正在研究一个将传统傅立叶变换与 NUFFT 进行比较的示例。示例代码如下。

// 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;
}

其中很多我不需要,例如生成测试系列并与传统 FFT 进行比较。此外,我想返回转换的值,而不仅仅是指示成功的错误代码。下面是我的代码。

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

当我尝试在 Rstudio 中获取它时,我收到错误“没有匹配的函数来调用‘as(std::complex *&)’”,指向声明 Fd 的行接近尾声。我相信该错误表明函数“as”未定义(我知道这是错误的),或者“as”的参数类型不正确。例子 here包括一个使用“as”转换为 NumericVector 的方法,因此除非复杂值有一些复杂性,否则我不明白为什么它会成为这里的问题。

我知道使用两个命名空间存在潜在问题,但我认为这不是问题所在。我最好的猜测是我尝试使用指针的方式存在问题,但我缺乏识别它的经验,而且我无法在网上找到任何类似的例子来指导我。

最佳答案

Rcpp::as<T>从 R 数据类型 ( SEXP ) 转换为 C++ 数据类型,例如Rcpp::ComplexVector .这不适合您尝试从 C 样式数组转换为 C++ 的情况。还好Rcpp::Vector , 这是 Rcpp::ComplexVector 的基础, 有一个用于此任务的构造函数:Vector (InputIterator first, InputIterator last) .对于另一个方向(从 C++ 到 C 样式数组),您可以使用 vector.begin()&vector[0] .

但是,需要一个 reinterpret_castRcomplex* 之间转换和 std::complex<double>* .不过,这应该不会造成任何问题,因为 Rcomplex (又名 complex double 在 C 中)和 std::complex<doulbe>compatible .

一个最小的例子:

#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))
*/

结果:

> 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

顺便说一句,你可以移动这些reinterpret_cast使用 std::vector<std::complex<double>> 是看不见的作为函数的参数和返回类型。 Rcpp 为您完成剩下的工作。这也有助于摆脱裸体 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;
}

关于c++ - Rcpp 中没有调用 'as' 的匹配函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56675308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com