File: DST.hpp

package info (click to toggle)
geographiclib 2.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,572 kB
  • sloc: cpp: 27,765; sh: 5,463; makefile: 695; python: 12; ansic: 10
file content (181 lines) | stat: -rw-r--r-- 7,143 bytes parent folder | download
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/**
 * \file DST.hpp
 * \brief Header for GeographicLib::DST class
 *
 * Copyright (c) Charles Karney (2022-2024) <karney@alum.mit.edu> and licensed
 * under the MIT/X11 License.  For more information, see
 * https://geographiclib.sourceforge.io/
 **********************************************************************/

#if !defined(GEOGRAPHICLIB_DST_HPP)
#define GEOGRAPHICLIB_DST_HPP 1

#include <GeographicLib/Constants.hpp>

#include <functional>
#include <memory>

/// \cond SKIP
template<typename scalar_t>
class kissfft;
/// \endcond

namespace GeographicLib {

  /**
   * \brief Discrete sine transforms
   *
   * This decomposes periodic functions \f$ f(\sigma) \f$ (period \f$ 2\pi \f$)
   * which are odd about \f$ \sigma = 0 \f$ and even about \f$ \sigma = \frac12
   * \pi \f$ into a Fourier series
   * \f[
   *   f(\sigma) = \sum_{l=0}^\infty F_l \sin\bigl((2l+1)\sigma\bigr).
   * \f]
   *
   * The first \f$ N \f$ components of \f$ F_l \f$, for \f$0 \le l < N\f$ may
   * be approximated by
   * \f[
   *   F_l = \frac2N \sum_{j=1}^{N}
   *   p_j f(\sigma_j)  \sin\bigl((2l+1)\sigma_j\bigr),
   * \f]
   * where \f$ \sigma_j = j\pi/(2N) \f$ and \f$ p_j = \frac12 \f$ for \f$ j = N
   * \f$ and \f$ 1 \f$ otherwise.  \f$ F_l \f$ is a discrete sine transform of
   * type DST-III and may be conveniently computed using the fast Fourier
   * transform, FFT; this is implemented with the DST::transform method.
   *
   * Having computed \f$ F_l \f$ based on \f$ N \f$ evaluations of \f$
   * f(\sigma) \f$ at \f$ \sigma_j = j\pi/(2N) \f$, it is possible to
   * refine these transform values and add another \f$ N \f$ coefficients by
   * evaluating \f$ f(\sigma) \f$ at \f$ (j-\frac12)\pi/(2N) \f$; this is
   * implemented with the DST::refine method.
   *
   * Here we compute FFTs using the kissfft package
   * https://github.com/mborgerding/kissfft by Mark Borgerding.
   *
   * Example of use:
   * \include example-DST.cpp
   *
   * \note The FFTW package https://www.fftw.org/ can also be used.  However
   * this is a more complicated dependency, its CMake support is broken, and it
   * doesn't work with mpreals (GEOGRAPHICLIB_PRECISION = 5).
   *
   * \deprecated The functionality offered by this class is also provided by
   *   the more general class Trigfun.  It is recommended to use Trigfun for
   *   new applications.
   **********************************************************************/

  class DST {
  private:
    typedef Math::real real;
    int _nN;
    typedef kissfft<real> fft_t;
    std::shared_ptr<fft_t> _fft;
    // Implement DST-III (centerp = false) or DST-IV (centerp = true)
    void fft_transform(real data[], real F[], bool centerp) const;
    // Add another N terms to F
    void fft_transform2(real data[], real F[]) const;
  public:
    /**
     * Constructor specifying the number of points to use.
     *
     * @param[in] N the number of points to use.
     **********************************************************************/
    GEOGRAPHICLIB_EXPORT DST(int N = 0);

    /**
     * Reset the given number of points.
     *
     * @param[in] N the number of points to use.
     **********************************************************************/
    void GEOGRAPHICLIB_EXPORT reset(int N);

    /**
     * Return the number of points.
     *
     * @return the number of points to use.
     **********************************************************************/
    int N() const { return _nN; }

    /**
     * Determine first \e N terms in the Fourier series
     *
     * @param[in] f the function used for evaluation.
     * @param[out] F the first \e N coefficients of the Fourier series.
     *
     * The evaluates \f$ f(\sigma) \f$ at \f$ \sigma = (j + 1) \pi / (2 N) \f$
     * for integer \f$ j \in [0, N) \f$.  \e F should be an array of length at
     * least \e N.
     **********************************************************************/
    void GEOGRAPHICLIB_EXPORT transform(std::function<real(real)> f, real F[])
      const;

    /**
     * Refine the Fourier series by doubling the number of points sampled
     *
     * @param[in] f the function used for evaluation.
     * @param[inout] F on input the first \e N coefficents of the Fourier
     *   series; on output the refined transform based on 2\e N points, i.e.,
     *   the first 2\e N coefficents.
     *
     * The evaluates \f$ f(\sigma) \f$ at additional points \f$ \sigma = (j +
     * \frac12) \pi / (2 N) \f$ for integer \f$ j \in [0, N) \f$, computes the
     * DST-IV transform of these, and combines this with the input \e F to
     * compute the 2\e N term DST-III discrete sine transform.  This is
     * equivalent to calling transform with twice the value of \e N but is more
     * efficient, given that the \e N term coefficients are already known.  See
     * the example code above.
     **********************************************************************/
    void GEOGRAPHICLIB_EXPORT refine(std::function<real(real)> f, real F[])
      const;

    /**
     * Evaluate the Fourier sum given the sine and cosine of the angle
     *
     * @param[in] sinx sin&sigma;.
     * @param[in] cosx cos&sigma;.
     * @param[in] F the array of Fourier coefficients.
     * @param[in] N the number of Fourier coefficients.
     * @return the value of the Fourier sum.
     **********************************************************************/
    static real GEOGRAPHICLIB_EXPORT eval(real sinx, real cosx,
                                          const real F[], int N);

    /**
     * Evaluate the integral of Fourier sum given the sine and cosine of the
     * angle
     *
     * @param[in] sinx sin&sigma;.
     * @param[in] cosx cos&sigma;.
     * @param[in] F the array of Fourier coefficients.
     * @param[in] N the number of Fourier coefficients.
     * @return the value of the integral.
     *
     * The constant of integration is chosen so that the integral is zero at
     * \f$ \sigma = \frac12\pi \f$.
     **********************************************************************/
    static real GEOGRAPHICLIB_EXPORT integral(real sinx, real cosx,
                                              const real F[], int N);

    /**
     * Evaluate the definite integral of Fourier sum given the sines and
     * cosines of the angles at the endpoints.
     *
     * @param[in] sinx sin&sigma;<sub>1</sub>.
     * @param[in] cosx cos&sigma;<sub>1</sub>.
     * @param[in] siny sin&sigma;<sub>2</sub>.
     * @param[in] cosy cos&sigma;<sub>2</sub>.
     * @param[in] F the array of Fourier coefficients.
     * @param[in] N the number of Fourier coefficients.
     * @return the value of the integral.
     *
     * The integral is evaluated between limits &sigma;<sub>1</sub> and
     * &sigma;<sub>2</sub>.
     **********************************************************************/
    static real GEOGRAPHICLIB_EXPORT integral(real sinx, real cosx,
                                              real siny, real cosy,
                                              const real F[], int N);
  };

} // namespace GeographicLib

#endif  // GEOGRAPHICLIB_DST_HPP