// fft.cpp - impelementation of class // of fast Fourier transform - FFT #include "fft.h" #ifdef __linux__ #include #include class ComplexDouble { private: double re; double im; public: explicit constexpr ComplexDouble () noexcept : re(0.0), im(0.0) {} //!< konstruktor explicit constexpr ComplexDouble (const double x, const double y) noexcept : re(x), im(y) {} //!< konstruktor void setc (double x, double y) {re = x; im = y;}; //!< nastavení hodnoty void operator&= (const ComplexDouble & x) { //!< přičti a normuj na jednotku re += x.re; im += x.im; double a (re*re + im*im); a = 1.0 / ::sqrt (a); re *= a; im *= a; }; void operator*= (const ComplexDouble & x) { //!< znásob komplexním číslem const double a(x.re*re - x.im*im); im = x.re*im + x.im*re; re = a; }; double gre (void) const {return re;}; //!< návrat reálné části double gim (void) const {return im;}; //!< návrat imaginární části }; static unsigned short Reverse [1 << FFTORDER]; static complex Ones [(1 << FFTORDER) >> 1]; // s tímhle nebude potřeba se zabývat - prosté přehození pořadí bitů // Zde do pole pouze pro zrychlení (není pro to instrukce procesoru) void IFFT::PrecomputeOrder (void) { const unsigned int half = N / 2; const unsigned int last = N - 1; unsigned j = 0u; for (unsigned i = 0; i < last; i++) { Reverse [i] = j; // printf ("i = %d, j = %d\n", i, j); unsigned k = half; while (k <= j) { j -= k; k /= 2; } j += k; } Reverse [last] = last; } void IFFT::PrecomputeOnes (void) { static constexpr double coeff = double((1UL << (HSHIFT)) - 1); const unsigned int half = N >> 1; unsigned int i,j,k; real reo, imo; // Tady to spočteme trochu jinak, bez použití sin a cos (ale stejně je potřeba sqrt) ComplexDouble reone (1.0, 0.0), xx; // reálná jednotka, pomocná proměnná ComplexDouble * aa = new ComplexDouble [M]; // pole komplexních jednotek - základní rotace k = M-1; aa[0].setc (0.0, 1.0); // nultá rotace je o 90st. - komplexní jednotka for (i=1; i> 1] = {"); const unsigned H = N >> 1; for (unsigned n=0u; n> 12, 0); // rozšířit z 12 na 16 bitů pro FFT } } #endif IFFT::IFFT() noexcept : reverse(Reverse), ones(reinterpret_cast (Ones)) { } // FORWARD FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output bool IFFT::Forward (complex * const Data) const { if (!Data) return false; Rearrange (Data); Perform (Data, false); return true; } // INVERSE FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output bool IFFT::Inverse (complex * const Data) const { if (!Data) return false; Rearrange (Data); Perform (Data, true); return true; } // Změna pořadí ve vstupním poli void IFFT::Rearrange (complex * const Data) const { unsigned int Target, Position; complex Temp; for (Position = 0; Position < N; Position++) { Target = reverse [Position]; if (Target > Position) { Temp = Data [Target]; Data [Target] = Data [Position]; Data [Position] = Temp; } } } // FFT implementation void IFFT::Perform (complex * const Data, const bool Inverse) const { unsigned int Dest, Step, Jump, Group, Pair, Incr, Roti; complex Factor, Produc; static constexpr real Shift = 1; // Úprava velikosti při forwardu, jinak to přeteče for (Step = 1; Step < N; Step <<= 1) { // 1,2,...N/2 // printf ("1.cyklus Step=%4d\n", Step); Jump = Step << 1; // 2,4,...N Incr = N / Jump; // N/2....1 Roti = 0; for (Group = 0; Group < Step; Group++) { // printf (" 2.cyklus Group=%4d, rotace=%4d\n", Group, Roti); for (Pair = Group; Pair < N; Pair += Jump) { Dest = Pair + Step; Factor = ones [Roti]; Produc = Data [Pair]; if (!Inverse) { Factor.conj(); Factor >>= Shift; // shifty s integer doprava o 1 bit Produc >>= Shift; // Zároveň normalizace (není potřeba při reverzi). } Factor *= Data [Dest]; // printf (" 3.cyklus Pair=%4d, Dest =%4d\n", Pair, Dest); Data [Pair].add (Produc, Factor); Data [Dest].sub (Produc, Factor); } Roti += Incr; } } }