00001 #include "fft.hpp"
00002 #include <math.h>
00003
00004
00005
00006 Complex::Complex(double _re, double _im)
00007 : re(_re), im(_im) { }
00008
00009 double Complex::GetRe() const
00010 {
00011 return re;
00012 }
00013
00014 double Complex::GetIm() const
00015 {
00016 return im;
00017 }
00018
00019 double Complex::GetNorm() const
00020 {
00021 return re * re + im * im;
00022 }
00023
00024 Complex Complex::operator+(const Complex &op2) const
00025 {
00026 Complex res(re + op2.re, im + op2.im);
00027 return res;
00028 }
00029
00030 Complex Complex::operator-(const Complex &op2) const
00031 {
00032 Complex res(re - op2.re, im - op2.im);
00033 return res;
00034 }
00035
00036 Complex Complex::operator*(const Complex &op2) const
00037 {
00038 Complex res(re * op2.re - im * op2.im,
00039 re * op2.im + im * op2.re);
00040 return res;
00041 }
00042
00043 Complex Complex::operator/(const Complex &op2) const
00044 {
00045 double dvs = op2.GetNorm();
00046 Complex res((re * op2.re + im * op2.im) / dvs,
00047 (im * op2.re - re * op2.im) / dvs);
00048 return res;
00049 }
00050
00051 void Complex::operator+=(const Complex &op2)
00052 {
00053 re += op2.re;
00054 im += op2.im;
00055 }
00056
00057 void Complex::operator*=(const Complex &op2)
00058 {
00059 double tmp;
00060 tmp = re * op2.re - im * op2.im;
00061 im = re * op2.im + im * op2.re;
00062 re = tmp;
00063 }
00064
00065 void Complex::operator/=(const Complex &op2) {
00066 double tmp, dvs = op2.GetNorm();
00067 tmp = (re * op2.re + im * op2.im) / dvs;
00068 im = (im * op2.re - re * op2.im) / dvs;
00069 re = tmp;
00070 }
00071
00072
00073
00074 FourierTransform::FourierTransform(unsigned _k)
00075 : k(_k), rev(0)
00076 {
00077 N = 1 << k;
00078 }
00079
00080 FourierTransform::~FourierTransform()
00081 {
00082 if(rev) {
00083 delete [] rev;
00084 }
00085 }
00086
00087 void FourierTransform::set_reverse()
00088 {
00089 unsigned i, h;
00090 h = -1;
00091 rev[0] = 0;
00092 for(i = 1; i < N; ++i) {
00093
00094 if((i & (i - 1)) == 0) {
00095
00096 h++;
00097 }
00098 rev[i] = rev[i ^ (1 << h)];
00099 rev[i] |= (1 << (k - h - 1));
00100 }
00101 }
00102
00103 void FourierTransform::Matvec(const Complex *vec, Complex *res,
00104 mv_mode mode) const
00105 {
00106 unsigned m, p;
00107 double a = -2.0 * M_PI / N;
00108 if(mode == conj) {
00109 a *= -1;
00110 }
00111 Complex w;
00112 for(m = 0; m < N; ++m) {
00113 res[m] = 0;
00114 for(p = 0; p < N; ++p) {
00115 w = Complex(cos(a * p * m), sin(a * p * m));
00116 res[m] += vec[p] * w;
00117 }
00118 }
00119 }
00120
00121 void FourierTransform::MatvecFast(const Complex *vec, Complex *res,
00122 mv_mode mode)
00123 {
00124 unsigned m, p, j;
00125 Complex t, u, w, wm;
00126 double a = -2.0 * M_PI;
00127 if(mode == conj) {
00128 a *= -1;
00129 }
00130 if(!rev) {
00131 rev = new unsigned[N];
00132 set_reverse();
00133 }
00134 for(m = 0; m < N; ++m) {
00135 res[m] = vec[rev[m]];
00136 }
00137
00138 for(m = 1; m <= N; m *= 2) {
00139 wm = Complex(cos(a / m), sin(a / m));
00140 for(p = 0; p < N; p += m) {
00141 w = 1;
00142 for(j = 0; j < m / 2; ++j) {
00143 t = w * res[p + j + m / 2];
00144 u = res[p + j];
00145 res[p + j] = u + t;
00146 res[p + j + m / 2] = u - t;
00147 w *= wm;
00148 }
00149 }
00150 }
00151 }