如何使用较小尺寸的FFT计算大尺寸FFT?

时间:2012-03-30 09:18:45

标签: fft

如果我有一个特定大小M(2的幂)的FFT实现,我如何计算一组大小P = k * M的FFT,其中k也是2的幂?

#define M 256  
#define P 1024  
complex float x[P];  
complex float X[P];

// Use FFT_M(y) to calculate X = FFT_P(x) here

[这个问题是出于一般意义上的目的。我知道FFT计算是一个巨大的领域,并且研究和开发了许多特定于体系结构的优化,但我想要了解的是如何在更抽象的层次上实现这一点。请注意,我不是FFT(或DFT,就此而言)专家,所以如果可以用简单的术语来解释,那将是值得赞赏的。

4 个答案:

答案 0 :(得分:4)

这是一个使用两个较小的FFT函数计算大小为P的FFT的算法,大小为M和N(原始问题称为大小为M和k)。

输入:
P是您想要计算的大FFT的大小 选择M,N使得MN = P. x [0 ... P-1]是输入数据
设置:
U是具有M行和N列的2D阵列。
y是长度为P的向量,它将保持x的FFT。

算法:
步骤1.从x按列填充U,以便U看起来像这样:
x(0) x(M) ... x(P-M)
x(1) x(M+1) ... x(P-M+1)
x(2) x(M+2) ... x(P-M+2)
... ... ... ...
x(M-1) x(2M-1) ... x(P-1)

步骤2.用自己的FFT(长度为N)替换U的每一行 步骤3.将U(m,n)的每个元素乘以exp(-2 * pi * j * m * n / P)。
步骤4.用自己的FFT(长度为M)替换U的每一列。
步骤5.将行的U元素读出为y,如下所示:

y(0) y(1) ... y(N-1)
y(N) y(N+1) ... y(2N-1)
y(2N) y(2N+1) ... y(3N-1)
... ... ... ...
y(P-N) y(P-N-1) ... y(P-1)

这是实现此算法的MATLAB代码。您可以输入fft_decomposition(randn(256,1), 8);

进行测试
function y = fft_decomposition(x, M)
% y = fft_decomposition(x, M)
% Computes FFT by decomposing into smaller FFTs.
%
% Inputs:
% x is a 1D array of the input data.
% M is the size of one of the FFTs to use.
%
% Outputs:
% y is the FFT of x.  It has been computed using FFTs of size M and
% length(x)/M.
%
% Note that this implementation doesn't explicitly use the 2D array U; it
% works on samples of x in-place.

q = 1;   % Offset because MATLAB starts at one.  Set to 0 for C code.
x_original = x;
P = length(x);
if mod(P,M)~=0, error('Invalid block size.'); end;
N = P/M;

% step 2: FFT-N on rows of U.
for m = 0 : M-1
    x(q+(m:M:P-1)) = fft(x(q+(m:M:P-1)));
end;

% step 3: Twiddle factors.
for m = 0 : M-1
    for n = 0 : N-1
        x(m+n*M+q) = x(m+n*M+q) * exp(-2*pi*j*m*n/P);
    end;
end;

% step 4:  FFT-M on columns of U.
for n = 0 : N-1
    x(q+n*M+(0:M-1)) = fft(x(q+n*M+(0:M-1)));
end;

% step 5:  Re-arrange samples for output.
y = zeros(size(x));
for m = 0 : M-1
    for n = 0 : N-1
        y(m*N+n+q) = x(m+n*M+q);
    end;
end;

err = max(abs(y-fft(x_original)));
fprintf( 1, 'The largest error amplitude is %g\n', err);
return;
% End of fft_decomposition().

答案 1 :(得分:0)

假设先前的FFT结果来自适当的交错数据子集,您可以使用基数-2 FFT的最后log2(k)次通过。

答案 2 :(得分:0)

FFT基本上是递归类型的傅里叶变换。它依赖于维基百科所说的事实:

  

最着名的FFT算法取决于N的因子分解,但是对于全部N,存在具有O(N log N)复杂度的FFT,即使对于素数N.许多FFT算法仅取决于e ^的事实。 (-2pi * i / N)是单位的第N个原始根,并且因此可以应用于任何有限域上的类似变换,例如数论变换。由于>逆DFT与DFT相同,但在指数和1 / N因子中具有相反的符号,因此任何FFT算法都可以很容易地适应它。

所以这已经在FFT中完成了。如果您正在谈论从变换中获取更长周期的信号,那么最好在有限频率的数据集上进行DFT。可能有一种方法可以从频域中进行,但是如果有人实际上已经完成了IDK。你能成为第一个!!!! :)

答案 3 :(得分:0)

kevin_o的反应非常好。我使用他的代码并使用一些基本的Matlab技巧消除了循环。它在功能上与他的版本相同

function y = fft_decomposition(x, M)
% y = fft_decomposition(x, M)
% Computes FFT by decomposing into smaller FFTs.
%
% Inputs:
% x is a 1D array of the input data.
% M is the size of one of the FFTs to use.
%
% Outputs:
% y is the FFT of x.  It has been computed using FFTs of size M and
% length(x)/M.
%
% Note that this implementation doesn't explicitly use the 2D array U; it
% works on samples of x in-place.

q = 1;   % Offset because MATLAB starts at one.  Set to 0 for C code.
x_original = x;
P = length(x);
if mod(P,M)~=0, error('Invalid block size.'); end;
N = P/M;

% step 2: FFT-N on rows of U.
X=fft(reshape(x,M,N),[],2);

% step 3: Twiddle factors.
X=X.*exp(-j*2*pi*(0:M-1)'*(0:N-1)/P);

% step 4:  FFT-M on columns of U.
X=fft(X);

% step 5:  Re-arrange samples for output.
x_twiddle=bsxfun(@plus,M*(0:N-1)',(0:M-1))+q;
y=X(x_twiddle(:));

% err = max(abs(y-fft(x_original)));
% fprintf( 1, 'The largest error amplitude is %g\n', err);
return;
% End of fft_decomposition()