├── license.txt ├── readme.txt └── src ├── Array.h ├── Array.hpp ├── DynArray.h ├── DynArray.hpp ├── FFTReal.h ├── FFTReal.hpp ├── FFTRealFixLen.h ├── FFTRealFixLen.hpp ├── FFTRealFixLenParam.h ├── FFTRealPassDirect.h ├── FFTRealPassDirect.hpp ├── FFTRealPassInverse.h ├── FFTRealPassInverse.hpp ├── FFTRealSelect.h ├── FFTRealSelect.hpp ├── FFTRealUseTrigo.h ├── FFTRealUseTrigo.hpp ├── OscSinCos.h ├── OscSinCos.hpp ├── def.h └── test ├── TestAccuracy.h ├── TestAccuracy.hpp ├── TestHelperFixLen.h ├── TestHelperFixLen.hpp ├── TestHelperNormal.h ├── TestHelperNormal.hpp ├── TestSpeed.h ├── TestSpeed.hpp ├── TestWhiteNoiseGen.h ├── TestWhiteNoiseGen.hpp ├── conf.h ├── fnc.h ├── fnc.hpp ├── main.cpp └── stopwatch ├── ClockCycleCounter.cpp ├── ClockCycleCounter.h ├── ClockCycleCounter.hpp ├── Int64.h ├── StopWatch.cpp ├── StopWatch.h ├── StopWatch.hpp ├── def.h ├── fnc.h └── fnc.hpp /license.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | FFTReal 4 | Version 2.11 5 | 6 | Fourier transformation (FFT, IFFT) library specialised for real data 7 | Portable ISO C++ 8 | 9 | Copyright (c) 1999-2010 Laurent de Soras 10 | Object Pascal port (c) Frederic Vanmol 11 | 12 | ============================================================================== 13 | 14 | 15 | 16 | Contents: 17 | 18 | 1. Legal 19 | 2. Content 20 | 3. Using FFTReal 21 | 3.1 FFTReal - Length fixed at run-time 22 | 3.2 FFTRealFixLen - Length fixed at compile-time 23 | 3.3 Data organisation 24 | 4. Compilation and testing 25 | 5. History 26 | 6. Contact 27 | 28 | 29 | 30 | 1. Legal 31 | -------- 32 | 33 | FFTReal is distributed under the terms of the Do What The Fuck You Want To 34 | Public License. 35 | 36 | Check the file license.txt to get full information about the license. 37 | 38 | 39 | 40 | 2. Content 41 | ---------- 42 | 43 | FFTReal is a library to compute Discrete Fourier Transforms (DFT) with the 44 | FFT algorithm (Fast Fourier Transform) on arrays of real numbers. It can 45 | also compute the inverse transform. 46 | 47 | You should find in this package a lot of files ; some of them are of 48 | particular interest: 49 | - readme.txt : you are reading it 50 | - ffft/FFTReal.h : FFT, length fixed at run-time 51 | - ffft/FFTRealFixLen.h: FFT, length fixed at compile-time 52 | - delphi/FFTReal.pas : Pascal implementation (working but not up-to-date) 53 | 54 | 55 | 56 | 3. Using FFTReal 57 | ---------------- 58 | 59 | Important - if you were using older versions of FFTReal (up to 1.03), some 60 | things have changed. FFTReal is now a template. Therefore use FFTReal 61 | or FFTReal in your code depending on the application datatype. The 62 | flt_t typedef has been removed. And if you were previously using FFTReal 2.0, 63 | note that all the classes have moved to the ffft namespace. 64 | 65 | You have two ways to use FFTReal. In the first way, the FFT has its length 66 | fixed at run-time, when the object is instanciated. It means that you have 67 | not to know the length when you write the code. This is the usual way of 68 | proceeding. 69 | 70 | 71 | 3.1 FFTReal - Length fixed at run-time 72 | -------------------------------------- 73 | 74 | Just instanciate one time a FFTReal object. Specify the data type you want 75 | as template parameter (only floating point: float, double, long double or 76 | custom type). The constructor precompute a lot of things, so it may be a bit 77 | long. The parameter is the number of points used for the next FFTs. It must 78 | be a power of 2: 79 | 80 | #include "ffft/FFTReal.h" 81 | ... 82 | long len = 1024; 83 | ... 84 | // 1024-point FFT object constructed. 85 | ffft::FFTReal fft_object (len); 86 | 87 | Then you can use this object to compute as many FFTs and IFFTs as you want. 88 | They will be computed very quickly because a lot of work has been done in the 89 | object construction. 90 | 91 | float x [1024]; 92 | float f [1024]; 93 | 94 | ... 95 | fft_object.do_fft (f, x); // x (real) --FFT---> f (complex) 96 | ... 97 | fft_object.do_ifft (f, x); // f (complex) --IFFT--> x (real) 98 | fft_object.rescale (x); // Post-scaling should be done after FFT+IFFT 99 | ... 100 | 101 | x [] and f [] are floating point number arrays. x [] is the real number 102 | sequence which we want to compute the FFT. f [] is the result, in the 103 | "frequency" domain. f has the same number of elements as x [], but f [] 104 | elements are complex numbers. The routine uses some FFT properties to 105 | optimize memory and to reduce calculations: the transformaton of a real 106 | number sequence is a conjugate complex number sequence: F [k] = F [-k]*. 107 | 108 | 109 | 3.2 FFTRealFixLen - Length fixed at compile-time 110 | ------------------------------------------------ 111 | 112 | This class is significantly faster than the previous one, giving a speed 113 | gain between 50 and 100 %. The template parameter is the base-2 logarithm of 114 | the FFT length. The datatype is float; it can be changed by modifying the 115 | DataType typedef in FFTRealFixLenParam.h. As FFTReal class, it supports 116 | only floating-point types or equivalent. 117 | 118 | Use is similar as the one of FFTReal. To instanciate the object, just proceed 119 | as indicated below: 120 | 121 | #include "ffft/FFTRealFixLen.h" 122 | ... 123 | // 1024-point (2^10) FFT object constructed. 124 | ffft::FFTRealFixLen <10> fft_object; 125 | 126 | Warning: long FFT objects may take a very long time to compile, depending on 127 | the compiler and its optimisation options. If compilation time is too high, 128 | encapsulate the FFT object in a seprate class whose header doesn't need 129 | to include FFTRealFixLen.h, so you just have to compile the wrapper once 130 | and only link it the other times. For example (quick, dirty and incomplete): 131 | 132 | ffft/FFTWrapper.h: | ffft/FFTWrapper.cpp: 133 | | 134 | class FFTWrapper | #include "ffft/FFTRealFixLen.h" 135 | { | #include "ffft/FFTWrapper.h" 136 | public: | 137 | FFTWrapper (); | FFTWrapper::FFTWrapper () 138 | ~FFTWrapper (); | : _impl_ptr ((void*) new FTRealFixLen <10>) 139 | void do_fft (...); | { 140 | void do_ifft (...); | } 141 | private: | 142 | void *_impl_ptr; | ... 143 | } | 144 | 145 | 146 | 3.3 Data organisation 147 | --------------------- 148 | 149 | Mathematically speaking, DFT formulas below show what does FFTReal: 150 | 151 | do_fft() : f(k) = sum (p = 0, N-1, x(p) * exp (+j*2*pi*k*p/N)) 152 | do_ifft(): x(k) = sum (p = 0, N-1, f(p) * exp (-j*2*pi*k*p/N)) 153 | 154 | Where j is the square root of -1. The formulas differ only by the sign of 155 | the exponential. When the sign is positive, the transform is called positive. 156 | Common formulas for Fourier transform are negative for the direct tranform and 157 | positive for the inverse one. 158 | 159 | However in these formulas, f is an array of complex numbers and doesn't 160 | correspound exactly to the f[] array taken as function parameter. The 161 | following table shows how the f[] sequence is mapped onto the usable FFT 162 | coefficients (called bins): 163 | 164 | FFTReal output | Positive FFT equiv. | Negative FFT equiv. 165 | ---------------+-----------------------+----------------------- 166 | f [0] | Real (bin 0) | Real (bin 0) 167 | f [...] | Real (bin ...) | Real (bin ...) 168 | f [length/2] | Real (bin length/2) | Real (bin length/2) 169 | f [length/2+1] | Imag (bin 1) | -Imag (bin 1) 170 | f [...] | Imag (bin ...) | -Imag (bin ...) 171 | f [length-1] | Imag (bin length/2-1) | -Imag (bin length/2-1) 172 | 173 | And FFT bins are distributed in f [] as above: 174 | 175 | | | Positive FFT | Negative FFT 176 | Bin | Real part | imaginary part | imaginary part 177 | ------------+----------------+-----------------+--------------- 178 | 0 | f [0] | 0 | 0 179 | 1 | f [1] | f [length/2+1] | -f [length/2+1] 180 | ... | f [...], | f [...] | -f [...] 181 | length/2-1 | f [length/2-1] | f [length-1] | -f [length-1] 182 | length/2 | f [length/2] | 0 | 0 183 | length/2+1 | f [length/2-1] | -f [length-1] | f [length-1] 184 | ... | f [...] | -f [...] | f [...] 185 | length-1 | f [1] | -f [length/2+1] | f [length/2+1] 186 | 187 | f [] coefficients have the same layout for FFT and IFFT functions. You may 188 | notice that scaling must be done if you want to retrieve x after FFT and IFFT. 189 | Actually, IFFT (FFT (x)) = x * length(x). This is a not a problem because 190 | most of the applications don't care about absolute values. Thus, the operation 191 | requires less calculation. If you want to use the FFT and IFFT to transform a 192 | signal, you have to apply post- (or pre-) processing yourself. Multiplying 193 | or dividing floating point numbers by a power of 2 doesn't generate extra 194 | computation noise. 195 | 196 | 197 | 198 | 4. Compilation and testing 199 | -------------------------- 200 | 201 | Drop the following files into your project or makefile: 202 | 203 | ffft/Array.* 204 | ffft/def.h 205 | ffft/DynArray.* 206 | ffft/FFTReal*.h* 207 | ffft/OscSinCos.* 208 | 209 | Other files are for testing purpose only, do not include them if you just need 210 | to use the library; they are not needed to use FFTReal in your own programs. 211 | 212 | FFTReal may be compiled in two versions: release and debug. Debug version 213 | has checks that could slow down the code. Define NDEBUG to set the Release 214 | mode. For example, the command line to compile the test bench on GCC would 215 | look like: 216 | 217 | Debug mode: 218 | g++ -Wall -I. -o ./fftreal_debug.exe ffft/test/*.cpp ffft/test/stopwatch/*.cpp 219 | 220 | Release mode: 221 | g++ -Wall -I. -o ./fftreal_release.exe -DNDEBUG -O3 ffft/test/*.cpp ffft/test/stopwatch/*.cpp 222 | 223 | It may be tricky to compile the test bench because the speed tests use the 224 | stopwatch sub-library, which is not that cross-platform. If you encounter 225 | any problem that you cannot easily fix while compiling it, edit the file 226 | ffft/test/conf.h and un-define the speed test macro. Remove the stopwatch 227 | directory from your source file list, too. 228 | 229 | If it's not done by default, you should activate the exception handling 230 | of your compiler to get the class memory-leak-safe. Thus, when a memory 231 | allocation fails (in the constructor), an exception is thrown and the entire 232 | object is safely destructed. It reduces the permanent error checking overhead 233 | in the client code. Also, the test bench requires Run-Time Type Information 234 | (RTTI) to be enabled in order to display the names of the tested classes - 235 | sometimes mangled, depending on the compiler. 236 | 237 | Please note: the test bench may take an insane time to compile, especially in 238 | Release mode, because a lot of recursive templates are instanciated. 239 | 240 | 241 | 242 | 5. History 243 | ---------- 244 | 245 | v2.11 (2010.09.12) 246 | - The LGPL was not well suited to 100% template code, therefore I changed 247 | the license again. Everything is released under the WTFPL. 248 | - Removed warnings in the testcode on MSVC++ 8.0 249 | - Fixed the multiple definition linking error with template specialisations 250 | on GCC 4. 251 | 252 | v2.10 (2008.05.28) 253 | - Classes are now in the ffft namespace 254 | - Changed directory structure 255 | - Fixed compilation information in the documentation 256 | 257 | v2.00 (2005.10.18) 258 | - Turned FFTReal class into template (data type as parameter) 259 | - Added FFTRealFixLen 260 | - Trigonometric tables are size-limited in order to preserve cache memory; 261 | over a given size, sin/cos functions are computed on the fly. 262 | - Better test bench for accuracy and speed 263 | - Changed license to LGPL 264 | 265 | v1.03 (2001.06.15) 266 | - Thanks to Frederic Vanmol for the Pascal port (works with Delphi). 267 | - Documentation improvement 268 | 269 | v1.02 (2001.03.25) 270 | - sqrt() is now precomputed when the object FFTReal is constructed, resulting 271 | in speed impovement for small size FFT. 272 | 273 | v1.01 (2000) 274 | - Small modifications, I don't remember what. 275 | 276 | v1.00 (1999.08.14) 277 | - First version released 278 | 279 | 280 | 281 | 6. Contact 282 | ---------- 283 | 284 | Please address any comment, bug report or flame to: 285 | 286 | Laurent de Soras 287 | laurent.de.soras@free.fr 288 | http://ldesoras.free.fr 289 | 290 | For the Pascal port: 291 | Frederic Vanmol 292 | frederic@fruityloops.com 293 | 294 | -------------------------------------------------------------------------------- /src/Array.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Array.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_Array_HEADER_INCLUDED) 19 | #define ffft_Array_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | template 38 | class Array 39 | { 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | public: 44 | 45 | typedef T DataType; 46 | 47 | Array (); 48 | 49 | inline const DataType & 50 | operator [] (long pos) const; 51 | inline DataType & 52 | operator [] (long pos); 53 | 54 | static inline long 55 | size (); 56 | 57 | 58 | 59 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 60 | 61 | protected: 62 | 63 | 64 | 65 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | private: 68 | 69 | DataType _data_arr [LEN]; 70 | 71 | 72 | 73 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 74 | 75 | private: 76 | 77 | Array (const Array &other); 78 | Array & operator = (const Array &other); 79 | bool operator == (const Array &other); 80 | bool operator != (const Array &other); 81 | 82 | }; // class Array 83 | 84 | 85 | 86 | } // namespace ffft 87 | 88 | 89 | 90 | #include "ffft/Array.hpp" 91 | 92 | 93 | 94 | #endif // ffft_Array_HEADER_INCLUDED 95 | 96 | 97 | 98 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 99 | -------------------------------------------------------------------------------- /src/Array.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Array.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_Array_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of Array code header. 20 | #endif 21 | #define ffft_Array_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_Array_CODEHEADER_INCLUDED) 24 | #define ffft_Array_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | Array ::Array () 45 | { 46 | // Nothing 47 | } 48 | 49 | 50 | 51 | template 52 | const typename Array ::DataType & Array ::operator [] (long pos) const 53 | { 54 | assert (pos >= 0); 55 | assert (pos < LEN); 56 | 57 | return (_data_arr [pos]); 58 | } 59 | 60 | 61 | 62 | template 63 | typename Array ::DataType & Array ::operator [] (long pos) 64 | { 65 | assert (pos >= 0); 66 | assert (pos < LEN); 67 | 68 | return (_data_arr [pos]); 69 | } 70 | 71 | 72 | 73 | template 74 | long Array ::size () 75 | { 76 | return (LEN); 77 | } 78 | 79 | 80 | 81 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 82 | 83 | 84 | 85 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #endif // ffft_Array_CODEHEADER_INCLUDED 94 | 95 | #undef ffft_Array_CURRENT_CODEHEADER 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/DynArray.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | DynArray.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_DynArray_HEADER_INCLUDED) 19 | #define ffft_DynArray_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | template 38 | class DynArray 39 | { 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | public: 44 | 45 | typedef T DataType; 46 | 47 | DynArray (); 48 | explicit DynArray (long size); 49 | ~DynArray (); 50 | 51 | inline long size () const; 52 | inline void resize (long size); 53 | 54 | inline const DataType & 55 | operator [] (long pos) const; 56 | inline DataType & 57 | operator [] (long pos); 58 | 59 | 60 | 61 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 62 | 63 | protected: 64 | 65 | 66 | 67 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | private: 70 | 71 | DataType * _data_ptr; 72 | long _len; 73 | 74 | 75 | 76 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 77 | 78 | private: 79 | 80 | DynArray (const DynArray &other); 81 | DynArray & operator = (const DynArray &other); 82 | bool operator == (const DynArray &other); 83 | bool operator != (const DynArray &other); 84 | 85 | }; // class DynArray 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #include "ffft/DynArray.hpp" 94 | 95 | 96 | 97 | #endif // ffft_DynArray_HEADER_INCLUDED 98 | 99 | 100 | 101 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 102 | -------------------------------------------------------------------------------- /src/DynArray.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | DynArray.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_DynArray_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of DynArray code header. 20 | #endif 21 | #define ffft_DynArray_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_DynArray_CODEHEADER_INCLUDED) 24 | #define ffft_DynArray_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | DynArray ::DynArray () 45 | : _data_ptr (0) 46 | , _len (0) 47 | { 48 | // Nothing 49 | } 50 | 51 | 52 | 53 | template 54 | DynArray ::DynArray (long size) 55 | : _data_ptr (0) 56 | , _len (0) 57 | { 58 | assert (size >= 0); 59 | if (size > 0) 60 | { 61 | _data_ptr = new DataType [size]; 62 | _len = size; 63 | } 64 | } 65 | 66 | 67 | 68 | template 69 | DynArray ::~DynArray () 70 | { 71 | delete [] _data_ptr; 72 | _data_ptr = 0; 73 | _len = 0; 74 | } 75 | 76 | 77 | 78 | template 79 | long DynArray ::size () const 80 | { 81 | return (_len); 82 | } 83 | 84 | 85 | 86 | template 87 | void DynArray ::resize (long size) 88 | { 89 | assert (size >= 0); 90 | if (size > 0) 91 | { 92 | DataType * old_data_ptr = _data_ptr; 93 | DataType * tmp_data_ptr = new DataType [size]; 94 | 95 | _data_ptr = tmp_data_ptr; 96 | _len = size; 97 | 98 | delete [] old_data_ptr; 99 | } 100 | } 101 | 102 | 103 | 104 | template 105 | const typename DynArray ::DataType & DynArray ::operator [] (long pos) const 106 | { 107 | assert (pos >= 0); 108 | assert (pos < _len); 109 | 110 | return (_data_ptr [pos]); 111 | } 112 | 113 | 114 | 115 | template 116 | typename DynArray ::DataType & DynArray ::operator [] (long pos) 117 | { 118 | assert (pos >= 0); 119 | assert (pos < _len); 120 | 121 | return (_data_ptr [pos]); 122 | } 123 | 124 | 125 | 126 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 127 | 128 | 129 | 130 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 131 | 132 | 133 | 134 | } // namespace ffft 135 | 136 | 137 | 138 | #endif // ffft_DynArray_CODEHEADER_INCLUDED 139 | 140 | #undef ffft_DynArray_CURRENT_CODEHEADER 141 | 142 | 143 | 144 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 145 | -------------------------------------------------------------------------------- /src/FFTReal.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTReal.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTReal_HEADER_INCLUDED) 19 | #define ffft_FFTReal_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/DynArray.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTReal 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | enum { MAX_BIT_DEPTH = 30 }; // So length can be represented as long int 50 | 51 | typedef DT DataType; 52 | 53 | explicit FFTReal (long length); 54 | virtual ~FFTReal () {} 55 | 56 | long get_length () const; 57 | void do_fft (DataType f [], const DataType x []) const; 58 | void do_ifft (const DataType f [], DataType x []) const; 59 | void rescale (DataType x []) const; 60 | DataType * use_buffer () const; 61 | 62 | 63 | 64 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 65 | 66 | protected: 67 | 68 | 69 | 70 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 71 | 72 | private: 73 | 74 | // Over this bit depth, we use direct calculation for sin/cos 75 | enum { TRIGO_BD_LIMIT = 12 }; 76 | 77 | typedef OscSinCos OscType; 78 | 79 | void init_br_lut (); 80 | void init_trigo_lut (); 81 | void init_trigo_osc (); 82 | 83 | ffft_FORCEINLINE const long * 84 | get_br_ptr () const; 85 | ffft_FORCEINLINE const DataType * 86 | get_trigo_ptr (int level) const; 87 | ffft_FORCEINLINE long 88 | get_trigo_level_index (int level) const; 89 | 90 | inline void compute_fft_general (DataType f [], const DataType x []) const; 91 | inline void compute_direct_pass_1_2 (DataType df [], const DataType x []) const; 92 | inline void compute_direct_pass_3 (DataType df [], const DataType sf []) const; 93 | inline void compute_direct_pass_n (DataType df [], const DataType sf [], int pass) const; 94 | inline void compute_direct_pass_n_lut (DataType df [], const DataType sf [], int pass) const; 95 | inline void compute_direct_pass_n_osc (DataType df [], const DataType sf [], int pass) const; 96 | 97 | inline void compute_ifft_general (const DataType f [], DataType x []) const; 98 | inline void compute_inverse_pass_n (DataType df [], const DataType sf [], int pass) const; 99 | inline void compute_inverse_pass_n_osc (DataType df [], const DataType sf [], int pass) const; 100 | inline void compute_inverse_pass_n_lut (DataType df [], const DataType sf [], int pass) const; 101 | inline void compute_inverse_pass_3 (DataType df [], const DataType sf []) const; 102 | inline void compute_inverse_pass_1_2 (DataType x [], const DataType sf []) const; 103 | 104 | const long _length; 105 | const int _nbr_bits; 106 | DynArray 107 | _br_lut; 108 | DynArray 109 | _trigo_lut; 110 | mutable DynArray 111 | _buffer; 112 | mutable DynArray 113 | _trigo_osc; 114 | 115 | 116 | 117 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 118 | 119 | private: 120 | 121 | FFTReal (); 122 | FFTReal (const FFTReal &other); 123 | FFTReal & operator = (const FFTReal &other); 124 | bool operator == (const FFTReal &other); 125 | bool operator != (const FFTReal &other); 126 | 127 | }; // class FFTReal 128 | 129 | 130 | 131 | } // namespace ffft 132 | 133 | 134 | 135 | #include "ffft/FFTReal.hpp" 136 | 137 | 138 | 139 | #endif // ffft_FFTReal_HEADER_INCLUDED 140 | 141 | 142 | 143 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 144 | -------------------------------------------------------------------------------- /src/FFTReal.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTReal.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTReal_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTReal code header. 20 | #endif 21 | #define ffft_FFTReal_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTReal_CODEHEADER_INCLUDED) 24 | #define ffft_FFTReal_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | #include 32 | 33 | 34 | 35 | namespace ffft 36 | { 37 | 38 | 39 | 40 | static inline bool FFTReal_is_pow2 (long x) 41 | { 42 | assert (x > 0); 43 | 44 | return ((x & -x) == x); 45 | } 46 | 47 | 48 | 49 | static inline int FFTReal_get_next_pow2 (long x) 50 | { 51 | --x; 52 | 53 | int p = 0; 54 | while ((x & ~0xFFFFL) != 0) 55 | { 56 | p += 16; 57 | x >>= 16; 58 | } 59 | while ((x & ~0xFL) != 0) 60 | { 61 | p += 4; 62 | x >>= 4; 63 | } 64 | while (x > 0) 65 | { 66 | ++p; 67 | x >>= 1; 68 | } 69 | 70 | return (p); 71 | } 72 | 73 | 74 | 75 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 76 | 77 | 78 | 79 | /* 80 | ============================================================================== 81 | Name: ctor 82 | Input parameters: 83 | - length: length of the array on which we want to do a FFT. Range: power of 84 | 2 only, > 0. 85 | Throws: std::bad_alloc 86 | ============================================================================== 87 | */ 88 | 89 | template 90 | FFTReal
::FFTReal (long length) 91 | : _length (length) 92 | , _nbr_bits (FFTReal_get_next_pow2 (length)) 93 | , _br_lut () 94 | , _trigo_lut () 95 | , _buffer (length) 96 | , _trigo_osc () 97 | { 98 | assert (FFTReal_is_pow2 (length)); 99 | assert (_nbr_bits <= MAX_BIT_DEPTH); 100 | 101 | init_br_lut (); 102 | init_trigo_lut (); 103 | init_trigo_osc (); 104 | } 105 | 106 | 107 | 108 | /* 109 | ============================================================================== 110 | Name: get_length 111 | Description: 112 | Returns the number of points processed by this FFT object. 113 | Returns: The number of points, power of 2, > 0. 114 | Throws: Nothing 115 | ============================================================================== 116 | */ 117 | 118 | template 119 | long FFTReal
::get_length () const 120 | { 121 | return (_length); 122 | } 123 | 124 | 125 | 126 | /* 127 | ============================================================================== 128 | Name: do_fft 129 | Description: 130 | Compute the FFT of the array. 131 | Input parameters: 132 | - x: pointer on the source array (time). 133 | Output parameters: 134 | - f: pointer on the destination array (frequencies). 135 | f [0...length(x)/2] = real values, 136 | f [length(x)/2+1...length(x)-1] = negative imaginary values of 137 | coefficents 1...length(x)/2-1. 138 | Throws: Nothing 139 | ============================================================================== 140 | */ 141 | 142 | template 143 | void FFTReal
::do_fft (DataType f [], const DataType x []) const 144 | { 145 | assert (f != 0); 146 | assert (f != use_buffer ()); 147 | assert (x != 0); 148 | assert (x != use_buffer ()); 149 | assert (x != f); 150 | 151 | // General case 152 | if (_nbr_bits > 2) 153 | { 154 | compute_fft_general (f, x); 155 | } 156 | 157 | // 4-point FFT 158 | else if (_nbr_bits == 2) 159 | { 160 | f [1] = x [0] - x [2]; 161 | f [3] = x [1] - x [3]; 162 | 163 | const DataType b_0 = x [0] + x [2]; 164 | const DataType b_2 = x [1] + x [3]; 165 | 166 | f [0] = b_0 + b_2; 167 | f [2] = b_0 - b_2; 168 | } 169 | 170 | // 2-point FFT 171 | else if (_nbr_bits == 1) 172 | { 173 | f [0] = x [0] + x [1]; 174 | f [1] = x [0] - x [1]; 175 | } 176 | 177 | // 1-point FFT 178 | else 179 | { 180 | f [0] = x [0]; 181 | } 182 | } 183 | 184 | 185 | 186 | /* 187 | ============================================================================== 188 | Name: do_ifft 189 | Description: 190 | Compute the inverse FFT of the array. Note that data must be post-scaled: 191 | IFFT (FFT (x)) = x * length (x). 192 | Input parameters: 193 | - f: pointer on the source array (frequencies). 194 | f [0...length(x)/2] = real values 195 | f [length(x)/2+1...length(x)-1] = negative imaginary values of 196 | coefficents 1...length(x)/2-1. 197 | Output parameters: 198 | - x: pointer on the destination array (time). 199 | Throws: Nothing 200 | ============================================================================== 201 | */ 202 | 203 | template 204 | void FFTReal
::do_ifft (const DataType f [], DataType x []) const 205 | { 206 | assert (f != 0); 207 | assert (f != use_buffer ()); 208 | assert (x != 0); 209 | assert (x != use_buffer ()); 210 | assert (x != f); 211 | 212 | // General case 213 | if (_nbr_bits > 2) 214 | { 215 | compute_ifft_general (f, x); 216 | } 217 | 218 | // 4-point IFFT 219 | else if (_nbr_bits == 2) 220 | { 221 | const DataType b_0 = f [0] + f [2]; 222 | const DataType b_2 = f [0] - f [2]; 223 | 224 | x [0] = b_0 + f [1] * 2; 225 | x [2] = b_0 - f [1] * 2; 226 | x [1] = b_2 + f [3] * 2; 227 | x [3] = b_2 - f [3] * 2; 228 | } 229 | 230 | // 2-point IFFT 231 | else if (_nbr_bits == 1) 232 | { 233 | x [0] = f [0] + f [1]; 234 | x [1] = f [0] - f [1]; 235 | } 236 | 237 | // 1-point IFFT 238 | else 239 | { 240 | x [0] = f [0]; 241 | } 242 | } 243 | 244 | 245 | 246 | /* 247 | ============================================================================== 248 | Name: rescale 249 | Description: 250 | Scale an array by divide each element by its length. This function should 251 | be called after FFT + IFFT. 252 | Input parameters: 253 | - x: pointer on array to rescale (time or frequency). 254 | Throws: Nothing 255 | ============================================================================== 256 | */ 257 | 258 | template 259 | void FFTReal
::rescale (DataType x []) const 260 | { 261 | const DataType mul = DataType (1.0 / _length); 262 | 263 | if (_length < 4) 264 | { 265 | long i = _length - 1; 266 | do 267 | { 268 | x [i] *= mul; 269 | --i; 270 | } 271 | while (i >= 0); 272 | } 273 | 274 | else 275 | { 276 | assert ((_length & 3) == 0); 277 | 278 | // Could be optimized with SIMD instruction sets (needs alignment check) 279 | long i = _length - 4; 280 | do 281 | { 282 | x [i + 0] *= mul; 283 | x [i + 1] *= mul; 284 | x [i + 2] *= mul; 285 | x [i + 3] *= mul; 286 | i -= 4; 287 | } 288 | while (i >= 0); 289 | } 290 | } 291 | 292 | 293 | 294 | /* 295 | ============================================================================== 296 | Name: use_buffer 297 | Description: 298 | Access the internal buffer, whose length is the FFT one. 299 | Buffer content will be erased at each do_fft() / do_ifft() call! 300 | This buffer cannot be used as: 301 | - source for FFT or IFFT done with this object 302 | - destination for FFT or IFFT done with this object 303 | Returns: 304 | Buffer start address 305 | Throws: Nothing 306 | ============================================================================== 307 | */ 308 | 309 | template 310 | typename FFTReal
::DataType * FFTReal
::use_buffer () const 311 | { 312 | return (&_buffer [0]); 313 | } 314 | 315 | 316 | 317 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 318 | 319 | 320 | 321 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 322 | 323 | 324 | 325 | template 326 | void FFTReal
::init_br_lut () 327 | { 328 | const long length = 1L << _nbr_bits; 329 | _br_lut.resize (length); 330 | 331 | _br_lut [0] = 0; 332 | long br_index = 0; 333 | for (long cnt = 1; cnt < length; ++cnt) 334 | { 335 | // ++br_index (bit reversed) 336 | long bit = length >> 1; 337 | while (((br_index ^= bit) & bit) == 0) 338 | { 339 | bit >>= 1; 340 | } 341 | 342 | _br_lut [cnt] = br_index; 343 | } 344 | } 345 | 346 | 347 | 348 | template 349 | void FFTReal
::init_trigo_lut () 350 | { 351 | using namespace std; 352 | 353 | if (_nbr_bits > 3) 354 | { 355 | const long total_len = (1L << (_nbr_bits - 1)) - 4; 356 | _trigo_lut.resize (total_len); 357 | 358 | for (int level = 3; level < _nbr_bits; ++level) 359 | { 360 | const long level_len = 1L << (level - 1); 361 | DataType * const level_ptr = 362 | &_trigo_lut [get_trigo_level_index (level)]; 363 | const double mul = PI / (level_len << 1); 364 | 365 | for (long i = 0; i < level_len; ++ i) 366 | { 367 | level_ptr [i] = static_cast (cos (i * mul)); 368 | } 369 | } 370 | } 371 | } 372 | 373 | 374 | 375 | template 376 | void FFTReal
::init_trigo_osc () 377 | { 378 | const int nbr_osc = _nbr_bits - TRIGO_BD_LIMIT; 379 | if (nbr_osc > 0) 380 | { 381 | _trigo_osc.resize (nbr_osc); 382 | 383 | for (int osc_cnt = 0; osc_cnt < nbr_osc; ++osc_cnt) 384 | { 385 | OscType & osc = _trigo_osc [osc_cnt]; 386 | 387 | const long len = 1L << (TRIGO_BD_LIMIT + osc_cnt); 388 | const double mul = (0.5 * PI) / len; 389 | osc.set_step (mul); 390 | } 391 | } 392 | } 393 | 394 | 395 | 396 | template 397 | const long * FFTReal
::get_br_ptr () const 398 | { 399 | return (&_br_lut [0]); 400 | } 401 | 402 | 403 | 404 | template 405 | const typename FFTReal
::DataType * FFTReal
::get_trigo_ptr (int level) const 406 | { 407 | assert (level >= 3); 408 | 409 | return (&_trigo_lut [get_trigo_level_index (level)]); 410 | } 411 | 412 | 413 | 414 | template 415 | long FFTReal
::get_trigo_level_index (int level) const 416 | { 417 | assert (level >= 3); 418 | 419 | return ((1L << (level - 1)) - 4); 420 | } 421 | 422 | 423 | 424 | // Transform in several passes 425 | template 426 | void FFTReal
::compute_fft_general (DataType f [], const DataType x []) const 427 | { 428 | assert (f != 0); 429 | assert (f != use_buffer ()); 430 | assert (x != 0); 431 | assert (x != use_buffer ()); 432 | assert (x != f); 433 | 434 | DataType * sf; 435 | DataType * df; 436 | 437 | if ((_nbr_bits & 1) != 0) 438 | { 439 | df = use_buffer (); 440 | sf = f; 441 | } 442 | else 443 | { 444 | df = f; 445 | sf = use_buffer (); 446 | } 447 | 448 | compute_direct_pass_1_2 (df, x); 449 | compute_direct_pass_3 (sf, df); 450 | 451 | for (int pass = 3; pass < _nbr_bits; ++ pass) 452 | { 453 | compute_direct_pass_n (df, sf, pass); 454 | 455 | DataType * const temp_ptr = df; 456 | df = sf; 457 | sf = temp_ptr; 458 | } 459 | } 460 | 461 | 462 | 463 | template 464 | void FFTReal
::compute_direct_pass_1_2 (DataType df [], const DataType x []) const 465 | { 466 | assert (df != 0); 467 | assert (x != 0); 468 | assert (df != x); 469 | 470 | const long * const bit_rev_lut_ptr = get_br_ptr (); 471 | long coef_index = 0; 472 | do 473 | { 474 | const long rev_index_0 = bit_rev_lut_ptr [coef_index]; 475 | const long rev_index_1 = bit_rev_lut_ptr [coef_index + 1]; 476 | const long rev_index_2 = bit_rev_lut_ptr [coef_index + 2]; 477 | const long rev_index_3 = bit_rev_lut_ptr [coef_index + 3]; 478 | 479 | DataType * const df2 = df + coef_index; 480 | df2 [1] = x [rev_index_0] - x [rev_index_1]; 481 | df2 [3] = x [rev_index_2] - x [rev_index_3]; 482 | 483 | const DataType sf_0 = x [rev_index_0] + x [rev_index_1]; 484 | const DataType sf_2 = x [rev_index_2] + x [rev_index_3]; 485 | 486 | df2 [0] = sf_0 + sf_2; 487 | df2 [2] = sf_0 - sf_2; 488 | 489 | coef_index += 4; 490 | } 491 | while (coef_index < _length); 492 | } 493 | 494 | 495 | 496 | template 497 | void FFTReal
::compute_direct_pass_3 (DataType df [], const DataType sf []) const 498 | { 499 | assert (df != 0); 500 | assert (sf != 0); 501 | assert (df != sf); 502 | 503 | const DataType sqrt2_2 = DataType (SQRT2 * 0.5); 504 | long coef_index = 0; 505 | do 506 | { 507 | DataType v; 508 | 509 | df [coef_index] = sf [coef_index] + sf [coef_index + 4]; 510 | df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4]; 511 | df [coef_index + 2] = sf [coef_index + 2]; 512 | df [coef_index + 6] = sf [coef_index + 6]; 513 | 514 | v = (sf [coef_index + 5] - sf [coef_index + 7]) * sqrt2_2; 515 | df [coef_index + 1] = sf [coef_index + 1] + v; 516 | df [coef_index + 3] = sf [coef_index + 1] - v; 517 | 518 | v = (sf [coef_index + 5] + sf [coef_index + 7]) * sqrt2_2; 519 | df [coef_index + 5] = v + sf [coef_index + 3]; 520 | df [coef_index + 7] = v - sf [coef_index + 3]; 521 | 522 | coef_index += 8; 523 | } 524 | while (coef_index < _length); 525 | } 526 | 527 | 528 | 529 | template 530 | void FFTReal
::compute_direct_pass_n (DataType df [], const DataType sf [], int pass) const 531 | { 532 | assert (df != 0); 533 | assert (sf != 0); 534 | assert (df != sf); 535 | assert (pass >= 3); 536 | assert (pass < _nbr_bits); 537 | 538 | if (pass <= TRIGO_BD_LIMIT) 539 | { 540 | compute_direct_pass_n_lut (df, sf, pass); 541 | } 542 | else 543 | { 544 | compute_direct_pass_n_osc (df, sf, pass); 545 | } 546 | } 547 | 548 | 549 | 550 | template 551 | void FFTReal
::compute_direct_pass_n_lut (DataType df [], const DataType sf [], int pass) const 552 | { 553 | assert (df != 0); 554 | assert (sf != 0); 555 | assert (df != sf); 556 | assert (pass >= 3); 557 | assert (pass < _nbr_bits); 558 | 559 | const long nbr_coef = 1 << pass; 560 | const long h_nbr_coef = nbr_coef >> 1; 561 | const long d_nbr_coef = nbr_coef << 1; 562 | long coef_index = 0; 563 | const DataType * const cos_ptr = get_trigo_ptr (pass); 564 | do 565 | { 566 | const DataType * const sf1r = sf + coef_index; 567 | const DataType * const sf2r = sf1r + nbr_coef; 568 | DataType * const dfr = df + coef_index; 569 | DataType * const dfi = dfr + nbr_coef; 570 | 571 | // Extreme coefficients are always real 572 | dfr [0] = sf1r [0] + sf2r [0]; 573 | dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] = 574 | dfr [h_nbr_coef] = sf1r [h_nbr_coef]; 575 | dfi [h_nbr_coef] = sf2r [h_nbr_coef]; 576 | 577 | // Others are conjugate complex numbers 578 | const DataType * const sf1i = sf1r + h_nbr_coef; 579 | const DataType * const sf2i = sf1i + nbr_coef; 580 | for (long i = 1; i < h_nbr_coef; ++ i) 581 | { 582 | const DataType c = cos_ptr [i]; // cos (i*PI/nbr_coef); 583 | const DataType s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef); 584 | DataType v; 585 | 586 | v = sf2r [i] * c - sf2i [i] * s; 587 | dfr [i] = sf1r [i] + v; 588 | dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] = 589 | 590 | v = sf2r [i] * s + sf2i [i] * c; 591 | dfi [i] = v + sf1i [i]; 592 | dfi [nbr_coef - i] = v - sf1i [i]; 593 | } 594 | 595 | coef_index += d_nbr_coef; 596 | } 597 | while (coef_index < _length); 598 | } 599 | 600 | 601 | 602 | template 603 | void FFTReal
::compute_direct_pass_n_osc (DataType df [], const DataType sf [], int pass) const 604 | { 605 | assert (df != 0); 606 | assert (sf != 0); 607 | assert (df != sf); 608 | assert (pass > TRIGO_BD_LIMIT); 609 | assert (pass < _nbr_bits); 610 | 611 | const long nbr_coef = 1 << pass; 612 | const long h_nbr_coef = nbr_coef >> 1; 613 | const long d_nbr_coef = nbr_coef << 1; 614 | long coef_index = 0; 615 | OscType & osc = _trigo_osc [pass - (TRIGO_BD_LIMIT + 1)]; 616 | do 617 | { 618 | const DataType * const sf1r = sf + coef_index; 619 | const DataType * const sf2r = sf1r + nbr_coef; 620 | DataType * const dfr = df + coef_index; 621 | DataType * const dfi = dfr + nbr_coef; 622 | 623 | osc.clear_buffers (); 624 | 625 | // Extreme coefficients are always real 626 | dfr [0] = sf1r [0] + sf2r [0]; 627 | dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] = 628 | dfr [h_nbr_coef] = sf1r [h_nbr_coef]; 629 | dfi [h_nbr_coef] = sf2r [h_nbr_coef]; 630 | 631 | // Others are conjugate complex numbers 632 | const DataType * const sf1i = sf1r + h_nbr_coef; 633 | const DataType * const sf2i = sf1i + nbr_coef; 634 | for (long i = 1; i < h_nbr_coef; ++ i) 635 | { 636 | osc.step (); 637 | const DataType c = osc.get_cos (); 638 | const DataType s = osc.get_sin (); 639 | DataType v; 640 | 641 | v = sf2r [i] * c - sf2i [i] * s; 642 | dfr [i] = sf1r [i] + v; 643 | dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] = 644 | 645 | v = sf2r [i] * s + sf2i [i] * c; 646 | dfi [i] = v + sf1i [i]; 647 | dfi [nbr_coef - i] = v - sf1i [i]; 648 | } 649 | 650 | coef_index += d_nbr_coef; 651 | } 652 | while (coef_index < _length); 653 | } 654 | 655 | 656 | 657 | // Transform in several pass 658 | template 659 | void FFTReal
::compute_ifft_general (const DataType f [], DataType x []) const 660 | { 661 | assert (f != 0); 662 | assert (f != use_buffer ()); 663 | assert (x != 0); 664 | assert (x != use_buffer ()); 665 | assert (x != f); 666 | 667 | DataType * sf = const_cast (f); 668 | DataType * df; 669 | DataType * df_temp; 670 | 671 | if (_nbr_bits & 1) 672 | { 673 | df = use_buffer (); 674 | df_temp = x; 675 | } 676 | else 677 | { 678 | df = x; 679 | df_temp = use_buffer (); 680 | } 681 | 682 | for (int pass = _nbr_bits - 1; pass >= 3; -- pass) 683 | { 684 | compute_inverse_pass_n (df, sf, pass); 685 | 686 | if (pass < _nbr_bits - 1) 687 | { 688 | DataType * const temp_ptr = df; 689 | df = sf; 690 | sf = temp_ptr; 691 | } 692 | else 693 | { 694 | sf = df; 695 | df = df_temp; 696 | } 697 | } 698 | 699 | compute_inverse_pass_3 (df, sf); 700 | compute_inverse_pass_1_2 (x, df); 701 | } 702 | 703 | 704 | 705 | template 706 | void FFTReal
::compute_inverse_pass_n (DataType df [], const DataType sf [], int pass) const 707 | { 708 | assert (df != 0); 709 | assert (sf != 0); 710 | assert (df != sf); 711 | assert (pass >= 3); 712 | assert (pass < _nbr_bits); 713 | 714 | if (pass <= TRIGO_BD_LIMIT) 715 | { 716 | compute_inverse_pass_n_lut (df, sf, pass); 717 | } 718 | else 719 | { 720 | compute_inverse_pass_n_osc (df, sf, pass); 721 | } 722 | } 723 | 724 | 725 | 726 | template 727 | void FFTReal
::compute_inverse_pass_n_lut (DataType df [], const DataType sf [], int pass) const 728 | { 729 | assert (df != 0); 730 | assert (sf != 0); 731 | assert (df != sf); 732 | assert (pass >= 3); 733 | assert (pass < _nbr_bits); 734 | 735 | const long nbr_coef = 1 << pass; 736 | const long h_nbr_coef = nbr_coef >> 1; 737 | const long d_nbr_coef = nbr_coef << 1; 738 | long coef_index = 0; 739 | const DataType * const cos_ptr = get_trigo_ptr (pass); 740 | do 741 | { 742 | const DataType * const sfr = sf + coef_index; 743 | const DataType * const sfi = sfr + nbr_coef; 744 | DataType * const df1r = df + coef_index; 745 | DataType * const df2r = df1r + nbr_coef; 746 | 747 | // Extreme coefficients are always real 748 | df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef] 749 | df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef] 750 | df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2; 751 | df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2; 752 | 753 | // Others are conjugate complex numbers 754 | DataType * const df1i = df1r + h_nbr_coef; 755 | DataType * const df2i = df1i + nbr_coef; 756 | for (long i = 1; i < h_nbr_coef; ++ i) 757 | { 758 | df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i] 759 | df1i [i] = sfi [i] - sfi [nbr_coef - i]; 760 | 761 | const DataType c = cos_ptr [i]; // cos (i*PI/nbr_coef); 762 | const DataType s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef); 763 | const DataType vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i] 764 | const DataType vi = sfi [i] + sfi [nbr_coef - i]; 765 | 766 | df2r [i] = vr * c + vi * s; 767 | df2i [i] = vi * c - vr * s; 768 | } 769 | 770 | coef_index += d_nbr_coef; 771 | } 772 | while (coef_index < _length); 773 | } 774 | 775 | 776 | 777 | template 778 | void FFTReal
::compute_inverse_pass_n_osc (DataType df [], const DataType sf [], int pass) const 779 | { 780 | assert (df != 0); 781 | assert (sf != 0); 782 | assert (df != sf); 783 | assert (pass > TRIGO_BD_LIMIT); 784 | assert (pass < _nbr_bits); 785 | 786 | const long nbr_coef = 1 << pass; 787 | const long h_nbr_coef = nbr_coef >> 1; 788 | const long d_nbr_coef = nbr_coef << 1; 789 | long coef_index = 0; 790 | OscType & osc = _trigo_osc [pass - (TRIGO_BD_LIMIT + 1)]; 791 | do 792 | { 793 | const DataType * const sfr = sf + coef_index; 794 | const DataType * const sfi = sfr + nbr_coef; 795 | DataType * const df1r = df + coef_index; 796 | DataType * const df2r = df1r + nbr_coef; 797 | 798 | osc.clear_buffers (); 799 | 800 | // Extreme coefficients are always real 801 | df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef] 802 | df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef] 803 | df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2; 804 | df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2; 805 | 806 | // Others are conjugate complex numbers 807 | DataType * const df1i = df1r + h_nbr_coef; 808 | DataType * const df2i = df1i + nbr_coef; 809 | for (long i = 1; i < h_nbr_coef; ++ i) 810 | { 811 | df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i] 812 | df1i [i] = sfi [i] - sfi [nbr_coef - i]; 813 | 814 | osc.step (); 815 | const DataType c = osc.get_cos (); 816 | const DataType s = osc.get_sin (); 817 | const DataType vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i] 818 | const DataType vi = sfi [i] + sfi [nbr_coef - i]; 819 | 820 | df2r [i] = vr * c + vi * s; 821 | df2i [i] = vi * c - vr * s; 822 | } 823 | 824 | coef_index += d_nbr_coef; 825 | } 826 | while (coef_index < _length); 827 | } 828 | 829 | 830 | 831 | template 832 | void FFTReal
::compute_inverse_pass_3 (DataType df [], const DataType sf []) const 833 | { 834 | assert (df != 0); 835 | assert (sf != 0); 836 | assert (df != sf); 837 | 838 | const DataType sqrt2_2 = DataType (SQRT2 * 0.5); 839 | long coef_index = 0; 840 | do 841 | { 842 | df [coef_index] = sf [coef_index] + sf [coef_index + 4]; 843 | df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4]; 844 | df [coef_index + 2] = sf [coef_index + 2] * 2; 845 | df [coef_index + 6] = sf [coef_index + 6] * 2; 846 | 847 | df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3]; 848 | df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7]; 849 | 850 | const DataType vr = sf [coef_index + 1] - sf [coef_index + 3]; 851 | const DataType vi = sf [coef_index + 5] + sf [coef_index + 7]; 852 | 853 | df [coef_index + 5] = (vr + vi) * sqrt2_2; 854 | df [coef_index + 7] = (vi - vr) * sqrt2_2; 855 | 856 | coef_index += 8; 857 | } 858 | while (coef_index < _length); 859 | } 860 | 861 | 862 | 863 | template 864 | void FFTReal
::compute_inverse_pass_1_2 (DataType x [], const DataType sf []) const 865 | { 866 | assert (x != 0); 867 | assert (sf != 0); 868 | assert (x != sf); 869 | 870 | const long * bit_rev_lut_ptr = get_br_ptr (); 871 | const DataType * sf2 = sf; 872 | long coef_index = 0; 873 | do 874 | { 875 | { 876 | const DataType b_0 = sf2 [0] + sf2 [2]; 877 | const DataType b_2 = sf2 [0] - sf2 [2]; 878 | const DataType b_1 = sf2 [1] * 2; 879 | const DataType b_3 = sf2 [3] * 2; 880 | 881 | x [bit_rev_lut_ptr [0]] = b_0 + b_1; 882 | x [bit_rev_lut_ptr [1]] = b_0 - b_1; 883 | x [bit_rev_lut_ptr [2]] = b_2 + b_3; 884 | x [bit_rev_lut_ptr [3]] = b_2 - b_3; 885 | } 886 | { 887 | const DataType b_0 = sf2 [4] + sf2 [6]; 888 | const DataType b_2 = sf2 [4] - sf2 [6]; 889 | const DataType b_1 = sf2 [5] * 2; 890 | const DataType b_3 = sf2 [7] * 2; 891 | 892 | x [bit_rev_lut_ptr [4]] = b_0 + b_1; 893 | x [bit_rev_lut_ptr [5]] = b_0 - b_1; 894 | x [bit_rev_lut_ptr [6]] = b_2 + b_3; 895 | x [bit_rev_lut_ptr [7]] = b_2 - b_3; 896 | } 897 | 898 | sf2 += 8; 899 | coef_index += 8; 900 | bit_rev_lut_ptr += 8; 901 | } 902 | while (coef_index < _length); 903 | } 904 | 905 | 906 | 907 | } // namespace ffft 908 | 909 | 910 | 911 | #endif // ffft_FFTReal_CODEHEADER_INCLUDED 912 | 913 | #undef ffft_FFTReal_CURRENT_CODEHEADER 914 | 915 | 916 | 917 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 918 | -------------------------------------------------------------------------------- /src/FFTRealFixLen.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealFixLen.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealFixLen_HEADER_INCLUDED) 19 | #define ffft_FFTRealFixLen_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/Array.h" 31 | #include "ffft/DynArray.h" 32 | #include "ffft/FFTRealFixLenParam.h" 33 | #include "ffft/OscSinCos.h" 34 | 35 | 36 | 37 | namespace ffft 38 | { 39 | 40 | 41 | 42 | template 43 | class FFTRealFixLen 44 | { 45 | typedef int CompileTimeCheck1 [(LL2 >= 0) ? 1 : -1]; 46 | typedef int CompileTimeCheck2 [(LL2 <= 30) ? 1 : -1]; 47 | 48 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 49 | 50 | public: 51 | 52 | typedef FFTRealFixLenParam::DataType DataType; 53 | typedef OscSinCos OscType; 54 | 55 | enum { FFT_LEN_L2 = LL2 }; 56 | enum { FFT_LEN = 1 << FFT_LEN_L2 }; 57 | 58 | FFTRealFixLen (); 59 | 60 | inline long get_length () const; 61 | void do_fft (DataType f [], const DataType x []); 62 | void do_ifft (const DataType f [], DataType x []); 63 | void rescale (DataType x []) const; 64 | 65 | 66 | 67 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | protected: 70 | 71 | 72 | 73 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 74 | 75 | private: 76 | 77 | enum { TRIGO_BD_LIMIT = FFTRealFixLenParam::TRIGO_BD_LIMIT }; 78 | 79 | enum { BR_ARR_SIZE_L2 = ((FFT_LEN_L2 - 3) < 0) ? 0 : (FFT_LEN_L2 - 2) }; 80 | enum { BR_ARR_SIZE = 1 << BR_ARR_SIZE_L2 }; 81 | 82 | enum { TRIGO_BD = ((FFT_LEN_L2 - TRIGO_BD_LIMIT) < 0) 83 | ? (int)FFT_LEN_L2 84 | : (int)TRIGO_BD_LIMIT }; 85 | enum { TRIGO_TABLE_ARR_SIZE_L2 = (LL2 < 4) ? 0 : (TRIGO_BD - 2) }; 86 | enum { TRIGO_TABLE_ARR_SIZE = 1 << TRIGO_TABLE_ARR_SIZE_L2 }; 87 | 88 | enum { NBR_TRIGO_OSC = FFT_LEN_L2 - TRIGO_BD }; 89 | enum { TRIGO_OSC_ARR_SIZE = (NBR_TRIGO_OSC > 0) ? NBR_TRIGO_OSC : 1 }; 90 | 91 | void build_br_lut (); 92 | void build_trigo_lut (); 93 | void build_trigo_osc (); 94 | 95 | DynArray 96 | _buffer; 97 | DynArray 98 | _br_data; 99 | DynArray 100 | _trigo_data; 101 | Array 102 | _trigo_osc; 103 | 104 | 105 | 106 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 107 | 108 | private: 109 | 110 | FFTRealFixLen (const FFTRealFixLen &other); 111 | FFTRealFixLen& operator = (const FFTRealFixLen &other); 112 | bool operator == (const FFTRealFixLen &other); 113 | bool operator != (const FFTRealFixLen &other); 114 | 115 | }; // class FFTRealFixLen 116 | 117 | 118 | 119 | } // namespace ffft 120 | 121 | 122 | 123 | #include "ffft/FFTRealFixLen.hpp" 124 | 125 | 126 | 127 | #endif // ffft_FFTRealFixLen_HEADER_INCLUDED 128 | 129 | 130 | 131 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 132 | -------------------------------------------------------------------------------- /src/FFTRealFixLen.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealFixLen.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealFixLen_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealFixLen code header. 20 | #endif 21 | #define ffft_FFTRealFixLen_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealFixLen_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealFixLen_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealPassDirect.h" 32 | #include "ffft/FFTRealPassInverse.h" 33 | #include "ffft/FFTRealSelect.h" 34 | 35 | #include 36 | #include 37 | 38 | namespace std { } 39 | 40 | 41 | 42 | namespace ffft 43 | { 44 | 45 | 46 | 47 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 48 | 49 | 50 | 51 | template 52 | FFTRealFixLen ::FFTRealFixLen () 53 | : _buffer (FFT_LEN) 54 | , _br_data (BR_ARR_SIZE) 55 | , _trigo_data (TRIGO_TABLE_ARR_SIZE) 56 | , _trigo_osc () 57 | { 58 | build_br_lut (); 59 | build_trigo_lut (); 60 | build_trigo_osc (); 61 | } 62 | 63 | 64 | 65 | template 66 | long FFTRealFixLen ::get_length () const 67 | { 68 | return (FFT_LEN); 69 | } 70 | 71 | 72 | 73 | // General case 74 | template 75 | void FFTRealFixLen ::do_fft (DataType f [], const DataType x []) 76 | { 77 | assert (f != 0); 78 | assert (x != 0); 79 | assert (x != f); 80 | assert (FFT_LEN_L2 >= 3); 81 | 82 | // Do the transform in several passes 83 | const DataType * cos_ptr = &_trigo_data [0]; 84 | const long * br_ptr = &_br_data [0]; 85 | 86 | FFTRealPassDirect ::process ( 87 | FFT_LEN, 88 | f, 89 | &_buffer [0], 90 | x, 91 | cos_ptr, 92 | TRIGO_TABLE_ARR_SIZE, 93 | br_ptr, 94 | &_trigo_osc [0] 95 | ); 96 | } 97 | 98 | // 4-point FFT 99 | template <> 100 | inline void FFTRealFixLen <2>::do_fft (DataType f [], const DataType x []) 101 | { 102 | assert (f != 0); 103 | assert (x != 0); 104 | assert (x != f); 105 | 106 | f [1] = x [0] - x [2]; 107 | f [3] = x [1] - x [3]; 108 | 109 | const DataType b_0 = x [0] + x [2]; 110 | const DataType b_2 = x [1] + x [3]; 111 | 112 | f [0] = b_0 + b_2; 113 | f [2] = b_0 - b_2; 114 | } 115 | 116 | // 2-point FFT 117 | template <> 118 | inline void FFTRealFixLen <1>::do_fft (DataType f [], const DataType x []) 119 | { 120 | assert (f != 0); 121 | assert (x != 0); 122 | assert (x != f); 123 | 124 | f [0] = x [0] + x [1]; 125 | f [1] = x [0] - x [1]; 126 | } 127 | 128 | // 1-point FFT 129 | template <> 130 | inline void FFTRealFixLen <0>::do_fft (DataType f [], const DataType x []) 131 | { 132 | assert (f != 0); 133 | assert (x != 0); 134 | 135 | f [0] = x [0]; 136 | } 137 | 138 | 139 | 140 | // General case 141 | template 142 | void FFTRealFixLen ::do_ifft (const DataType f [], DataType x []) 143 | { 144 | assert (f != 0); 145 | assert (x != 0); 146 | assert (x != f); 147 | assert (FFT_LEN_L2 >= 3); 148 | 149 | // Do the transform in several passes 150 | DataType * s_ptr = 151 | FFTRealSelect ::sel_bin (&_buffer [0], x); 152 | DataType * d_ptr = 153 | FFTRealSelect ::sel_bin (x, &_buffer [0]); 154 | const DataType * cos_ptr = &_trigo_data [0]; 155 | const long * br_ptr = &_br_data [0]; 156 | 157 | FFTRealPassInverse ::process ( 158 | FFT_LEN, 159 | d_ptr, 160 | s_ptr, 161 | f, 162 | cos_ptr, 163 | TRIGO_TABLE_ARR_SIZE, 164 | br_ptr, 165 | &_trigo_osc [0] 166 | ); 167 | } 168 | 169 | // 4-point IFFT 170 | template <> 171 | inline void FFTRealFixLen <2>::do_ifft (const DataType f [], DataType x []) 172 | { 173 | assert (f != 0); 174 | assert (x != 0); 175 | assert (x != f); 176 | 177 | const DataType b_0 = f [0] + f [2]; 178 | const DataType b_2 = f [0] - f [2]; 179 | 180 | x [0] = b_0 + f [1] * 2; 181 | x [2] = b_0 - f [1] * 2; 182 | x [1] = b_2 + f [3] * 2; 183 | x [3] = b_2 - f [3] * 2; 184 | } 185 | 186 | // 2-point IFFT 187 | template <> 188 | inline void FFTRealFixLen <1>::do_ifft (const DataType f [], DataType x []) 189 | { 190 | assert (f != 0); 191 | assert (x != 0); 192 | assert (x != f); 193 | 194 | x [0] = f [0] + f [1]; 195 | x [1] = f [0] - f [1]; 196 | } 197 | 198 | // 1-point IFFT 199 | template <> 200 | inline void FFTRealFixLen <0>::do_ifft (const DataType f [], DataType x []) 201 | { 202 | assert (f != 0); 203 | assert (x != 0); 204 | assert (x != f); 205 | 206 | x [0] = f [0]; 207 | } 208 | 209 | 210 | 211 | 212 | template 213 | void FFTRealFixLen ::rescale (DataType x []) const 214 | { 215 | assert (x != 0); 216 | 217 | const DataType mul = DataType (1.0 / FFT_LEN); 218 | 219 | if (FFT_LEN < 4) 220 | { 221 | long i = FFT_LEN - 1; 222 | do 223 | { 224 | x [i] *= mul; 225 | --i; 226 | } 227 | while (i >= 0); 228 | } 229 | 230 | else 231 | { 232 | assert ((FFT_LEN & 3) == 0); 233 | 234 | // Could be optimized with SIMD instruction sets (needs alignment check) 235 | long i = FFT_LEN - 4; 236 | do 237 | { 238 | x [i + 0] *= mul; 239 | x [i + 1] *= mul; 240 | x [i + 2] *= mul; 241 | x [i + 3] *= mul; 242 | i -= 4; 243 | } 244 | while (i >= 0); 245 | } 246 | } 247 | 248 | 249 | 250 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 251 | 252 | 253 | 254 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 255 | 256 | 257 | 258 | template 259 | void FFTRealFixLen ::build_br_lut () 260 | { 261 | _br_data [0] = 0; 262 | for (long cnt = 1; cnt < BR_ARR_SIZE; ++cnt) 263 | { 264 | long index = cnt << 2; 265 | long br_index = 0; 266 | 267 | int bit_cnt = FFT_LEN_L2; 268 | do 269 | { 270 | br_index <<= 1; 271 | br_index += (index & 1); 272 | index >>= 1; 273 | 274 | -- bit_cnt; 275 | } 276 | while (bit_cnt > 0); 277 | 278 | _br_data [cnt] = br_index; 279 | } 280 | } 281 | 282 | 283 | 284 | template 285 | void FFTRealFixLen ::build_trigo_lut () 286 | { 287 | const double mul = (0.5 * PI) / TRIGO_TABLE_ARR_SIZE; 288 | for (long i = 0; i < TRIGO_TABLE_ARR_SIZE; ++ i) 289 | { 290 | using namespace std; 291 | 292 | _trigo_data [i] = DataType (cos (i * mul)); 293 | } 294 | } 295 | 296 | 297 | 298 | template 299 | void FFTRealFixLen ::build_trigo_osc () 300 | { 301 | for (int i = 0; i < NBR_TRIGO_OSC; ++i) 302 | { 303 | OscType & osc = _trigo_osc [i]; 304 | 305 | const long len = static_cast (TRIGO_TABLE_ARR_SIZE) << (i + 1); 306 | const double mul = (0.5 * PI) / len; 307 | osc.set_step (mul); 308 | } 309 | } 310 | 311 | 312 | 313 | } // namespace ffft 314 | 315 | 316 | 317 | #endif // ffft_FFTRealFixLen_CODEHEADER_INCLUDED 318 | 319 | #undef ffft_FFTRealFixLen_CURRENT_CODEHEADER 320 | 321 | 322 | 323 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 324 | -------------------------------------------------------------------------------- /src/FFTRealFixLenParam.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealFixLenParam.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealFixLenParam_HEADER_INCLUDED) 19 | #define ffft_FFTRealFixLenParam_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | class FFTRealFixLenParam 38 | { 39 | 40 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 41 | 42 | public: 43 | 44 | // Over this bit depth, we use direct calculation for sin/cos 45 | enum { TRIGO_BD_LIMIT = 12 }; 46 | 47 | typedef float DataType; 48 | 49 | 50 | 51 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 52 | 53 | protected: 54 | 55 | 56 | 57 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | private: 60 | 61 | 62 | 63 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | FFTRealFixLenParam (); 68 | FFTRealFixLenParam (const FFTRealFixLenParam &other); 69 | FFTRealFixLenParam & 70 | operator = (const FFTRealFixLenParam &other); 71 | bool operator == (const FFTRealFixLenParam &other); 72 | bool operator != (const FFTRealFixLenParam &other); 73 | 74 | }; // class FFTRealFixLenParam 75 | 76 | 77 | 78 | } // namespace ffft 79 | 80 | 81 | 82 | //#include "ffft/FFTRealFixLenParam.hpp" 83 | 84 | 85 | 86 | #endif // ffft_FFTRealFixLenParam_HEADER_INCLUDED 87 | 88 | 89 | 90 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 91 | -------------------------------------------------------------------------------- /src/FFTRealPassDirect.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassDirect.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealPassDirect_HEADER_INCLUDED) 19 | #define ffft_FFTRealPassDirect_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTRealPassDirect 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef FFTRealFixLenParam::DataType DataType; 50 | typedef OscSinCos OscType; 51 | 52 | ffft_FORCEINLINE static void 53 | process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 54 | 55 | 56 | 57 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | protected: 60 | 61 | 62 | 63 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | 68 | 69 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 70 | 71 | private: 72 | 73 | FFTRealPassDirect (); 74 | FFTRealPassDirect (const FFTRealPassDirect &other); 75 | FFTRealPassDirect & 76 | operator = (const FFTRealPassDirect &other); 77 | bool operator == (const FFTRealPassDirect &other); 78 | bool operator != (const FFTRealPassDirect &other); 79 | 80 | }; // class FFTRealPassDirect 81 | 82 | 83 | 84 | } // namespace ffft 85 | 86 | 87 | 88 | #include "ffft/FFTRealPassDirect.hpp" 89 | 90 | 91 | 92 | #endif // ffft_FFTRealPassDirect_HEADER_INCLUDED 93 | 94 | 95 | 96 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 97 | -------------------------------------------------------------------------------- /src/FFTRealPassDirect.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassDirect.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealPassDirect_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealPassDirect code header. 20 | #endif 21 | #define ffft_FFTRealPassDirect_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealPassDirect_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealPassDirect_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/FFTRealUseTrigo.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template <> 44 | inline void FFTRealPassDirect <1>::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 45 | { 46 | // First and second pass at once 47 | const long qlen = len >> 2; 48 | 49 | long coef_index = 0; 50 | do 51 | { 52 | // To do: unroll the loop (2x). 53 | const long ri_0 = br_ptr [coef_index >> 2]; 54 | const long ri_1 = ri_0 + 2 * qlen; // bit_rev_lut_ptr [coef_index + 1]; 55 | const long ri_2 = ri_0 + 1 * qlen; // bit_rev_lut_ptr [coef_index + 2]; 56 | const long ri_3 = ri_0 + 3 * qlen; // bit_rev_lut_ptr [coef_index + 3]; 57 | 58 | DataType * const df2 = dest_ptr + coef_index; 59 | df2 [1] = x_ptr [ri_0] - x_ptr [ri_1]; 60 | df2 [3] = x_ptr [ri_2] - x_ptr [ri_3]; 61 | 62 | const DataType sf_0 = x_ptr [ri_0] + x_ptr [ri_1]; 63 | const DataType sf_2 = x_ptr [ri_2] + x_ptr [ri_3]; 64 | 65 | df2 [0] = sf_0 + sf_2; 66 | df2 [2] = sf_0 - sf_2; 67 | 68 | coef_index += 4; 69 | } 70 | while (coef_index < len); 71 | } 72 | 73 | template <> 74 | inline void FFTRealPassDirect <2>::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 75 | { 76 | // Executes "previous" passes first. Inverts source and destination buffers 77 | FFTRealPassDirect <1>::process ( 78 | len, 79 | src_ptr, 80 | dest_ptr, 81 | x_ptr, 82 | cos_ptr, 83 | cos_len, 84 | br_ptr, 85 | osc_list 86 | ); 87 | 88 | // Third pass 89 | const DataType sqrt2_2 = DataType (SQRT2 * 0.5); 90 | 91 | long coef_index = 0; 92 | do 93 | { 94 | dest_ptr [coef_index ] = src_ptr [coef_index] + src_ptr [coef_index + 4]; 95 | dest_ptr [coef_index + 4] = src_ptr [coef_index] - src_ptr [coef_index + 4]; 96 | dest_ptr [coef_index + 2] = src_ptr [coef_index + 2]; 97 | dest_ptr [coef_index + 6] = src_ptr [coef_index + 6]; 98 | 99 | DataType v; 100 | 101 | v = (src_ptr [coef_index + 5] - src_ptr [coef_index + 7]) * sqrt2_2; 102 | dest_ptr [coef_index + 1] = src_ptr [coef_index + 1] + v; 103 | dest_ptr [coef_index + 3] = src_ptr [coef_index + 1] - v; 104 | 105 | v = (src_ptr [coef_index + 5] + src_ptr [coef_index + 7]) * sqrt2_2; 106 | dest_ptr [coef_index + 5] = v + src_ptr [coef_index + 3]; 107 | dest_ptr [coef_index + 7] = v - src_ptr [coef_index + 3]; 108 | 109 | coef_index += 8; 110 | } 111 | while (coef_index < len); 112 | } 113 | 114 | template 115 | void FFTRealPassDirect ::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 116 | { 117 | // Executes "previous" passes first. Inverts source and destination buffers 118 | FFTRealPassDirect ::process ( 119 | len, 120 | src_ptr, 121 | dest_ptr, 122 | x_ptr, 123 | cos_ptr, 124 | cos_len, 125 | br_ptr, 126 | osc_list 127 | ); 128 | 129 | const long dist = 1L << (PASS - 1); 130 | const long c1_r = 0; 131 | const long c1_i = dist; 132 | const long c2_r = dist * 2; 133 | const long c2_i = dist * 3; 134 | const long cend = dist * 4; 135 | const long table_step = cos_len >> (PASS - 1); 136 | 137 | enum { TRIGO_OSC = PASS - FFTRealFixLenParam::TRIGO_BD_LIMIT }; 138 | enum { TRIGO_DIRECT = (TRIGO_OSC >= 0) ? 1 : 0 }; 139 | 140 | long coef_index = 0; 141 | do 142 | { 143 | const DataType * const sf = src_ptr + coef_index; 144 | DataType * const df = dest_ptr + coef_index; 145 | 146 | // Extreme coefficients are always real 147 | df [c1_r] = sf [c1_r] + sf [c2_r]; 148 | df [c2_r] = sf [c1_r] - sf [c2_r]; 149 | df [c1_i] = sf [c1_i]; 150 | df [c2_i] = sf [c2_i]; 151 | 152 | FFTRealUseTrigo ::prepare (osc_list [TRIGO_OSC]); 153 | 154 | // Others are conjugate complex numbers 155 | for (long i = 1; i < dist; ++ i) 156 | { 157 | DataType c; 158 | DataType s; 159 | FFTRealUseTrigo ::iterate ( 160 | osc_list [TRIGO_OSC], 161 | c, 162 | s, 163 | cos_ptr, 164 | i * table_step, 165 | (dist - i) * table_step 166 | ); 167 | 168 | const DataType sf_r_i = sf [c1_r + i]; 169 | const DataType sf_i_i = sf [c1_i + i]; 170 | 171 | const DataType v1 = sf [c2_r + i] * c - sf [c2_i + i] * s; 172 | df [c1_r + i] = sf_r_i + v1; 173 | df [c2_r - i] = sf_r_i - v1; 174 | 175 | const DataType v2 = sf [c2_r + i] * s + sf [c2_i + i] * c; 176 | df [c2_r + i] = v2 + sf_i_i; 177 | df [cend - i] = v2 - sf_i_i; 178 | } 179 | 180 | coef_index += cend; 181 | } 182 | while (coef_index < len); 183 | } 184 | 185 | 186 | 187 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 188 | 189 | 190 | 191 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 192 | 193 | 194 | 195 | } // namespace ffft 196 | 197 | 198 | 199 | #endif // ffft_FFTRealPassDirect_CODEHEADER_INCLUDED 200 | 201 | #undef ffft_FFTRealPassDirect_CURRENT_CODEHEADER 202 | 203 | 204 | 205 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 206 | -------------------------------------------------------------------------------- /src/FFTRealPassInverse.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassInverse.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealPassInverse_HEADER_INCLUDED) 19 | #define ffft_FFTRealPassInverse_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | 37 | namespace ffft 38 | { 39 | 40 | 41 | 42 | template 43 | class FFTRealPassInverse 44 | { 45 | 46 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 47 | 48 | public: 49 | 50 | typedef FFTRealFixLenParam::DataType DataType; 51 | typedef OscSinCos OscType; 52 | 53 | ffft_FORCEINLINE static void 54 | process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType f_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 55 | ffft_FORCEINLINE static void 56 | process_rec (long len, DataType dest_ptr [], DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 57 | ffft_FORCEINLINE static void 58 | process_internal (long len, DataType dest_ptr [], const DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 59 | 60 | 61 | 62 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 63 | 64 | protected: 65 | 66 | 67 | 68 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 69 | 70 | private: 71 | 72 | 73 | 74 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 75 | 76 | private: 77 | 78 | FFTRealPassInverse (); 79 | FFTRealPassInverse (const FFTRealPassInverse &other); 80 | FFTRealPassInverse & 81 | operator = (const FFTRealPassInverse &other); 82 | bool operator == (const FFTRealPassInverse &other); 83 | bool operator != (const FFTRealPassInverse &other); 84 | 85 | }; // class FFTRealPassInverse 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #include "ffft/FFTRealPassInverse.hpp" 94 | 95 | 96 | 97 | #endif // ffft_FFTRealPassInverse_HEADER_INCLUDED 98 | 99 | 100 | 101 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 102 | -------------------------------------------------------------------------------- /src/FFTRealPassInverse.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassInverse.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealPassInverse_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealPassInverse code header. 20 | #endif 21 | #define ffft_FFTRealPassInverse_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealPassInverse_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealPassInverse_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/FFTRealUseTrigo.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | void FFTRealPassInverse ::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType f_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 45 | { 46 | process_internal ( 47 | len, 48 | dest_ptr, 49 | f_ptr, 50 | cos_ptr, 51 | cos_len, 52 | br_ptr, 53 | osc_list 54 | ); 55 | FFTRealPassInverse ::process_rec ( 56 | len, 57 | src_ptr, 58 | dest_ptr, 59 | cos_ptr, 60 | cos_len, 61 | br_ptr, 62 | osc_list 63 | ); 64 | } 65 | 66 | 67 | 68 | template 69 | void FFTRealPassInverse ::process_rec (long len, DataType dest_ptr [], DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 70 | { 71 | process_internal ( 72 | len, 73 | dest_ptr, 74 | src_ptr, 75 | cos_ptr, 76 | cos_len, 77 | br_ptr, 78 | osc_list 79 | ); 80 | FFTRealPassInverse ::process_rec ( 81 | len, 82 | src_ptr, 83 | dest_ptr, 84 | cos_ptr, 85 | cos_len, 86 | br_ptr, 87 | osc_list 88 | ); 89 | } 90 | 91 | template <> 92 | inline void FFTRealPassInverse <0>::process_rec (long len, DataType dest_ptr [], DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 93 | { 94 | // Stops recursion 95 | } 96 | 97 | 98 | 99 | template 100 | void FFTRealPassInverse ::process_internal (long len, DataType dest_ptr [], const DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 101 | { 102 | const long dist = 1L << (PASS - 1); 103 | const long c1_r = 0; 104 | const long c1_i = dist; 105 | const long c2_r = dist * 2; 106 | const long c2_i = dist * 3; 107 | const long cend = dist * 4; 108 | const long table_step = cos_len >> (PASS - 1); 109 | 110 | enum { TRIGO_OSC = PASS - FFTRealFixLenParam::TRIGO_BD_LIMIT }; 111 | enum { TRIGO_DIRECT = (TRIGO_OSC >= 0) ? 1 : 0 }; 112 | 113 | long coef_index = 0; 114 | do 115 | { 116 | const DataType * const sf = src_ptr + coef_index; 117 | DataType * const df = dest_ptr + coef_index; 118 | 119 | // Extreme coefficients are always real 120 | df [c1_r] = sf [c1_r] + sf [c2_r]; 121 | df [c2_r] = sf [c1_r] - sf [c2_r]; 122 | df [c1_i] = sf [c1_i] * 2; 123 | df [c2_i] = sf [c2_i] * 2; 124 | 125 | FFTRealUseTrigo ::prepare (osc_list [TRIGO_OSC]); 126 | 127 | // Others are conjugate complex numbers 128 | for (long i = 1; i < dist; ++ i) 129 | { 130 | df [c1_r + i] = sf [c1_r + i] + sf [c2_r - i]; 131 | df [c1_i + i] = sf [c2_r + i] - sf [cend - i]; 132 | 133 | DataType c; 134 | DataType s; 135 | FFTRealUseTrigo ::iterate ( 136 | osc_list [TRIGO_OSC], 137 | c, 138 | s, 139 | cos_ptr, 140 | i * table_step, 141 | (dist - i) * table_step 142 | ); 143 | 144 | const DataType vr = sf [c1_r + i] - sf [c2_r - i]; 145 | const DataType vi = sf [c2_r + i] + sf [cend - i]; 146 | 147 | df [c2_r + i] = vr * c + vi * s; 148 | df [c2_i + i] = vi * c - vr * s; 149 | } 150 | 151 | coef_index += cend; 152 | } 153 | while (coef_index < len); 154 | } 155 | 156 | template <> 157 | inline void FFTRealPassInverse <2>::process_internal (long len, DataType dest_ptr [], const DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 158 | { 159 | // Antepenultimate pass 160 | const DataType sqrt2_2 = DataType (SQRT2 * 0.5); 161 | 162 | long coef_index = 0; 163 | do 164 | { 165 | dest_ptr [coef_index ] = src_ptr [coef_index] + src_ptr [coef_index + 4]; 166 | dest_ptr [coef_index + 4] = src_ptr [coef_index] - src_ptr [coef_index + 4]; 167 | dest_ptr [coef_index + 2] = src_ptr [coef_index + 2] * 2; 168 | dest_ptr [coef_index + 6] = src_ptr [coef_index + 6] * 2; 169 | 170 | dest_ptr [coef_index + 1] = src_ptr [coef_index + 1] + src_ptr [coef_index + 3]; 171 | dest_ptr [coef_index + 3] = src_ptr [coef_index + 5] - src_ptr [coef_index + 7]; 172 | 173 | const DataType vr = src_ptr [coef_index + 1] - src_ptr [coef_index + 3]; 174 | const DataType vi = src_ptr [coef_index + 5] + src_ptr [coef_index + 7]; 175 | 176 | dest_ptr [coef_index + 5] = (vr + vi) * sqrt2_2; 177 | dest_ptr [coef_index + 7] = (vi - vr) * sqrt2_2; 178 | 179 | coef_index += 8; 180 | } 181 | while (coef_index < len); 182 | } 183 | 184 | template <> 185 | inline void FFTRealPassInverse <1>::process_internal (long len, DataType dest_ptr [], const DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []) 186 | { 187 | // Penultimate and last pass at once 188 | const long qlen = len >> 2; 189 | 190 | long coef_index = 0; 191 | do 192 | { 193 | const long ri_0 = br_ptr [coef_index >> 2]; 194 | 195 | const DataType b_0 = src_ptr [coef_index ] + src_ptr [coef_index + 2]; 196 | const DataType b_2 = src_ptr [coef_index ] - src_ptr [coef_index + 2]; 197 | const DataType b_1 = src_ptr [coef_index + 1] * 2; 198 | const DataType b_3 = src_ptr [coef_index + 3] * 2; 199 | 200 | dest_ptr [ri_0 ] = b_0 + b_1; 201 | dest_ptr [ri_0 + 2 * qlen] = b_0 - b_1; 202 | dest_ptr [ri_0 + 1 * qlen] = b_2 + b_3; 203 | dest_ptr [ri_0 + 3 * qlen] = b_2 - b_3; 204 | 205 | coef_index += 4; 206 | } 207 | while (coef_index < len); 208 | } 209 | 210 | 211 | 212 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 213 | 214 | 215 | 216 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 217 | 218 | 219 | 220 | } // namespace ffft 221 | 222 | 223 | 224 | #endif // ffft_FFTRealPassInverse_CODEHEADER_INCLUDED 225 | 226 | #undef ffft_FFTRealPassInverse_CURRENT_CODEHEADER 227 | 228 | 229 | 230 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 231 | -------------------------------------------------------------------------------- /src/FFTRealSelect.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealSelect.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealSelect_HEADER_INCLUDED) 19 | #define ffft_FFTRealSelect_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #endif 24 | 25 | 26 | 27 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 28 | 29 | #include "ffft/def.h" 30 | 31 | 32 | 33 | namespace ffft 34 | { 35 | 36 | 37 | 38 | template 39 | class FFTRealSelect 40 | { 41 | 42 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 43 | 44 | public: 45 | 46 | ffft_FORCEINLINE static float * 47 | sel_bin (float *e_ptr, float *o_ptr); 48 | 49 | 50 | 51 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 52 | 53 | private: 54 | 55 | FFTRealSelect (); 56 | ~FFTRealSelect (); 57 | FFTRealSelect (const FFTRealSelect &other); 58 | FFTRealSelect& operator = (const FFTRealSelect &other); 59 | bool operator == (const FFTRealSelect &other); 60 | bool operator != (const FFTRealSelect &other); 61 | 62 | }; // class FFTRealSelect 63 | 64 | 65 | 66 | } // namespace ffft 67 | 68 | 69 | 70 | #include "ffft/FFTRealSelect.hpp" 71 | 72 | 73 | 74 | #endif // ffft_FFTRealSelect_HEADER_INCLUDED 75 | 76 | 77 | 78 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 79 | -------------------------------------------------------------------------------- /src/FFTRealSelect.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealSelect.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealSelect_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealSelect code header. 20 | #endif 21 | #define ffft_FFTRealSelect_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealSelect_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealSelect_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | namespace ffft 29 | { 30 | 31 | 32 | 33 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 34 | 35 | 36 | 37 | template 38 | float * FFTRealSelect

::sel_bin (float *e_ptr, float *o_ptr) 39 | { 40 | return (o_ptr); 41 | } 42 | 43 | 44 | 45 | template <> 46 | inline float * FFTRealSelect <0>::sel_bin (float *e_ptr, float *o_ptr) 47 | { 48 | return (e_ptr); 49 | } 50 | 51 | 52 | 53 | } // namespace ffft 54 | 55 | 56 | 57 | #endif // ffft_FFTRealSelect_CODEHEADER_INCLUDED 58 | 59 | #undef ffft_FFTRealSelect_CURRENT_CODEHEADER 60 | 61 | 62 | 63 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | -------------------------------------------------------------------------------- /src/FFTRealUseTrigo.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealUseTrigo.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealUseTrigo_HEADER_INCLUDED) 19 | #define ffft_FFTRealUseTrigo_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTRealUseTrigo 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef FFTRealFixLenParam::DataType DataType; 50 | typedef OscSinCos OscType; 51 | 52 | ffft_FORCEINLINE static void 53 | prepare (OscType &osc); 54 | ffft_FORCEINLINE static void 55 | iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s); 56 | 57 | 58 | 59 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 60 | 61 | protected: 62 | 63 | 64 | 65 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | private: 68 | 69 | 70 | 71 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 72 | 73 | private: 74 | 75 | FFTRealUseTrigo (); 76 | ~FFTRealUseTrigo (); 77 | FFTRealUseTrigo (const FFTRealUseTrigo &other); 78 | FFTRealUseTrigo & 79 | operator = (const FFTRealUseTrigo &other); 80 | bool operator == (const FFTRealUseTrigo &other); 81 | bool operator != (const FFTRealUseTrigo &other); 82 | 83 | }; // class FFTRealUseTrigo 84 | 85 | 86 | 87 | } // namespace ffft 88 | 89 | 90 | 91 | #include "ffft/FFTRealUseTrigo.hpp" 92 | 93 | 94 | 95 | #endif // ffft_FFTRealUseTrigo_HEADER_INCLUDED 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/FFTRealUseTrigo.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealUseTrigo.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealUseTrigo_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealUseTrigo code header. 20 | #endif 21 | #define ffft_FFTRealUseTrigo_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/OscSinCos.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | void FFTRealUseTrigo ::prepare (OscType &osc) 45 | { 46 | osc.clear_buffers (); 47 | } 48 | 49 | template <> 50 | inline void FFTRealUseTrigo <0>::prepare (OscType &osc) 51 | { 52 | // Nothing 53 | } 54 | 55 | 56 | 57 | template 58 | void FFTRealUseTrigo ::iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s) 59 | { 60 | osc.step (); 61 | c = osc.get_cos (); 62 | s = osc.get_sin (); 63 | } 64 | 65 | template <> 66 | inline void FFTRealUseTrigo <0>::iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s) 67 | { 68 | c = cos_ptr [index_c]; 69 | s = cos_ptr [index_s]; 70 | } 71 | 72 | 73 | 74 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 75 | 76 | 77 | 78 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 79 | 80 | 81 | 82 | } // namespace ffft 83 | 84 | 85 | 86 | #endif // ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED 87 | 88 | #undef ffft_FFTRealUseTrigo_CURRENT_CODEHEADER 89 | 90 | 91 | 92 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 93 | -------------------------------------------------------------------------------- /src/OscSinCos.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | OscSinCos.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_OscSinCos_HEADER_INCLUDED) 19 | #define ffft_OscSinCos_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | template 40 | class OscSinCos 41 | { 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | public: 46 | 47 | typedef T DataType; 48 | 49 | OscSinCos (); 50 | 51 | ffft_FORCEINLINE void 52 | set_step (double angle_rad); 53 | 54 | ffft_FORCEINLINE DataType 55 | get_cos () const; 56 | ffft_FORCEINLINE DataType 57 | get_sin () const; 58 | ffft_FORCEINLINE void 59 | step (); 60 | ffft_FORCEINLINE void 61 | clear_buffers (); 62 | 63 | 64 | 65 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | protected: 68 | 69 | 70 | 71 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 72 | 73 | private: 74 | 75 | DataType _pos_cos; // Current phase expressed with sin and cos. [-1 ; 1] 76 | DataType _pos_sin; // - 77 | DataType _step_cos; // Phase increment per step, [-1 ; 1] 78 | DataType _step_sin; // - 79 | 80 | 81 | 82 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 83 | 84 | private: 85 | 86 | OscSinCos (const OscSinCos &other); 87 | OscSinCos & operator = (const OscSinCos &other); 88 | bool operator == (const OscSinCos &other); 89 | bool operator != (const OscSinCos &other); 90 | 91 | }; // class OscSinCos 92 | 93 | 94 | 95 | } // namespace ffft 96 | 97 | 98 | 99 | #include "ffft/OscSinCos.hpp" 100 | 101 | 102 | 103 | #endif // ffft_OscSinCos_HEADER_INCLUDED 104 | 105 | 106 | 107 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 108 | -------------------------------------------------------------------------------- /src/OscSinCos.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | OscSinCos.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_OscSinCos_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of OscSinCos code header. 20 | #endif 21 | #define ffft_OscSinCos_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_OscSinCos_CODEHEADER_INCLUDED) 24 | #define ffft_OscSinCos_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | namespace std { } 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | 44 | 45 | template 46 | OscSinCos ::OscSinCos () 47 | : _pos_cos (1) 48 | , _pos_sin (0) 49 | , _step_cos (1) 50 | , _step_sin (0) 51 | { 52 | // Nothing 53 | } 54 | 55 | 56 | 57 | template 58 | void OscSinCos ::set_step (double angle_rad) 59 | { 60 | using namespace std; 61 | 62 | _step_cos = static_cast (cos (angle_rad)); 63 | _step_sin = static_cast (sin (angle_rad)); 64 | } 65 | 66 | 67 | 68 | template 69 | typename OscSinCos ::DataType OscSinCos ::get_cos () const 70 | { 71 | return (_pos_cos); 72 | } 73 | 74 | 75 | 76 | template 77 | typename OscSinCos ::DataType OscSinCos ::get_sin () const 78 | { 79 | return (_pos_sin); 80 | } 81 | 82 | 83 | 84 | template 85 | void OscSinCos ::step () 86 | { 87 | const DataType old_cos = _pos_cos; 88 | const DataType old_sin = _pos_sin; 89 | 90 | _pos_cos = old_cos * _step_cos - old_sin * _step_sin; 91 | _pos_sin = old_cos * _step_sin + old_sin * _step_cos; 92 | } 93 | 94 | 95 | 96 | template 97 | void OscSinCos ::clear_buffers () 98 | { 99 | _pos_cos = static_cast (1); 100 | _pos_sin = static_cast (0); 101 | } 102 | 103 | 104 | 105 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 106 | 107 | 108 | 109 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 110 | 111 | 112 | 113 | } // namespace ffft 114 | 115 | 116 | 117 | #endif // ffft_OscSinCos_CODEHEADER_INCLUDED 118 | 119 | #undef ffft_OscSinCos_CURRENT_CODEHEADER 120 | 121 | 122 | 123 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 124 | -------------------------------------------------------------------------------- /src/def.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | def.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_def_HEADER_INCLUDED) 19 | #define ffft_def_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | const double PI = 3.1415926535897932384626433832795; 38 | const double SQRT2 = 1.41421356237309514547462185873883; 39 | 40 | #if defined (_MSC_VER) 41 | 42 | #define ffft_FORCEINLINE __forceinline 43 | 44 | #else 45 | 46 | #define ffft_FORCEINLINE inline 47 | 48 | #endif 49 | 50 | 51 | 52 | } // namespace ffft 53 | 54 | 55 | 56 | #endif // ffft_def_HEADER_INCLUDED 57 | 58 | 59 | 60 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 61 | -------------------------------------------------------------------------------- /src/test/TestAccuracy.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestAccuracy.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_TestAccuracy_HEADER_INCLUDED) 19 | #define ffft_test_TestAccuracy_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | namespace test 35 | { 36 | 37 | 38 | 39 | template 40 | class TestAccuracy 41 | { 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | public: 46 | 47 | typedef typename FO::DataType DataType; 48 | typedef long double BigFloat; // To get maximum accuracy during intermediate calculations 49 | 50 | static int perform_test_single_object (FO &fft); 51 | static int perform_test_d (FO &fft, const char *class_name_0); 52 | static int perform_test_i (FO &fft, const char *class_name_0); 53 | static int perform_test_di (FO &fft, const char *class_name_0); 54 | 55 | 56 | 57 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | protected: 60 | 61 | 62 | 63 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | enum { NBR_ACC_TESTS = 10 * 1000 * 1000 }; 68 | enum { MAX_NBR_TESTS = 10000 }; 69 | 70 | static void compute_tf (DataType s [], const DataType x [], long length); 71 | static void compute_itf (DataType x [], const DataType s [], long length); 72 | static int compare_vect_display (const DataType x_ptr [], const DataType y_ptr [], long len, BigFloat &max_err_rel); 73 | static BigFloat 74 | compute_power (const DataType x_ptr [], long len); 75 | static BigFloat 76 | compute_power (const DataType x_ptr [], const DataType y_ptr [], long len); 77 | static void compare_vect (const DataType x_ptr [], const DataType y_ptr [], BigFloat &power, long &max_err_pos, long len); 78 | 79 | 80 | 81 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 82 | 83 | private: 84 | 85 | TestAccuracy (); 86 | TestAccuracy (const TestAccuracy &other); 87 | TestAccuracy & operator = (const TestAccuracy &other); 88 | bool operator == (const TestAccuracy &other); 89 | bool operator != (const TestAccuracy &other); 90 | 91 | }; // class TestAccuracy 92 | 93 | 94 | 95 | } // namespace test 96 | } // namespace ffft 97 | 98 | 99 | 100 | #include "ffft/test/TestAccuracy.hpp" 101 | 102 | 103 | 104 | #endif // ffft_test_TestAccuracy_HEADER_INCLUDED 105 | 106 | 107 | 108 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 109 | -------------------------------------------------------------------------------- /src/test/TestAccuracy.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestAccuracy.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_TestAccuracy_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of TestAccuracy code header. 20 | #endif 21 | #define ffft_test_TestAccuracy_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_TestAccuracy_CODEHEADER_INCLUDED) 24 | #define ffft_test_TestAccuracy_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/test/fnc.h" 32 | #include "ffft/test/TestWhiteNoiseGen.h" 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | 41 | 42 | namespace ffft 43 | { 44 | namespace test 45 | { 46 | 47 | 48 | 49 | static const double TestAccuracy_LN10 = 2.3025850929940456840179914546844; 50 | 51 | 52 | 53 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 54 | 55 | 56 | 57 | template 58 | int TestAccuracy ::perform_test_single_object (FO &fft) 59 | { 60 | assert (&fft != 0); 61 | 62 | using namespace std; 63 | 64 | int ret_val = 0; 65 | 66 | const std::type_info & ti = typeid (fft); 67 | const char * class_name_0 = ti.name (); 68 | 69 | if (ret_val == 0) 70 | { 71 | ret_val = perform_test_d (fft, class_name_0); 72 | } 73 | if (ret_val == 0) 74 | { 75 | ret_val = perform_test_i (fft, class_name_0); 76 | } 77 | if (ret_val == 0) 78 | { 79 | ret_val = perform_test_di (fft, class_name_0); 80 | } 81 | 82 | if (ret_val == 0) 83 | { 84 | printf ("\n"); 85 | } 86 | 87 | return (ret_val); 88 | } 89 | 90 | 91 | 92 | template 93 | int TestAccuracy ::perform_test_d (FO &fft, const char *class_name_0) 94 | { 95 | assert (&fft != 0); 96 | assert (class_name_0 != 0); 97 | 98 | using namespace std; 99 | 100 | int ret_val = 0; 101 | const long len = fft.get_length (); 102 | const long nbr_tests = limit ( 103 | NBR_ACC_TESTS / len / len, 104 | 1L, 105 | static_cast (MAX_NBR_TESTS) 106 | ); 107 | 108 | printf ("Testing %s::do_fft () [%ld samples]... ", class_name_0, len); 109 | fflush (stdout); 110 | TestWhiteNoiseGen noise; 111 | std::vector x (len); 112 | std::vector s1 (len); 113 | std::vector s2 (len); 114 | BigFloat err_avg = 0; 115 | 116 | for (long test = 0; test < nbr_tests && ret_val == 0; ++ test) 117 | { 118 | noise.generate (&x [0], len); 119 | fft.do_fft (&s1 [0], &x [0]); 120 | compute_tf (&s2 [0], &x [0], len); 121 | 122 | BigFloat max_err; 123 | compare_vect_display (&s1 [0], &s2 [0], len, max_err); 124 | err_avg += max_err; 125 | } 126 | err_avg /= NBR_ACC_TESTS; 127 | 128 | printf ("done.\n"); 129 | printf ( 130 | "Average maximum error: %.6f %% (%f dB)\n", 131 | static_cast (err_avg * 100), 132 | static_cast ((20 / TestAccuracy_LN10) * log (err_avg + 1e-300)) 133 | ); 134 | 135 | return (ret_val); 136 | } 137 | 138 | 139 | 140 | template 141 | int TestAccuracy ::perform_test_i (FO &fft, const char *class_name_0) 142 | { 143 | assert (&fft != 0); 144 | assert (class_name_0 != 0); 145 | 146 | using namespace std; 147 | 148 | int ret_val = 0; 149 | const long len = fft.get_length (); 150 | const long nbr_tests = limit ( 151 | NBR_ACC_TESTS / len / len, 152 | 10L, 153 | static_cast (MAX_NBR_TESTS) 154 | ); 155 | 156 | printf ("Testing %s::do_ifft () [%ld samples]... ", class_name_0, len); 157 | fflush (stdout); 158 | TestWhiteNoiseGen noise; 159 | std::vector s (len); 160 | std::vector x1 (len); 161 | std::vector x2 (len); 162 | BigFloat err_avg = 0; 163 | 164 | for (long test = 0; test < nbr_tests && ret_val == 0; ++ test) 165 | { 166 | noise.generate (&s [0], len); 167 | fft.do_ifft (&s [0], &x1 [0]); 168 | compute_itf (&x2 [0], &s [0], len); 169 | 170 | BigFloat max_err; 171 | compare_vect_display (&x1 [0], &x2 [0], len, max_err); 172 | err_avg += max_err; 173 | } 174 | err_avg /= NBR_ACC_TESTS; 175 | 176 | printf ("done.\n"); 177 | printf ( 178 | "Average maximum error: %.6f %% (%f dB)\n", 179 | static_cast (err_avg * 100), 180 | static_cast ((20 / TestAccuracy_LN10) * log (err_avg + 1e-300)) 181 | ); 182 | 183 | return (ret_val); 184 | } 185 | 186 | 187 | 188 | template 189 | int TestAccuracy ::perform_test_di (FO &fft, const char *class_name_0) 190 | { 191 | assert (&fft != 0); 192 | assert (class_name_0 != 0); 193 | 194 | using namespace std; 195 | 196 | int ret_val = 0; 197 | const long len = fft.get_length (); 198 | const long nbr_tests = limit ( 199 | NBR_ACC_TESTS / len / len, 200 | 1L, 201 | static_cast (MAX_NBR_TESTS) 202 | ); 203 | 204 | printf ( 205 | "Testing %s::do_fft () / do_ifft () / rescale () [%ld samples]... ", 206 | class_name_0, 207 | len 208 | ); 209 | fflush (stdout); 210 | TestWhiteNoiseGen noise; 211 | std::vector x (len); 212 | std::vector s (len); 213 | std::vector y (len); 214 | BigFloat err_avg = 0; 215 | 216 | for (long test = 0; test < nbr_tests && ret_val == 0; ++ test) 217 | { 218 | noise.generate (&x [0], len); 219 | fft.do_fft (&s [0], &x [0]); 220 | fft.do_ifft (&s [0], &y [0]); 221 | fft.rescale (&y [0]); 222 | 223 | BigFloat max_err; 224 | compare_vect_display (&x [0], &y [0], len, max_err); 225 | err_avg += max_err; 226 | } 227 | err_avg /= NBR_ACC_TESTS; 228 | 229 | printf ("done.\n"); 230 | printf ( 231 | "Average maximum error: %.6f %% (%f dB)\n", 232 | static_cast (err_avg * 100), 233 | static_cast ((20 / TestAccuracy_LN10) * log (err_avg + 1e-300)) 234 | ); 235 | 236 | return (ret_val); 237 | } 238 | 239 | 240 | 241 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 242 | 243 | 244 | 245 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 246 | 247 | 248 | 249 | // Positive transform 250 | template 251 | void TestAccuracy ::compute_tf (DataType s [], const DataType x [], long length) 252 | { 253 | assert (s != 0); 254 | assert (x != 0); 255 | assert (length >= 2); 256 | assert ((length & 1) == 0); 257 | 258 | const long nbr_bins = length >> 1; 259 | 260 | // DC and Nyquist 261 | BigFloat dc = 0; 262 | BigFloat ny = 0; 263 | for (long pos = 0; pos < length; pos += 2) 264 | { 265 | const BigFloat even = x [pos ]; 266 | const BigFloat odd = x [pos + 1]; 267 | dc += even + odd; 268 | ny += even - odd; 269 | } 270 | s [0 ] = static_cast (dc); 271 | s [nbr_bins] = static_cast (ny); 272 | 273 | // Regular bins 274 | for (long bin = 1; bin < nbr_bins; ++ bin) 275 | { 276 | BigFloat sum_r = 0; 277 | BigFloat sum_i = 0; 278 | 279 | const BigFloat m = bin * static_cast (2 * PI) / length; 280 | 281 | for (long pos = 0; pos < length; ++pos) 282 | { 283 | using namespace std; 284 | 285 | const BigFloat phase = pos * m; 286 | const BigFloat e_r = cos (phase); 287 | const BigFloat e_i = sin (phase); 288 | 289 | sum_r += x [pos] * e_r; 290 | sum_i += x [pos] * e_i; 291 | } 292 | 293 | s [ bin] = static_cast (sum_r); 294 | s [nbr_bins + bin] = static_cast (sum_i); 295 | } 296 | } 297 | 298 | 299 | 300 | // Negative transform 301 | template 302 | void TestAccuracy ::compute_itf (DataType x [], const DataType s [], long length) 303 | { 304 | assert (s != 0); 305 | assert (x != 0); 306 | assert (length >= 2); 307 | assert ((length & 1) == 0); 308 | 309 | const long nbr_bins = length >> 1; 310 | 311 | // DC and Nyquist 312 | BigFloat dc = s [0 ]; 313 | BigFloat ny = s [nbr_bins]; 314 | 315 | // Regular bins 316 | for (long pos = 0; pos < length; ++pos) 317 | { 318 | BigFloat sum = dc + ny * (1 - 2 * (pos & 1)); 319 | 320 | const BigFloat m = pos * static_cast (-2 * PI) / length; 321 | 322 | for (long bin = 1; bin < nbr_bins; ++ bin) 323 | { 324 | using namespace std; 325 | 326 | const BigFloat phase = bin * m; 327 | const BigFloat e_r = cos (phase); 328 | const BigFloat e_i = sin (phase); 329 | 330 | sum += 2 * ( e_r * s [bin ] 331 | - e_i * s [bin + nbr_bins]); 332 | } 333 | 334 | x [pos] = static_cast (sum); 335 | } 336 | } 337 | 338 | 339 | 340 | template 341 | int TestAccuracy ::compare_vect_display (const DataType x_ptr [], const DataType y_ptr [], long len, BigFloat &max_err_rel) 342 | { 343 | assert (x_ptr != 0); 344 | assert (y_ptr != 0); 345 | assert (len > 0); 346 | assert (&max_err_rel != 0); 347 | 348 | using namespace std; 349 | 350 | int ret_val = 0; 351 | 352 | BigFloat power = compute_power (&x_ptr [0], &y_ptr [0], len); 353 | BigFloat power_dif; 354 | long max_err_pos; 355 | compare_vect (&x_ptr [0], &y_ptr [0], power_dif, max_err_pos, len); 356 | 357 | if (power == 0) 358 | { 359 | power = power_dif; 360 | } 361 | const BigFloat power_err_rel = power_dif / power; 362 | 363 | BigFloat max_err = 0; 364 | max_err_rel = 0; 365 | if (max_err_pos >= 0) 366 | { 367 | max_err = y_ptr [max_err_pos] - x_ptr [max_err_pos]; 368 | max_err_rel = 2 * fabs (max_err) / ( fabs (y_ptr [max_err_pos]) 369 | + fabs (x_ptr [max_err_pos])); 370 | } 371 | 372 | if (power_err_rel > 0.001) 373 | { 374 | printf ("Power error : %f (%.6f %%)\n", 375 | static_cast (power_err_rel), 376 | static_cast (power_err_rel * 100) 377 | ); 378 | if (max_err_pos >= 0) 379 | { 380 | printf ( 381 | "Maximum error: %f - %f = %f (%f)\n", 382 | static_cast (y_ptr [max_err_pos]), 383 | static_cast (x_ptr [max_err_pos]), 384 | static_cast (max_err), 385 | static_cast (max_err_pos) 386 | ); 387 | } 388 | } 389 | 390 | return (ret_val); 391 | } 392 | 393 | 394 | 395 | template 396 | typename TestAccuracy ::BigFloat TestAccuracy ::compute_power (const DataType x_ptr [], long len) 397 | { 398 | assert (x_ptr != 0); 399 | assert (len > 0); 400 | 401 | BigFloat power = 0; 402 | for (long pos = 0; pos < len; ++pos) 403 | { 404 | const BigFloat val = x_ptr [pos]; 405 | 406 | power += val * val; 407 | } 408 | 409 | using namespace std; 410 | 411 | power = sqrt (power) / len; 412 | 413 | return (power); 414 | } 415 | 416 | 417 | 418 | template 419 | typename TestAccuracy ::BigFloat TestAccuracy ::compute_power (const DataType x_ptr [], const DataType y_ptr [], long len) 420 | { 421 | assert (x_ptr != 0); 422 | assert (y_ptr != 0); 423 | assert (len > 0); 424 | 425 | return ((compute_power (x_ptr, len) + compute_power (y_ptr, len)) * 0.5); 426 | } 427 | 428 | 429 | 430 | template 431 | void TestAccuracy ::compare_vect (const DataType x_ptr [], const DataType y_ptr [], BigFloat &power, long &max_err_pos, long len) 432 | { 433 | assert (x_ptr != 0); 434 | assert (y_ptr != 0); 435 | assert (len > 0); 436 | assert (&power != 0); 437 | assert (&max_err_pos != 0); 438 | 439 | power = 0; 440 | BigFloat max_dif2 = 0; 441 | max_err_pos = -1; 442 | 443 | for (long pos = 0; pos < len; ++pos) 444 | { 445 | const BigFloat x = x_ptr [pos]; 446 | const BigFloat y = y_ptr [pos]; 447 | const BigFloat dif = y - x; 448 | const BigFloat dif2 = dif * dif; 449 | 450 | power += dif2; 451 | if (dif2 > max_dif2) 452 | { 453 | max_err_pos = pos; 454 | max_dif2 = dif2; 455 | } 456 | } 457 | 458 | using namespace std; 459 | 460 | power = sqrt (power) / len; 461 | } 462 | 463 | 464 | 465 | } // namespace test 466 | } // namespace ffft 467 | 468 | 469 | 470 | #endif // ffft_test_TestAccuracy_CODEHEADER_INCLUDED 471 | 472 | #undef ffft_test_TestAccuracy_CURRENT_CODEHEADER 473 | 474 | 475 | 476 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 477 | -------------------------------------------------------------------------------- /src/test/TestHelperFixLen.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestHelperFixLen.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_TestHelperFixLen_HEADER_INCLUDED) 19 | #define ffft_test_TestHelperFixLen_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/FFTRealFixLen.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | namespace test 37 | { 38 | 39 | 40 | 41 | template 42 | class TestHelperFixLen 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef FFTRealFixLen FftType; 50 | 51 | static void perform_test_accuracy (int &ret_val); 52 | static void perform_test_speed (int &ret_val); 53 | 54 | 55 | 56 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 57 | 58 | protected: 59 | 60 | 61 | 62 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 63 | 64 | private: 65 | 66 | 67 | 68 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 69 | 70 | private: 71 | 72 | TestHelperFixLen (); 73 | TestHelperFixLen (const TestHelperFixLen &other); 74 | TestHelperFixLen & 75 | operator = (const TestHelperFixLen &other); 76 | bool operator == (const TestHelperFixLen &other); 77 | bool operator != (const TestHelperFixLen &other); 78 | 79 | }; // class TestHelperFixLen 80 | 81 | 82 | 83 | } // namespace test 84 | } // namespace ffft 85 | 86 | 87 | 88 | #include "ffft/test/TestHelperFixLen.hpp" 89 | 90 | 91 | 92 | #endif // ffft_test_TestHelperFixLen_HEADER_INCLUDED 93 | 94 | 95 | 96 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 97 | -------------------------------------------------------------------------------- /src/test/TestHelperFixLen.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestHelperFixLen.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_TestHelperFixLen_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of TestHelperFixLen code header. 20 | #endif 21 | #define ffft_test_TestHelperFixLen_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_TestHelperFixLen_CODEHEADER_INCLUDED) 24 | #define ffft_test_TestHelperFixLen_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/test/conf.h" 31 | 32 | #include "ffft/test/TestAccuracy.h" 33 | #if defined (ffft_test_SPEED_TEST_ENABLED) 34 | #include "ffft/test/TestSpeed.h" 35 | #endif 36 | 37 | 38 | 39 | namespace ffft 40 | { 41 | namespace test 42 | { 43 | 44 | 45 | 46 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 47 | 48 | 49 | 50 | template 51 | void TestHelperFixLen ::perform_test_accuracy (int &ret_val) 52 | { 53 | if (ret_val == 0) 54 | { 55 | FftType fft; 56 | ret_val = TestAccuracy ::perform_test_single_object (fft); 57 | } 58 | } 59 | 60 | 61 | 62 | template 63 | void TestHelperFixLen ::perform_test_speed (int &ret_val) 64 | { 65 | #if defined (ffft_test_SPEED_TEST_ENABLED) 66 | 67 | if (ret_val == 0) 68 | { 69 | FftType fft; 70 | ret_val = TestSpeed ::perform_test_single_object (fft); 71 | } 72 | 73 | #endif 74 | } 75 | 76 | 77 | 78 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 79 | 80 | 81 | 82 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 83 | 84 | 85 | 86 | } // namespace test 87 | } // namespace ffft 88 | 89 | 90 | 91 | #endif // ffft_test_TestHelperFixLen_CODEHEADER_INCLUDED 92 | 93 | #undef ffft_test_TestHelperFixLen_CURRENT_CODEHEADER 94 | 95 | 96 | 97 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 98 | -------------------------------------------------------------------------------- /src/test/TestHelperNormal.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestHelperNormal.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_TestHelperNormal_HEADER_INCLUDED) 19 | #define ffft_test_TestHelperNormal_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/FFTReal.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | namespace test 37 | { 38 | 39 | 40 | 41 | template 42 | class TestHelperNormal 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef DT DataType; 50 | typedef FFTReal FftType; 51 | 52 | static void perform_test_accuracy (int &ret_val); 53 | static void perform_test_speed (int &ret_val); 54 | 55 | 56 | 57 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | protected: 60 | 61 | 62 | 63 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | 68 | 69 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 70 | 71 | private: 72 | 73 | TestHelperNormal (); 74 | TestHelperNormal (const TestHelperNormal &other); 75 | TestHelperNormal & 76 | operator = (const TestHelperNormal &other); 77 | bool operator == (const TestHelperNormal &other); 78 | bool operator != (const TestHelperNormal &other); 79 | 80 | }; // class TestHelperNormal 81 | 82 | 83 | 84 | } // namespace test 85 | } // namespace ffft 86 | 87 | 88 | 89 | #include "ffft/test/TestHelperNormal.hpp" 90 | 91 | 92 | 93 | #endif // ffft_test_TestHelperNormal_HEADER_INCLUDED 94 | 95 | 96 | 97 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 98 | -------------------------------------------------------------------------------- /src/test/TestHelperNormal.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestHelperNormal.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_TestHelperNormal_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of TestHelperNormal code header. 20 | #endif 21 | #define ffft_test_TestHelperNormal_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_TestHelperNormal_CODEHEADER_INCLUDED) 24 | #define ffft_test_TestHelperNormal_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/test/conf.h" 31 | 32 | #include "ffft/test/TestAccuracy.h" 33 | #if defined (ffft_test_SPEED_TEST_ENABLED) 34 | #include "ffft/test/TestSpeed.h" 35 | #endif 36 | 37 | 38 | 39 | namespace ffft 40 | { 41 | namespace test 42 | { 43 | 44 | 45 | 46 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 47 | 48 | 49 | 50 | template 51 | void TestHelperNormal

::perform_test_accuracy (int &ret_val) 52 | { 53 | const int len_arr [] = { 1, 2, 3, 4, 7, 8, 10, 12 }; 54 | const int nbr_len = sizeof (len_arr) / sizeof (len_arr [0]); 55 | for (int k = 0; k < nbr_len && ret_val == 0; ++k) 56 | { 57 | const long len = 1L << (len_arr [k]); 58 | FftType fft (len); 59 | ret_val = TestAccuracy ::perform_test_single_object (fft); 60 | } 61 | } 62 | 63 | 64 | 65 | template 66 | void TestHelperNormal
::perform_test_speed (int &ret_val) 67 | { 68 | #if defined (ffft_test_SPEED_TEST_ENABLED) 69 | 70 | const int len_arr [] = { 1, 2, 3, 4, 7, 8, 10, 12, 14, 16, 18, 20, 22 }; 71 | const int nbr_len = sizeof (len_arr) / sizeof (len_arr [0]); 72 | for (int k = 0; k < nbr_len && ret_val == 0; ++k) 73 | { 74 | const long len = 1L << (len_arr [k]); 75 | FftType fft (len); 76 | ret_val = TestSpeed ::perform_test_single_object (fft); 77 | } 78 | 79 | #endif 80 | } 81 | 82 | 83 | 84 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 85 | 86 | 87 | 88 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 89 | 90 | 91 | 92 | } // namespace test 93 | } // namespace ffft 94 | 95 | 96 | 97 | #endif // ffft_test_TestHelperNormal_CODEHEADER_INCLUDED 98 | 99 | #undef ffft_test_TestHelperNormal_CURRENT_CODEHEADER 100 | 101 | 102 | 103 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 104 | -------------------------------------------------------------------------------- /src/test/TestSpeed.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestSpeed.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_TestSpeed_HEADER_INCLUDED) 19 | #define ffft_test_TestSpeed_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | namespace test 35 | { 36 | 37 | 38 | 39 | template 40 | class TestSpeed 41 | { 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | public: 46 | 47 | typedef typename FO::DataType DataType; 48 | 49 | static int perform_test_single_object (FO &fft); 50 | static int perform_test_d (FO &fft, const char *class_name_0); 51 | static int perform_test_i (FO &fft, const char *class_name_0); 52 | static int perform_test_di (FO &fft, const char *class_name_0); 53 | 54 | 55 | 56 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 57 | 58 | protected: 59 | 60 | 61 | 62 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 63 | 64 | private: 65 | 66 | enum { NBR_SPD_TESTS = 10 * 1000 * 1000 }; 67 | enum { MAX_NBR_TESTS = 10000 }; 68 | 69 | 70 | 71 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 72 | 73 | private: 74 | 75 | TestSpeed (); 76 | ~TestSpeed (); 77 | TestSpeed (const TestSpeed &other); 78 | TestSpeed & operator = (const TestSpeed &other); 79 | bool operator == (const TestSpeed &other); 80 | bool operator != (const TestSpeed &other); 81 | 82 | }; // class TestSpeed 83 | 84 | 85 | 86 | } // namespace test 87 | } // namespace ffft 88 | 89 | 90 | 91 | #include "ffft/test/TestSpeed.hpp" 92 | 93 | 94 | 95 | #endif // ffft_test_TestSpeed_HEADER_INCLUDED 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/test/TestSpeed.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestSpeed.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_TestSpeed_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of TestSpeed code header. 20 | #endif 21 | #define ffft_test_TestSpeed_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_TestSpeed_CODEHEADER_INCLUDED) 24 | #define ffft_test_TestSpeed_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/test/fnc.h" 31 | #include "ffft/test/TestWhiteNoiseGen.h" 32 | #include "stopwatch/StopWatch.h" 33 | 34 | #include 35 | 36 | #include 37 | 38 | 39 | 40 | namespace ffft 41 | { 42 | namespace test 43 | { 44 | 45 | 46 | 47 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 48 | 49 | 50 | 51 | template 52 | int TestSpeed ::perform_test_single_object (FO &fft) 53 | { 54 | assert (&fft != 0); 55 | 56 | int ret_val = 0; 57 | 58 | const std::type_info & ti = typeid (fft); 59 | const char * class_name_0 = ti.name (); 60 | 61 | if (ret_val == 0) 62 | { 63 | perform_test_d (fft, class_name_0); 64 | } 65 | if (ret_val == 0) 66 | { 67 | perform_test_i (fft, class_name_0); 68 | } 69 | if (ret_val == 0) 70 | { 71 | perform_test_di (fft, class_name_0); 72 | } 73 | 74 | if (ret_val == 0) 75 | { 76 | printf ("\n"); 77 | } 78 | 79 | return (ret_val); 80 | } 81 | 82 | 83 | 84 | template 85 | int TestSpeed ::perform_test_d (FO &fft, const char *class_name_0) 86 | { 87 | assert (&fft != 0); 88 | assert (class_name_0 != 0); 89 | 90 | const long len = fft.get_length (); 91 | const long nbr_tests = limit ( 92 | static_cast (NBR_SPD_TESTS / len / len), 93 | 1L, 94 | static_cast (MAX_NBR_TESTS) 95 | ); 96 | 97 | TestWhiteNoiseGen noise; 98 | std::vector x (len, 0); 99 | std::vector s (len); 100 | noise.generate (&x [0], len); 101 | 102 | printf ( 103 | "%s::do_fft () speed test [%ld samples]... ", 104 | class_name_0, 105 | len 106 | ); 107 | fflush (stdout); 108 | 109 | stopwatch::StopWatch chrono; 110 | chrono.start (); 111 | for (long test = 0; test < nbr_tests; ++ test) 112 | { 113 | fft.do_fft (&s [0], &x [0]); 114 | chrono.stop_lap (); 115 | } 116 | 117 | printf ("%.1f clocks/sample\n", chrono.get_time_best_lap (len)); 118 | 119 | return (0); 120 | } 121 | 122 | 123 | 124 | template 125 | int TestSpeed ::perform_test_i (FO &fft, const char *class_name_0) 126 | { 127 | assert (&fft != 0); 128 | assert (class_name_0 != 0); 129 | 130 | const long len = fft.get_length (); 131 | const long nbr_tests = limit ( 132 | static_cast (NBR_SPD_TESTS / len / len), 133 | 1L, 134 | static_cast (MAX_NBR_TESTS) 135 | ); 136 | 137 | TestWhiteNoiseGen noise; 138 | std::vector x (len); 139 | std::vector s (len, 0); 140 | noise.generate (&s [0], len); 141 | 142 | printf ( 143 | "%s::do_ifft () speed test [%ld samples]... ", 144 | class_name_0, 145 | len 146 | ); 147 | fflush (stdout); 148 | 149 | stopwatch::StopWatch chrono; 150 | chrono.start (); 151 | for (long test = 0; test < nbr_tests; ++ test) 152 | { 153 | fft.do_ifft (&s [0], &x [0]); 154 | chrono.stop_lap (); 155 | } 156 | 157 | printf ("%.1f clocks/sample\n", chrono.get_time_best_lap (len)); 158 | 159 | return (0); 160 | } 161 | 162 | 163 | 164 | template 165 | int TestSpeed ::perform_test_di (FO &fft, const char *class_name_0) 166 | { 167 | assert (&fft != 0); 168 | assert (class_name_0 != 0); 169 | 170 | const long len = fft.get_length (); 171 | const long nbr_tests = limit ( 172 | static_cast (NBR_SPD_TESTS / len / len), 173 | 1L, 174 | static_cast (MAX_NBR_TESTS) 175 | ); 176 | 177 | TestWhiteNoiseGen noise; 178 | std::vector x (len, 0); 179 | std::vector s (len); 180 | std::vector y (len); 181 | noise.generate (&x [0], len); 182 | 183 | printf ( 184 | "%s::do_fft () / do_ifft () / rescale () speed test [%ld samples]... ", 185 | class_name_0, 186 | len 187 | ); 188 | fflush (stdout); 189 | 190 | stopwatch::StopWatch chrono; 191 | 192 | chrono.start (); 193 | for (long test = 0; test < nbr_tests; ++ test) 194 | { 195 | fft.do_fft (&s [0], &x [0]); 196 | fft.do_ifft (&s [0], &y [0]); 197 | fft.rescale (&y [0]); 198 | chrono.stop_lap (); 199 | } 200 | 201 | printf ("%.1f clocks/sample\n", chrono.get_time_best_lap (len)); 202 | 203 | return (0); 204 | } 205 | 206 | 207 | 208 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 209 | 210 | 211 | 212 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 213 | 214 | 215 | 216 | } // namespace test 217 | } // namespace ffft 218 | 219 | 220 | 221 | #endif // ffft_test_TestSpeed_CODEHEADER_INCLUDED 222 | 223 | #undef ffft_test_TestSpeed_CURRENT_CODEHEADER 224 | 225 | 226 | 227 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 228 | -------------------------------------------------------------------------------- /src/test/TestWhiteNoiseGen.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestWhiteNoiseGen.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_TestWhiteNoiseGen_HEADER_INCLUDED) 19 | #define ffft_test_TestWhiteNoiseGen_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | namespace test 35 | { 36 | 37 | 38 | 39 | template 40 | class TestWhiteNoiseGen 41 | { 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | public: 46 | 47 | typedef DT DataType; 48 | 49 | TestWhiteNoiseGen (); 50 | virtual ~TestWhiteNoiseGen () {} 51 | 52 | void generate (DataType data_ptr [], long len); 53 | 54 | 55 | 56 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 57 | 58 | protected: 59 | 60 | 61 | 62 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 63 | 64 | private: 65 | 66 | typedef unsigned long StateType; 67 | 68 | StateType _rand_state; 69 | 70 | 71 | 72 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 73 | 74 | private: 75 | 76 | TestWhiteNoiseGen (const TestWhiteNoiseGen &other); 77 | TestWhiteNoiseGen & 78 | operator = (const TestWhiteNoiseGen &other); 79 | bool operator == (const TestWhiteNoiseGen &other); 80 | bool operator != (const TestWhiteNoiseGen &other); 81 | 82 | }; // class TestWhiteNoiseGen 83 | 84 | 85 | 86 | } // namespace test 87 | } // namespace ffft 88 | 89 | 90 | 91 | #include "ffft/test/TestWhiteNoiseGen.hpp" 92 | 93 | 94 | 95 | #endif // ffft_test_TestWhiteNoiseGen_HEADER_INCLUDED 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/test/TestWhiteNoiseGen.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | TestWhiteNoiseGen.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_TestWhiteNoiseGen_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of TestWhiteNoiseGen code header. 20 | #endif 21 | #define ffft_test_TestWhiteNoiseGen_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_TestWhiteNoiseGen_CODEHEADER_INCLUDED) 24 | #define ffft_test_TestWhiteNoiseGen_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | namespace test 37 | { 38 | 39 | 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | 44 | 45 | template 46 | TestWhiteNoiseGen
::TestWhiteNoiseGen () 47 | : _rand_state (0) 48 | { 49 | _rand_state = StateType (reinterpret_cast (this)); 50 | } 51 | 52 | 53 | 54 | template 55 | void TestWhiteNoiseGen
::generate (DataType data_ptr [], long len) 56 | { 57 | assert (data_ptr != 0); 58 | assert (len > 0); 59 | 60 | const DataType one = static_cast (1); 61 | const DataType mul = one / static_cast (0x80000000UL); 62 | 63 | long pos = 0; 64 | do 65 | { 66 | const DataType x = static_cast (_rand_state & 0xFFFFFFFFUL); 67 | data_ptr [pos] = x * mul - one; 68 | 69 | _rand_state = _rand_state * 1234567UL + 890123UL; 70 | 71 | ++ pos; 72 | } 73 | while (pos < len); 74 | } 75 | 76 | 77 | 78 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 79 | 80 | 81 | 82 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 83 | 84 | 85 | 86 | } // namespace test 87 | } // namespace ffft 88 | 89 | 90 | 91 | #endif // ffft_test_TestWhiteNoiseGen_CODEHEADER_INCLUDED 92 | 93 | #undef ffft_test_TestWhiteNoiseGen_CURRENT_CODEHEADER 94 | 95 | 96 | 97 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 98 | -------------------------------------------------------------------------------- /src/test/conf.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | conf.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_conf_HEADER_INCLUDED) 19 | #define ffft_test_conf_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | namespace ffft 29 | { 30 | namespace test 31 | { 32 | 33 | 34 | 35 | // #undef this label to avoid speed test compilation. 36 | #define ffft_test_SPEED_TEST_ENABLED 37 | 38 | 39 | 40 | } // namespace test 41 | } // namespace ffft 42 | 43 | 44 | 45 | #endif // ffft_test_conf_HEADER_INCLUDED 46 | 47 | 48 | 49 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 50 | -------------------------------------------------------------------------------- /src/test/fnc.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | fnc.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_test_fnc_HEADER_INCLUDED) 19 | #define ffft_test_fnc_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | namespace test 35 | { 36 | 37 | 38 | 39 | template 40 | inline T limit (const T &x, const T &inf, const T &sup); 41 | 42 | 43 | 44 | } // namespace test 45 | } // namespace ffft 46 | 47 | 48 | 49 | #include "ffft/test/fnc.hpp" 50 | 51 | 52 | 53 | #endif // ffft_test_fnc_HEADER_INCLUDED 54 | 55 | 56 | 57 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | -------------------------------------------------------------------------------- /src/test/fnc.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | fnc.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_test_fnc_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of fnc code header. 20 | #endif 21 | #define ffft_test_fnc_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_test_fnc_CODEHEADER_INCLUDED) 24 | #define ffft_test_fnc_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | namespace test 35 | { 36 | 37 | 38 | 39 | template 40 | T limit (const T &x, const T &inf, const T &sup) 41 | { 42 | assert (! (sup < inf)); 43 | 44 | return ((x < inf) ? inf : ((sup < x) ? sup : x)); 45 | } 46 | 47 | 48 | 49 | } // namespace test 50 | } // namespace ffft 51 | 52 | 53 | 54 | #endif // ffft_test_fnc_CODEHEADER_INCLUDED 55 | 56 | #undef ffft_test_fnc_CURRENT_CODEHEADER 57 | 58 | 59 | 60 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 61 | -------------------------------------------------------------------------------- /src/test/main.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | test.cpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (_MSC_VER) 19 | #pragma warning (4 : 4786) // "identifier was truncated to '255' characters in the debug information" 20 | #pragma warning (4 : 4800) // "forcing value to bool 'true' or 'false' (performance warning)" 21 | #endif 22 | 23 | 24 | 25 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 26 | 27 | #include "ffft/test/conf.h" 28 | #include "ffft/test/TestHelperFixLen.h" 29 | #include "ffft/test/TestHelperNormal.h" 30 | 31 | #if defined (_MSC_VER) 32 | #include 33 | #include 34 | #endif // _MSC_VER 35 | 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | 42 | 43 | /*\\\ FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | 46 | 47 | static int TEST_perform_test_accuracy_all (); 48 | static int TEST_perform_test_speed_all (); 49 | 50 | static void TEST_prog_init (); 51 | static void TEST_prog_end (); 52 | 53 | 54 | 55 | int main (int argc, char *argv []) 56 | { 57 | using namespace std; 58 | 59 | int ret_val = 0; 60 | 61 | TEST_prog_init (); 62 | 63 | try 64 | { 65 | if (ret_val == 0) 66 | { 67 | ret_val = TEST_perform_test_accuracy_all (); 68 | } 69 | 70 | if (ret_val == 0) 71 | { 72 | ret_val = TEST_perform_test_speed_all (); 73 | } 74 | } 75 | 76 | catch (std::exception &e) 77 | { 78 | printf ("\n*** main(): Exception (std::exception) : %s\n", e.what ()); 79 | ret_val = -1; 80 | } 81 | 82 | catch (...) 83 | { 84 | printf ("\n*** main(): Undefined exception\n"); 85 | ret_val = -1; 86 | } 87 | 88 | TEST_prog_end (); 89 | 90 | return (ret_val); 91 | } 92 | 93 | 94 | 95 | int TEST_perform_test_accuracy_all () 96 | { 97 | int ret_val = 0; 98 | 99 | ffft::test::TestHelperNormal ::perform_test_accuracy (ret_val); 100 | ffft::test::TestHelperNormal ::perform_test_accuracy (ret_val); 101 | 102 | ffft::test::TestHelperFixLen < 1>::perform_test_accuracy (ret_val); 103 | ffft::test::TestHelperFixLen < 2>::perform_test_accuracy (ret_val); 104 | ffft::test::TestHelperFixLen < 3>::perform_test_accuracy (ret_val); 105 | ffft::test::TestHelperFixLen < 4>::perform_test_accuracy (ret_val); 106 | ffft::test::TestHelperFixLen < 7>::perform_test_accuracy (ret_val); 107 | ffft::test::TestHelperFixLen < 8>::perform_test_accuracy (ret_val); 108 | ffft::test::TestHelperFixLen <10>::perform_test_accuracy (ret_val); 109 | ffft::test::TestHelperFixLen <12>::perform_test_accuracy (ret_val); 110 | ffft::test::TestHelperFixLen <13>::perform_test_accuracy (ret_val); 111 | 112 | return (ret_val); 113 | } 114 | 115 | 116 | 117 | int TEST_perform_test_speed_all () 118 | { 119 | int ret_val = 0; 120 | 121 | #if defined (ffft_test_SPEED_TEST_ENABLED) 122 | 123 | ffft::test::TestHelperNormal ::perform_test_speed (ret_val); 124 | ffft::test::TestHelperNormal ::perform_test_speed (ret_val); 125 | 126 | ffft::test::TestHelperFixLen < 1>::perform_test_speed (ret_val); 127 | ffft::test::TestHelperFixLen < 2>::perform_test_speed (ret_val); 128 | ffft::test::TestHelperFixLen < 3>::perform_test_speed (ret_val); 129 | ffft::test::TestHelperFixLen < 4>::perform_test_speed (ret_val); 130 | ffft::test::TestHelperFixLen < 7>::perform_test_speed (ret_val); 131 | ffft::test::TestHelperFixLen < 8>::perform_test_speed (ret_val); 132 | ffft::test::TestHelperFixLen <10>::perform_test_speed (ret_val); 133 | ffft::test::TestHelperFixLen <12>::perform_test_speed (ret_val); 134 | ffft::test::TestHelperFixLen <14>::perform_test_speed (ret_val); 135 | ffft::test::TestHelperFixLen <16>::perform_test_speed (ret_val); 136 | ffft::test::TestHelperFixLen <20>::perform_test_speed (ret_val); 137 | 138 | #endif 139 | 140 | return (ret_val); 141 | } 142 | 143 | 144 | 145 | #if defined (_MSC_VER) 146 | static int __cdecl TEST_new_handler_cb (size_t dummy) 147 | { 148 | throw std::bad_alloc (); 149 | return (0); 150 | } 151 | #endif // _MSC_VER 152 | 153 | 154 | 155 | #if defined (_MSC_VER) && ! defined (NDEBUG) 156 | static int __cdecl TEST_debug_alloc_hook_cb (int alloc_type, void *user_data_ptr, size_t size, int block_type, long request_nbr, const unsigned char *filename_0, int line_nbr) 157 | { 158 | if (block_type != _CRT_BLOCK) // Ignore CRT blocks to prevent infinite recursion 159 | { 160 | switch (alloc_type) 161 | { 162 | case _HOOK_ALLOC: 163 | case _HOOK_REALLOC: 164 | case _HOOK_FREE: 165 | 166 | // Put some debug code here 167 | 168 | break; 169 | 170 | default: 171 | assert (false); // Undefined allocation type 172 | break; 173 | } 174 | } 175 | 176 | return (1); 177 | } 178 | #endif 179 | 180 | 181 | 182 | #if defined (_MSC_VER) && ! defined (NDEBUG) 183 | static int __cdecl TEST_debug_report_hook_cb (int report_type, char *user_msg_0, int *ret_val_ptr) 184 | { 185 | *ret_val_ptr = 0; // 1 to override the CRT default reporting mode 186 | 187 | switch (report_type) 188 | { 189 | case _CRT_WARN: 190 | case _CRT_ERROR: 191 | case _CRT_ASSERT: 192 | 193 | // Put some debug code here 194 | 195 | break; 196 | } 197 | 198 | return (*ret_val_ptr); 199 | } 200 | #endif 201 | 202 | 203 | 204 | static void TEST_prog_init () 205 | { 206 | #if defined (_MSC_VER) 207 | ::_set_new_handler (::TEST_new_handler_cb); 208 | #endif // _MSC_VER 209 | 210 | #if defined (_MSC_VER) && ! defined (NDEBUG) 211 | { 212 | const int mode = (1 * _CRTDBG_MODE_DEBUG) 213 | | (1 * _CRTDBG_MODE_WNDW); 214 | ::_CrtSetReportMode (_CRT_WARN, mode); 215 | ::_CrtSetReportMode (_CRT_ERROR, mode); 216 | ::_CrtSetReportMode (_CRT_ASSERT, mode); 217 | 218 | const int old_flags = ::_CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); 219 | ::_CrtSetDbgFlag ( old_flags 220 | | (1 * _CRTDBG_LEAK_CHECK_DF) 221 | | (1 * _CRTDBG_CHECK_ALWAYS_DF)); 222 | ::_CrtSetBreakAlloc (-1); // Specify here a memory bloc number 223 | ::_CrtSetAllocHook (TEST_debug_alloc_hook_cb); 224 | ::_CrtSetReportHook (TEST_debug_report_hook_cb); 225 | 226 | // Speed up I/O but breaks C stdio compatibility 227 | // std::cout.sync_with_stdio (false); 228 | // std::cin.sync_with_stdio (false); 229 | // std::cerr.sync_with_stdio (false); 230 | // std::clog.sync_with_stdio (false); 231 | } 232 | #endif // _MSC_VER, NDEBUG 233 | } 234 | 235 | 236 | 237 | static void TEST_prog_end () 238 | { 239 | #if defined (_MSC_VER) && ! defined (NDEBUG) 240 | { 241 | const int mode = (1 * _CRTDBG_MODE_DEBUG) 242 | | (0 * _CRTDBG_MODE_WNDW); 243 | ::_CrtSetReportMode (_CRT_WARN, mode); 244 | ::_CrtSetReportMode (_CRT_ERROR, mode); 245 | ::_CrtSetReportMode (_CRT_ASSERT, mode); 246 | 247 | ::_CrtMemState mem_state; 248 | ::_CrtMemCheckpoint (&mem_state); 249 | ::_CrtMemDumpStatistics (&mem_state); 250 | } 251 | #endif // _MSC_VER, NDEBUG 252 | } 253 | 254 | 255 | 256 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 257 | -------------------------------------------------------------------------------- /src/test/stopwatch/ClockCycleCounter.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | ClockCycleCounter.cpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (_MSC_VER) 19 | #pragma warning (1 : 4130) // "'operator' : logical operation on address of string constant" 20 | #pragma warning (1 : 4223) // "nonstandard extension used : non-lvalue array converted to pointer" 21 | #pragma warning (1 : 4705) // "statement has no effect" 22 | #pragma warning (1 : 4706) // "assignment within conditional expression" 23 | #pragma warning (4 : 4786) // "identifier was truncated to '255' characters in the debug information" 24 | #pragma warning (4 : 4800) // "forcing value to bool 'true' or 'false' (performance warning)" 25 | #pragma warning (4 : 4355) // "'this' : used in base member initializer list" 26 | #endif 27 | 28 | 29 | 30 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 31 | 32 | #include "ClockCycleCounter.h" 33 | 34 | #include 35 | 36 | 37 | 38 | namespace stopwatch 39 | { 40 | 41 | 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | 46 | 47 | /* 48 | ============================================================================== 49 | Name: ctor 50 | Description: 51 | The first object constructed initialise global data. This first 52 | construction may be a bit slow. 53 | Throws: Nothing 54 | ============================================================================== 55 | */ 56 | 57 | ClockCycleCounter::ClockCycleCounter () 58 | : _start_time (0) 59 | , _state (0) 60 | , _best_score (-1) 61 | { 62 | if (! _init_flag) 63 | { 64 | // Should be executed in this order 65 | compute_clk_mul (); 66 | compute_measure_time_total (); 67 | compute_measure_time_lap (); 68 | 69 | // Restores object state 70 | _start_time = 0; 71 | _state = 0; 72 | _best_score = -1; 73 | 74 | _init_flag = true; 75 | } 76 | } 77 | 78 | 79 | 80 | /* 81 | ============================================================================== 82 | Name: get_time_total 83 | Description: 84 | Gives the time elapsed between the latest stop_lap() and start() calls. 85 | Returns: 86 | The duration, in clock cycles. 87 | Throws: Nothing 88 | ============================================================================== 89 | */ 90 | 91 | Int64 ClockCycleCounter::get_time_total () const 92 | { 93 | const Int64 duration = _state - _start_time; 94 | assert (duration >= 0); 95 | 96 | const Int64 t = max ( 97 | duration - _measure_time_total, 98 | static_cast (0) 99 | ); 100 | 101 | return (t * _clk_mul); 102 | } 103 | 104 | 105 | 106 | /* 107 | ============================================================================== 108 | Name: get_time_best_lap 109 | Description: 110 | Gives the smallest time between two consecutive stop_lap() or between 111 | the stop_lap() and start(). The value is reset by a call to start(). 112 | Call this function only after a stop_lap(). 113 | The time is amputed from the duration of the stop_lap() call itself. 114 | Returns: 115 | The smallest duration, in clock cycles. 116 | Throws: Nothing 117 | ============================================================================== 118 | */ 119 | 120 | Int64 ClockCycleCounter::get_time_best_lap () const 121 | { 122 | assert (_best_score >= 0); 123 | 124 | const Int64 t1 = max ( 125 | _best_score - _measure_time_lap, 126 | static_cast (0) 127 | ); 128 | const Int64 t = min (t1, get_time_total ()); 129 | 130 | return (t * _clk_mul); 131 | } 132 | 133 | 134 | 135 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 136 | 137 | 138 | 139 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 140 | 141 | 142 | 143 | #if defined (__MACOS__) 144 | 145 | static inline double stopwatch_ClockCycleCounter_get_time_s () 146 | { 147 | const Nanoseconds ns = AbsoluteToNanoseconds (UpTime ()); 148 | 149 | return (ns.hi * 4294967296e-9 + ns.lo * 1e-9); 150 | } 151 | 152 | #endif // __MACOS__ 153 | 154 | 155 | 156 | /* 157 | ============================================================================== 158 | Name: compute_clk_mul 159 | Description: 160 | This function, only for PowerPC/MacOS computers, computes the multiplier 161 | required to deduce clock cycles from the internal counter. 162 | Throws: Nothing 163 | ============================================================================== 164 | */ 165 | 166 | void ClockCycleCounter::compute_clk_mul () 167 | { 168 | assert (! _init_flag); 169 | 170 | #if defined (__MACOS__) 171 | 172 | long clk_speed_mhz = CurrentProcessorSpeed (); 173 | const Int64 clk_speed = 174 | static_cast (clk_speed_mhz) * (1000L*1000L); 175 | 176 | const double start_time_s = stopwatch_ClockCycleCounter_get_time_s (); 177 | start (); 178 | 179 | const double duration = 0.01; // Seconds 180 | while (stopwatch_ClockCycleCounter_get_time_s () - start_time_s < duration) 181 | { 182 | continue; 183 | } 184 | 185 | const double stop_time_s = stopwatch_ClockCycleCounter_get_time_s (); 186 | stop (); 187 | 188 | const double diff_time_s = stop_time_s - start_time_s; 189 | const double nbr_cycles = diff_time_s * static_cast (clk_speed); 190 | 191 | const Int64 diff_time_c = _state - _start_time; 192 | const double clk_mul = nbr_cycles / static_cast (diff_time_c); 193 | 194 | _clk_mul = round_int (clk_mul); 195 | 196 | #endif // __MACOS__ 197 | } 198 | 199 | 200 | 201 | void ClockCycleCounter::compute_measure_time_total () 202 | { 203 | start (); 204 | spend_time (); 205 | 206 | Int64 best_result = 0x7FFFFFFFL; // Should be enough 207 | long nbr_tests = 100; 208 | for (long cnt = 0; cnt < nbr_tests; ++cnt) 209 | { 210 | start (); 211 | stop_lap (); 212 | const Int64 duration = _state - _start_time; 213 | best_result = min (best_result, duration); 214 | } 215 | 216 | _measure_time_total = best_result; 217 | } 218 | 219 | 220 | 221 | /* 222 | ============================================================================== 223 | Name: compute_measure_time_lap 224 | Description: 225 | Computes the duration of one stop_lap() call and store it. It will be used 226 | later to get the real duration of the measured operation (by substracting 227 | the measurement duration). 228 | Throws: Nothing 229 | ============================================================================== 230 | */ 231 | 232 | void ClockCycleCounter::compute_measure_time_lap () 233 | { 234 | start (); 235 | spend_time (); 236 | 237 | long nbr_tests = 10; 238 | for (long cnt = 0; cnt < nbr_tests; ++cnt) 239 | { 240 | stop_lap (); 241 | stop_lap (); 242 | stop_lap (); 243 | stop_lap (); 244 | } 245 | 246 | _measure_time_lap = _best_score; 247 | } 248 | 249 | 250 | 251 | void ClockCycleCounter::spend_time () 252 | { 253 | const Int64 nbr_clocks = 500; // Number of clock cycles to spend 254 | 255 | const Int64 start = read_clock_counter (); 256 | Int64 current; 257 | 258 | do 259 | { 260 | current = read_clock_counter (); 261 | } 262 | while ((current - start) * _clk_mul < nbr_clocks); 263 | } 264 | 265 | 266 | 267 | Int64 ClockCycleCounter::_measure_time_total = 0; 268 | Int64 ClockCycleCounter::_measure_time_lap = 0; 269 | int ClockCycleCounter::_clk_mul = 1; 270 | bool ClockCycleCounter::_init_flag = false; 271 | 272 | 273 | } // namespace stopwatch 274 | 275 | 276 | 277 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 278 | -------------------------------------------------------------------------------- /src/test/stopwatch/ClockCycleCounter.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | ClockCycleCounter.h 4 | By Laurent de Soras 5 | 6 | Instrumentation class, for accurate time interval measurement. You may have 7 | to modify the implementation to adapt it to your system and/or compiler. 8 | 9 | --- Legal stuff --- 10 | 11 | This program is free software. It comes without any warranty, to 12 | the extent permitted by applicable law. You can redistribute it 13 | and/or modify it under the terms of the Do What The Fuck You Want 14 | To Public License, Version 2, as published by Sam Hocevar. See 15 | http://sam.zoy.org/wtfpl/COPYING for more details. 16 | 17 | *Tab=3***********************************************************************/ 18 | 19 | 20 | 21 | #if ! defined (stopwatch_ClockCycleCounter_HEADER_INCLUDED) 22 | #define stopwatch_ClockCycleCounter_HEADER_INCLUDED 23 | 24 | #if defined (_MSC_VER) 25 | #pragma once 26 | #pragma warning (4 : 4250) // "Inherits via dominance." 27 | #endif 28 | 29 | 30 | 31 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 32 | 33 | #include "def.h" 34 | #include "Int64.h" 35 | 36 | 37 | 38 | namespace stopwatch 39 | { 40 | 41 | 42 | 43 | class ClockCycleCounter 44 | { 45 | 46 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 47 | 48 | public: 49 | 50 | ClockCycleCounter (); 51 | 52 | stopwatch_FORCEINLINE void 53 | start (); 54 | stopwatch_FORCEINLINE void 55 | stop_lap (); 56 | Int64 get_time_total () const; 57 | Int64 get_time_best_lap () const; 58 | 59 | 60 | 61 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 62 | 63 | protected: 64 | 65 | 66 | 67 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | private: 70 | 71 | void compute_clk_mul (); 72 | void compute_measure_time_total (); 73 | void compute_measure_time_lap (); 74 | 75 | static void spend_time (); 76 | static stopwatch_FORCEINLINE Int64 77 | read_clock_counter (); 78 | 79 | Int64 _start_time; 80 | Int64 _state; 81 | Int64 _best_score; 82 | 83 | static Int64 _measure_time_total; 84 | static Int64 _measure_time_lap; 85 | static int _clk_mul; 86 | static bool _init_flag; 87 | 88 | 89 | 90 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 91 | 92 | private: 93 | 94 | ClockCycleCounter (const ClockCycleCounter &other); 95 | ClockCycleCounter & 96 | operator = (const ClockCycleCounter &other); 97 | bool operator == (const ClockCycleCounter &other); 98 | bool operator != (const ClockCycleCounter &other); 99 | 100 | }; // class ClockCycleCounter 101 | 102 | 103 | 104 | } // namespace stopwatch 105 | 106 | 107 | 108 | #include "ClockCycleCounter.hpp" 109 | 110 | 111 | 112 | #endif // stopwatch_ClockCycleCounter_HEADER_INCLUDED 113 | 114 | 115 | 116 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 117 | -------------------------------------------------------------------------------- /src/test/stopwatch/ClockCycleCounter.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | ClockCycleCounter.hpp 4 | By Laurent de Soras 5 | 6 | Please complete the definitions according to your compiler/architecture. 7 | It's not a big deal if it's not possible to get the clock count... 8 | 9 | --- Legal stuff --- 10 | 11 | This program is free software. It comes without any warranty, to 12 | the extent permitted by applicable law. You can redistribute it 13 | and/or modify it under the terms of the Do What The Fuck You Want 14 | To Public License, Version 2, as published by Sam Hocevar. See 15 | http://sam.zoy.org/wtfpl/COPYING for more details. 16 | 17 | *Tab=3***********************************************************************/ 18 | 19 | 20 | 21 | #if defined (stopwatch_ClockCycleCounter_CURRENT_CODEHEADER) 22 | #error Recursive inclusion of ClockCycleCounter code header. 23 | #endif 24 | #define stopwatch_ClockCycleCounter_CURRENT_CODEHEADER 25 | 26 | #if ! defined (stopwatch_ClockCycleCounter_CODEHEADER_INCLUDED) 27 | #define stopwatch_ClockCycleCounter_CODEHEADER_INCLUDED 28 | 29 | 30 | 31 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 32 | 33 | #include "fnc.h" 34 | 35 | #include 36 | 37 | 38 | 39 | namespace stopwatch 40 | { 41 | 42 | 43 | 44 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 45 | 46 | 47 | 48 | /* 49 | ============================================================================== 50 | Name: start 51 | Description: 52 | Starts the counter. 53 | Throws: Nothing 54 | ============================================================================== 55 | */ 56 | 57 | void ClockCycleCounter::start () 58 | { 59 | _best_score = (static_cast (1) << (sizeof (Int64) * CHAR_BIT - 2)); 60 | const Int64 start_clock = read_clock_counter (); 61 | _start_time = start_clock; 62 | _state = start_clock - _best_score; 63 | } 64 | 65 | 66 | 67 | /* 68 | ============================================================================== 69 | Name: stop_lap 70 | Description: 71 | Captures the current time and updates the smallest duration between two 72 | consecutive calls to stop_lap() or the latest start(). 73 | start() must have been called at least once before calling this function. 74 | Throws: Nothing 75 | ============================================================================== 76 | */ 77 | 78 | void ClockCycleCounter::stop_lap () 79 | { 80 | const Int64 end_clock = read_clock_counter (); 81 | _best_score = min (end_clock - _state, _best_score); 82 | _state = end_clock; 83 | } 84 | 85 | 86 | 87 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 88 | 89 | 90 | 91 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 92 | 93 | 94 | 95 | Int64 ClockCycleCounter::read_clock_counter () 96 | { 97 | register Int64 clock_cnt; 98 | 99 | #if defined (_MSC_VER) 100 | 101 | __asm 102 | { 103 | lea edi, clock_cnt 104 | rdtsc 105 | mov [edi ], eax 106 | mov [edi + 4], edx 107 | } 108 | 109 | #elif defined (__GNUC__) && defined (__i386__) 110 | 111 | __asm__ __volatile__ ("rdtsc" : "=A" (clock_cnt)); 112 | 113 | #elif (__MWERKS__) && defined (__POWERPC__) 114 | 115 | asm 116 | { 117 | loop: 118 | mftbu clock_cnt@hiword 119 | mftb clock_cnt@loword 120 | mftbu r5 121 | cmpw clock_cnt@hiword,r5 122 | bne loop 123 | } 124 | 125 | #endif 126 | 127 | return (clock_cnt); 128 | } 129 | 130 | 131 | 132 | } // namespace stopwatch 133 | 134 | 135 | 136 | #endif // stopwatch_ClockCycleCounter_CODEHEADER_INCLUDED 137 | 138 | #undef stopwatch_ClockCycleCounter_CURRENT_CODEHEADER 139 | 140 | 141 | 142 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 143 | -------------------------------------------------------------------------------- /src/test/stopwatch/Int64.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Int64.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (stopwatch_Int64_HEADER_INCLUDED) 19 | #define stopwatch_Int64_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace stopwatch 33 | { 34 | 35 | 36 | #if defined (_MSC_VER) 37 | 38 | typedef __int64 Int64; 39 | 40 | #elif defined (__MWERKS__) || defined (__GNUC__) 41 | 42 | typedef long long Int64; 43 | 44 | #elif defined (__BEOS__) 45 | 46 | typedef int64 Int64; 47 | 48 | #else 49 | 50 | #error No 64-bit integer type defined for this compiler ! 51 | 52 | #endif 53 | 54 | 55 | } // namespace stopwatch 56 | 57 | 58 | 59 | #endif // stopwatch_Int64_HEADER_INCLUDED 60 | 61 | 62 | 63 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | -------------------------------------------------------------------------------- /src/test/stopwatch/StopWatch.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | StopWatch.cpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (_MSC_VER) 19 | #pragma warning (1 : 4130) // "'operator' : logical operation on address of string constant" 20 | #pragma warning (1 : 4223) // "nonstandard extension used : non-lvalue array converted to pointer" 21 | #pragma warning (1 : 4705) // "statement has no effect" 22 | #pragma warning (1 : 4706) // "assignment within conditional expression" 23 | #pragma warning (4 : 4786) // "identifier was truncated to '255' characters in the debug information" 24 | #pragma warning (4 : 4800) // "forcing value to bool 'true' or 'false' (performance warning)" 25 | #pragma warning (4 : 4355) // "'this' : used in base member initializer list" 26 | #endif 27 | 28 | 29 | 30 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 31 | 32 | #include "StopWatch.h" 33 | 34 | #include 35 | 36 | 37 | 38 | namespace stopwatch 39 | { 40 | 41 | 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | 46 | 47 | StopWatch::StopWatch () 48 | : _ccc () 49 | , _nbr_laps (0) 50 | { 51 | // Nothing 52 | } 53 | 54 | 55 | 56 | double StopWatch::get_time_total (Int64 nbr_op) const 57 | { 58 | assert (_nbr_laps > 0); 59 | assert (nbr_op > 0); 60 | 61 | return ( 62 | static_cast (_ccc.get_time_total ()) 63 | / (static_cast (nbr_op) * static_cast (_nbr_laps)) 64 | ); 65 | } 66 | 67 | 68 | 69 | double StopWatch::get_time_best_lap (Int64 nbr_op) const 70 | { 71 | assert (nbr_op > 0); 72 | 73 | return ( 74 | static_cast (_ccc.get_time_best_lap ()) 75 | / static_cast (nbr_op) 76 | ); 77 | } 78 | 79 | 80 | 81 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 82 | 83 | 84 | 85 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 86 | 87 | 88 | 89 | } // namespace stopwatch 90 | 91 | 92 | 93 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 94 | -------------------------------------------------------------------------------- /src/test/stopwatch/StopWatch.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | StopWatch.h 4 | By Laurent de Soras 5 | 6 | Utility class based on ClockCycleCounter to measure the unit time of a 7 | repeated operation. 8 | 9 | --- Legal stuff --- 10 | 11 | This program is free software. It comes without any warranty, to 12 | the extent permitted by applicable law. You can redistribute it 13 | and/or modify it under the terms of the Do What The Fuck You Want 14 | To Public License, Version 2, as published by Sam Hocevar. See 15 | http://sam.zoy.org/wtfpl/COPYING for more details. 16 | 17 | *Tab=3***********************************************************************/ 18 | 19 | 20 | 21 | #if ! defined (stopwatch_StopWatch_HEADER_INCLUDED) 22 | #define stopwatch_StopWatch_HEADER_INCLUDED 23 | 24 | #if defined (_MSC_VER) 25 | #pragma once 26 | #pragma warning (4 : 4250) // "Inherits via dominance." 27 | #endif 28 | 29 | 30 | 31 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 32 | 33 | #include "ClockCycleCounter.h" 34 | 35 | 36 | 37 | namespace stopwatch 38 | { 39 | 40 | 41 | 42 | class StopWatch 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | StopWatch (); 50 | 51 | stopwatch_FORCEINLINE void 52 | start (); 53 | stopwatch_FORCEINLINE void 54 | stop_lap (); 55 | 56 | double get_time_total (Int64 nbr_op) const; 57 | double get_time_best_lap (Int64 nbr_op) const; 58 | 59 | 60 | 61 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 62 | 63 | protected: 64 | 65 | 66 | 67 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | private: 70 | 71 | ClockCycleCounter 72 | _ccc; 73 | Int64 _nbr_laps; 74 | 75 | 76 | 77 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 78 | 79 | private: 80 | 81 | StopWatch (const StopWatch &other); 82 | StopWatch & operator = (const StopWatch &other); 83 | bool operator == (const StopWatch &other); 84 | bool operator != (const StopWatch &other); 85 | 86 | }; // class StopWatch 87 | 88 | 89 | 90 | } // namespace stopwatch 91 | 92 | 93 | 94 | #include "StopWatch.hpp" 95 | 96 | 97 | 98 | #endif // stopwatch_StopWatch_HEADER_INCLUDED 99 | 100 | 101 | 102 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 103 | -------------------------------------------------------------------------------- /src/test/stopwatch/StopWatch.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | StopWatch.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (stopwatch_StopWatch_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of StopWatch code header. 20 | #endif 21 | #define stopwatch_StopWatch_CURRENT_CODEHEADER 22 | 23 | #if ! defined (stopwatch_StopWatch_CODEHEADER_INCLUDED) 24 | #define stopwatch_StopWatch_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace stopwatch 33 | { 34 | 35 | 36 | 37 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 38 | 39 | 40 | 41 | void StopWatch::start () 42 | { 43 | _nbr_laps = 0; 44 | _ccc.start (); 45 | } 46 | 47 | 48 | 49 | void StopWatch::stop_lap () 50 | { 51 | _ccc.stop_lap (); 52 | ++ _nbr_laps; 53 | } 54 | 55 | 56 | 57 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | 60 | 61 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 62 | 63 | 64 | 65 | } // namespace stopwatch 66 | 67 | 68 | 69 | #endif // stopwatch_StopWatch_CODEHEADER_INCLUDED 70 | 71 | #undef stopwatch_StopWatch_CURRENT_CODEHEADER 72 | 73 | 74 | 75 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 76 | -------------------------------------------------------------------------------- /src/test/stopwatch/def.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | def.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (stopwatch_def_HEADER_INCLUDED) 19 | #define stopwatch_def_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace stopwatch 33 | { 34 | 35 | 36 | 37 | #if defined (_MSC_VER) 38 | 39 | #define stopwatch_FORCEINLINE __forceinline 40 | 41 | #else 42 | 43 | #define stopwatch_FORCEINLINE inline 44 | 45 | #endif 46 | 47 | 48 | 49 | } // namespace stopwatch 50 | 51 | 52 | 53 | #endif // stopwatch_def_HEADER_INCLUDED 54 | 55 | 56 | 57 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | -------------------------------------------------------------------------------- /src/test/stopwatch/fnc.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | fnc.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (stopwatch_fnc_HEADER_INCLUDED) 19 | #define stopwatch_fnc_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace stopwatch 33 | { 34 | 35 | 36 | 37 | template 38 | inline T min (T a, T b); 39 | 40 | template 41 | inline T max (T a, T b); 42 | 43 | inline int round_int (double x); 44 | 45 | 46 | 47 | } // namespace rsp 48 | 49 | 50 | 51 | #include "fnc.hpp" 52 | 53 | 54 | 55 | #endif // stopwatch_fnc_HEADER_INCLUDED 56 | 57 | 58 | 59 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 60 | -------------------------------------------------------------------------------- /src/test/stopwatch/fnc.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | fnc.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (stopwatch_fnc_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of fnc code header. 20 | #endif 21 | #define stopwatch_fnc_CURRENT_CODEHEADER 22 | 23 | #if ! defined (stopwatch_fnc_CODEHEADER_INCLUDED) 24 | #define stopwatch_fnc_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | #include 32 | 33 | namespace std {} 34 | 35 | 36 | 37 | namespace stopwatch 38 | { 39 | 40 | 41 | 42 | template 43 | inline T min (T a, T b) 44 | { 45 | return ((a < b) ? a : b); 46 | } 47 | 48 | 49 | 50 | template 51 | inline T max (T a, T b) 52 | { 53 | return ((b < a) ? a : b); 54 | } 55 | 56 | 57 | 58 | int round_int (double x) 59 | { 60 | using namespace std; 61 | 62 | return (static_cast (floor (x + 0.5))); 63 | } 64 | 65 | 66 | 67 | } // namespace stopwatch 68 | 69 | 70 | 71 | #endif // stopwatch_fnc_CODEHEADER_INCLUDED 72 | 73 | #undef stopwatch_fnc_CURRENT_CODEHEADER 74 | 75 | 76 | 77 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 78 | --------------------------------------------------------------------------------