R基2 DIT情况下的Cooley-Tukey FFT

时间:2019-03-16 01:54:28

标签: r fft

因此,我一直在尝试(手动)在R中实现Cooley-Turkey FFT算法(对于大小为N = n ^ 2的输入)。我尝试过:

myfft <- function(s){
  N <- length(s)
  if (N != 1){
    s[1:(N/2)] <- myfft(s[(1:(N/2))*2-1])
    s[(N/2+1):N] <- myfft(s[(1:(N/2))*2])

    for (k in 1:(N/2)){
      t <- s[k]
      s[k] <- t + exp(-1i*2*pi*(k-1)/N) * s[k+N/2]
      s[k+N/2] <- t - exp(-1i*2*pi*(k-1)/N) * s[k+N/2]
    }
  }
  s
}

这会编译,但是对于n> 1,N = 2 ^ n不会计算正确的值。我实现了DFT函数,并使用fft()函数进行了比较,当归一化时,两个计算都给出相同的值,但似乎与我上面的算法不一致。

如果有人感兴趣并看到我出了问题,将非常感谢您的帮助,如果我什至不了解这种FFT算法,我就会发疯寻找错误并开始提出疑问。

更新:我已修复它,我不确定100%到底是哪里出问题,但这是可行的实现方式:

myfft <- function(s){
  N <- length(s)
  if (N != 1){
    t <- s
    t[1:(N/2)] <- myfft(s[(1:(N/2))*2-1]) # 1 3 5 7 ... 
    t[(N/2+1):N] <- myfft(s[(1:(N/2))*2]) # 2 4 6 8 ... 

    s[1:(N/2)] <- t[1:(N/2)] + exp(-1i*2*pi*(0:(N/2-1))/N) * t[(N/2+1):N]
    s[(N/2+1):N] <- t[1:(N/2)] - exp(-1i*2*pi*(0:(N/2-1))/N) * t[(N/2+1):N]

  }
  return(s)
}

1 个答案:

答案 0 :(得分:0)

问题出在下面一行

s[1:(N/2)] <- myfft(s[(1:(N/2))*2-1])

正在覆盖下一行中所需的未转换值的一部分:

s[(N/2+1):N] <- myfft(s[(1:(N/2))*2])

例如,当N=4时,对myfft的第二次调用使用s[2]s[4],但是从第一次调用myfft的分配写入s[1]s[2](因此将s[2]中的原始值覆盖)。

您复制整个阵列的解决方案可以防止这种覆盖。

常用的替代解决方案是分别复制偶数和奇数部分:

myfft <- function(s){
  N <- length(s)
  if (N != 1){
    odd <- s[(1:(N/2))*2-1]
    even <- s[(1:(N/2))*2]
    s[1:(N/2)] <- myfft(odd)
    s[(N/2+1):N] <- myfft(even)

    s[1:(N/2)] <- t[1:(N/2)] + exp(-1i*2*pi*(0:(N/2-1))/N) * t[(N/2+1):N]
    s[(N/2+1):N] <- t[1:(N/2)] - exp(-1i*2*pi*(0:(N/2-1))/N) * t[(N/2+1):N]
  }
  return(s)
}