一维和二维傅里叶变换的CPP代码

时间:2021-11-17 12:38:37

自己写了一个,和Matlab对比了一下,结果是一样的,供各位参考吧

 

// ==============================================================================
// 快速离散傅里叶变换和功率谱
// 一维快速傅里叶变换FFT1和二维快速傅里叶变换FFT2
// 测试环境 C++ builder 2010
// MinGW (GCC) 4.5
// wuxuping 2010-08-10
// 一定要将文件保存为UTF-8的格式,这是MinGW的默认格式.
// ==============================================================================

#ifndef FFT_H
#define FFT_H
// --------------------
#include <vector>
#include<complex>
#include<bitset>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <sstream>
using namespace std;

const double pai = 3.1415926535897932384626433832795028841971; // 圆周率

typedef vector<vector<complex<double> > >VVCD;
typedef vector<vector<double> >VVD;

// -------------------------------------------------
class FFT1 {
private:
unsigned N; // 数据长度

unsigned NFFT; // 使用快速傅里叶变化所计算的长度

unsigned r; // 数据长度NFFT=2^r,且2^(r-1)<N<<NFFT

vector<complex<double> >TS; // 时间域序列

vector<complex<double> >FS; // 频率域序列FrequencySeries

vector<double>PSD; // PSD功率谱密度(离散谱)

vector<double>PS; // 返回PS=PSD*Frequency
int sign;

// sign > 0为正变换否则为逆变换
// ------------------------------------
void Set_NFFT_r(unsigned n);
unsigned RevBit(unsigned num);
void GetIndex(unsigned L, unsigned ALindex, unsigned &AL_1index0,
unsigned &AL_1index1, unsigned &Windex);

// ------------------------------------

void doFFT1();

// 执行傅里叶变换
// ------------------------------------
public:

// ------实序列构造函数-------------
FFT1(vector<double>TimeSeries, int sign_ = 1) {
N = TimeSeries.size();
if (sign_ > 0) {
sign = 1.0; // 正变换
}
else {
sign = -1.0; // 逆变换
}
Set_NFFT_r(N);

complex<double>W0(0.0, 0.0); // 旋转因子
// --------------------------------
for (unsigned i = 0; i < NFFT; i++) { // 赋初值
if (i < N) {
FS.push_back(W0);
complex<double>Wi(TimeSeries[i], 0.0); // 旋转因子
TS.push_back(Wi);
}
else {
FS.push_back(W0); // 补零
TS.push_back(W0); // 补零
}

}
// --------------------------------

doFFT1(); // 执行傅里叶变换
// --------------------------------
};

// -------复序列构造函数-------------
FFT1(vector<complex<double> >TimeSeries, int sign_ = 1) { // 赋初值
N = TimeSeries.size();
if (sign_ > 0) {
sign = 1.0; // 正变换
}
else {
sign = -1.0; // 逆变换
}
Set_NFFT_r(N);

complex<double>W0(0.0, 0.0); // 旋转因子
// --------------------------------
for (unsigned i = 0; i < NFFT; i++) { // 赋初值
if (i < N) {
FS.push_back(W0);
TS.push_back(TimeSeries[i]);
}
else {
FS.push_back(W0); // 补零
TS.push_back(W0); // 补零
}

}
// --------------------------------

doFFT1(); // 执行傅里叶变换
// --------------------------------
};

// ----------成员函数------

// ----------成员函数 -------------
vector<complex<double> >GetFS() { // 返回频率域序列FrequencySeries
return FS;
};

// ----------成员函数 -------------
vector<double>GetFrequency() { // 返回频率
vector<double>Frequency;
// ----------------------
for (unsigned int i = 0; i < FS.size(); i++) {
Frequency.push_back(i);
}
return Frequency;
};

// ----------成员函数 -------------
vector<double>GetPSD() { // 返回FS^2
if (PSD.size() > 0) {
PSD.clear();
}
// ----------------------
for (unsigned int i = 0; i < FS.size(); i++) {
PSD.push_back(real(FS[i] * conj(FS[i])));
}
return PSD;
};

vector<double>GetPS() { // 返回PS=PSD*Frequency
if (PS.size() > 0) {
PS.clear();
}
// ----------------------
for (unsigned int i = 0; i < FS.size(); i++) {
PS.push_back(i * 1.0 * real(FS[i] * conj(FS[i])));
}
return PS;
};
// ----------析构函数 -------------

~FFT1() {
};
// -----------------------------------
};

// ------设置NFFT和r的值--------
void FFT1::Set_NFFT_r(unsigned n) {
bitset<32>bsn(n);
r = 0;
while ((n >> r) > 0) {
r++;
}

if ((bsn.count() == 1) && (r > 0)) {
r--;
}
bitset<32>bsNFFT(0);
bsNFFT.set(r);
NFFT = (unsigned)bsNFFT.to_ulong();
};

// ---- 比特倒序函数
unsigned FFT1::RevBit(unsigned num) {
bitset<32>bs(num);
bitset<32>bsR;
// ---------逆序
for (unsigned i = 0; i < r; i++) {
bsR.set(i, bs[r - i - 1]);
}
return(unsigned)bsR.to_ulong();
};

// ------------------------------------------------------------------------------
// 计算公式中的索引AL(ALindex)=AL-1(AL_1index0)+AL-1(AL_1index1)W(Windex)
// ------------------------------------------------------------------------------
void FFT1::GetIndex(unsigned L, unsigned ALindex, unsigned &AL_1index0,
unsigned &AL_1index1, unsigned &Windex) {
// ALindex为AL()的索引
// AL_1index0 = 0; // AL-1()的第一项索引
// AL_1index1 = 0; // AL-1()的第二项索引
// Windex = 0; // 相位角中的索引
bitset<32>bs(ALindex);
bitset<32>bs1(ALindex);
bs1.set(r - L, 0);
AL_1index0 = bs1.to_ulong();
// -----------------------------------
bitset<32>bs2(ALindex);
bs2.set(r - L, 1);
AL_1index1 = bs2.to_ulong();
// -----------------------------------
bitset<32>bs3; // 左L位
for (unsigned i = 0; i < L; i++) {
bs3.set(r - L + i, bs[r - i - 1]);
}
Windex = bs3.to_ulong();
}

// ------------------------------------
void FFT1::doFFT1() { // 一维快速Fourier变换
unsigned AL_1index0 = 0; // AL-1()的第一项索引
unsigned AL_1index1 = 0; // AL-1()的第二项索引
unsigned Windex = 0; // 相位角中的索引
double alpha; // 相位角
// ----------------------------
vector<complex<double> >X = TS; // X中间临时变量

for (unsigned L = 1; L <= r; L++) { // 蝶形计算过程
for (unsigned ALindex = 0; ALindex < NFFT; ALindex++) {
// ALindex为AL()的索引
GetIndex(L, ALindex, AL_1index0, AL_1index1, Windex);
alpha = -2.0 * sign * pai * Windex / (1.0 * NFFT); // 旋转因子的相位角
complex<double>W(cos(alpha), sin(alpha)); // 旋转因子
FS[ALindex] = X[AL_1index0] + X[AL_1index1] * W;
}
X = FS; // 复制数组
}
//
if (sign > 0) { // 为正变换
for (unsigned i = 0; i < NFFT; i++) {
FS[i] = X[RevBit(i)]; // 索引按二进制倒序
}
}
else { // 为逆变换
complex<double>WN(NFFT, 0.0); // 数据的个数
for (unsigned i = 0; i < NFFT; i++) {
FS[i] = X[RevBit(i)] / WN; // 索引按二进制倒序
}
}
}
// ==============================================================================
// 计算二维快速傅里叶变换FFT2
// ==============================================================================

// ----------------------------------------------
class FFT2 {

private:

// ----------------------------------------------
unsigned N1; // 数据行长度 0<=k1<N1 0<=j1<N1

unsigned N2; // 数据列长度 0<=k2<N2 0<=j2<N2

int sign; // sign > 0为正变换否则为逆变换

VVCD Tk1k2; // 二维时间域序列,行k1列k2

VVCD Yj1k2; // 中间序列对 Ak1k2每一行(k1)做傅里叶变换的结果

VVCD Fj1j2; // 频率域序列FrequencySeries

VVD PSD; // PSD功率谱密度(离散谱)

VVD PS; // 返回PS=PSD*Frequency

// ------------------------------------
VVCD TranspositionVVCD(VVCD dv); // 矩阵转置
// ------------------------------------

public:

// ------实序列构造函数-------------
FFT2(VVD TK1K2, int sign_ = 1) { // 赋初值

N1 = TK1K2.size(); // 获取行数
Tk1k2.resize(N1);
for (unsigned k1 = 0; k1 < N1; k1++) {
N2 = TK1K2[k1].size();
Tk1k2[k1].resize(N2);
for (unsigned k2 = 0; k2 < N2; k2++) {
complex<double>W(TK1K2[k1][k2], 0.0);
Tk1k2[k1][k2] = W;
}

}
// -----------------------------------------
for (unsigned k1 = 0; k1 < N1; k1++) {
FFT1 fft1(Tk1k2[k1], sign_);
Yj1k2.push_back(fft1.GetFS());
}
// -----------------------------------------
Yj1k2 = TranspositionVVCD(Yj1k2); // 将矩阵转置
// -----------------------------------------
N2 = Yj1k2.size(); // 获取列数
for (unsigned k2 = 0; k2 < N2; k2++) {
FFT1 fft1(Yj1k2[k2], sign_);
Fj1j2.push_back(fft1.GetFS());
}
// --------------
Fj1j2 = TranspositionVVCD(Fj1j2); // 将矩阵转置
// -----------------------
};

// -------复序列构造函数-------------
FFT2(VVCD TK1K2, int sign_ = 1) { // 赋初值
Tk1k2 = TK1K2;
N1 = Tk1k2.size(); // 获取行数
for (unsigned k1 = 0; k1 < N1; k1++) {
FFT1 fft1(Tk1k2[k1], sign_);
Yj1k2.push_back(fft1.GetFS());
}
// -----------------------------------------
Yj1k2 = TranspositionVVCD(Yj1k2); // 将矩阵转置
// -----------------------------------------
N2 = Yj1k2.size(); // 获取列数
for (unsigned k2 = 0; k2 < N2; k2++) {
FFT1 fft1(Yj1k2[k2], sign_);
Fj1j2.push_back(fft1.GetFS());
}
// --------------
Fj1j2 = TranspositionVVCD(Fj1j2); // 将矩阵转置
// -----------------------
};

// ----------成员函数 -------------
VVCD GetFS() { // 返回频率域序列Fj1j2
return Fj1j2;
};

// ----------成员函数 -------------
VVD GetPSD() { // 返回FS^2
PSD.resize(Fj1j2.size());
for (unsigned i = 0; i < Fj1j2.size(); i++) {
PSD[i].resize(Fj1j2[i].size());
}
// ----------------------
for (unsigned i = 0; i < Fj1j2.size(); i++) {
for (unsigned j = 0; j < Fj1j2[i].size(); j++) {
PSD[i][j] = real(Fj1j2[i][j] * conj(Fj1j2[i][j]));
}
}
return PSD;
};

// ----------成员函数 -------------
VVD GetPS() { // 返回PS=PSD*Frequency
PS.resize(Fj1j2.size());
for (unsigned i = 0; i < Fj1j2.size(); i++) {
PS[i].resize(Fj1j2[i].size());
}
// ----------------------
for (unsigned i = 0; i < Fj1j2.size(); i++) {
for (unsigned j = 0; j < Fj1j2[i].size(); j++) {
PS[i][j] = (double)i * (double)j * real
(Fj1j2[i][j] * conj(Fj1j2[i][j]));
}
}
return PS;
};
// ----------析构函数 -------------

~FFT2() {
};
// -----------------------------------
};

// ----------------------------------------
VVCD FFT2::TranspositionVVCD(VVCD dv) { // 将矩阵转置
unsigned dvRow = dv.size();
unsigned maxcol = 0;
unsigned mincol = 99999;
VVCD temp;
if (dv.size() > 0) {
// ------------------------------
for (unsigned i = 0; i < dvRow; i++) {
if (maxcol < dv[i].size()) {
maxcol = dv[i].size();
}
if (mincol > dv[i].size()) {
mincol = dv[i].size();
}
}
// ------------------------------
if (mincol == maxcol && mincol > 0) {
temp.resize(mincol);
for (unsigned i = 0; i < mincol; i++) {
temp[i].resize(dvRow);
}
for (unsigned i = 0; i < dvRow; i++) {
for (unsigned j = 0; j < mincol; j++) {
temp[j][i] = dv[i][j];
}
}
}
}
return temp;
}

// ==============================================================================
// 此处定义的函数是为了控制台输出查看方便
// ==============================================================================
// VVCD==vector<vector<complex<double> > >
// VVD== vector<vector<double> >
// ---------------------------------
void PrintVVCD(vector<vector<complex<double> > >Data) {
cout << "Data : " << endl;
for (unsigned i = 0; i < Data.size(); i++) {
cout << "Row[" << i << "]=\t";
vector<complex<double> >v = Data[i];
copy(v.begin(), v.end(), ostream_iterator<complex<double> >(cout,
"\t"));
cout << endl;
}
}

// ---------------------------------
void PrintVCD(vector<vector<double> >Data) {
cout << "Data : " << endl;
for (unsigned i = 0; i < Data.size(); i++) {
cout << "Row[" << i << "]=\t";
vector<double>v = Data[i];
copy(v.begin(), v.end(), ostream_iterator<double>(cout, "\t"));
cout << endl;
}
}
// ---------------------------------

// --------------------------------------------------------------------------------
#endif


 

用类实现的