-
Notifications
You must be signed in to change notification settings - Fork 227
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Numerical evaluation of Fourier transform of Daubechies scaling funct…
…ions. [ci skip]
- Loading branch information
1 parent
e2c989c
commit d793bbc
Showing
8 changed files
with
474 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
example/calculate_fourier_transform_daubechies_constants.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include <utility> | ||
#include <boost/math/filters/daubechies.hpp> | ||
#include <boost/math/tools/polynomial.hpp> | ||
#include <boost/multiprecision/cpp_bin_float.hpp> | ||
#include <boost/math/constants/constants.hpp> | ||
|
||
using std::pow; | ||
using boost::multiprecision::cpp_bin_float_100; | ||
using boost::math::filters::daubechies_scaling_filter; | ||
using boost::math::tools::polynomial; | ||
using boost::math::constants::half; | ||
using boost::math::constants::root_two; | ||
|
||
template<typename Real, size_t N> | ||
std::vector<Real> get_constants() { | ||
auto h = daubechies_scaling_filter<cpp_bin_float_100, N>(); | ||
auto p = polynomial<cpp_bin_float_100>(h.begin(), h.end()); | ||
|
||
auto q = polynomial({half<cpp_bin_float_100>(), half<cpp_bin_float_100>()}); | ||
q = pow(q, N); | ||
auto l = p/q; | ||
return l.data(); | ||
} | ||
|
||
template<typename Real> | ||
void print_constants(std::vector<Real> const & l) { | ||
std::cout << std::setprecision(std::numeric_limits<Real>::digits10 -10); | ||
std::cout << "return std::array<Real, " << l.size() << ">{"; | ||
for (size_t i = 0; i < l.size() - 1; ++i) { | ||
std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << l[i]/root_two<Real>() << "), "; | ||
} | ||
std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << l.back()/root_two<Real>() << ")};\n"; | ||
} | ||
|
||
int main() { | ||
auto constants = get_constants<cpp_bin_float_100, 10>(); | ||
print_constants(constants); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <boost/math/special_functions/fourier_transform_daubechies_scaling.hpp> | ||
#include <boost/math/tools/ulps_plot.hpp> | ||
|
||
using boost::math::fourier_transform_daubechies_scaling; | ||
using boost::math::tools::ulps_plot; | ||
|
||
int main() { | ||
|
||
auto phi_real_hi_acc = [](double omega) { | ||
auto z = fourier_transform_daubechies_scaling<double, 6>(omega); | ||
return z.real(); | ||
}; | ||
|
||
auto phi_real_lo_acc = [](float omega) { | ||
auto z = fourier_transform_daubechies_scaling<float, 6>(omega); | ||
return z.real(); | ||
}; | ||
auto plot = ulps_plot<decltype(phi_real_hi_acc), double, float>(phi_real_hi_acc, float(0.0), float(100.0), 20000); | ||
plot.ulp_envelope(false); | ||
plot.add_fn(phi_real_lo_acc); | ||
plot.clip(100); | ||
plot.title("Accuracy of Fourier transform of 6 vanishing moment Daubechies scaling function"); | ||
plot.write("ft_daub_scaling_6.svg"); | ||
return 0; | ||
} |
231 changes: 231 additions & 0 deletions
231
include/boost/math/special_functions/fourier_transform_daubechies_scaling.hpp
Large diffs are not rendered by default.
Oops, something went wrong.
33 changes: 33 additions & 0 deletions
33
reporting/performance/fourier_transform_daubechies_scaling_performance.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// (C) Copyright Nick Thompson 2023. | ||
// Use, modification and distribution are subject to the | ||
// Boost Software License, Version 1.0. (See accompanying file | ||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <random> | ||
#include <array> | ||
#include <vector> | ||
#include <iostream> | ||
#include <benchmark/benchmark.h> | ||
#include <boost/math/special_functions/fourier_transform_daubechies_scaling.hpp> | ||
|
||
using boost::math::fourier_transform_daubechies_scaling; | ||
|
||
template<class Real> | ||
void FourierTransformDaubechiesScaling(benchmark::State& state) | ||
{ | ||
std::random_device rd; | ||
auto seed = rd(); | ||
std::mt19937_64 mt(seed); | ||
std::uniform_real_distribution<Real> unif(0, 10); | ||
|
||
for (auto _ : state) | ||
{ | ||
benchmark::DoNotOptimize(fourier_transform_daubechies_scaling<Real, 3>(unif(mt))); | ||
} | ||
} | ||
|
||
BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float); | ||
BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double); | ||
//BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, long double); | ||
|
||
BENCHMARK_MAIN(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Copyright Nick Thompson, 2023 | ||
* Use, modification and distribution are subject to the | ||
* Boost Software License, Version 1.0. (See accompanying file | ||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
|
||
#include "math_unit_test.hpp" | ||
#include <numeric> | ||
#include <utility> | ||
#include <iomanip> | ||
#include <iostream> | ||
#include <random> | ||
#include <boost/math/tools/condition_numbers.hpp> | ||
#include <boost/math/constants/constants.hpp> | ||
#include <boost/math/quadrature/trapezoidal.hpp> | ||
#include <boost/math/special_functions/daubechies_scaling.hpp> | ||
#include <boost/math/special_functions/fourier_transform_daubechies_scaling.hpp> | ||
|
||
#ifdef BOOST_HAS_FLOAT128 | ||
#include <boost/multiprecision/float128.hpp> | ||
using boost::multiprecision::float128; | ||
#endif | ||
|
||
using boost::math::fourier_transform_daubechies_scaling; | ||
using boost::math::tools::summation_condition_number; | ||
using boost::math::constants::two_pi; | ||
using boost::math::constants::one_div_root_two_pi; | ||
using boost::math::quadrature::trapezoidal; | ||
// 𝓕[φ](-ω) = 𝓕[φ](ω)* | ||
template<typename Real, int p> | ||
void test_evaluation_symmetry() { | ||
auto phi = fourier_transform_daubechies_scaling<Real, p>(0.0); | ||
CHECK_ULP_CLOSE(one_div_root_two_pi<Real>(), phi.real(), 3); | ||
CHECK_ULP_CLOSE(static_cast<Real>(0), phi.imag(), 3); | ||
|
||
Real domega = Real(1)/128; | ||
for (Real omega = domega; omega < 10; omega += domega) { | ||
auto phi1 = fourier_transform_daubechies_scaling<Real, p>(-omega); | ||
auto phi2 = fourier_transform_daubechies_scaling<Real, p>(omega); | ||
CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); | ||
CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); | ||
} | ||
|
||
for (Real omega = 10; omega < std::sqrt(std::numeric_limits<Real>::max()); omega *= 10) { | ||
auto phi1 = fourier_transform_daubechies_scaling<Real, p>(-omega); | ||
auto phi2 = fourier_transform_daubechies_scaling<Real, p>(omega); | ||
CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); | ||
CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); | ||
} | ||
return; | ||
} | ||
|
||
template<int p> | ||
void test_quadrature() { | ||
auto phi = boost::math::daubechies_scaling<double, p>(); | ||
auto [tmin, tmax] = phi.support(); | ||
double domega = 1/8.0; | ||
for (double omega = domega; omega < 10; omega += domega) { | ||
// I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: | ||
auto f = [&](double t) { | ||
return phi(t)*std::exp(std::complex<double>(0, -omega*t))*one_div_root_two_pi<double>(); | ||
}; | ||
auto expected = trapezoidal(f, tmin, tmax, 2*std::numeric_limits<double>::epsilon()); | ||
auto computed = fourier_transform_daubechies_scaling<float, p>(static_cast<float>(omega)); | ||
CHECK_MOLLIFIED_CLOSE(static_cast<float>(expected.real()), computed.real(), 1e-4); | ||
CHECK_MOLLIFIED_CLOSE(static_cast<float>(expected.imag()), computed.imag(), 1e-4); | ||
} | ||
} | ||
|
||
// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.19: | ||
template<typename Real, int p> | ||
void test_ten_lectures_eq_5_1_19() { | ||
Real domega = Real(1)/Real(16); | ||
for (Real omega = 0; omega < 1; omega += domega) { | ||
Real term = std::norm(fourier_transform_daubechies_scaling<Real, p>(omega)); | ||
auto sum = summation_condition_number<Real>(term); | ||
int64_t l = 1; | ||
while (l < 50 && term > 2*std::numeric_limits<Real>::epsilon()) { | ||
Real tpl = std::norm(fourier_transform_daubechies_scaling<Real, p>(omega + two_pi<Real>()*l)); | ||
Real tml = std::norm(fourier_transform_daubechies_scaling<Real, p>(omega - two_pi<Real>()*l)); | ||
|
||
sum += tpl; | ||
sum += tml; | ||
Real term = tpl + tml; | ||
++l; | ||
} | ||
// With arg promotion, I can get this to 13 ULPS: | ||
if (!CHECK_ULP_CLOSE(1/two_pi<Real>(), sum.sum(), 125)) { | ||
std::cerr << " Failure with occurs on " << p << " vanishing moments.\n"; | ||
} | ||
} | ||
} | ||
|
||
int main() | ||
{ | ||
test_evaluation_symmetry<float, 2>(); | ||
test_evaluation_symmetry<float, 3>(); | ||
test_evaluation_symmetry<float, 4>(); | ||
test_evaluation_symmetry<float, 5>(); | ||
test_evaluation_symmetry<float, 6>(); | ||
test_evaluation_symmetry<float, 7>(); | ||
test_evaluation_symmetry<float, 8>(); | ||
test_evaluation_symmetry<float, 9>(); | ||
test_evaluation_symmetry<float, 10>(); | ||
|
||
// Slow tests: | ||
//test_quadrature<2>(); | ||
//test_quadrature<3>(); | ||
//test_quadrature<4>(); | ||
//test_quadrature<5>(); | ||
|
||
test_ten_lectures_eq_5_1_19<float, 2>(); | ||
test_ten_lectures_eq_5_1_19<float, 3>(); | ||
test_ten_lectures_eq_5_1_19<float, 4>(); | ||
test_ten_lectures_eq_5_1_19<float, 5>(); | ||
test_ten_lectures_eq_5_1_19<float, 6>(); | ||
test_ten_lectures_eq_5_1_19<float, 7>(); | ||
test_ten_lectures_eq_5_1_19<float, 8>(); | ||
test_ten_lectures_eq_5_1_19<float, 9>(); | ||
test_ten_lectures_eq_5_1_19<float, 10>(); | ||
|
||
return boost::math::test::report_errors(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters