• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2  Copyright Nick Thompson, John Maddock, 2020
3  Distributed under the Boost Software License, Version 1.0.
4  (See accompanying file LICENSE_1_0.txt or copy at
5  http://www.boost.org/LICENSE_1_0.txt).
6]
7
8[section:daubechies Daubechies Wavelets and Scaling Functions]
9
10[h4 Synopsis]
11
12    #include <boost/math/special_functions/daubechies_scaling.hpp>
13
14    namespace boost::math {
15
16    template<class Real, int p>
17    class daubechies_scaling {
18    public:
19        daubechies_scaling(int grid_refinements = -1);
20
21        inline Real operator()(Real x) const;
22
23        inline Real prime(Real x) const;
24
25        inline Real double_prime(Real x) const;
26
27        std::pair<Real, Real> support() const;
28
29        int64_t bytes() const;
30    };
31
32    template<class Real, int p, int order>
33    std::vector<Real> dyadic_grid(int64_t j_max);
34
35
36    #include <boost/math/special_functions/daubechies_wavelet.hpp>
37    template<class Real, int p>
38    class daubechies_wavelet {
39    public:
40        daubechies_wavelet(int grid_refinements = -1);
41
42        inline Real operator()(Real x) const;
43
44        inline Real prime(Real x) const;
45
46        inline Real double_prime(Real x) const;
47
48        std::pair<Real, Real> support() const;
49
50        int64_t bytes() const;
51    };
52
53
54    } // namespaces
55
56
57Daubechies wavelets and scaling functions are a family of compactly supported functions indexed by an integer /p/ which have /p/ vanishing moments and an associated filter of length /2p/.
58They are used in signal denoising, Galerkin methods for PDEs, and compression.
59
60The canonical reference on these functions is Daubechies' monograph /Ten Lectures on Wavelets/,
61whose notational conventions we attempt to follow here.
62
63A basic usage is as follows:
64
65    auto phi = boost::math::daubechies_scaling<double, 8>();
66    double y = phi(0.38);
67    double dydx = phi.prime(0.38);
68
69    auto psi = boost::math::daubechies_wavelet<double, 8>();
70    y = psi(0.38);
71
72Note that the constructor call is expensive, as it must assemble a /dyadic grid/--values of [sub /p/]\u03C6 at dyadic rationals,
73i.e., numbers of the form n/2[super /j/].
74You should only instantiate this class once in the duration of a program.
75The class is pimpl'd and all its member functions are threadsafe, so it can be copied cheaply and shared between threads.
76The default number of grid refinements is chosen so that the relative error is controlled to ~2-3 ULPs away from the right-hand side of the support,
77where superexponential growth of the condition number of function evaluation makes this impossible.
78However, controlling relative error of Daubechies wavelets and scaling functions is much more difficult than controlling absolute error,
79and the memory consumption is much higher in relative mode.
80The memory consumption of the class can be queried via
81
82    int64_t mem = phi.bytes();
83
84and if this is deemed unacceptably large, the user may choose to control absolute error via calling the constructor with the `grid_refinements` parameter set to -2,
85so
86
87    auto phi = boost::math::daubechies_scaling<double, 8>(-2);
88
89gives a scaling function which keeps the absolute error bounded by roughly the double precision unit roundoff.
90
91If context precludes the ability to reuse the class throughout the program, it makes sense to reduce the accuracy even further.
92This can be done by specifying the grid refinements, for example,
93
94    auto phi = boost::math::daubechies_scaling<double, 8>(12);
95
96creates a Daubechies scaling function interpolated from a dyadic grid computed down to depth /j/ = 12.
97The call to the constructor is exponential time in the number of grid refinements, and the call operator, `.prime`, and `.double_prime` are constant time.
98
99Note that the only reason that this is a class, rather than a free function is that the dyadic grids would make the Boost source download extremely large.
100Hence, it may make sense to precompute the dyadic grid and dump it in a `.cpp` file; this can be achieved via
101
102    using boost::multiprecision::float128;
103    int grid_refinements = 12;
104    constexpr const derivative = 0;
105    constexpr const p = 8;
106    std::vector<float128> v = boost::math::dyadic_grid<float128, p, derivative>(grid_refinements);
107
108Note that quad precision is the most accurate precision provided, for both the dyadic grid and for the scaling function.
1091ULP accuracy can only be achieved for float and double precision, in well-conditioned regions.
110
111Derivatives are only available if the wavelet and scaling function has sufficient smoothness.
112The compiler will gladly inform you of your error if you try to call `.prime` on [sub 2]\u03C6, which is not differentiable,
113but be aware that smoothness increases with the number of vanishing moments.
114
115The axioms of a multiresolution analysis ensure that integer shifts of the scaling functions are elements of the multiresolution analysis;
116a side effect is that the supports of the (unshifted) wavelet and scaling functions are arbitrary.
117For this reason, we have provided `.support()` so that you can check our conventions:
118
119    auto [a, b] = phi.support();
120
121For definiteness though, for the scaling function, the support is always [0, /2p/ - 1], and the support of the wavelet is [ -/p/ + 1, /p/].
122
123
124[$../graphs/daubechies_2_scaling.svg]
125The 2 vanishing moment scaling function.
126
127[$../graphs/daubechies_8_scaling.svg]
128The 8 vanishing moment scaling function.
129
130[heading References]
131
132* Daubechies, Ingrid. ['Ten Lectures on Wavelets.] Vol. 61. Siam, 1992.
133* Mallat, Stephane. ['A Wavelet Tour of Signal Processing: the sparse way] Academic press, 2008.
134
135
136
137[endsect]
138