├── .gitattributes ├── .gitignore ├── README.md ├── SIMD.sln ├── SIMD ├── SIMD.cpp ├── SIMD.vcxproj ├── SIMD.vcxproj.filters └── fft_1024.txt ├── complex_mul.png ├── task1_solution.md └── task2_solution.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fft_simd 2 | A simple demo shows how to use the SIMD,*Single Instruction Multiple Data*, to optimize and accelerate the FFT algorithm. 3 | 4 | - [x] **Task 1.** Implement standard DFT algorithm with C++. See [task1_solution](https://github.com/jagger2048/fft_simd/blob/master/task1_solution.md) 5 | 6 | - [x] **Task 2.** Rewrite the DFT with Cooley–Tukey FFT algorithm. See [task2_solution](https://github.com/jagger2048/fft_simd/blob/master/task2_solution.md) 7 | 8 | - [x] **Task 3.** Ues SIMD to accelerate the FFT alogrithm. See blews in this page. 9 | 10 | - [x] **Task 4.** Make a time consuming contrast among these algorithms.See the table as blews: 11 | 12 | | Algorithm | Time consum | 13 | | ------------- | ----------------------------------------------- | 14 | | Standard dft | 606 ms | 15 | | FFT | 74 ms (out-off-place algorithm) ,7ms (in-place) | 16 | | FFT with SIMD | 1.011 ms | 17 | 18 | ---------- 19 | 20 | ### **Introduction to SIMD** 21 | 22 | Referecnr [the wiki of SIMD](https://en.wikipedia.org/wiki/SIMD). 23 | 24 | ### **SIMD instructions chosen** 25 | 26 | We use SSE2 in this project. SSE2 (Streaming SIMD Extensions 2) is one of the Intel SIMD, it supports two double-precision-floate operations as its MMX rigister are extended from 64 to 128 bits. 27 | 28 | 29 | 30 | ### **SIMD instructions exercise** 31 | 32 | To be familiar with SSE2 instructions, we use SSE2 to compute the complex multiplication as an exercise. 33 | 34 | Complex multiplication can be described as follows: 35 | 36 | 37 | $$ 38 | if A = a+b*j,B=c+d*j,then,A*B=(ac-bd)+(bc+ad)*j 39 | $$ 40 | 41 | 42 | We use a figure to summary and described the complex multiplication using SSE2: 43 | 44 | ![complex_mul](https://github.com/jagger2048/fft_simd/blob/master/complex_mul.png) 45 | 46 | You can find the code in the **complex_mul(double * A, double * B)** function in the project. 47 | 48 | 49 | 50 | ### **Using SIMD to accelerate the FFT** 51 | 52 | The FFT algorithm was introduced in [task2_solution](), reviewing the codes, we can find that the combing part consum most time. So we can use SIMD to rewrite this part. Blew is the orginal code: 53 | 54 | ```c++ 55 | ... 56 | // combine the odd and even parts 57 | complex e = X[k]; // even 58 | complex o = X[k + N / 2]; // odd 59 | // w is the "twiddle-factor" 60 | complex w = exp(complex(0, -2.*PI*k / N)); 61 | X[k] = e + w * o; 62 | X[k + N / 2] = e - w * o; 63 | ... 64 | ``` 65 | 66 | Well, parameters e,o and w are complex type, and our goal becomes using SIMD to process a complex addition, a complex subtraction and a complex multiplication. 67 | 68 | - First, using a struct type ,***comp***,to replace the C++ built-in complex type. 69 | 70 | ```c++ 71 | struct comp { 72 | double real =0; 73 | double imag = 0; 74 | }; 75 | ``` 76 | 77 | The comp struct pack two double-type value, real part and imag part. So we can use a *comp-pointer* to access a complex number. In fact, a *comp* takes up 8 bytes,128 bit, and it can be loaded into a SSE2's MMX rigister. 78 | 79 | - Rewrite the original codes with SSE2 instructions. 80 | 81 | ```c++ 82 | __m128d o = _mm_load_pd( (double *)&X[k + N/2 ] ); // odd 83 | double cc = cos(-2.*PI*k / N); 84 | double ss = sin(-2.*PI*k / N); 85 | __m128d wr = _mm_set_pd( cc,cc ); // cc 86 | __m128d wi = _mm_set_pd( ss, ss ); // dd 87 | // compute the w*o 88 | wr = _mm_mul_pd(o,wr); // ac|bc 89 | __m128d n1 = _mm_shuffle_pd(o,o,_MM_SHUFFLE2(0,1) ); // invert 90 | wi = _mm_mul_pd(n1, wi); // bd|ad 91 | n1 = _mm_sub_pd(wr, wi); // ac-bd|x 92 | wr = _mm_add_pd(wr, wi); // x|bc+ad 93 | n1 = _mm_shuffle_pd(n1,wr,_MM_SHUFFLE2(1,0));// select ac-bd|bc+ad 94 | 95 | o = _mm_load_pd((double *)&X[k]); // load even part 96 | wr = _mm_add_pd(o, n1); // compute even part, X_e + w * X_o; 97 | wi = _mm_sub_pd(o, n1); // compute odd part, X_e - w * X_o; 98 | _mm_store_pd((double *)&X[k],wr); 99 | _mm_store_pd((double *)&X[k + N/2],wi); 100 | ``` 101 | 102 | We use 4 MMX rigisters, and cost 4 load/store , 2 set ,6 ops( +-*/) , 2 reorder operations. It's obvious that the time consuming of 1024-point FFT was decreased from 7ms to 1.01ms ! 103 | 104 | 105 | 106 | ---------------------- 107 | 108 | ### Some useful link:. 109 | 110 | **FFT:** 111 | 112 | https://en.wikipedia.org/wiki/Fast_Fourier_transform Introduction to FFT 113 | 114 | https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm Cooley–Tukey FFT algorithm 115 | 116 | **SIMD:** 117 | 118 | SIMD and sse2 introduction: 119 | 120 | ​ https://www.intel.com/content/www/us/en/support/articles/000005779/processors.html 121 | 122 | **Intel(R) C++ Compiler Intrinsics Reference - Intel® Software:** 123 | 124 | ​ https://software.intel.com/sites/default/files/ee/11/6373 125 | 126 | **Streaming SIMD Extensions 2 Instructions:** 127 | 128 | ​ https://msdn.microsoft.com/zh-cn/library/kcwz153a%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 129 | 130 | Intrinsics Guide: 131 | 132 | ​ https://software.intel.com/sites/landingpage/IntrinsicsGuide/#cats=Load&expand=3296 133 | -------------------------------------------------------------------------------- /SIMD.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2000 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SIMD", "SIMD\SIMD.vcxproj", "{139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Debug|x64.ActiveCfg = Debug|x64 17 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Debug|x64.Build.0 = Debug|x64 18 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Debug|x86.ActiveCfg = Debug|Win32 19 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Debug|x86.Build.0 = Debug|Win32 20 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Release|x64.ActiveCfg = Release|x64 21 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Release|x64.Build.0 = Release|x64 22 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Release|x86.ActiveCfg = Release|Win32 23 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E3E1FF75-B69C-4DC7-95F4-7833423EA8D2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SIMD/SIMD.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jagger2048/fft_simd/7929762d5c4caffc5b7246f5dcab6919c4e6a711/SIMD/SIMD.cpp -------------------------------------------------------------------------------- /SIMD/SIMD.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {139C6AB7-15A4-49CD-8B08-5FCBF60BE7E4} 24 | Win32Proj 25 | SIMD 26 | 10.0.17134.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | 100 | 101 | Use 102 | Level3 103 | Disabled 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Use 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | Use 134 | Level3 135 | MaxSpeed 136 | true 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | NotUsing 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /SIMD/SIMD.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /SIMD/fft_1024.txt: -------------------------------------------------------------------------------- 1 | 0.0878753662109375 2 | 0.0903930664062500 3 | 0.0926055908203125 4 | 0.0951538085937500 5 | 0.0977478027343750 6 | 0.100296020507813 7 | 0.102767944335938 8 | 0.105133056640625 9 | 0.107299804687500 10 | 0.109924316406250 11 | 0.111343383789063 12 | 0.112335205078125 13 | 0.112228393554688 14 | 0.112533569335938 15 | 0.113128662109375 16 | 0.114044189453125 17 | 0.113952636718750 18 | 0.113372802734375 19 | 0.112319946289063 20 | 0.110733032226563 21 | 0.108917236328125 22 | 0.107040405273438 23 | 0.103973388671875 24 | 0.0996093750000000 25 | 0.0949859619140625 26 | 0.0908813476562500 27 | 0.0871734619140625 28 | 0.0841522216796875 29 | 0.0805511474609375 30 | 0.0776824951171875 31 | 0.0751495361328125 32 | 0.0729522705078125 33 | 0.0717163085937500 34 | 0.0704956054687500 35 | 0.0687561035156250 36 | 0.0675659179687500 37 | 0.0655517578125000 38 | 0.0637207031250000 39 | 0.0618743896484375 40 | 0.0603027343750000 41 | 0.0598907470703125 42 | 0.0600891113281250 43 | 0.0603179931640625 44 | 0.0618896484375000 45 | 0.0627899169921875 46 | 0.0645446777343750 47 | 0.0661621093750000 48 | 0.0681152343750000 49 | 0.0697479248046875 50 | 0.0718536376953125 51 | 0.0745849609375000 52 | 0.0768127441406250 53 | 0.0792388916015625 54 | 0.0817108154296875 55 | 0.0848693847656250 56 | 0.0881652832031250 57 | 0.0914306640625000 58 | 0.0953979492187500 59 | 0.0994567871093750 60 | 0.103179931640625 61 | 0.107208251953125 62 | 0.109634399414063 63 | 0.111511230468750 64 | 0.112533569335938 65 | 0.113494873046875 66 | 0.114334106445313 67 | 0.115234375000000 68 | 0.115356445312500 69 | 0.116058349609375 70 | 0.116958618164063 71 | 0.117248535156250 72 | 0.117446899414063 73 | 0.116851806640625 74 | 0.115264892578125 75 | 0.114364624023438 76 | 0.112777709960938 77 | 0.110549926757813 78 | 0.108551025390625 79 | 0.106399536132813 80 | 0.104049682617188 81 | 0.101776123046875 82 | 0.100280761718750 83 | 0.0983581542968750 84 | 0.0969848632812500 85 | 0.0962524414062500 86 | 0.0955352783203125 87 | 0.0942382812500000 88 | 0.0931243896484375 89 | 0.0913848876953125 90 | 0.0899963378906250 91 | 0.0876464843750000 92 | 0.0857238769531250 93 | 0.0834655761718750 94 | 0.0819549560546875 95 | 0.0798339843750000 96 | 0.0782318115234375 97 | 0.0773620605468750 98 | 0.0760955810546875 99 | 0.0750732421875000 100 | 0.0738830566406250 101 | 0.0732421875000000 102 | 0.0733337402343750 103 | 0.0738067626953125 104 | 0.0754852294921875 105 | 0.0778808593750000 106 | 0.0803222656250000 107 | 0.0837707519531250 108 | 0.0866394042968750 109 | 0.0898742675781250 110 | 0.0927429199218750 111 | 0.0950012207031250 112 | 0.0973358154296875 113 | 0.0994567871093750 114 | 0.101791381835938 115 | 0.103744506835938 116 | 0.105422973632813 117 | 0.107955932617188 118 | 0.110321044921875 119 | 0.112869262695313 120 | 0.115600585937500 121 | 0.118759155273438 122 | 0.123748779296875 123 | 0.127471923828125 124 | 0.131103515625000 125 | 0.133880615234375 126 | 0.136093139648438 127 | 0.137481689453125 128 | 0.138473510742188 129 | 0.139266967773438 130 | 0.139480590820313 131 | 0.138687133789063 132 | 0.138473510742188 133 | 0.138549804687500 134 | 0.138778686523438 135 | 0.138092041015625 136 | 0.137283325195313 137 | 0.137115478515625 138 | 0.135772705078125 139 | 0.134033203125000 140 | 0.132415771484375 141 | 0.131240844726563 142 | 0.130065917968750 143 | 0.129547119140625 144 | 0.128662109375000 145 | 0.127685546875000 146 | 0.126159667968750 147 | 0.123947143554688 148 | 0.121871948242188 149 | 0.120147705078125 150 | 0.118118286132813 151 | 0.116394042968750 152 | 0.114456176757813 153 | 0.112670898437500 154 | 0.110107421875000 155 | 0.108703613281250 156 | 0.107086181640625 157 | 0.105804443359375 158 | 0.104217529296875 159 | 0.102462768554688 160 | 0.100921630859375 161 | 0.100723266601563 162 | 0.101089477539063 163 | 0.101226806640625 164 | 0.101119995117188 165 | 0.101348876953125 166 | 0.101547241210938 167 | 0.102096557617188 168 | 0.102203369140625 169 | 0.101577758789063 170 | 0.100830078125000 171 | 0.0999450683593750 172 | 0.0997924804687500 173 | 0.0989074707031250 174 | 0.0990600585937500 175 | 0.0995025634765625 176 | 0.0984344482421875 177 | 0.0984802246093750 178 | 0.0981597900390625 179 | 0.0971374511718750 180 | 0.0963897705078125 181 | 0.0944976806640625 182 | 0.0923614501953125 183 | 0.0907592773437500 184 | 0.0890197753906250 185 | 0.0876770019531250 186 | 0.0855407714843750 187 | 0.0825653076171875 188 | 0.0794067382812500 189 | 0.0754852294921875 190 | 0.0721130371093750 191 | 0.0686950683593750 192 | 0.0651550292968750 193 | 0.0619659423828125 194 | 0.0582427978515625 195 | 0.0540161132812500 196 | 0.0505218505859375 197 | 0.0466003417968750 198 | 0.0431823730468750 199 | 0.0397949218750000 200 | 0.0362396240234375 201 | 0.0332336425781250 202 | 0.0303039550781250 203 | 0.0272979736328125 204 | 0.0244445800781250 205 | 0.0210113525390625 206 | 0.0178833007812500 207 | 0.0150299072265625 208 | 0.0130462646484375 209 | 0.0115661621093750 210 | 0.00926208496093750 211 | 0.00762939453125000 212 | 0.00540161132812500 213 | 0.00347900390625000 214 | 0.00109863281250000 215 | -0.00140380859375000 216 | -0.00291442871093750 217 | -0.00367736816406250 218 | -0.00305175781250000 219 | -0.00198364257812500 220 | -0.000244140625000000 221 | 0.00177001953125000 222 | 0.00344848632812500 223 | 0.00482177734375000 224 | 0.00674438476562500 225 | 0.00807189941406250 226 | 0.00962829589843750 227 | 0.0108337402343750 228 | 0.0115203857421875 229 | 0.0125122070312500 230 | 0.0136260986328125 231 | 0.0163421630859375 232 | 0.0182647705078125 233 | 0.0203247070312500 234 | 0.0230407714843750 235 | 0.0260620117187500 236 | 0.0303955078125000 237 | 0.0341796875000000 238 | 0.0370178222656250 239 | 0.0406494140625000 240 | 0.0437469482421875 241 | 0.0467071533203125 242 | 0.0511627197265625 243 | 0.0542449951171875 244 | 0.0573883056640625 245 | 0.0604248046875000 246 | 0.0633239746093750 247 | 0.0665283203125000 248 | 0.0690155029296875 249 | 0.0709686279296875 250 | 0.0716705322265625 251 | 0.0733337402343750 252 | 0.0741729736328125 253 | 0.0761871337890625 254 | 0.0789031982421875 255 | 0.0818786621093750 256 | 0.0853271484375000 257 | 0.0876922607421875 258 | 0.0907440185546875 259 | 0.0943298339843750 260 | 0.0980987548828125 261 | 0.101776123046875 262 | 0.105712890625000 263 | 0.110580444335938 264 | 0.115432739257813 265 | 0.120407104492188 266 | 0.124359130859375 267 | 0.128662109375000 268 | 0.134124755859375 269 | 0.139846801757813 270 | 0.145843505859375 271 | 0.151641845703125 272 | 0.157180786132813 273 | 0.162826538085938 274 | 0.169525146484375 275 | 0.175231933593750 276 | 0.180740356445313 277 | 0.186141967773438 278 | 0.191436767578125 279 | 0.197006225585938 280 | 0.202682495117188 281 | 0.208419799804688 282 | 0.213928222656250 283 | 0.218673706054688 284 | 0.223526000976563 285 | 0.227020263671875 286 | 0.230545043945313 287 | 0.233062744140625 288 | 0.235763549804688 289 | 0.237655639648438 290 | 0.239746093750000 291 | 0.240325927734375 292 | 0.241424560546875 293 | 0.241622924804688 294 | 0.241943359375000 295 | 0.241867065429688 296 | 0.240875244140625 297 | 0.239379882812500 298 | 0.237930297851563 299 | 0.236099243164063 300 | 0.233215332031250 301 | 0.229293823242188 302 | 0.225280761718750 303 | 0.220550537109375 304 | 0.216110229492188 305 | 0.211288452148438 306 | 0.207046508789063 307 | 0.202606201171875 308 | 0.199111938476563 309 | 0.194519042968750 310 | 0.189010620117188 311 | 0.183288574218750 312 | 0.176727294921875 313 | 0.170867919921875 314 | 0.164291381835938 315 | 0.157455444335938 316 | 0.150939941406250 317 | 0.144302368164063 318 | 0.137634277343750 319 | 0.130950927734375 320 | 0.123397827148438 321 | 0.116561889648438 322 | 0.109191894531250 323 | 0.102279663085938 324 | 0.0956268310546875 325 | 0.0879821777343750 326 | 0.0807952880859375 327 | 0.0732574462890625 328 | 0.0661468505859375 329 | 0.0597229003906250 330 | 0.0539093017578125 331 | 0.0479278564453125 332 | 0.0424194335937500 333 | 0.0365142822265625 334 | 0.0306091308593750 335 | 0.0242309570312500 336 | 0.0177459716796875 337 | 0.00985717773437500 338 | 0.00204467773437500 339 | -0.00572204589843750 340 | -0.0131378173828125 341 | -0.0198059082031250 342 | -0.0260314941406250 343 | -0.0318908691406250 344 | -0.0379486083984375 345 | -0.0439910888671875 346 | -0.0499114990234375 347 | -0.0558166503906250 348 | -0.0615844726562500 349 | -0.0677337646484375 350 | -0.0738677978515625 351 | -0.0796508789062500 352 | -0.0860748291015625 353 | -0.0926818847656250 354 | -0.0999145507812500 355 | -0.107803344726563 356 | -0.116058349609375 357 | -0.124343872070313 358 | -0.132858276367188 359 | -0.141738891601563 360 | -0.150955200195313 361 | -0.161499023437500 362 | -0.171768188476563 363 | -0.181015014648438 364 | -0.189849853515625 365 | -0.197814941406250 366 | -0.205383300781250 367 | -0.212387084960938 368 | -0.218429565429688 369 | -0.224777221679688 370 | -0.230621337890625 371 | -0.237152099609375 372 | -0.243301391601563 373 | -0.249465942382813 374 | -0.254928588867188 375 | -0.260452270507813 376 | -0.265914916992188 377 | -0.270812988281250 378 | -0.275878906250000 379 | -0.280517578125000 380 | -0.284194946289063 381 | -0.287139892578125 382 | -0.289138793945313 383 | -0.291717529296875 384 | -0.293029785156250 385 | -0.294464111328125 386 | -0.295120239257813 387 | -0.295135498046875 388 | -0.295257568359375 389 | -0.296142578125000 390 | -0.296966552734375 391 | -0.296524047851563 392 | -0.296127319335938 393 | -0.294586181640625 394 | -0.293624877929688 395 | -0.293060302734375 396 | -0.291961669921875 397 | -0.290542602539063 398 | -0.289001464843750 399 | -0.288253784179688 400 | -0.287139892578125 401 | -0.285461425781250 402 | -0.284500122070313 403 | -0.283615112304688 404 | -0.283782958984375 405 | -0.284545898437500 406 | -0.285217285156250 407 | -0.285583496093750 408 | -0.287277221679688 409 | -0.287948608398438 410 | -0.288894653320313 411 | -0.290267944335938 412 | -0.292144775390625 413 | -0.294677734375000 414 | -0.297195434570313 415 | -0.300796508789063 416 | -0.304443359375000 417 | -0.309020996093750 418 | -0.313491821289063 419 | -0.317703247070313 420 | -0.321121215820313 421 | -0.324371337890625 422 | -0.328231811523438 423 | -0.333084106445313 424 | -0.337066650390625 425 | -0.340896606445313 426 | -0.344360351562500 427 | -0.347137451171875 428 | -0.351028442382813 429 | -0.354751586914063 430 | -0.358413696289063 431 | -0.361633300781250 432 | -0.364868164062500 433 | -0.369262695312500 434 | -0.372344970703125 435 | -0.375244140625000 436 | -0.377807617187500 437 | -0.379516601562500 438 | -0.382232666015625 439 | -0.384368896484375 440 | -0.386367797851563 441 | -0.388046264648438 442 | -0.389602661132813 443 | -0.391540527343750 444 | -0.392501831054688 445 | -0.393188476562500 446 | -0.392745971679688 447 | -0.393035888671875 448 | -0.393692016601563 449 | -0.393188476562500 450 | -0.393356323242188 451 | -0.393051147460938 452 | -0.393310546875000 453 | -0.393035888671875 454 | -0.392135620117188 455 | -0.390319824218750 456 | -0.388397216796875 457 | -0.386138916015625 458 | -0.383728027343750 459 | -0.380477905273438 460 | -0.377349853515625 461 | -0.374588012695313 462 | -0.371490478515625 463 | -0.369033813476563 464 | -0.366195678710938 465 | -0.363830566406250 466 | -0.362731933593750 467 | -0.361495971679688 468 | -0.360870361328125 469 | -0.359130859375000 470 | -0.357543945312500 471 | -0.355758666992188 472 | -0.354064941406250 473 | -0.353790283203125 474 | -0.353271484375000 475 | -0.353439331054688 476 | -0.353851318359375 477 | -0.355010986328125 478 | -0.355728149414063 479 | -0.356170654296875 480 | -0.355316162109375 481 | -0.354736328125000 482 | -0.354782104492188 483 | -0.354141235351563 484 | -0.353103637695313 485 | -0.351791381835938 486 | -0.349456787109375 487 | -0.347290039062500 488 | -0.344009399414063 489 | -0.340621948242188 490 | -0.337188720703125 491 | -0.333389282226563 492 | -0.329696655273438 493 | -0.326339721679688 494 | -0.323120117187500 495 | -0.318786621093750 496 | -0.314056396484375 497 | -0.308288574218750 498 | -0.302612304687500 499 | -0.296066284179688 500 | -0.289016723632813 501 | -0.282562255859375 502 | -0.275634765625000 503 | -0.269943237304688 504 | -0.263366699218750 505 | -0.256515502929688 506 | -0.249053955078125 507 | -0.241928100585938 508 | -0.234512329101563 509 | -0.226699829101563 510 | -0.219924926757813 511 | -0.212829589843750 512 | -0.206085205078125 513 | -0.198425292968750 514 | -0.190216064453125 515 | -0.182144165039063 516 | -0.174301147460938 517 | -0.167556762695313 518 | -0.161239624023438 519 | -0.155426025390625 520 | -0.149765014648438 521 | -0.144256591796875 522 | -0.139602661132813 523 | -0.134796142578125 524 | -0.129974365234375 525 | -0.125732421875000 526 | -0.121749877929688 527 | -0.118148803710938 528 | -0.115020751953125 529 | -0.112075805664063 530 | -0.110046386718750 531 | -0.107818603515625 532 | -0.105392456054688 533 | -0.102905273437500 534 | -0.100234985351563 535 | -0.0978546142578125 536 | -0.0957641601562500 537 | -0.0947265625000000 538 | -0.0936431884765625 539 | -0.0922851562500000 540 | -0.0914001464843750 541 | -0.0903625488281250 542 | -0.0896911621093750 543 | -0.0895996093750000 544 | -0.0895385742187500 545 | -0.0897979736328125 546 | -0.0913238525390625 547 | -0.0919494628906250 548 | -0.0918273925781250 549 | -0.0918579101562500 550 | -0.0918884277343750 551 | -0.0923004150390625 552 | -0.0927886962890625 553 | -0.0928497314453125 554 | -0.0917663574218750 555 | -0.0909271240234375 556 | -0.0897827148437500 557 | -0.0883026123046875 558 | -0.0873107910156250 559 | -0.0855255126953125 560 | -0.0840911865234375 561 | -0.0834350585937500 562 | -0.0834503173828125 563 | -0.0834503173828125 564 | -0.0842895507812500 565 | -0.0845947265625000 566 | -0.0843811035156250 567 | -0.0836486816406250 568 | -0.0821533203125000 569 | -0.0811767578125000 570 | -0.0794525146484375 571 | -0.0771942138671875 572 | -0.0748748779296875 573 | -0.0725555419921875 574 | -0.0716094970703125 575 | -0.0714874267578125 576 | -0.0716552734375000 577 | -0.0718078613281250 578 | -0.0724792480468750 579 | -0.0739288330078125 580 | -0.0758209228515625 581 | -0.0774230957031250 582 | -0.0780029296875000 583 | -0.0785522460937500 584 | -0.0796508789062500 585 | -0.0809936523437500 586 | -0.0832519531250000 587 | -0.0847625732421875 588 | -0.0870208740234375 589 | -0.0891571044921875 590 | -0.0908050537109375 591 | -0.0914154052734375 592 | -0.0913696289062500 593 | -0.0913391113281250 594 | -0.0906066894531250 595 | -0.0905456542968750 596 | -0.0899658203125000 597 | -0.0898437500000000 598 | -0.0909118652343750 599 | -0.0923156738281250 600 | -0.0932312011718750 601 | -0.0937194824218750 602 | -0.0943450927734375 603 | -0.0945129394531250 604 | -0.0939025878906250 605 | -0.0932464599609375 606 | -0.0909576416015625 607 | -0.0887145996093750 608 | -0.0870513916015625 609 | -0.0841064453125000 610 | -0.0814056396484375 611 | -0.0777130126953125 612 | -0.0743103027343750 613 | -0.0705413818359375 614 | -0.0671997070312500 615 | -0.0638275146484375 616 | -0.0597686767578125 617 | -0.0554199218750000 618 | -0.0509643554687500 619 | -0.0458831787109375 620 | -0.0411529541015625 621 | -0.0356140136718750 622 | -0.0304412841796875 623 | -0.0249023437500000 624 | -0.0198211669921875 625 | -0.0153350830078125 626 | -0.0111083984375000 627 | -0.00785827636718750 628 | -0.00352478027343750 629 | -0.000274658203125000 630 | 0.00221252441406250 631 | 0.00570678710937500 632 | 0.00932312011718750 633 | 0.0132293701171875 634 | 0.0165710449218750 635 | 0.0199584960937500 636 | 0.0231628417968750 637 | 0.0266876220703125 638 | 0.0302429199218750 639 | 0.0332031250000000 640 | 0.0357513427734375 641 | 0.0382385253906250 642 | 0.0403900146484375 643 | 0.0418548583984375 644 | 0.0430603027343750 645 | 0.0448760986328125 646 | 0.0468750000000000 647 | 0.0498504638671875 648 | 0.0514678955078125 649 | 0.0530090332031250 650 | 0.0550079345703125 651 | 0.0570983886718750 652 | 0.0584716796875000 653 | 0.0597229003906250 654 | 0.0607757568359375 655 | 0.0620117187500000 656 | 0.0636596679687500 657 | 0.0647888183593750 658 | 0.0657196044921875 659 | 0.0668334960937500 660 | 0.0683288574218750 661 | 0.0704193115234375 662 | 0.0723419189453125 663 | 0.0743713378906250 664 | 0.0759582519531250 665 | 0.0777587890625000 666 | 0.0792236328125000 667 | 0.0818481445312500 668 | 0.0835723876953125 669 | 0.0850830078125000 670 | 0.0867767333984375 671 | 0.0884552001953125 672 | 0.0911560058593750 673 | 0.0927124023437500 674 | 0.0955200195312500 675 | 0.0977325439453125 676 | 0.100173950195313 677 | 0.101425170898438 678 | 0.103942871093750 679 | 0.105697631835938 680 | 0.107864379882813 681 | 0.110412597656250 682 | 0.112335205078125 683 | 0.113983154296875 684 | 0.115158081054688 685 | 0.117004394531250 686 | 0.118225097656250 687 | 0.119689941406250 688 | 0.121612548828125 689 | 0.123077392578125 690 | 0.124649047851563 691 | 0.125457763671875 692 | 0.125274658203125 693 | 0.124740600585938 694 | 0.123443603515625 695 | 0.122222900390625 696 | 0.119842529296875 697 | 0.117126464843750 698 | 0.113845825195313 699 | 0.111206054687500 700 | 0.108154296875000 701 | 0.105621337890625 702 | 0.101959228515625 703 | 0.0991973876953125 704 | 0.0965118408203125 705 | 0.0944671630859375 706 | 0.0926055908203125 707 | 0.0899810791015625 708 | 0.0878143310546875 709 | 0.0850830078125000 710 | 0.0832519531250000 711 | 0.0807647705078125 712 | 0.0788574218750000 713 | 0.0778045654296875 714 | 0.0764007568359375 715 | 0.0765686035156250 716 | 0.0758209228515625 717 | 0.0762176513671875 718 | 0.0767364501953125 719 | 0.0767211914062500 720 | 0.0773773193359375 721 | 0.0789337158203125 722 | 0.0807952880859375 723 | 0.0838012695312500 724 | 0.0876007080078125 725 | 0.0908203125000000 726 | 0.0948028564453125 727 | 0.0989685058593750 728 | 0.103805541992188 729 | 0.109191894531250 730 | 0.114456176757813 731 | 0.119338989257813 732 | 0.123840332031250 733 | 0.129898071289063 734 | 0.135681152343750 735 | 0.141357421875000 736 | 0.145843505859375 737 | 0.150268554687500 738 | 0.154754638671875 739 | 0.158920288085938 740 | 0.163314819335938 741 | 0.166656494140625 742 | 0.169601440429688 743 | 0.172302246093750 744 | 0.174819946289063 745 | 0.177291870117188 746 | 0.178939819335938 747 | 0.181121826171875 748 | 0.182403564453125 749 | 0.183380126953125 750 | 0.184402465820313 751 | 0.184906005859375 752 | 0.186019897460938 753 | 0.186126708984375 754 | 0.186019897460938 755 | 0.185516357421875 756 | 0.185226440429688 757 | 0.185028076171875 758 | 0.185226440429688 759 | 0.184860229492188 760 | 0.183792114257813 761 | 0.182998657226563 762 | 0.182647705078125 763 | 0.182037353515625 764 | 0.181045532226563 765 | 0.180664062500000 766 | 0.179473876953125 767 | 0.179077148437500 768 | 0.178482055664063 769 | 0.177703857421875 770 | 0.178024291992188 771 | 0.177429199218750 772 | 0.177886962890625 773 | 0.178970336914063 774 | 0.180374145507813 775 | 0.181503295898438 776 | 0.183120727539063 777 | 0.185440063476563 778 | 0.188278198242188 779 | 0.192123413085938 780 | 0.195846557617188 781 | 0.199829101562500 782 | 0.203399658203125 783 | 0.206390380859375 784 | 0.208633422851563 785 | 0.210845947265625 786 | 0.212387084960938 787 | 0.214035034179688 788 | 0.216140747070313 789 | 0.218566894531250 790 | 0.220458984375000 791 | 0.222534179687500 792 | 0.225967407226563 793 | 0.229888916015625 794 | 0.234008789062500 795 | 0.238037109375000 796 | 0.242111206054688 797 | 0.245056152343750 798 | 0.247940063476563 799 | 0.249938964843750 800 | 0.251983642578125 801 | 0.253646850585938 802 | 0.254852294921875 803 | 0.255676269531250 804 | 0.255599975585938 805 | 0.255187988281250 806 | 0.255050659179688 807 | 0.254531860351563 808 | 0.254547119140625 809 | 0.253646850585938 810 | 0.251937866210938 811 | 0.249450683593750 812 | 0.247116088867188 813 | 0.244201660156250 814 | 0.239883422851563 815 | 0.235305786132813 816 | 0.230987548828125 817 | 0.226623535156250 818 | 0.222793579101563 819 | 0.220046997070313 820 | 0.217041015625000 821 | 0.213897705078125 822 | 0.211120605468750 823 | 0.207565307617188 824 | 0.203430175781250 825 | 0.198822021484375 826 | 0.194030761718750 827 | 0.189971923828125 828 | 0.185272216796875 829 | 0.181503295898438 830 | 0.177627563476563 831 | 0.174911499023438 832 | 0.172576904296875 833 | 0.171035766601563 834 | 0.169265747070313 835 | 0.167663574218750 836 | 0.166580200195313 837 | 0.164932250976563 838 | 0.162796020507813 839 | 0.160858154296875 840 | 0.158447265625000 841 | 0.156860351562500 842 | 0.155593872070313 843 | 0.154479980468750 844 | 0.153045654296875 845 | 0.152786254882813 846 | 0.152847290039063 847 | 0.153213500976563 848 | 0.153549194335938 849 | 0.152984619140625 850 | 0.152862548828125 851 | 0.152908325195313 852 | 0.152816772460938 853 | 0.152343750000000 854 | 0.152343750000000 855 | 0.152267456054688 856 | 0.152511596679688 857 | 0.152572631835938 858 | 0.152801513671875 859 | 0.152648925781250 860 | 0.152130126953125 861 | 0.151611328125000 862 | 0.150299072265625 863 | 0.148239135742188 864 | 0.146530151367188 865 | 0.143508911132813 866 | 0.140426635742188 867 | 0.136795043945313 868 | 0.132797241210938 869 | 0.129577636718750 870 | 0.126815795898438 871 | 0.123718261718750 872 | 0.121017456054688 873 | 0.117767333984375 874 | 0.114379882812500 875 | 0.111328125000000 876 | 0.107299804687500 877 | 0.103439331054688 878 | 0.0995941162109375 879 | 0.0966949462890625 880 | 0.0937652587890625 881 | 0.0909271240234375 882 | 0.0876007080078125 883 | 0.0847167968750000 884 | 0.0835266113281250 885 | 0.0816192626953125 886 | 0.0801849365234375 887 | 0.0787658691406250 888 | 0.0774536132812500 889 | 0.0773773193359375 890 | 0.0774688720703125 891 | 0.0779724121093750 892 | 0.0783996582031250 893 | 0.0788269042968750 894 | 0.0797119140625000 895 | 0.0807037353515625 896 | 0.0824127197265625 897 | 0.0847167968750000 898 | 0.0873413085937500 899 | 0.0908050537109375 900 | 0.0934753417968750 901 | 0.0961914062500000 902 | 0.0989685058593750 903 | 0.101562500000000 904 | 0.104019165039063 905 | 0.106536865234375 906 | 0.110015869140625 907 | 0.114044189453125 908 | 0.118286132812500 909 | 0.123107910156250 910 | 0.128021240234375 911 | 0.132720947265625 912 | 0.137680053710938 913 | 0.142395019531250 914 | 0.146957397460938 915 | 0.151153564453125 916 | 0.155548095703125 917 | 0.158874511718750 918 | 0.162689208984375 919 | 0.167022705078125 920 | 0.170608520507813 921 | 0.173706054687500 922 | 0.176620483398438 923 | 0.179412841796875 924 | 0.181518554687500 925 | 0.183792114257813 926 | 0.186340332031250 927 | 0.188583374023438 928 | 0.190856933593750 929 | 0.193038940429688 930 | 0.195327758789063 931 | 0.197875976562500 932 | 0.199752807617188 933 | 0.201828002929688 934 | 0.204116821289063 935 | 0.206420898437500 936 | 0.208801269531250 937 | 0.210968017578125 938 | 0.213531494140625 939 | 0.215713500976563 940 | 0.218658447265625 941 | 0.222045898437500 942 | 0.225402832031250 943 | 0.229003906250000 944 | 0.232192993164063 945 | 0.235580444335938 946 | 0.239578247070313 947 | 0.243392944335938 948 | 0.246215820312500 949 | 0.248199462890625 950 | 0.250747680664063 951 | 0.253234863281250 952 | 0.257095336914063 953 | 0.261596679687500 954 | 0.266769409179688 955 | 0.271713256835938 956 | 0.276885986328125 957 | 0.281204223632813 958 | 0.285263061523438 959 | 0.289260864257813 960 | 0.293121337890625 961 | 0.296463012695313 962 | 0.299026489257813 963 | 0.301193237304688 964 | 0.303298950195313 965 | 0.304306030273438 966 | 0.304901123046875 967 | 0.305389404296875 968 | 0.305084228515625 969 | 0.304611206054688 970 | 0.304504394531250 971 | 0.303176879882813 972 | 0.301422119140625 973 | 0.299682617187500 974 | 0.296875000000000 975 | 0.294021606445313 976 | 0.290252685546875 977 | 0.286117553710938 978 | 0.282272338867188 979 | 0.276947021484375 980 | 0.272048950195313 981 | 0.266342163085938 982 | 0.260650634765625 983 | 0.255294799804688 984 | 0.249038696289063 985 | 0.243148803710938 986 | 0.238388061523438 987 | 0.233032226562500 988 | 0.227798461914063 989 | 0.222442626953125 990 | 0.216552734375000 991 | 0.209091186523438 992 | 0.202255249023438 993 | 0.195480346679688 994 | 0.188003540039063 995 | 0.180831909179688 996 | 0.174057006835938 997 | 0.167724609375000 998 | 0.161514282226563 999 | 0.155227661132813 1000 | 0.148361206054688 1001 | 0.141616821289063 1002 | 0.135467529296875 1003 | 0.129058837890625 1004 | 0.123550415039063 1005 | 0.118118286132813 1006 | 0.113189697265625 1007 | 0.107742309570313 1008 | 0.101806640625000 1009 | 0.0958557128906250 1010 | 0.0892486572265625 1011 | 0.0835571289062500 1012 | 0.0775451660156250 1013 | 0.0710906982421875 1014 | 0.0647125244140625 1015 | 0.0585174560546875 1016 | 0.0534210205078125 1017 | 0.0490112304687500 1018 | 0.0441436767578125 1019 | 0.0388641357421875 1020 | 0.0343017578125000 1021 | 0.0299072265625000 1022 | 0.0262603759765625 1023 | 0.0215606689453125 1024 | 0.0161590576171875 -------------------------------------------------------------------------------- /complex_mul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jagger2048/fft_simd/7929762d5c4caffc5b7246f5dcab6919c4e6a711/complex_mul.png -------------------------------------------------------------------------------- /task1_solution.md: -------------------------------------------------------------------------------- 1 | # Task1 solution 2 | 3 | - Task 1. Implement standard DFT algorithm with C++. 4 | 5 | As we all know, The DFT, *discrete Fourier transform* transforms, can be defined by follow formula: 6 | 7 | $$ 8 | {\begin{aligned}X_{k}&=\sum _{n=0}^{N-1}x_{n}\cdot e^{-{\frac {2\pi i}{N}}kn}=\sum _{n=0}^{N-1}x_{n}\cdot [\cos(2\pi kn/N)-i\cdot \sin(2\pi kn/N)]\end{aligned}} 9 | $$ 10 | The last expression follows from the previous one by Euler's formula, which can caculate the exponent using cosine operates. We can implement the DFT formula with C++ as belows: 11 | 12 | ```c++ 13 | int standard_fft(vector fft_in, vector> &fft_out) 14 | { 15 | // Standard fft algorithm without any optimization. 16 | // Ref:https://en.wikipedia.org/wiki/DFT 17 | 18 | int N = fft_in.size(); 19 | for (size_t k = 0; k != N; ++k) { 20 | //complex x_n(0, 0); 21 | double re = 0; // the real part 22 | double im = 0; // the imag part 23 | for (size_t n = 0; n != N; ++n) { 24 | re += fft_in[n] * cos(-double(k * 2 * PI * n / N)); // Euler's formula: exp( i*x ) = cos_x + i*sin_x 25 | im += fft_in[n] * sin(-double(k * 2 * PI * n / N)); 26 | //x_n += fft_in[n] * exp( (double)k *-1i * 2.0*PI* (double)( n )/double( N) ); 27 | // be careful for the division in C++ 28 | } 29 | 30 | fft_out.push_back(complex(re, im)); 31 | } 32 | return 0; 33 | } 34 | ``` 35 | 36 | Ps. The number of dft is the fft_i's size. 37 | 38 | The standard DFT algorithm takes a long time to compute the retult and it's inefficient in real application.So we should consider the other faster algorithm , the famous solution is Cooley–Tukey FFT algorithm. 39 | 40 | See [Task2: Cooley–Tukey FFT algorithm](https://github.com/jagger2048/fft_simd/blob/master/task2_solution.md). 41 | -------------------------------------------------------------------------------- /task2_solution.md: -------------------------------------------------------------------------------- 1 | # Task2 solution 2 | 3 | - Task 2. Rewrite the DFT with Cooley–Tukey FFT algorithm. 4 | 5 | Cooley–Tukey FFT algorithm is the most common [fast Fourier transform](https://en.wikipedia.org/wiki/Fast_Fourier_transform) (FFT) algorithm. Our goals is to replace the standard DFT algorithm with FFT. In general, the DFT algoritm can be described as follows formula: 6 | $$ 7 | {\displaystyle {\begin{matrix}X_{k}=\underbrace {\sum \limits _{m=0}^{N/2-1}x_{2m}e^{-{\frac {2\pi i}{N/2}}mk}} _{\mathrm {DFT\;of\;even-indexed\;part\;of\;} x_{n}}{}+e^{-{\frac {2\pi i}{N}}k}\underbrace {\sum \limits _{m=0}^{N/2-1}x_{2m+1}e^{-{\frac {2\pi i}{N/2}}mk}} _{\mathrm {DFT\;of\;odd-indexed\;part\;of\;} x_{n}}=E_{k}+e^{-{\frac {2\pi i}{N}}k}O_{k}.\end{matrix}}} 8 | $$ 9 | The input sequeue's DFT, $ X_{k} $ , can be separed into two parts , the even part and oven part, and compute the two parts' DFT respectively .Then finally,combine them you will get the orginal sequeue's DFT. The process continues until the length of sequeue as small as possible ,at that moment subsequeue's DFT can be computed easily. We can reference the code blows and learn how the FFT is going: 10 | 11 | ```c++ 12 | void fft2(complex* X, int N) { 13 | if (N < 2) { 14 | // bottom of recursion. 15 | // Do nothing here, because already X[0] = x[0] 16 | } 17 | else { 18 | separate(X, N); // all evens to lower half, all odds to upper half 19 | fft2(X, N / 2); // recurse even items 20 | fft2(X + N / 2, N / 2); // recurse odd items 21 | // combine results of two half recursions 22 | for (int k = 0; k e = X[k]; // even 25 | complex o = X[k + N / 2]; // odd 26 | // w is the "twiddle-factor" 27 | complex w = exp(complex(0, -2.*PI*k / N)); 28 | X[k] = e + w * o; 29 | X[k + N / 2] = e - w * o; 30 | /* 31 | comp e = X[k]; // even 32 | comp o = X[k + N / 2]; // odd 33 | complex ww = exp(complex(0, -2.*PI*k / N)); 34 | comp w; 35 | w.real = ww.real(); 36 | w.imag = ww.imag(); 37 | comp wo = complex_mul_c(w, o); 38 | X[k].real = e.real + wo.real; 39 | X[k].imag = e.imag + wo.imag; 40 | X[k + N / 2].real = e.real - wo.real; 41 | X[k + N / 2].imag = e.imag - wo.imag; 42 | */ 43 | } 44 | } 45 | } 46 | ``` 47 | 48 | With this FFT algorithm,it cost 7ms to compute a 1024 points DFT .Our processor is Intel(R) Core I5-3470. And it is faster than the standard DFT algorithm at the same condition, almost 600ms. 49 | 50 | In the next section we will use SIMD to accelerate the FFT alogrithm above. 51 | 52 | See [Task3: Accelerate the FFT alogrithm](https://github.com/jagger2048/fft_simd/blob/master/README.md). 53 | 54 | 55 | 56 | _______ 57 | 58 | Ps: At the begining I writed a FFT algorithm myself, which is a out-off-place algorithm and it cost 70ms to compute a 1024-point DFT. For learning SIMD operate , I chosed a faster and easy to understand FFT algorithm from the wiki . 59 | 60 | Ref: https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm 61 | --------------------------------------------------------------------------------