61 using TimeBlock = DataBlock<time_t, N>;
67 [[nodiscard]] TimeBlock& timeBlock(pos_t block) {
return time_[block]; }
69 [[nodiscard]] TimeBlock
const& timeBlock(pos_t block)
const {
return time_[block]; }
75 [[nodiscard]] time_t time(Index node)
const {
return time_[node.pos][node.offset]; }
77 [[nodiscard]] time_t time(Node node)
const {
return time(derived().
index(node)); }
79 [[nodiscard]] time_t time(Code code)
const {
return time(derived().
index(code)); }
81 [[nodiscard]] time_t time(Key key)
const {
return time(derived().
index(key)); }
83 [[nodiscard]] time_t time(Coord coord, depth_t depth = 0)
const
85 return time(derived().
index(coord, depth));
92 void setTime(Index node, time_t value)
95 node, [
this, value](Index node) { time_[node.pos][node.offset] = value; },
96 [
this, value](pos_t pos) { time_[pos].fill(value); });
99 Node setTime(Node node, time_t value,
bool propagate =
true)
101 return derived().apply(
102 node, [
this, value](Index node) { time_[node.pos][node.offset] = value; },
103 [
this, value](pos_t pos) { time_[pos].fill(value); }, propagate);
106 Node setTime(Code code, time_t value,
bool propagate =
true)
108 return derived().apply(
109 code, [
this, value](Index node) { time_[node.pos][node.offset] = value; },
110 [
this, value](pos_t pos) { time_[pos].fill(value); }, propagate);
113 Node setTime(Key key, time_t value,
bool propagate =
true)
115 return setTime(derived().toCode(key), value, propagate);
118 Node setTime(Coord coord, time_t value,
bool propagate =
true, depth_t depth = 0)
120 return setTime(derived().toCode(coord, depth), value, propagate);
127 template <
class UnaryOp,
128 std::enable_if_t<std::is_invocable_v<UnaryOp, time_t>,
bool> =
true>
129 void updateTime(Index node, UnaryOp unary_op)
133 [
this, unary_op](Index node) {
134 time_[node.pos][node.offset] = unary_op(time_[node.pos][node.offset]);
136 [
this, unary_op](pos_t pos) {
137 for (
auto& e : time_[pos]) {
143 template <
class BinaryOp,
144 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, time_t>,
bool> =
true>
145 void updateTime(Index node, BinaryOp binary_op)
149 [
this, binary_op](Index node) {
150 time_[node.pos][node.offset] = binary_op(node, time_[node.pos][node.offset]);
152 [
this, binary_op](pos_t pos) {
154 for (
auto& e : time_[pos]) {
155 e = binary_op(Index(pos, i++), e);
160 template <
class UnaryOp,
161 std::enable_if_t<std::is_invocable_v<UnaryOp, time_t>,
bool> =
true>
162 Node updateTime(Node node, UnaryOp unary_op,
bool propagate =
true)
164 return derived().apply(
166 [
this, unary_op](Index node) {
167 time_[node.pos][node.offset] = unary_op(time_[node.pos][node.offset]);
169 [
this, unary_op](pos_t pos) {
170 for (
auto& e : time_[pos]) {
177 template <
class BinaryOp,
178 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, time_t>,
bool> =
true>
179 Node updateTime(Node node, BinaryOp binary_op,
bool propagate =
true)
181 return derived().apply(
183 [
this, binary_op](Index node) {
184 time_[node.pos][node.offset] = binary_op(node, time_[node.pos][node.offset]);
186 [
this, binary_op](pos_t pos) {
188 for (
auto& e : time_[pos]) {
189 e = binary_op(Index(pos, i++), e);
195 template <
class UnaryOp,
196 std::enable_if_t<std::is_invocable_v<UnaryOp, time_t>,
bool> =
true>
197 Node updateTime(Code code, UnaryOp unary_op,
bool propagate =
true)
199 return derived().apply(
201 [
this, unary_op](Index node) {
202 time_[node.pos][node.offset] = unary_op(time_[node.pos][node.offset]);
204 [
this, unary_op](pos_t pos) {
205 for (
auto& e : time_[pos]) {
212 template <
class BinaryOp,
213 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, time_t>,
bool> =
true>
214 Node updateTime(Code code, BinaryOp binary_op,
bool propagate =
true)
216 return derived().apply(
218 [
this, binary_op](Index node) {
219 time_[node.pos][node.offset] = binary_op(node, time_[node.pos][node.offset]);
221 [
this, binary_op](pos_t pos) {
223 for (
auto& e : time_[pos]) {
224 e = binary_op(Index(pos, i++), e);
230 template <
class UnaryOp,
231 std::enable_if_t<std::is_invocable_v<UnaryOp, time_t>,
bool> =
true>
232 Node updateTime(Key key, UnaryOp unary_op,
bool propagate =
true)
234 return updateTime(derived().toCode(key), unary_op, propagate);
237 template <
class BinaryOp,
238 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, time_t>,
bool> =
true>
239 Node updateTime(Key key, BinaryOp binary_op,
bool propagate =
true)
241 return updateTime(derived().toCode(key), binary_op, propagate);
244 template <
class UnaryOp,
245 std::enable_if_t<std::is_invocable_v<UnaryOp, time_t>,
bool> =
true>
246 Node updateTime(Coord coord, UnaryOp unary_op,
bool propagate =
true, depth_t depth = 0)
248 return updateTime(derived().toCode(coord, depth), unary_op, propagate);
251 template <
class BinaryOp,
252 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, time_t>,
bool> =
true>
253 Node updateTime(Coord coord, BinaryOp binary_op,
bool propagate =
true,
256 return updateTime(derived().toCode(coord, depth), binary_op, propagate);
263 [[nodiscard]]
constexpr PropagationCriteria timePropagationCriteria()
const noexcept
265 return prop_criteria_;
268 void setTimePropagationCriteria(PropagationCriteria prop_criteria,
269 bool propagate =
true)
noexcept
271 if (prop_criteria_ == prop_criteria) {
275 prop_criteria_ = prop_criteria;
277 derived().setModified();
280 derived().propagateModified();
289 TimeMap() { time_.emplace_back(); }
295 template <
class Derived2>
297 : time_(other.time_), prop_criteria_(other.prop_criteria_)
301 template <
class Derived2>
303 : time_(std::move(other.time_)), prop_criteria_(std::move(other.prop_criteria_))
321 template <
class Derived2>
325 prop_criteria_ = rhs.prop_criteria_;
329 template <
class Derived2>
332 time_ = std::move(rhs.time_);
333 prop_criteria_ = std::move(rhs.prop_criteria_);
341 void swap(
TimeMap& other)
noexcept
343 std::swap(time_, other.time_);
344 std::swap(prop_criteria_, other.prop_criteria_);
351 [[nodiscard]]
constexpr Derived& derived() {
return *
static_cast<Derived*
>(
this); }
353 [[nodiscard]]
constexpr Derived
const& derived()
const
355 return *
static_cast<Derived const*
>(
this);
364 auto node = derived().rootIndex();
365 time_[node.pos][node.offset] = 0;
372 void createBlock(Index node)
374 time_.emplace_back();
375 time_.back().fill(time_[node.pos][node.offset]);
382 void fill(Index node, pos_t children)
384 time_[children].fill(time_[node.pos][node.offset]);
391 void resize(std::size_t count)
401 void reserveImpl(std::size_t new_cap) { time_.reserve(new_cap); }
407 void clearImpl() { time_.resize(1); }
409 void clearImpl(pos_t) {}
415 void updateBlock(pos_t block, std::array<bool, N> modified_parent)
417 for (offset_t i{}; N != i; ++i) {
418 if (modified_parent[i]) {
419 Index node(block, i);
420 updateNode(node, derived().children(node));
425 constexpr inline void updateNode(Index node, pos_t children)
427 switch (timePropagationCriteria()) {
428 case PropagationCriteria::MIN: time_[node.pos][node.offset] = min(children);
return;
429 case PropagationCriteria::MAX: time_[node.pos][node.offset] = max(children);
return;
430 case PropagationCriteria::MEAN:
431 time_[node.pos][node.offset] = mean(children);
433 case PropagationCriteria::NONE:
return;
437 [[nodiscard]]
constexpr inline time_t min(pos_t block)
const
439 time_t ret = time_[block][0];
440 for (time_t e : time_[block]) {
441 ret = std::min(ret, e);
446 [[nodiscard]]
constexpr inline time_t max(pos_t block)
const
448 time_t ret = time_[block][0];
449 for (time_t e : time_[block]) {
450 ret = std::max(ret, e);
455 [[nodiscard]]
constexpr inline time_t mean(pos_t block)
const
457 return static_cast<time_t
>(
458 std::accumulate(std::cbegin(time_[block]), std::cend(time_[block]), 0.0) / N);
465 [[nodiscard]]
bool isPrunable(pos_t block)
const
467 return std::all_of(std::cbegin(time_[block]) + 1, std::cend(time_[block]),
468 [
a = time_[block].front()](
auto b) {
return a ==
b; });
471 void preparePrune(Index node) {}
477 [[nodiscard]]
static constexpr std::size_t sizeofNodeTimesN(Index)
noexcept
479 return sizeofBlockLowerBound();
482 [[nodiscard]]
static constexpr std::size_t sizeofBlock(pos_t)
noexcept
484 return sizeofBlockLowerBound();
487 [[nodiscard]]
static constexpr std::size_t sizeofBlockLowerBound()
noexcept
489 return sizeof(
typename decltype(time_)::value_type);
492 [[nodiscard]]
static constexpr std::size_t sizeofMap()
noexcept
494 return sizeof(time_) +
sizeof(prop_criteria_);
501 [[nodiscard]]
static constexpr MapType mapType()
noexcept {
return MapType::TIME; }
503 [[nodiscard]]
static constexpr std::size_t serializedSizeBlock()
noexcept
505 return sizeof(
typename decltype(time_)::value_type);
508 template <
class Container>
509 constexpr std::size_t serializedSize(Container
const& c)
const
511 return c.size() * serializedSizeBlock();
514 template <
class Container>
515 void readNodes(
ReadBuffer& in, Container
const& c)
517 for (
auto const [pos, offsets] : c) {
519 in.read(time_[pos].data(), serializedSizeBlock());
522 in.read(time.data(), serializedSizeBlock());
523 for (offset_t i{}; N != i; ++i) {
524 time_[pos][i] = offsets[i] ? time[i] : time_[pos][i];
530 template <
class BlockRange>
531 void writeBlocks(
WriteBuffer& out, BlockRange
const& blocks)
const
533 for (
auto block : blocks) {
534 out.write(time_[block].data(), serializedSizeBlock());
540 Container<TimeBlock> time_;
543 PropagationCriteria prop_criteria_ = PropagationCriteria::MAX;
545 template <
class Derived2, offset_t N2,
class Index2,
class Node2,
class Code2,