mirror of https://github.com/davisking/dlib.git
[FFT] split FFT API into different layers (#2793)
* fft refactoring * separate header for STL overloads * ditto --------- Co-authored-by: pf <pf@me>pull/2794/head
parent
48fdace271
commit
ff331517b9
@ -0,0 +1,49 @@
|
||||
#include "fft.h"
|
||||
|
||||
#ifdef DLIB_USE_MKL_FFT
|
||||
#include "mkl_fft.h"
|
||||
#else
|
||||
#include "kiss_fft.h"
|
||||
#endif
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
template<typename T>
|
||||
void fft(const fft_size& dims, const std::complex<T>* in, std::complex<T>* out, bool is_inverse)
|
||||
{
|
||||
#ifdef DLIB_USE_MKL_FFT
|
||||
mkl_fft(dims, in, out, is_inverse);
|
||||
#else
|
||||
kiss_fft(dims, in, out, is_inverse);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void fftr(const fft_size& dims, const T* in, std::complex<T>* out)
|
||||
{
|
||||
#ifdef DLIB_USE_MKL_FFT
|
||||
mkl_fftr(dims, in, out);
|
||||
#else
|
||||
kiss_fftr(dims, in, out);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ifftr(const fft_size& dims, const std::complex<T>* in, T* out)
|
||||
{
|
||||
#ifdef DLIB_USE_MKL_FFT
|
||||
mkl_ifftr(dims, in, out);
|
||||
#else
|
||||
kiss_ifftr(dims, in, out);
|
||||
#endif
|
||||
}
|
||||
|
||||
template void fft<float>(const fft_size& dims, const std::complex<float>* in, std::complex<float>* out, bool is_inverse);
|
||||
template void fft<double>(const fft_size& dims, const std::complex<double>* in, std::complex<double>* out, bool is_inverse);
|
||||
|
||||
template void fftr<float>(const fft_size& dims, const float* in, std::complex<float>* out);
|
||||
template void fftr<double>(const fft_size& dims, const double* in, std::complex<double>* out);
|
||||
|
||||
template void ifftr<float>(const fft_size& dims, const std::complex<float>* in, float* out);
|
||||
template void ifftr<double>(const fft_size& dims, const std::complex<double>* in, double* out);
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2023 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_FFT_DETAILS_Hh_
|
||||
#define DLIB_FFT_DETAILS_Hh_
|
||||
|
||||
#include <complex>
|
||||
#include "fft_size.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
constexpr bool is_power_of_two (
|
||||
const unsigned long n
|
||||
)
|
||||
/*!
|
||||
ensures
|
||||
- returns true if value contains a power of two and false otherwise. As a
|
||||
special case, we also consider 0 to be a power of two.
|
||||
!*/
|
||||
{
|
||||
return n == 0 ? true : (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
constexpr long fftr_nc_size(
|
||||
long nc
|
||||
)
|
||||
/*!
|
||||
ensures
|
||||
- returns the output dimension of a 1D real FFT
|
||||
!*/
|
||||
{
|
||||
return nc == 0 ? 0 : nc/2+1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
constexpr long ifftr_nc_size(
|
||||
long nc
|
||||
)
|
||||
/*!
|
||||
ensures
|
||||
- returns the output dimension of an inverse 1D real FFT
|
||||
!*/
|
||||
{
|
||||
return nc == 0 ? 0 : 2*(nc-1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void fft(const fft_size& dims, const std::complex<T>* in, std::complex<T>* out, bool is_inverse);
|
||||
/*!
|
||||
requires
|
||||
- T must be either float or double
|
||||
- dims represents the dimensions of both `in` and `out`
|
||||
- dims.num_dims() > 0
|
||||
ensures
|
||||
- performs an FFT on `in` and stores the result in `out`.
|
||||
- if `is_inverse` is true, a backward FFT is performed,
|
||||
otherwise a forward FFT is performed.
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void fftr(const fft_size& dims, const T* in, std::complex<T>* out);
|
||||
/*!
|
||||
requires
|
||||
- T must be either float or double
|
||||
- dims represent the dimensions of `in`
|
||||
- `in` has dimensions {dims[0], dims[1], ..., dims[-2], dims[-1]}
|
||||
- `out` has dimensions {dims[0], dims[1], ..., dims[-2], dims[-1]/2+1}
|
||||
- dims.num_dims() > 0
|
||||
- dims.back() must be even
|
||||
ensures
|
||||
- performs a real FFT on `in` and stores the result in `out`.
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void ifftr(const fft_size& dims, const std::complex<T>* in, T* out);
|
||||
/*!
|
||||
requires
|
||||
- T must be either float or double
|
||||
- dims represent the dimensions of `out`
|
||||
- `in` has dimensions {dims[0], dims[1], ..., dims[-2], dims[-1]/2+1}
|
||||
- `out` has dimensions {dims[0], dims[1], ..., dims[-2], dims[-1]}
|
||||
- dims.num_dims() > 0
|
||||
- dims.back() must be even
|
||||
ensures
|
||||
- performs an inverse real FFT on `in` and stores the result in `out`.
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif //DLIB_FFT_DETAILS_Hh_
|
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2023 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_FFT_STL_Hh_
|
||||
#define DLIB_FFT_STL_Hh_
|
||||
|
||||
#include <vector>
|
||||
#include "fft.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template < typename T, typename Alloc >
|
||||
void fft_inplace (std::vector<std::complex<T>, Alloc>& data)
|
||||
/*!
|
||||
requires
|
||||
- data contains elements of type std::complex<> that itself contains double, float, or long double.
|
||||
ensures
|
||||
- This function is identical to fft() except that it does the FFT in-place.
|
||||
That is, after this function executes we will have:
|
||||
- #data == fft(data)
|
||||
!*/
|
||||
{
|
||||
static_assert(std::is_floating_point<T>::value, "only support floating point types");
|
||||
if (data.size() != 0)
|
||||
fft({(long)data.size()}, &data[0], &data[0], false);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template < typename T, typename Alloc >
|
||||
void ifft_inplace (std::vector<std::complex<T>, Alloc>& data)
|
||||
/*!
|
||||
requires
|
||||
- data contains elements of type std::complex<> that itself contains double, float, or long double.
|
||||
ensures
|
||||
- This function is identical to ifft() except that it does the inverse FFT
|
||||
in-place. That is, after this function executes we will have:
|
||||
- #data == ifft(data)*data.size()
|
||||
- Note that the output needs to be divided by data.size() to complete the
|
||||
inverse transformation.
|
||||
!*/
|
||||
{
|
||||
static_assert(std::is_floating_point<T>::value, "only support floating point types");
|
||||
if (data.size() != 0)
|
||||
fft({(long)data.size()}, &data[0], &data[0], true);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif //DLIB_FFT_STL_Hh_
|
Loading…
Reference in new issue