1 #ifndef SOPT_WAVELETS_INNARDS_H
2 #define SOPT_WAVELETS_INNARDS_H
4 #include "sopt/config.h"
14 template <
typename T0>
15 auto copy(Eigen::ArrayBase<T0>
const &
a) ->
16 typename std::remove_const<
typename std::remove_reference<decltype(
a.eval())>::type>::type {
25 template <
typename T0,
typename T2>
26 typename T0::Scalar periodic_scalar_product(Eigen::ArrayBase<T0>
const &
a,
27 Eigen::ArrayBase<T2>
const &
b,
28 typename T0::Index offset) {
29 auto const Na =
static_cast<typename T0::Index
>(
a.size());
30 auto const Nb =
static_cast<typename T0::Index
>(
b.size());
33 if (offset < 0) offset += Na;
35 if (Na > Nb + offset) {
36 return (
a.segment(offset, Nb) *
b).sum();
40 for (
typename T0::Index i(0), j(offset); i < Nb; ++i, ++j) result +=
a(j % Na) *
b(i);
46 template <
typename T0,
typename T1,
typename T2>
47 void convolve(Eigen::ArrayBase<T0> &result, Eigen::ArrayBase<T1>
const &signal,
48 Eigen::ArrayBase<T2>
const &filter) {
49 assert(result.size() == signal.size());
50 for (
typename T0::Index i(0); i <
t_int(signal.size()); ++i)
51 result(i) = periodic_scalar_product(signal, filter, i);
54 template <
typename T0,
typename T1,
typename T2>
55 void convolve(Eigen::VectorBlock<T0> &&result, Eigen::ArrayBase<T1>
const &signal,
56 Eigen::ArrayBase<T2>
const &filter) {
57 return convolve(result, signal, filter);
62 template <
typename T0,
typename T1,
typename T2>
63 void down_convolve(Eigen::ArrayBase<T0> &result, Eigen::ArrayBase<T1>
const &signal,
64 Eigen::ArrayBase<T2>
const &filter) {
65 assert(result.size() * 2 <= signal.size());
66 if (signal.rows() == 1) {
68 #pragma omp parallel for
70 for (
typename T0::Index i = 0; i < result.size(); ++i)
71 result(i) = periodic_scalar_product(signal.transpose(), filter, 2 * i);
74 #pragma omp parallel for
76 for (
typename T0::Index i = 0; i < result.size(); ++i)
77 result(i) = periodic_scalar_product(signal, filter, 2 * i);
81 template <
typename T0,
typename T1,
typename T2>
82 void down_convolve(Eigen::VectorBlock<T0> &&result, Eigen::ArrayBase<T1>
const &signal,
83 Eigen::ArrayBase<T2>
const &filter) {
84 down_convolve(result, signal, filter);
88 template <
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
89 void convolve_sum(Eigen::ArrayBase<T0> &result, Eigen::ArrayBase<T1>
const &low_pass_signal,
90 Eigen::ArrayBase<T2>
const &low_pass,
91 Eigen::ArrayBase<T3>
const &high_pass_signal,
92 Eigen::ArrayBase<T4>
const &high_pass) {
93 assert(result.size() == low_pass_signal.size());
94 assert(result.size() == high_pass_signal.size());
95 assert(low_pass.size() == high_pass.size());
96 static_assert(std::is_signed<typename T0::Index>::value,
"loffset, hoffset expect signed values");
97 auto const loffset = 1 -
static_cast<typename T0::Index
>(low_pass.size());
98 auto const hoffset = 1 -
static_cast<typename T0::Index
>(high_pass.size());
99 for (
typename T0::Index i(0); i < result.size(); ++i) {
100 result(i) = periodic_scalar_product(low_pass_signal, low_pass, i + loffset) +
101 periodic_scalar_product(high_pass_signal, high_pass, i + hoffset);
112 template <
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
113 void up_convolve_sum(Eigen::ArrayBase<T0> &result, Eigen::ArrayBase<T1>
const &coeffs,
114 Eigen::ArrayBase<T2>
const &low_even, Eigen::ArrayBase<T3>
const &low_odd,
115 Eigen::ArrayBase<T4>
const &high_even, Eigen::ArrayBase<T5>
const &high_odd) {
116 assert(result.size() <= coeffs.size());
117 assert(result.size() % 2 == 0);
118 assert(low_even.size() == high_even.size());
119 assert(low_odd.size() == high_odd.size());
120 auto const Nlow = (coeffs.size() + 1) / 2;
121 auto const Nhigh = coeffs.size() / 2;
122 auto const size = low_even.size() + low_odd.size();
123 auto const is_even = size % 2 == 0;
124 auto const even_offset = (1 - size) / 2;
125 auto const odd_offset = (1 - size) / 2 + (is_even ? 0 : 1);
126 auto const index_place_even = (is_even ? 1 : 0);
127 auto const index_place_odd = (is_even ? 0 : 1);
129 #pragma omp parallel for
131 for (
typename T0::Index i = 0; i < result.size() / 2; i++) {
132 result(2 * i + index_place_even) =
133 periodic_scalar_product(coeffs.head(Nlow), low_even, i + even_offset) +
134 periodic_scalar_product(coeffs.tail(Nhigh), high_even, i + even_offset);
135 result(2 * i + index_place_odd) =
136 periodic_scalar_product(coeffs.head(Nlow), low_odd, i + odd_offset) +
137 periodic_scalar_product(coeffs.tail(Nhigh), high_odd, i + odd_offset);
int t_int
Root of the type hierarchy for signed integers.