64 using CountBlock = DataBlock<count_t, N>;
70 [[nodiscard]] CountBlock& countBlock(pos_t block) {
return count_[block]; }
72 [[nodiscard]] CountBlock
const& countBlock(pos_t block)
const {
return count_[block]; }
78 [[nodiscard]] count_t count(Index node)
const {
return count_[node.pos][node.offset]; }
80 [[nodiscard]] count_t count(Node node)
const {
return count(derived().
index(node)); }
82 [[nodiscard]] count_t count(Code code)
const {
return count(derived().
index(code)); }
84 [[nodiscard]] count_t count(Key key)
const {
return count(derived().
index(key)); }
86 [[nodiscard]] count_t count(Coord coord, depth_t depth = 0)
const
88 return count(derived().
index(coord, depth));
95 void setCount(Index node, count_t count)
97 return derived().apply(
98 node, [
this, count](Index node) { count_[node.pos][node.offset] = count; },
99 [
this, count](pos_t pos) { count_[pos].fill(count); });
102 Node setCount(Node node, count_t count,
bool propagate =
true)
104 return derived().apply(
105 node, [
this, count](Index node) { count_[node.pos][node.offset] = count; },
106 [
this, count](pos_t pos) { count_[pos].fill(count); }, propagate);
109 Node setCount(Code code, count_t count,
bool propagate =
true)
111 return derived().apply(
112 code, [
this, count](Index node) { count_[node.pos][node.offset] = count; },
113 [
this, count](pos_t pos) { count_[pos].fill(count); }, propagate);
116 Node setCount(Key key, count_t count,
bool propagate =
true)
118 return setCount(derived().toCode(key), count, propagate);
121 Node setCount(Coord coord, count_t count,
bool propagate =
true, depth_t depth = 0)
123 return setCount(derived().toCode(coord, depth), count, propagate);
130 void updateCount(Index node,
int change)
133 node, [
this, change](Index node) { count_[node.pos][node.offset] += change; },
134 [
this, change](pos_t pos) {
135 for (
auto& e : count_[pos]) {
141 template <
class UnaryOp,
142 std::enable_if_t<std::is_invocable_v<UnaryOp, count_t>,
bool> =
true>
143 void updateCount(Index node, UnaryOp unary_op)
147 [
this, unary_op](Index node) {
148 count_[node.pos][node.offset] = unary_op(count_[node.pos][node.offset]);
150 [
this, unary_op](pos_t pos) {
151 for (
auto& e : count_[pos]) {
157 template <
class BinaryOp,
158 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, count_t>,
bool> =
true>
159 void updateCount(Index node, BinaryOp binary_op)
163 [
this, binary_op](Index node) {
164 count_[node.pos][node.offset] = binary_op(node, count_[node.pos][node.offset]);
166 [
this, binary_op](pos_t pos) {
168 for (
auto& e : count_[pos]) {
169 e = binary_op(Index(pos, i++), e);
174 Node updateCount(Node node,
int change,
bool propagate =
true)
176 return derived().apply(
177 node, [
this, change](Index node) { count_[node.pos][node.offset] += change; },
178 [
this, change](pos_t pos) {
179 for (
auto& e : count_[pos]) {
186 template <
class UnaryOp,
187 std::enable_if_t<std::is_invocable_v<UnaryOp, count_t>,
bool> =
true>
188 Node updateCount(Node node, UnaryOp unary_op,
bool propagate =
true)
190 return derived().apply(
192 [
this, unary_op](Index node) {
193 count_[node.pos][node.offset] = unary_op(count_[node.pos][node.offset]);
195 [
this, unary_op](pos_t pos) {
196 for (
auto& e : count_[pos]) {
203 template <
class BinaryOp,
204 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, count_t>,
bool> =
true>
205 Node updateCount(Node node, BinaryOp binary_op,
bool propagate =
true)
207 return derived().apply(
209 [
this, binary_op](Index node) {
210 count_[node.pos][node.offset] = binary_op(node, count_[node.pos][node.offset]);
212 [
this, binary_op](pos_t pos) {
214 for (
auto& e : count_[pos]) {
215 e = binary_op(Index(pos, i++), e);
221 Node updateCount(Code code,
int change,
bool propagate =
true)
223 return derived().apply(
224 code, [
this, change](Index node) { count_[node.pos][node.offset] += change; },
225 [
this, change](pos_t pos) {
226 for (
auto& e : count_[pos]) {
233 template <
class UnaryOp,
234 std::enable_if_t<std::is_invocable_v<UnaryOp, count_t>,
bool> =
true>
235 Node updateCount(Code code, UnaryOp unary_op,
bool propagate =
true)
237 return derived().apply(
239 [
this, unary_op](Index node) {
240 count_[node.pos][node.offset] = unary_op(count_[node.pos][node.offset]);
242 [
this, unary_op](pos_t pos) {
243 for (
auto& e : count_[pos]) {
250 template <
class BinaryOp,
251 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, count_t>,
bool> =
true>
252 Node updateCount(Code code, BinaryOp binary_op,
bool propagate =
true)
254 return derived().apply(
256 [
this, binary_op](Index node) {
257 count_[node.pos][node.offset] = binary_op(node, count_[node.pos][node.offset]);
259 [
this, binary_op](pos_t pos) {
261 for (
auto& e : count_[pos]) {
262 e = binary_op(Index(pos, i++), e);
268 Node updateCount(Key key,
int change,
bool propagate =
true)
270 return updateCount(derived().toCode(key), change, propagate);
273 template <
class UnaryOp,
274 std::enable_if_t<std::is_invocable_v<UnaryOp, count_t>,
bool> =
true>
275 Node updateCount(Key key, UnaryOp unary_op,
bool propagate =
true)
277 return updateCount(derived().toCode(key), unary_op, propagate);
280 template <
class BinaryOp,
281 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, count_t>,
bool> =
true>
282 Node updateCount(Key key, BinaryOp binary_op,
bool propagate =
true)
284 return updateCount(derived().toCode(key), binary_op, propagate);
287 Node updateCount(Coord coord,
int change,
bool propagate =
true, depth_t depth = 0)
289 return updateCount(derived().toCode(coord, depth), change, propagate);
292 template <
class UnaryOp,
293 std::enable_if_t<std::is_invocable_v<UnaryOp, count_t>,
bool> =
true>
294 Node updateCount(Coord coord, UnaryOp unary_op,
bool propagate =
true,
297 return updateCount(derived().toCode(coord, depth), unary_op, propagate);
300 template <
class BinaryOp,
301 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, count_t>,
bool> =
true>
302 Node updateCount(Coord coord, BinaryOp binary_op,
bool propagate =
true,
305 return updateCount(derived().toCode(coord, depth), binary_op, propagate);
312 [[nodiscard]]
constexpr PropagationCriteria countPropagationCriteria()
const noexcept
314 return prop_criteria_;
317 void setCountPropagationCriteria(PropagationCriteria prop_criteria,
318 bool propagate =
true)
320 if (prop_criteria_ == prop_criteria) {
324 prop_criteria_ = prop_criteria;
326 derived().setModified();
329 derived().propagateModified();
338 CountMap() { count_.emplace_back(); }
344 template <
class Derived2>
346 : count_(other.count_), prop_criteria_(other.prop_criteria_)
350 template <
class Derived2>
352 : count_(std::move(other.count_)), prop_criteria_(std::move(other.prop_criteria_))
370 template <
class Derived2>
374 prop_criteria_ = rhs.prop_criteria_;
378 template <
class Derived2>
381 count_ = std::move(rhs.count_);
382 prop_criteria_ = std::move(rhs.prop_criteria_);
392 std::swap(count_, other.count_);
393 std::swap(prop_criteria_, other.prop_criteria_);
400 [[nodiscard]]
constexpr Derived& derived() {
return *
static_cast<Derived*
>(
this); }
402 [[nodiscard]]
constexpr Derived
const& derived()
const
404 return *
static_cast<Derived const*
>(
this);
411 void createBlock(Index node)
413 count_.emplace_back();
414 count_.back().fill(count_[node.pos][node.offset]);
421 void resize(std::size_t count)
424 count_.resize(count);
431 void reserveImpl(std::size_t new_cap) { count_.reserve(new_cap); }
439 auto node = derived().rootIndex();
440 count_[node.pos][node.offset] = 0;
447 void fill(Index node, pos_t children)
449 count_[children].fill(count_[node.pos][node.offset]);
456 void clearImpl() { count_.resize(1); }
458 void clearImpl(pos_t) {}
464 void updateBlock(pos_t block, std::array<bool, N> modified_parent)
466 for (offset_t i{}; N != i; ++i) {
467 if (modified_parent[i]) {
468 Index node(block, i);
469 updateNode(node, derived().children(node));
474 void updateNode(Index node, pos_t children)
476 switch (countPropagationCriteria()) {
477 case PropagationCriteria::MIN:
478 count_[node.pos][node.offset] = min(children);
480 case PropagationCriteria::MAX:
481 count_[node.pos][node.offset] = max(children);
483 case PropagationCriteria::MEAN:
484 count_[node.pos][node.offset] = mean(children);
486 case PropagationCriteria::NONE:
return;
490 [[nodiscard]]
constexpr count_t min(pos_t block)
const
492 count_t ret = count_[block][0];
493 for (
auto e : count_[block]) {
494 ret = std::min(ret, e);
499 [[nodiscard]]
constexpr count_t max(pos_t block)
const
501 count_t ret = count_[block][0];
502 for (
auto e : count_[block]) {
503 ret = std::max(ret, e);
508 [[nodiscard]]
constexpr count_t mean(pos_t block)
const
511 if constexpr (std::is_unsigned_v<count_t>) {
512 return std::accumulate(std::cbegin(count_[block]), std::cend(count_[block]),
516 return std::accumulate(std::cbegin(count_[block]), std::cend(count_[block]), 0.0) /
525 [[nodiscard]]
bool isPrunable(pos_t block)
const
527 return std::all_of(std::cbegin(count_[block]) + 1, std::cend(count_[block]),
528 [
a = count_[block].front()](
auto b) {
return a ==
b; });
535 [[nodiscard]]
static constexpr std::size_t sizeofNodeTimesN(Index)
noexcept
537 return sizeofBlockLowerBound();
540 [[nodiscard]]
static constexpr std::size_t sizeofBlock(pos_t)
noexcept
542 return sizeofBlockLowerBound();
545 [[nodiscard]]
static constexpr std::size_t sizeofBlockLowerBound()
noexcept
547 return sizeof(
typename decltype(count_)::value_type);
550 [[nodiscard]]
static constexpr std::size_t sizeofMap()
noexcept
552 return sizeof(count_) +
sizeof(prop_criteria_);
559 [[nodiscard]]
static constexpr MapType mapType()
noexcept {
return MapType::COUNT; }
561 [[nodiscard]]
static constexpr std::size_t serializedSizeBlock()
noexcept
563 return sizeof(
typename decltype(count_)::value_type);
566 template <
class Container>
567 std::size_t serializedSize(Container
const& c)
const
569 return c.size() * serializedSizeBlock();
572 template <
class Container>
573 void readNodes(
ReadBuffer& in, Container
const& c)
575 for (
auto const [pos, offsets] : c) {
577 in.read(count_[pos].data(), serializedSizeBlock());
580 in.read(count.data(), serializedSizeBlock());
581 for (offset_t i{}; N != i; ++i) {
582 count_[pos][i] = offsets[i] ? count[i] : count_[pos][i];
588 template <
class BlockRange>
589 void writeBlocks(
WriteBuffer& out, BlockRange
const& blocks)
const
591 for (
auto block : blocks) {
592 out.write(count_[block].data(), serializedSizeBlock());
598 Container<CountBlock> count_;
601 PropagationCriteria prop_criteria_ = PropagationCriteria::MAX;
603 template <
class Derived2, offset_t N2,
class Index2,
class Node2,
class Code2,