237 if (work.leaves_ != leaves_ || work.block_ != block_)
241 const auto last = work.levels_[work.levelCount_ - 1];
242 std::fill_n(work.moments_.get(), last.offset + last.count, Coefficients{});
244 for (std::size_t leaf = 0; leaf < leaves_; ++leaf)
246 const auto first =
static_cast<std::int64_t
>(leaf) * block_;
247 work.
read(source, first, block_, work.input_.get());
248 auto &dst = work.moments_[leaf];
249 for (
int i = 0; i < block_; ++i)
250 for (
int p = 0; p < order; ++p)
251 dst[
static_cast<std::size_t
>((i % 2) * order + p)] +=
252 work.input_[i] * work.weights_[
static_cast<std::size_t
>(p) * block_ + i];
254 first + std::min<std::int64_t>(block_, work.frames_ - first),
257 for (std::size_t level = 1; level < work.levelCount_; ++level)
259 const auto current = work.levels_[level], previous = work.levels_[level - 1];
260 for (std::size_t parent = 0; parent < current.count; ++parent)
262 auto &dst = work.moments_[current.offset + parent];
263 for (
int side = 0; side < 2; ++side)
265 const auto child = 2 * parent + side;
266 if (child >= previous.count)
268 const auto &src = work.moments_[previous.offset + child];
269 add(dst, src, work.matrices_[side], 1);
271 if ((parent & 255) == 0)
275 auto *local = local_.get(), *children = work.local_.get();
276 *local = Coefficients{};
277 for (std::size_t remaining = work.levelCount_; remaining > 0; --remaining)
279 const auto level = remaining - 1;
280 const auto current = work.levels_[level];
281 const double width = std::ldexp(
static_cast<double>(block_),
static_cast<int>(level));
282 for (std::size_t target = 0; target < current.count; ++target)
284 const auto first =
static_cast<std::int64_t
>(2 * (target / 2)) - 2;
285 for (
auto other = first; other < first + 6; ++other)
287 if (other < 0 ||
static_cast<std::uint64_t
>(other) >= current.count)
289 const auto offset =
static_cast<std::int64_t
>(target) - other;
290 if (std::abs(offset) <= 1)
292 const int kernel = offset == -3 ? 4 : offset == -2 ? 5 : offset == 2 ? 6 : 7;
293 add(local[target], work.moments_[current.offset +
static_cast<std::size_t
>(other)],
294 work.matrices_[kernel], 1 / width);
296 if ((target & 255) == 0)
301 for (std::size_t child = 0; child < work.levels_[level - 1].count; ++child)
303 children[child] = Coefficients{};
304 add(children[child], local[child / 2], work.matrices_[2 + child % 2], 1);
306 std::swap(local, children);
308 if (local != local_.get())
309 local_.swap(work.local_);
333 bool alternating =
false)
const
335 if (leaf >= leaves_ || !std::isfinite(shift) || std::abs(shift) > 1)
338 const auto *coefficients = local_[leaf].data();
339 for (
int i = 0; i < block_; ++i)
341 const double u = (i + shift - (block_ - 1) * .5) / (block_ * .5);
342 double even = coefficients[order - 1], odd = coefficients[2 * order - 1];
343 for (
int p = order - 2; p >= 0; --p)
345 even = even * u + coefficients[p];
346 odd = odd * u + coefficients[order + p];
348 output[i] = alternating ? even - odd : even + odd;
361 const auto *close = work.nearField(leaf, source, outer, cauchy, alternating);