我以前用fftw_plan_dft进行多维傅里叶变换.
fftw_plan fftw_plan_dft(int rank, const int *n, fftw_complex *in,
fftw_complex *out, int sign, unsigned flags);现在我想将64位整数传递给fftw,看起来我需要使用fftw guru接口。
fftw_plan fftw_plan_guru64_dft(
int rank, const fftw_iodim64 *dims,
int howmany_rank, const fftw_iodim64 *howmany_dims,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);但我不明白howmany_rank和howmany_dims是什么意思。fftw_plan_guru_dft手册上写着:
这两个函数分别为交错格式和分裂格式规划了复杂数据、多维DFT .变换维数由维数的多维向量(howmany_rank,howmany_dims)上的(秩,差)表示.dims和howmany_dims应该分别指向长度等级和howmany_rank的fftw_iodim数组。
我知道“维的多维向量(循环)”(howmany_rank,howmany_dims)是什么意思.你能给我举个例子或者解释一下如何使用这个guru接口吗?
发布于 2016-10-14 17:16:22
如果多维数组的大小和步幅大于2^32,则64位guru接口将变得有用。
创建复杂的DTFs功能的原型是:
fftw_plan fftw_plan_guru64_dft(
int rank, const fftw_iodim64 *dims,
int howmany_rank, const fftw_iodim64 *howmany_dims,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);其中:
rank是要执行的FFTW变换的级别,即维数。dims是一个大小为rank的数组。对于每个维i,dims[i].n是直线的大小,dims[i].is是输入数组的线条之间的跨距,dims[i].os是输出数组的线条之间的跨距。例如,如果数组在内存中是连续的,那么guru接口的文档建议使用递归dims[i].is = n[i+1] * dims[i+1].is。要执行的转换数和起点之间的偏移量由howmany_rank和howmany_dims给出。howmany_rank指定具有特定偏移量的转换数。howmany_dims是一个大小为howmany_rank的数组。对于每个转换i,howmany_dims[i].n是要计算的转换数,每个转换都具有输入howmany_dims[i].is和输出howmany_dims[i].os之间的偏移量。有关这些参数的更多详细信息在关于FFTW3古鲁接口的困惑:3个同时复杂的FFT中提供。
下面的代码调用fftw_plan_guru64_dft(),以便它执行与fftw_plan_dft_3d()相同的操作。它可以由gcc main.c -o main -lfftw3 -lm -Wall编译
#include<stdlib.h>
#include<complex.h>
#include<math.h>
#include<fftw3.h>
int main(void){
fftw_plan p;
unsigned long int N = 10;
unsigned long int M = 12;
unsigned long int P = 14;
fftw_complex *in=fftw_malloc(N*M*P*sizeof(fftw_complex));
if(in==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
fftw_complex *out=fftw_malloc(N*M*P*sizeof(fftw_complex));
if(out==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
unsigned int i,j,k;
int rank=3;
fftw_iodim64 *dims=malloc(rank*sizeof(fftw_iodim64));
if(dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
dims[0].n=N;
dims[0].is=P*M;
dims[0].os=P*M;
dims[1].n=M;
dims[1].is=P;
dims[1].os=P;
dims[2].n=P;
dims[2].is=1;
dims[2].os=1;
int howmany_rank=1;
fftw_iodim64 *howmany_dims=malloc(howmany_rank*sizeof(fftw_iodim64));
if(howmany_dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
howmany_dims[0].n=1;
howmany_dims[0].is=1;
howmany_dims[0].os=1;
printf("sizeof fftw complex %ld\n",sizeof(fftw_complex));
printf("sizeof fftw_iodim64 %ld\n",sizeof(fftw_iodim64));
printf("creating the plan\n");
p=fftw_plan_guru64_dft(rank, dims,howmany_rank, howmany_dims,in, out,FFTW_FORWARD, FFTW_ESTIMATE);
if (p==NULL){fprintf(stderr,"plan creation failed\n");exit(1);}
printf("created the plan\n");
for(i=0;i<N;i++){
for(j=0;j<M;j++){
for(k=0;k<P;k++){
//printf("ijk\n");
in[(i*M+j)*P+k]=30.+12.*sin(2*3.1415926535*i/((double)N))*sin(2*3.1415926535*j/((double)M))*sin(2*3.1415926535*k/((double)P))*I;
}
}
}
fftw_execute(p);
for (i = 0; i < N; i++){
for (j = 0; j < M; j++){
for (k = 0; k < P; k++){
printf("result: %d %d %d %g %gI\n", i,j,k, creal(out[(i*M+j)*P+k]), cimag(out[(i*M+j)*P+k]));
}
}
}
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
free(dims);
free(howmany_dims);
return(0);
}例如,guru接口可以用来计算复杂的三维电场的DFT。在网格的每一点上,电场都是一个大小为3的矢量。因此,我可以将电场存储为一个4D阵列,最后一个维数指定矢量的分量。最后,可以使用guru接口同时执行三个3D DFT:
#include<stdlib.h>
#include<complex.h>
#include<math.h>
#include<fftw3.h>
int main(void){
fftw_plan p;
unsigned long int N = 10;
unsigned long int M = 12;
unsigned long int P = 14;
unsigned long int DOF = 3;
fftw_complex *in=fftw_malloc(N*M*P*DOF*sizeof(fftw_complex));
if(in==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
fftw_complex *out=fftw_malloc(N*M*P*DOF*sizeof(fftw_complex));
if(out==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
unsigned int i,j,k;
int rank=3;
fftw_iodim64 *dims=malloc(rank*sizeof(fftw_iodim64));
if(dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
dims[0].n=N;
dims[0].is=P*M*DOF;
dims[0].os=P*M*DOF;
dims[1].n=M;
dims[1].is=P*DOF;
dims[1].os=P*DOF;
dims[2].n=P;
dims[2].is=DOF;
dims[2].os=DOF;
int howmany_rank=1;
fftw_iodim64 *howmany_dims=malloc(howmany_rank*sizeof(fftw_iodim64));
if(howmany_dims==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
howmany_dims[0].n=DOF;
howmany_dims[0].is=1;
howmany_dims[0].os=1;
printf("sizeof fftw complex %ld\n",sizeof(fftw_complex));
printf("sizeof fftw_iodim64 %ld\n",sizeof(fftw_iodim64));
printf("creating the plan\n");
p=fftw_plan_guru64_dft(rank, dims,howmany_rank, howmany_dims,in, out,FFTW_FORWARD, FFTW_ESTIMATE);
if (p==NULL){fprintf(stderr,"plan creation failed\n");exit(1);}
printf("created the plan\n");
for(i=0;i<N;i++){
for(j=0;j<M;j++){
for(k=0;k<P;k++){
//printf("ijk\n");
in[((i*M+j)*P+k)*DOF]=30.+12.*sin(2*3.1415926535*i/((double)N))*sin(2*3.1415926535*j/((double)M))*sin(2*3.1415926535*k/((double)P))*I;
in[((i*M+j)*P+k)*DOF+1]=42.0;
in[((i*M+j)*P+k)*DOF+2]=1.0;
}
}
}
fftw_execute(p);
for (i = 0; i < N; i++){
for (j = 0; j < M; j++){
for (k = 0; k < P; k++){
printf("result: %d %d %d || %g %gI | %g %gI | %g %gI\n", i,j,k, creal(out[((i*M+j)*P+k)*DOF]), cimag(out[((i*M+j)*P+k)*DOF]),creal(out[((i*M+j)*P+k)*DOF+1]), cimag(out[((i*M+j)*P+k)*DOF+1]),creal(out[((i*M+j)*P+k)*DOF+2]), cimag(out[((i*M+j)*P+k)*DOF+2]));
}
}
}
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
free(dims);
free(howmany_dims);
return(0);
}https://stackoverflow.com/questions/39938409
复制相似问题