PocketFFT

repository·cpp·Indexed 41 days ago

https://github.com/mreineck/pocketfft

A high-performance, C++11 compliant header-only FFT library. It provides multidimensional transforms, support for various floating-point types, and specialized algorithms like Bluestein's for large prime factors. Features include complex-to-complex (c2c), real-to-complex (r2c), and complex-to-real (c2r) transforms, as well as Discrete Cosine (DCT), Discrete Sine (DST), and Fast Hartley Transforms (FHT).

Tokens
2K
Snippets
5
Records
7
Agent score
1%

What's inside PocketFFT

  1. Understand PocketFFT transform arguments

    cpp

    When calling PocketFFT functions, you must provide several parameters to define the transform geometry and direction:

    • shape[_*]: A std::vector<std::size_t> containing the number of entries along each axis. For r2c transforms, provide the input shape; for c2r, provide the output shape.
    • stride_*: A std::vector<std::ptrdiff_t> describing the memory distance (in bytes) between neighboring entries along an axis. Supports negative strides.
    • axes: A vector of non-negative integers specifying which axes to transform. For r2c/c2r, the last entry in axes is treated specially.
    • forward: Direction of the transform. Use the symbolic constants FORWARD or BACKWARD.
    • fct: A scaling factor applied to the result (transforms are not normalized by default).
    • nthreads: A non-negative integer for multi-threading. 0 uses all logical CPU cores. Note that multi-threading is disabled for 1D transforms and if POCKETFFT_NO_MULTITHREADING is defined.

    Constraints

    • shape, stride_in, and stride_out must have the same size and not be empty.
    • Axis indices must be in the range [0, shape.size() - 1].
    • For r2c/c2r transforms, the complex array length along the specified axis is assumed to be s/2 + 1, where s is the real array axis length.
  2. Configure PocketFFT via preprocessor macros

    cpp

    PocketFFT is a header-only library, so configuration is handled through preprocessor macros. You can control caching, vectorization, multi-threading, and the namespace.

    Available Macros

    MacroDescription
    POCKETFFT_CACHE_SIZESets the size of the LRU cache for FFT plans. If 0, caching is disabled. If undefined, it defaults to 0. Warning: Use with caution for large axis lengths as it can consume significant memory.
    POCKETFFT_NO_VECTORSIf defined, disables all CPU vector instruction support.
    POCKETFFT_NO_MULTITHREADINGIf defined, disables multi-threading support.
    POCKETFFT_NAMESPACEDefines the namespace for all pocketfft functionality. If undefined, the default is pocketfft.
  3. Use Complex-to-Real (c2r) transforms

    cpp

    PocketFFT provides two ways to perform complex-to-real transforms:

    1. Single axis transform: Performs a c2r transform along a specific axis.
    2. Multidimensional transform: Performs c2c transforms along all axes except the last one (using a temporary array), then performs a c2r transform along the last axis in axes.

    To achieve traditional behavior, call c2r with forward=false.

    // Single axis
    template<typename T> void c2r(const shape_t &shape_out, const stride_t &stride_in, 
      const stride_t &stride_out, size_t axis, bool forward, 
      const complex<T> *data_in, T *data_out, T fct, size_t nthreads=1)
    
    // Multidimensional
    template<typename T> void c2r(const shape_t &shape_out, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, bool forward, 
      const complex<T> *data_in, T *data_out, T fct, size_t nthreads=1)
  4. Use Complex-to-Complex (c2c) transforms

    cpp

    The c2c function performs a complex-to-complex FFT. It supports multidimensional arrays and can be used for in-place transforms if data_in == data_out (provided strides are identical).

    template<typename T> void c2c(const shape_t &shape, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, bool forward, 
      const complex<T> *data_in, complex<T> *data_out, T fct, 
      size_t nthreads=1)
  5. Perform Fast Hartley Transforms (FHT)

    cpp

    PocketFFT supports several variations of the Fast Hartley Transform:

    • r2r_separable_fht: For every requested axis, carries out a forward Fourier transform and computes re(x)-im(x) before the next axis is processed.
    • r2r_genuine_fht: Carries out a full Fourier transform over the requested axes and stores re(x)-im(x) in the output. Note: This allocates temporary working space comparable to the input array.

    Note: r2r_separable_hartley and r2r_genuine_hartley are kept for backwards compatibility and should be avoided in favor of the FHT versions.

    template<typename T> void r2r_separable_fht(const shape_t &shape, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, const T *data_in, 
      T *data_out, T fct, size_t nthreads=1);
    
    template<typename T> void r2r_genuine_fht(const shape_t &shape, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, const T *data_in, 
      T *data_out, T fct, size_t nthreads=1);
  6. Perform Discrete Cosine (DCT) and Sine (DST) transforms

    cpp

    The dct and dst functions support Types I-IV. You can specify if the transform should be orthogonal using the ortho parameter.

    DCT Orthogonality

    • Type 1: Multiply first/last input by $\sqrt{2}$, divide first/last output by $\sqrt{2}$.
    • Type 2: Divide first output by $\sqrt{2}$.
    • Type 3: Multiply first input by $\sqrt{2}$.
    • Type 4: No additional steps.
    template<typename T> void dct(const shape_t &shape, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, int type, 
      const T *data_in, T *data_out, T fct, bool ortho, size_t nthreads=1);
    
    template<typename T> void dst(const shape_t &shape, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, int type, 
      const T *data_in, T *data_out, T fct, bool ortho, size_t nthreads=1);
  7. Use Real-to-Complex (r2c) transforms

    cpp

    PocketFFT provides two ways to perform real-to-complex transforms:

    1. Single axis transform: Performs an r2c transform along a specific axis.
    2. Multidimensional transform: Performs an r2c transform along the last axis in axes, followed by in-place c2c transforms along all other axes in axes.

    To achieve traditional behavior, call r2c with forward=true.

    // Single axis
    template<typename T> void r2c(const shape_t &shape_in, const stride_t &stride_in, 
      const stride_t &stride_out, size_t axis, bool forward, 
      const T *data_in, complex<T> *data_out, T fct, size_t nthreads=1)
    
    // Multidimensional
    template<typename T> void r2c(const shape_t &shape_in, const stride_t &stride_in, 
      const stride_t &stride_out, const shape_t &axes, bool forward, 
      const T *data_in, complex<T> *data_out, T fct, size_t nthreads=1)