File: Convolve.h

package info (click to toggle)
bornagain 23.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 103,936 kB
  • sloc: cpp: 423,131; python: 40,997; javascript: 11,167; awk: 630; sh: 318; ruby: 173; xml: 130; makefile: 51; ansic: 24
file content (109 lines) | stat: -rw-r--r-- 4,071 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Device/Resolution/Convolve.h
//! @brief     Defines class Math::Convolve.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
#define BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H

#include "Base/Type/Field2D.h"
#include <fftw3.h>

//! Convolution of two real vectors (in 1D or 2D) using Fast Fourier Transform.
//!
//! Usage:
//! std::vector<double> signal, kernel, result;
//! Convolve cv;
//! cv.fftconvolve(signal, kernel, result)
//!
//! Inspired by code from Jeremy Fix.
//! Original provenance http://jeremy.fix.free.fr/spip.php?article15 no longer online.
//! Code repository now at https://github.com/jeremyfix/FFTConvolution.
//! Paper "Efficient convolution using the Fast Fourier Transform, Application in C++"
//! by Jeremy Fix, May 30, 2011, preserved in ba-inter/lit/JFix_FFTConvolution.pdf

class Convolve {
public:
    Convolve();

    //! convolution  modes
    //! use LINEAR_SAME or CIRCULAR_SAME_SHIFTED for maximum performance
    enum ConvolutionMode {
        FFTW_LINEAR_FULL,
        FFTW_LINEAR_SAME_UNPADDED,
        FFTW_LINEAR_SAME,
        FFTW_LINEAR_VALID,
        FFTW_CIRCULAR_SAME,
        FFTW_CIRCULAR_SAME_SHIFTED,
        FFTW_UNDEFINED
    };

    //! convolution in 1D
    void fftconvolve1D(const std::vector<double>& source, const std::vector<double>& kernel,
                       std::vector<double>& result);

    //! convolution in 2D
    void fftconvolve2D(const double2d_t& source, const double2d_t& kernel, double2d_t& result);

    //! prepare arrays for 2D convolution of given vectors
    void init(int h_src, int w_src, int h_kernel, int w_kernel);

private:
    //! compute circual convolution of source and kernel using fast Fourier transformation
    void fftw_circular_convolution(const double2d_t& src, const double2d_t& kernel);

    //! Workspace for Fourier convolution.

    //! Workspace contains input (source and kernel), intermediate and output
    //! arrays to run convolution via fft; 'source' it is our signal, 'kernel'
    //! it is our resolution function.
    //! Sizes of input arrays are adjusted; output arrays are alocated via
    //! fftw3 allocation for maximum performance.
    class Workspace {
    public:
        Workspace() = default;
        ~Workspace();
        void clear();
        friend class Convolve;

    private:
        int h_src{0}, w_src{0};       // size of original 'source' array in 2 dimensions
        int h_kernel{0}, w_kernel{0}; // size of original 'kernel' array in 2 dimensions
        // size of adjusted source and kernel arrays (in_src, out_src, in_kernel, out_kernel)
        int w_fftw{0}, h_fftw{0};
        //! adjusted input 'source' array
        double* in_src{nullptr};
        //! result of Fourier transformation of source
        double* out_src{nullptr};
        //! adjusted input 'kernel' array
        double* in_kernel{nullptr};
        //! result of Fourier transformation of kernel
        double* out_kernel{nullptr};
        //! result of product of FFT(source) and FFT(kernel)
        double* dst_fft{nullptr};
        int h_dst{0}, w_dst{0};       // size of resulting array
        int h_offset{0}, w_offset{0}; // offsets to copy result into output arrays
        fftw_plan p_forw_src{nullptr};
        fftw_plan p_forw_kernel{nullptr};
        fftw_plan p_back{nullptr};
    };

    //! input and output data for fftw3
    Workspace ws;
    //! convolution mode
    ConvolutionMode m_mode;
};

#endif // BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H