diff --git a/DFT.cc b/DFT.cc index c31c9e9d8aa4baf276ee39c6548b6175e657a5ca..da5e5bb75346616fffa0ac70a2e706ac48517a18 100644 --- a/DFT.cc +++ b/DFT.cc @@ -1,82 +1,86 @@ -#include <complex> #include <cmath> #include <iomanip> #include "Header files/DFT.h" #include <iostream> #include <fstream> -#include <string> using namespace std::complex_literals; +const double PI{std::acos(-1)}; + +// Alg start --------------------------------------------------------------------------------------- +std::vector<std::complex<double>> dft(std::vector<std::complex<double>> f,int n,int flag) +{ + std::vector<std::complex<double>> answer; + for(int i = 0; i<n; i++) + { + std::complex<double> s = 0; + for(int j = 0; j<n; j++) + { + std::complex<double> exponent = static_cast<double> (i*j); + s += std::exp(flag*2*PI*1i*exponent/static_cast<double>(n)) * f[j]; + } + answer.push_back(s / static_cast<double>(std::sqrt(n))); + } + + return answer; +} +// Alg slut --------------------------------------------------------------------------------------- int main() { - // PI - const double PI{std::acos(-1)}; + DFT call; + // inFile innehåller uHatt data och outFile är resulterande filen + std::string inFile{"sinus.txt"}; + std::string outFile{"inversSinusDFT.txt"}; + int const n{16}; + + // Får data från inFile och lägger på en vektor + std::vector<std::complex<double>> inputVector = call.getInput(inFile,n); + // Anroppar alg ---------------------------------------------------------- + std::vector<std::complex<double>> transfer = dft(inputVector,n,-1); + std::vector<std::complex<double>> invTransfer = dft(transfer,n,1); + // ----------------------------------------------------------------------------------- + call.printToFile(invTransfer,outFile,n); + std::cout << "DFT done"<<'\n'; + return 0; +} + + + - // inFile innehåller uHatt data och outFile är resulterande filen - std::string inFile{"sinus.txt"}; - std::string outFile{"inversSinusDFT.txt"}; - - // Perioden för funktionen - double T{2*PI}; - - int const n{20}; - std::complex<double> inputFunction[n]; - std::complex<double> F[n][n]; - std::complex<double> funcTransf[n]; - std::complex<double> inverseFuncTransf[n]; +std::vector<std::complex<double>> DFT::getInput(std::string inFile, int n) +{ + std::vector<std::complex<double>> inputVector; + // Hämtar data och sätter den på en vector + int loop = 0; std::string dataLine; std::ifstream functionData (inFile); - - // while-loop variabel samt element i - int loop = 0; std::complex<double> element; - if (functionData.is_open()) { while ((std::getline (functionData,dataLine)) && (loop < n) ) { std::istringstream is(dataLine); is >> element; - inputFunction[loop] = element; + inputVector.push_back(element); loop++; } functionData.close(); } + return inputVector; +} - for(int i = 0; i<n; i++) - { - for(int j = 0; j<n; j++) - { - std::complex<double> exponent = static_cast<double> (i*j); - F[j][i] = std::exp(-1.0*T*1i*exponent/(n+1.0)); - funcTransf[i] = funcTransf[i] + F[j][i]*inputFunction[i]; - } - - } - - for(int i = 0; i<n; i++) - { - for(int j = 0; j<n; j++) - { - std::complex<double> exponent = static_cast<double> (i*j); - F[j][i] = std::exp(1.0*T*1i*exponent/(n+1.0)); - inverseFuncTransf[i] = inverseFuncTransf[i] + F[j][i]*funcTransf[i]; - } - } - - +void DFT::printToFile(std::vector<std::complex<double>> printVector, std::string fileName, int n) +{ + // Skriver ut inversFuncTransf till en fil std::ofstream resultFile; - resultFile.open(outFile); + resultFile.open(fileName); // Sätter önskad antal decimaler resultFile << std::fixed << std::setprecision(10); for (int i=0;i<n;i++) { - resultFile << inverseFuncTransf[i].real() << "," << inverseFuncTransf[i].imag() << '\n'; + resultFile << printVector[i].real() << "," << printVector[i].imag() << '\n'; } resultFile.close(); - std::cout << "DFT done"<<'\n'; - return 0; -} - +} \ No newline at end of file diff --git a/FFT.cc b/FFT.cc new file mode 100644 index 0000000000000000000000000000000000000000..8765e389159d6d5775c9728b537de307ae2a670e --- /dev/null +++ b/FFT.cc @@ -0,0 +1,98 @@ +#include <complex> +#include <cmath> +#include <iomanip> +#include "Header files/FFT.h" +#include <iostream> +#include <fstream> +#include <string> +#include <bits/stdc++.h> +using namespace std::complex_literals; + +int main() +{ + // PI + const double PI{std::acos(-1)}; + + // inFile innehåller uHatt data och outFile är resulterande filen + std::string inFile{"sinus.txt"}; + std::string outFile{"sinusFFT.txt"}; + + // Perioden för funktionen + double T{2*PI}; + int const n{16}; + std::vector<std::complex<double>> inputVector; + std::complex<double> funcTransf[n]; + + + // Hämtar data och sätter den på en vector + int loop = 0; + std::string dataLine; + std::ifstream functionData (inFile); + std::complex<double> element; + + if (functionData.is_open()) + { + while ((std::getline (functionData,dataLine)) && (loop < n) ) + { + std::istringstream is(dataLine); + is >> element; + inputVector.push_back(element); + loop++; + } + functionData.close(); + } + + // alg start ------------------------------------------------------------- + std::complex<double> my[n]; + for(int i=0;i<n;i++) + { + my[i]=std::exp(-1i*T*static_cast<double> (i)/static_cast<double> (n)); + } + + + // "Bitreversal" + std::stable_partition(std::begin(inputVector), std::end(inputVector), + [&inputVector](std::complex<double> const& a){return 0==((&a-&inputVector[0])%2);}); + + + // F2 mult. + for(int i=0;i<n;i+=2) + { + funcTransf[i]=inputVector[i]+inputVector[i+1]; + funcTransf[i+1]=inputVector[i]-inputVector[i+1]; + } + + // I and D mult. + for(int m=0;m<n;m++) + { + std::complex<double> s = 0; + if(m % 2 == 0) + { + for(int j=0;j<n;j+=4) + { + s = s + funcTransf[j] + std::pow(my[m],m) * funcTransf[j+2]; + } + } + else + { + for(int j=1;j<n;j+=4) + { + s = s + funcTransf[j] + std::pow(my[m],m) * funcTransf[j+2]; + } + } + funcTransf[m]= s / static_cast<double> (std::sqrt(n)); + } + // Alg end ---------------------------------------------------------------- + + std::ofstream resultFile; + resultFile.open(outFile); + // Sätter önskad antal decimaler + resultFile << std::fixed << std::setprecision(10); + for (int i=0;i<n;i++) + { + resultFile << funcTransf[i].real() << "," << funcTransf[i].imag() << '\n'; + } + resultFile.close(); + std::cout << "FFT done"<<'\n'; + return 0; +} \ No newline at end of file diff --git a/Header files/DFT.h b/Header files/DFT.h index 0f8bf18c6a63aa5874e20182121085658ea66c8f..d55533fd49e1787eab65f65602db97ee2a04eb0b 100644 --- a/Header files/DFT.h +++ b/Header files/DFT.h @@ -1,7 +1,11 @@ #include <complex> +#include <vector> +#include <string> class DFT { public: + void printToFile(std::vector<std::complex<double>> printVector, std::string fileName, int n); + std::vector<std::complex<double>> getInput(std::string inFile, int n); private: }; diff --git a/Header files/FFT.h b/Header files/FFT.h new file mode 100644 index 0000000000000000000000000000000000000000..8fe06a9eb6a1cd40108d27e940b4ac90b77b95d1 --- /dev/null +++ b/Header files/FFT.h @@ -0,0 +1,7 @@ +#include <complex> + +class FFT +{ +public: +private: +}; diff --git a/Header files/RECFFT.h b/Header files/RECFFT.h new file mode 100644 index 0000000000000000000000000000000000000000..312ee57add95dc09a46c311e597e5a486a435baf --- /dev/null +++ b/Header files/RECFFT.h @@ -0,0 +1,11 @@ +#include <complex> +#include <vector> +#include <string> + +class RECFFT +{ +public: + void printToFile(std::vector<std::complex<double>> printVector, std::string fileName, int n); + std::vector<std::complex<double>> getInput(std::string inFile, int n); +private: +}; diff --git a/PlotData.py b/PlotData.py index e8754785ef91680081cf748e69c8c175fe1a34d9..389ce3b2a88d312855d613ad10fcf8293a5bf350 100644 --- a/PlotData.py +++ b/PlotData.py @@ -4,10 +4,12 @@ import numpy as np filename0 = 'sinus.txt' filename1 = 'inversSinusDFT.txt' filename2 = 'inversSinusFFTW.txt' +filename3 = 'inversSinusRECFFT.txt' name0 = filename0[:len(filename0)-4] name1 = filename1[:len(filename1)-4] name2 = filename2[:len(filename2)-4] +name3 = filename3[:len(filename3)-4] # Tar fram data och plotar datan i filename0 mot x=1...len() Y = np.loadtxt(filename0, unpack=True) @@ -27,6 +29,12 @@ XHat2 = list(range(0,len((YHat2)))) plt.plot(XHat2, YHat2, label = name2, color='k') plt.scatter(XHat2, YHat2, color='k') +# Tar fram data och plotar datan i filename2 mot xHat2=1...len() +YHat3,Imaginary = np.loadtxt(filename3, delimiter =',',unpack=True) +XHat3 = list(range(0,len((YHat3)))) +plt.plot(XHat3, YHat3, label = name3, color='c') +plt.scatter(XHat3, YHat3, color='c') + plt.legend() plt.title(name0) plt.xlabel('X') diff --git a/RECFFT.cc b/RECFFT.cc new file mode 100644 index 0000000000000000000000000000000000000000..b2ddd016a8e735cbcee6822c48800c6e78226527 --- /dev/null +++ b/RECFFT.cc @@ -0,0 +1,122 @@ +#include <complex> +#include <cmath> +#include <iomanip> +#include "Header files/RECFFT.h" +#include <iostream> +#include <fstream> +#include <string> +#include <vector> +using namespace std::complex_literals; + +const double PI{std::acos(-1)}; + +// Alg start ----------------------------------------------------------------------------------------------- +std::vector<std::complex<double>> fftrec(std::vector<std::complex<double>> f,int NN,std::vector<std::complex<double>> fftv, int flag) +{ + int N = f.size(); + std::complex<double> w = std::exp(flag*2*PI*1i/static_cast<double> (N)); + if(N==2) + { + for(int i=0; i <= NN-1; i++) + { + fftv[i] = f[0]+std::pow(w,-NN/2+i)*f[2]; + } + } + else + { + std::vector<std::complex<double>> a1; + std::vector<std::complex<double>> b1; + for(int i=0;i<=N;i++) + { + if(i%2==0) + { + a1.push_back(f[i]); + } + else + { + b1.push_back(f[i]); + } + } + std::vector<std::complex<double>> a2 = fftrec(a1,NN,fftv,flag); + std::vector<std::complex<double>> b2 = fftrec(b1,NN,fftv,flag); + for(int k = 0; k <= NN-1; k++) + { + fftv[k] = a2[k] + b2[k]*std::pow(w,k-NN/2.0); + } + } + return fftv; +} +// Alg slut ----------------------------------------------------------------------------------------------- + +int main() +{ + RECFFT call; + std::string inFile{"sinus.txt"}; + std::string outFile{"inversSinusRECFFT.txt"}; + + int const n{16}; + // Får data från inFile och lägger på en vektor + std::vector<std::complex<double>> inputVector = call.getInput(inFile,n); + + // Skapar två vektorer av storlek n med nollor i sig + std::vector<std::complex<double>> fftv1; + std::vector<std::complex<double>> fftv2; + for(int i=0;i<n;i++) + { + fftv1.push_back(0); + fftv2.push_back(0); + } + + // Anroppar alg ---------------------------------------------------------------- + std::vector<std::complex<double>> transf = fftrec(inputVector,n,fftv1,-1); + std::vector<std::complex<double>> invTransf = fftrec(transf,n,fftv2,1); + // ----------------------------------------------------------------------------- + call.printToFile(invTransf,outFile,n); + + std::cout<<"RECFFT done"<<'\n'; + +} + + + + + + + + +std::vector<std::complex<double>> RECFFT::getInput(std::string inFile, int n) +{ + std::vector<std::complex<double>> inputVector; + // Hämtar data och sätter den på en vector + int loop = 0; + std::string dataLine; + std::ifstream functionData (inFile); + std::complex<double> element; + + if (functionData.is_open()) + { + while ((std::getline (functionData,dataLine)) && (loop < n) ) + { + std::istringstream is(dataLine); + is >> element; + inputVector.push_back(element); + loop++; + } + functionData.close(); + } + return inputVector; +} + +void RECFFT::printToFile(std::vector<std::complex<double>> printVector, std::string fileName, int n) +{ + // Skriver ut inversFuncTransf till en fil + std::ofstream resultFile; + resultFile.open(fileName); + // Sätter önskad antal decimaler + resultFile << std::fixed << std::setprecision(10); + for (int i=0;i<n;i++) + { + resultFile << printVector[i].real() << "," << printVector[i].imag() << '\n'; + } + resultFile.close(); +} \ No newline at end of file diff --git a/a.out b/a.out index 634c2f9334a48227c91bb4fc0d65bfa8266b8775..b2d99b83c42f7267193543eec5e9786faa298bda 100755 Binary files a/a.out and b/a.out differ diff --git a/inversSinusDFT.txt b/inversSinusDFT.txt index 936556e578e0d655c6b739af2e08970c999ff6e9..20eb3e7c965afb5c6a38b137db392dbb7393c3a6 100644 --- a/inversSinusDFT.txt +++ b/inversSinusDFT.txt @@ -2,19 +2,15 @@ 0.8414709848,-0.0000000000 0.9092974268,0.0000000000 0.1411200081,-0.0000000000 --0.7568024953,-0.0000000000 +-0.7568024953,0.0000000000 -0.9589242747,0.0000000000 --0.2794154982,-0.0000000000 -0.6569865987,0.0000000000 -0.9893582466,-0.0000000000 +-0.2794154982,0.0000000000 +0.6569865987,-0.0000000000 +0.9893582466,0.0000000000 0.4121184852,0.0000000000 -0.5440211109,-0.0000000000 --0.9999902066,-0.0000000000 +-0.9999902066,0.0000000000 -0.5365729180,-0.0000000000 -0.4201670368,0.0000000000 -0.9906073557,-0.0000000000 -0.6502878402,-0.0000000000 --0.2879033167,-0.0000000000 --0.9613974919,-0.0000000000 --0.7509872468,0.0000000000 -0.1498772097,0.0000000000 +0.4201670368,-0.0000000000 +0.9906073557,0.0000000000 +0.6502878402,0.0000000000 diff --git a/inversSinusRECFFT.txt b/inversSinusRECFFT.txt new file mode 100644 index 0000000000000000000000000000000000000000..696c25a14291906db305be413574579273801acf --- /dev/null +++ b/inversSinusRECFFT.txt @@ -0,0 +1,16 @@ +9.1398206044,-5.4536844553 +9.6809334767,-2.9346356508 +-4.8533132756,5.9696298177 +3.1631893166,-3.1673031952 +-1.0681141449,-3.9889275745 +2.5085516570,4.2659503988 +-2.0451485834,-2.2295090922 +-0.9188801268,0.4380280064 +-0.9681317764,-0.3772564925 +-9.1997883841,3.8848288233 +-1.0035716440,-21.6139703680 +10.2159678974,8.3013102465 +0.3726256441,0.3068522515 +-12.6332527731,5.2140573888 +-3.2499819989,-13.7342402161 +4.0199196309,-4.8413742979 diff --git a/sinusDFT.txt b/sinusDFT.txt new file mode 100644 index 0000000000000000000000000000000000000000..f036fd0dd46b3c9fcc17d3f176827db0e10b9389 --- /dev/null +++ b/sinusDFT.txt @@ -0,0 +1,16 @@ +0.4839218698,0.0000000000 +0.5728138574,0.0359040572 +1.2704524334,0.1525576481 +-1.2704178589,-0.2109423635 +-0.3451213350,-0.0666069980 +-0.1871078472,-0.0360227643 +-0.1290856034,-0.0204001227 +-0.1046463980,-0.0094059210 +-0.0976963665,0.0000000000 +-0.1046463980,0.0094059210 +-0.1290856034,0.0204001227 +-0.1871078472,0.0360227643 +-0.3451213350,0.0666069980 +-1.2704178589,0.2109423635 +1.2704524334,-0.1525576481 +0.5728138574,-0.0359040572 diff --git a/sinusFFT.txt b/sinusFFT.txt new file mode 100644 index 0000000000000000000000000000000000000000..2f05a2aa79188f72a07ca10a754d392bc73841de --- /dev/null +++ b/sinusFFT.txt @@ -0,0 +1,16 @@ +0.4839218698,0.0000000000 +-0.2052369891,0.3683901055 +0.3309945693,-0.0465834113 +1.7495228981,-0.2762925791 +0.7193811213,-0.0116458528 +1.2616069280,0.0005730662 +0.3878597128,-0.3912980152 +0.3907509831,0.1837652531 +0.7713484365,-0.1123818198 +0.8513163208,0.0427193630 +0.2372245699,-0.4028497890 +0.7708398190,0.1524420635 +0.8533283588,-0.2411897220 +0.2049880275,0.3455750247 +0.4968121427,-0.5979377809 +1.1531292822,-0.0533400012 diff --git a/sinusRECFFT.txt b/sinusRECFFT.txt new file mode 100644 index 0000000000000000000000000000000000000000..fe98e1cfc9d914c762b6726756f3671508adf047 --- /dev/null +++ b/sinusRECFFT.txt @@ -0,0 +1,16 @@ +-0.4512556488,-2.0328835177 +-1.0583024753,1.6556270252 +-0.5953326772,-2.0157905705 +0.5477123041,0.7768255909 +-5.3680736541,0.6023996661 +3.3988211217,3.4049866271 +0.5281248517,0.9961761991 +1.1167614080,-0.5013865645 +1.2853996392,0.0000000000 +1.1167614080,0.5013865645 +0.5281248517,-0.9961761991 +3.3988211217,-3.4049866271 +-5.3680736541,-0.6023996661 +0.5477123041,-0.7768255909 +-0.5953326772,2.0157905705 +-1.0583024753,-1.6556270252