C FFTW和长双精度

C FFTW和长双精度,c,C,我用()编译了FFTW 3.3.5库: 我用gcc-std=gnu99 main.c-o sample.x-lfftw3l-lm编译下面的代码 #include <math.h> #include <complex.h> #include <fftw3.h> #include <string.h> #define PI acosl(-1.0L) #define FMODE FFTW_MEASURE int main() { fftwl_co

我用()编译了FFTW 3.3.5库:

我用gcc-std=gnu99 main.c-o sample.x-lfftw3l-lm编译下面的代码

#include <math.h>
#include <complex.h>
#include <fftw3.h>
#include <string.h>

#define PI acosl(-1.0L)
#define FMODE FFTW_MEASURE

int main() {
  fftwl_complex  *A = fftwl_malloc(4096*sizeof(fftwl_complex));
  fftwl_plan     ft = fftwl_plan_dft_1d(4096, A, A, FFTW_BACKWARD, FMODE);
  long double    q, u, overN = ((long double) 1.L/4096);

  for (long int j = 0; j < 4096; j++) {
    q = 2.L*PI*(j*overN - 0.5L);
    u = 2.L*atan2l(0.5L*sinl(0.5L*q),cosl(0.5L*q));
    A[j] = -1.IL*cpowl(0.01L*(1.L/ctanl(0.5L*(u-0.1IL)) - 1.IL),2);
  }
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
  fftwl_execute(ft);
  for (int j = 0; j < 2048; j++) {
    A[j] = -1.0IL*((fftwl_complex) j*A[j])*overN;
  }
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
  memset(A+2048, 0, 2048*sizeof(fftwl_complex));
  fftwl_execute(ft);
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
}

关于我丢失长双精度的地方有什么想法吗?

由复FFT产生的数组的每个项都可以用不同的方法计算。如前所述,对错误传播方式进行研究

由于和的权重始终为范数1,因此输出数组项的方差是输入数组项的方差之和(输入数组项被视为独立随机变量)

精度1e-18是标准偏差与数值范数的比率。因此,如果使用长双精度:

最后,结果的精度写入:

该方程的一个直接后果是灾难性抵消现象:输出的标准偏差是有限的,但值
|y
非常小,因为相似的值被减去。。。因此,没有一个数字是有效的!例如,请参见here()。这解释了为什么在您的情况下
7.463682637972633967E-24
很容易变成
1.965167197605865111E-23
。事实上,如果发生部分抵消,精度很容易从1e-18降低到1e-14这样的值。| y |值越小,有效数字越少

由于使用了标志
FFTW\u MEASURE
,因此每次运行的输出都不同。如果使用此标志,将尝试不同的算法,FFTW将选择最快的算法。由于长度为4096的1D FFT现在非常快,因此计时可能不太一致,可以选择具有类似性能的不同算法。对于非有效数字,不同的算法将导致不同的计算和不同的结果。如果使用标志
FFTW\u ESTIMATE
,这些变化是否仍然存在?如果使用此标志。这种启发式很可能是确定性的

#include <math.h>
#include <complex.h>
#include <fftw3.h>
#include <string.h>

#define PI acosl(-1.0L)
#define FMODE FFTW_MEASURE

int main() {
  fftwl_complex  *A = fftwl_malloc(4096*sizeof(fftwl_complex));
  fftwl_plan     ft = fftwl_plan_dft_1d(4096, A, A, FFTW_BACKWARD, FMODE);
  long double    q, u, overN = ((long double) 1.L/4096);

  for (long int j = 0; j < 4096; j++) {
    q = 2.L*PI*(j*overN - 0.5L);
    u = 2.L*atan2l(0.5L*sinl(0.5L*q),cosl(0.5L*q));
    A[j] = -1.IL*cpowl(0.01L*(1.L/ctanl(0.5L*(u-0.1IL)) - 1.IL),2);
  }
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
  fftwl_execute(ft);
  for (int j = 0; j < 2048; j++) {
    A[j] = -1.0IL*((fftwl_complex) j*A[j])*overN;
  }
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
  memset(A+2048, 0, 2048*sizeof(fftwl_complex));
  fftwl_execute(ft);
  printf("%26.18LE\t%26.18LE\n", creall(A[1]), cimagl(A[1]));
}
  2.907416794556517046E-07    9.025765251354815022E-05
 -5.697284273172913999E-04    7.463682637972633967E-24
  1.895341327532694420E-04    3.343168537700265992E-07

  2.907416794556517046E-07    9.025765251354815022E-05
 -5.697284273172913999E-04    1.965167197605865111E-23
  1.895341327532697672E-04    3.343168537692799396E-07