|
@ -4,108 +4,99 @@ |
|
|
|
|
|
|
|
|
#include "striding_iterator.hpp" |
|
|
#include "striding_iterator.hpp" |
|
|
#include "periodic_iterator.hpp" |
|
|
#include "periodic_iterator.hpp" |
|
|
|
|
|
#include "wavelet_constants.hpp" |
|
|
|
|
|
|
|
|
static double const evn_coef[] = { |
|
|
namespace wvlt { |
|
|
(1.0 + std::sqrt(3.0))/(std::sqrt(32.0)), |
|
|
namespace V1 { |
|
|
(3.0 + std::sqrt(3.0))/(std::sqrt(32.0)), |
|
|
// Apply the matrix Wn with the DAUB4 coefficients
|
|
|
(3.0 - std::sqrt(3.0))/(std::sqrt(32.0)), |
|
|
template <typename Iterator> |
|
|
(1.0 - std::sqrt(3.0))/(std::sqrt(32.0)) |
|
|
void wavelet_mul(Iterator begin, Iterator end){ |
|
|
}; |
|
|
auto mul = end - begin; |
|
|
|
|
|
std::vector<double> out(mul, 0.0); |
|
|
static double const odd_coef[] = { |
|
|
for(int i = 0; i < mul; i += 2){ |
|
|
evn_coef[3], |
|
|
out[i] = std::inner_product(evn_coef, evn_coef+4, periodic(begin, end) + i, 0.0); |
|
|
-evn_coef[2], |
|
|
out[i+1] = std::inner_product(odd_coef, odd_coef+4, periodic(begin, end) + i, 0.0); |
|
|
evn_coef[1], |
|
|
} |
|
|
-evn_coef[0] |
|
|
for(int i = 0; i < mul; ++i){ |
|
|
}; |
|
|
*begin++ = out[i]; |
|
|
|
|
|
} |
|
|
// Apply the matrix Wn with the DAUB4 coefficients
|
|
|
} |
|
|
// Assumes input to be periodic
|
|
|
|
|
|
template <typename Iterator> |
|
|
|
|
|
void wavelet_mul(Iterator begin, Iterator end){ |
|
|
|
|
|
auto mul = end - begin; |
|
|
|
|
|
std::vector<double> out(mul, 0.0); |
|
|
|
|
|
for(int i = 0; i < mul; i += 2){ |
|
|
|
|
|
out[i] = std::inner_product(evn_coef, evn_coef+4, periodic(begin, end) + i, 0.0); |
|
|
|
|
|
out[i+1] = std::inner_product(odd_coef, odd_coef+4, periodic(begin, end) + i, 0.0); |
|
|
|
|
|
} |
|
|
|
|
|
for(int i = 0; i < mul; ++i){ |
|
|
|
|
|
*begin++ = out[i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Iterator> |
|
|
// Apply inverse of the matrix Wn with the DAUB4 coefficients
|
|
|
void wavelet_inv(Iterator begin, Iterator end){ |
|
|
template <typename Iterator> |
|
|
auto mul = end - begin; |
|
|
void wavelet_inv(Iterator begin, Iterator end){ |
|
|
std::vector<double> out(mul, 0.0); |
|
|
auto mul = end - begin; |
|
|
Iterator bc = begin; |
|
|
std::vector<double> out(mul, 0.0); |
|
|
for(int i = 0; i < mul; i += 2, begin += 2){ |
|
|
Iterator bc = begin; |
|
|
Iterator b2 = begin + 1; |
|
|
for(int i = 0; i < mul; i += 2, begin += 2){ |
|
|
for(int j = 0; j < 4; ++j){ |
|
|
Iterator b2 = begin + 1; |
|
|
out[(i+j) % mul] += *begin * evn_coef[j] + *b2 * odd_coef[j]; |
|
|
for(int j = 0; j < 4; ++j){ |
|
|
|
|
|
out[(i+j) % mul] += *begin * evn_coef[j] + *b2 * odd_coef[j]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
for(int i = 0; i < mul; ++i){ |
|
|
|
|
|
*bc++ = out[i]; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
for(int i = 0; i < mul; ++i){ |
|
|
|
|
|
*bc++ = out[i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Shuffle works with an extra copy, might be inefficient, but it is at least correct ;)
|
|
|
// Shuffle works with an extra copy, might be inefficient, but it is at least correct ;)
|
|
|
// It applies the even-odd-sort matrix Sn
|
|
|
// It applies the even-odd-sort matrix Sn
|
|
|
template <typename Iterator> |
|
|
template <typename Iterator> |
|
|
void shuffle(Iterator begin, Iterator end){ |
|
|
void shuffle(Iterator begin, Iterator end){ |
|
|
typedef typename std::iterator_traits<Iterator>::value_type value_type; |
|
|
typedef typename std::iterator_traits<Iterator>::value_type value_type; |
|
|
auto s = end - begin; |
|
|
auto s = end - begin; |
|
|
assert(s % 2 == 0); |
|
|
assert(s % 2 == 0); |
|
|
|
|
|
|
|
|
std::vector<value_type> v(s); |
|
|
std::vector<value_type> v(s); |
|
|
std::copy(strided(begin , 2), strided(end , 2), v.begin()); |
|
|
std::copy(strided(begin , 2), strided(end , 2), v.begin()); |
|
|
std::copy(strided(begin+1, 2), strided(end+1, 2), v.begin() + s/2); |
|
|
std::copy(strided(begin+1, 2), strided(end+1, 2), v.begin() + s/2); |
|
|
std::copy(v.begin(), v.end(), begin); |
|
|
std::copy(v.begin(), v.end(), begin); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Iterator> |
|
|
template <typename Iterator> |
|
|
void unshuffle(Iterator begin, Iterator end){ |
|
|
void unshuffle(Iterator begin, Iterator end){ |
|
|
typedef typename std::iterator_traits<Iterator>::value_type value_type; |
|
|
typedef typename std::iterator_traits<Iterator>::value_type value_type; |
|
|
auto s = end - begin; |
|
|
auto s = end - begin; |
|
|
assert(s % 2 == 0); |
|
|
assert(s % 2 == 0); |
|
|
|
|
|
|
|
|
std::vector<value_type> v(s); |
|
|
std::vector<value_type> v(s); |
|
|
std::copy(begin, begin + s/2, strided(v.begin(), 2)); |
|
|
std::copy(begin, begin + s/2, strided(v.begin(), 2)); |
|
|
std::copy(begin + s/2, end, strided(v.begin()+1, 2)); |
|
|
std::copy(begin + s/2, end, strided(v.begin()+1, 2)); |
|
|
std::copy(v.begin(), v.end(), begin); |
|
|
std::copy(v.begin(), v.end(), begin); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Combines the matrix Wn and Sn recusrively
|
|
|
// Combines the matrix Wn and Sn recusrively
|
|
|
// Only works for inputs of size 2^m
|
|
|
// Only works for inputs of size 2^m
|
|
|
template <typename Iterator> |
|
|
template <typename Iterator> |
|
|
void wavelet(Iterator begin, Iterator end){ |
|
|
void wavelet(Iterator begin, Iterator end){ |
|
|
auto s = end - begin; |
|
|
auto s = end - begin; |
|
|
assert(s >= 4); |
|
|
assert(s >= 4); |
|
|
for(int i = s; i >= 4; i >>= 1){ |
|
|
for(int i = s; i >= 4; i >>= 1){ |
|
|
// half interval
|
|
|
// half interval
|
|
|
end = begin + i; |
|
|
end = begin + i; |
|
|
assert(is_pow_of_two(end - begin)); |
|
|
assert(is_pow_of_two(end - begin)); |
|
|
|
|
|
|
|
|
// multiply with Wn
|
|
|
// multiply with Wn
|
|
|
wavelet_mul(begin, end); |
|
|
wavelet_mul(begin, end); |
|
|
// then with Sn
|
|
|
// then with Sn
|
|
|
shuffle(begin, end); |
|
|
shuffle(begin, end); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Iterator> |
|
|
template <typename Iterator> |
|
|
void unwavelet(Iterator begin, Iterator end){ |
|
|
void unwavelet(Iterator begin, Iterator end){ |
|
|
auto s = end - begin; |
|
|
auto s = end - begin; |
|
|
assert(s >= 4); |
|
|
assert(s >= 4); |
|
|
for(int i = 4; i <= s; i <<= 1){ |
|
|
for(int i = 4; i <= s; i <<= 1){ |
|
|
// double interval
|
|
|
// double interval
|
|
|
end = begin + i; |
|
|
end = begin + i; |
|
|
assert(is_pow_of_two(end - begin)); |
|
|
assert(is_pow_of_two(end - begin)); |
|
|
|
|
|
|
|
|
// unshuffle: Sn^-1
|
|
|
// unshuffle: Sn^-1
|
|
|
unshuffle(begin, end); |
|
|
unshuffle(begin, end); |
|
|
// then Wn^-1
|
|
|
// then Wn^-1
|
|
|
wavelet_inv(begin, end); |
|
|
wavelet_inv(begin, end); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|