- C++ 85.9%
- CMake 7.1%
- Python 7%
- Allow rfft with same size for in and out (in this case the last frequency real part is stored in the first frequency imag part) - Fixes for debug mode. - Remove "const" from some class attributes to make it copyable. |
||
|---|---|---|
| benchmarks | ||
| include | ||
| pytests | ||
| src | ||
| tests | ||
| .gitignore | ||
| CMakeLists.txt | ||
| LICENSE.md | ||
| README.md | ||
Simple FFT Radix 2 code
Simple FFT code, just for input sizes which are a power of 2. Nothing really special about it.
Performance
In my very simple measurements, performance is similar to e.g. kissfft, sometimes worse sometimes better, but in the range of +-20%.
There are also python bindings, mainly used for testing. Compared to numpy, performance is ~30% worse, but in numpy you do not have to create a class first. So there are not really good reasons to use the python bindings.
Compilation
The c++-code are header-only and contained in a single file, so the easiest way is to just copy the include/r2fft.h-header over.
Besides, you can use the cmake. Use the target r2fft::r2fftx if you want to compile against the library. Mind the x at the end, which I used to avoid clashes with the python bindings.
If you have enabled python, the bindings will install into lib/python3.14/site-packages/r2fft.cpython-xxx-x86_64-linux-gnu.so inside the install path. The python-bindings use nanobind as binding library. cmake will download this directly.
Tests use kissfft as a reference and googletest. Both are downloaded by cmake if enabled.
There are also some benchmarks using googlebench. If enabled cmake, will download the library and compile it.
Usage
In c++, this can be used as follows:
// import
#include "r2fft.h"
// create the fft object for complex transforms
// - the template-type is the underlying scalar, so don't use `complex` here.
// - n is are the number of values to be treated and must be a power of 2.
r2fft::CFFT<double> cfft(n);
// run the fft, for complex input:
cfft.fft(input, output);
// same for inverse fft:
cfft.ifft(input, output);
// similarly, create an fft object for real transforms
// - the template-type is the underlying scalar
// - n is are the number of values to be treated and must be a power of 2.
r2fft::RFFT<double> rfft(n);
// run fft, input is a span of scalar numbers, output is
// a span of complex numbers, size of output is n / 2 + 1.
rfft.fft(input, output);
// and inverse fft, here input are n / 2 + 1 complex numbers,
// and output are n scalar numbers.
rfft.ifft(input, output);
You can also query the frequencies:
auto f = cfft.freq(i, dt); // for getting a single frequency of the complex fft
auto f = rfft.freq(i, dt); // for getting a single frequency of the real fft
cfft.freqs(freqs, dt); // for getting all frequencies of the complex fft
rfft.freqs(freqs, dt); // for getting all frequencies of the real fft
Or simply get the frequency resolution:
auto df = cfft.df(dt); // complex fft
auto df = rfft.df(dt); // real fft
The python api is similar:
import r2fft
# complex
cfft = r2fft.CFFT(n)
freqdom = cfft.fft(timedom) # complex fft
timedom = cfft.ifft(freqdom) # complex inverse fft
freqs = cfft.freqs(dt) # frequencies of complex fft
# real
rfft = r2fft.RFFT(n)
freqdom = rfft.fft(timedom) # real fft
timedom = rfft.ifft(freqdom) # real inverse fft
freqs = rfft.freqs(dt) # frequencies of real fft
Why does this project exist?
Mainly since I needed such code for deeper integration into other projects.
License
It is not really worth having a license here, since there is nothing special about this project. To still name a license, the Zero-Clause BSD license is used, mainly meaning you can copy the files over, without even mentioning this project, but no warranties.