Skip to content

Commit 96d761e

Browse files
committed
Numerical evaluation of Fourier transform of Daubechies scaling functions. [ci skip] [CI SKIP]
1 parent 4aac532 commit 96d761e

9 files changed

+612
-1
lines changed
451 KB
Loading

doc/sf/daubechies.qbk

+17
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,23 @@ The 2 vanishing moment scaling function.
127127
[$../graphs/daubechies_8_scaling.svg]
128128
The 8 vanishing moment scaling function.
129129

130+
Boost.Math also provides numerical evaluation of the Fourier transform of these functions.
131+
This is useful in sparse recovery problems where the measurements are taken in the Fourier basis.
132+
The usage is exhibited below:
133+
134+
#include <boost/math/special_functions/fourier_transform_daubechies_scaling.hpp>
135+
using boost::math::fourier_transform_daubechies_scaling;
136+
// Evaluate the Fourier transform of the 4-vanishing moment Daubechies scaling function at ω=1.8:
137+
std::complex<float> hat_phi = fourier_transform_daubechies_scaling<float, 4>(1.8f);
138+
139+
The Fourier transform convention is unitary with the sign of i being given in Daubechies Ten Lectures.
140+
In particular, this means that `fourier_transform_daubechies_scaling<float, p>(0.0)` returns 1/sqrt(2π).
141+
142+
The implementation computes an infinite product of trigonometric polynomials as can be found from recursive application of the identity 𝓕[φ](ω) = m(ω/2)𝓕[φ](ω/2).
143+
This is neither particularly fast nor accurate, but there appears to be no literature on this extremely useful topic, and hence the naive method must suffice.
144+
145+
[$../graphs/fourier_transform_daubechies.png]
146+
130147
[heading References]
131148

132149
* Daubechies, Ingrid. ['Ten Lectures on Wavelets.] Vol. 61. Siam, 1992.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <utility>
2+
#include <boost/math/filters/daubechies.hpp>
3+
#include <boost/math/tools/polynomial.hpp>
4+
#include <boost/multiprecision/cpp_bin_float.hpp>
5+
#include <boost/math/constants/constants.hpp>
6+
7+
using std::pow;
8+
using boost::multiprecision::cpp_bin_float_100;
9+
using boost::math::filters::daubechies_scaling_filter;
10+
using boost::math::tools::polynomial;
11+
using boost::math::constants::half;
12+
using boost::math::constants::root_two;
13+
14+
template<typename Real, size_t N>
15+
std::vector<Real> get_constants() {
16+
auto h = daubechies_scaling_filter<cpp_bin_float_100, N>();
17+
auto p = polynomial<cpp_bin_float_100>(h.begin(), h.end());
18+
19+
auto q = polynomial({half<cpp_bin_float_100>(), half<cpp_bin_float_100>()});
20+
q = pow(q, N);
21+
auto l = p/q;
22+
return l.data();
23+
}
24+
25+
template<typename Real>
26+
void print_constants(std::vector<Real> const & l) {
27+
std::cout << std::setprecision(std::numeric_limits<Real>::digits10 -10);
28+
std::cout << "return std::array<Real, " << l.size() << ">{";
29+
for (size_t i = 0; i < l.size() - 1; ++i) {
30+
std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << l[i]/root_two<Real>() << "), ";
31+
}
32+
std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << l.back()/root_two<Real>() << ")};\n";
33+
}
34+
35+
int main() {
36+
auto constants = get_constants<cpp_bin_float_100, 1>();
37+
print_constants(constants);
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <boost/math/special_functions/fourier_transform_daubechies_scaling.hpp>
2+
#include <boost/math/tools/ulps_plot.hpp>
3+
4+
using boost::math::fourier_transform_daubechies_scaling;
5+
using boost::math::tools::ulps_plot;
6+
7+
template<int p>
8+
void real_part() {
9+
auto phi_real_hi_acc = [](double omega) {
10+
auto z = fourier_transform_daubechies_scaling<double, p>(omega);
11+
return z.real();
12+
};
13+
14+
auto phi_real_lo_acc = [](float omega) {
15+
auto z = fourier_transform_daubechies_scaling<float, p>(omega);
16+
return z.real();
17+
};
18+
auto plot = ulps_plot<decltype(phi_real_hi_acc), double, float>(phi_real_hi_acc, float(0.0), float(100.0), 20000);
19+
plot.ulp_envelope(false);
20+
plot.add_fn(phi_real_lo_acc);
21+
plot.clip(100);
22+
plot.title("Accuracy of 𝔑(𝓕[𝜙](ω)) with " + std::to_string(p) + " vanishing moments.");
23+
plot.write("real_ft_daub_scaling_" + std::to_string(p) + ".svg");
24+
25+
}
26+
27+
template<int p>
28+
void imaginary_part() {
29+
auto phi_imag_hi_acc = [](double omega) {
30+
auto z = fourier_transform_daubechies_scaling<double, p>(omega);
31+
return z.imag();
32+
};
33+
34+
auto phi_imag_lo_acc = [](float omega) {
35+
auto z = fourier_transform_daubechies_scaling<float, p>(omega);
36+
return z.imag();
37+
};
38+
auto plot = ulps_plot<decltype(phi_imag_hi_acc), double, float>(phi_imag_hi_acc, float(0.0), float(100.0), 20000);
39+
plot.ulp_envelope(false);
40+
plot.add_fn(phi_imag_lo_acc);
41+
plot.clip(100);
42+
plot.title("Accuracy of 𝕴(𝓕[𝜙](ω)) with " + std::to_string(p) + " vanishing moments.");
43+
plot.write("imag_ft_daub_scaling_" + std::to_string(p) + ".svg");
44+
45+
}
46+
47+
48+
int main() {
49+
real_part<3>();
50+
imaginary_part<3>();
51+
real_part<6>();
52+
imaginary_part<6>();
53+
return 0;
54+
}

0 commit comments

Comments
 (0)