[英]Trouble with my FFT implementation in C
標准非遞歸基數2算法。 我意識到這里的性能並不是最佳的(例如重復的trig調用),我只想在優化並移植到VHDL之前就將其正確設置。 我正在使用complex.h標頭。
對於長度為8的數組,我得到正確的結果,但對於16或32的數組卻沒有得到正確的結果。但是,對於真實信號,我們仍然得到正確的共軛對稱性結果,只是值是錯誤的。 這使我相信排序是正確的,但是對於較小的值,trig調用可能有問題嗎? 有人可以幫忙嗎?
我很抱歉,我的代碼沒有得到很好的注釋,但是老實說,這對FFT算法沒有多大幫助。
void FFT(double complex x[], int N){
//bit reverse
int s = log2(N);
for(int i = 0; i < N/2; i++){
int h = bitrev(i, s);
printf("%u ", h);
double complex temp = x[i];
x[i] = x[h];
x[h] = temp;
}
unsigned int Np = 2; //NUM POINTS IN EACH BLOCK. INITIALLY 2
unsigned int Bp = (N/2);
for(int i = 0; i < s; i++){
int NpP = Np>>1; //num butterflies
int BaseT = 0;
for (int j = 0; j < Bp; j++){
int BaseB = BaseT + NpP;
for(int k = 0; k < NpP; k++){
double complex top = x[BaseT + k];
double complex bot = (ccos(2*pi*k/Np) - I*csin(2*pi*k/Np))*x[BaseB + k];
x[BaseT + k] = top+bot;
x[BaseB + k] = top-bot;
}
BaseT = BaseT + Np;
}
Bp = Bp>>1;
Np = Np<<1;
}
}
輸出打印有:
for(int i = 0; i < LENGTH; i++){
printf("%f + %fj\n", creal(x[i]), cimag(x[i]));
}
這是長度為8的輸入,以及正確的輸出:
double complex x[LENGTH] = {1.0, -1.0, 1.0, -1.0, 10.0, -1.0, 5.0, -1.0};
輸出:
13.000000 + 0.000000j
-9.000000 + 4.000000j
5.000000 + 0.000000j
-9.000000 + -4.000000j
21.000000 + 0.000000j
-9.000000 + 4.000000j
5.000000 + 0.000000j
-9.000000 + -4.000000j
這是長度為16的輸入,我得到的錯誤輸出以及應該是什么:
double complex x[SIZE] = {10.0, -1.0, 5.0, -1.0, 4.0, 4.0, 2.0, 6.0, 9.0, 3.0, 8.0, 4.0, 5.0, 4.0, 3.0, 8.0};
輸出(不正確):
73.000000 + 0.000000j
-4.882497 + 10.451032j
12.535534 + 5.020815j
6.975351 + 7.165394j
12.000000 + 7.000000j
-0.732710 + 0.094326j
5.464466 + 19.020815j
2.639856 + 3.379964j
19.000000 + 0.000000j
2.639856 + -3.379964j
5.464466 + -19.020815j
-0.732710 + -0.094326j
12.000000 + -7.000000j
6.975351 + -7.165394j
12.535534 + -5.020815j
-4.882497 + -10.451032j
正確的輸出:
73.000000 + 0.000000j
-4.175390 + 10.743925j
13.535534 + 4.020815j
6.268244 + 5.458287j
10.000000 + 7.000000j
-1.439817 + 1.801433j
6.464466 + 20.020815j
3.346963 + 3.087071j
19.000000 + 0.000000j
3.346963 + -3.087071j
6.464466 + -20.020815j
-1.439817 + -1.801433j
10.000000 + -7.000000j
6.268244 + -5.458287j
13.535534 + -4.020815j
-4.175390 + -10.743925j
對於這個長度為16的示例,它給出正確的輸出(!?):
double complex x[SIZE] = {30.0, -1.0, 4.0, -6.0, 4.0, 9.0, 2.0, 6.0, 9.0, 3.0, -8.0, 4.0, -5.0, 4.0, 3.0, 8.0};
66.000000 + 0.000000j
22.604378 + -9.862676j
43.535534 + 28.091883j
24.900438 + 4.851685j
37.000000 + -3.000000j
-1.285214 + 2.408035j
36.464466 + 10.091883j
37.780399 + 23.693673j
12.000000 + 0.000000j
37.780399 + -23.693673j
36.464466 + -10.091883j
-1.285214 + -2.408035j
37.000000 + 3.000000j
24.900438 + -4.851685j
43.535534 + -28.091883j
22.604378 + 9.862676j
編輯:我已經意識到我的問題:我的位反轉循環是完全錯誤的。 我應該考慮一下看似簡單的部分,並對其進行更徹底的測試。 它在最后一種情況下起作用的原因是因為它具有重復的值,巧合地給出了與工作反轉相同的向量。 這是固定循環:
int s = log2(N);
for(int i = 0; i < N; i++){
int h = bitrev(i, s);
if(i < h){
double complex temp = x[i];
x[i] = x[h];
x[h] = temp;
}
}
這部分2*pi*k/Np
讓編譯器決定類型轉換。 我還要檢查這些值是否正確計算。 例如,當使用2*pi*k/Np;
時,我得到不同的結果2*pi*k/Np;
和2.0*pi*(double) k*(double) Np;
(Mods:我寧願將此添加為評論,但我的聲譽不高。請隨便提出我的回復:))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.