97 :
public Tree<Map<Dim, Maps...>, Dim, typename Maps::Block...>
99 Map<Dim, Maps...>, Tree<Map<Dim, Maps...>, Dim, typename Maps::Block...>>>...
101 using Base =
Tree<
Map<Dim, Maps...>, Dim,
typename Maps::Block...>;
103 using MapBases =
decltype(std::tuple_cat(
104 std::declval<as_tuple_t<
typename Maps::template
Map<Map, Base>>>()...));
106 using MapBasesISeq = std::make_index_sequence<std::tuple_size_v<MapBases>>;
111 static constexpr inline bool const is_node_type_v = Base::template is_node_type_v<T>;
119#define UFO_MAP_FRIEND(F) \
120 friend std::tuple_element_t<std::min(static_cast<std::size_t>(F + 1), \
121 MapBasesISeq::size()), \
122 decltype(std::tuple_cat(std::declval<std::tuple<void>>(), \
123 std::declval<MapBases>()))>;
124 UFO_REPEAT_128(UFO_MAP_FRIEND, 0)
141 using coord_type =
typename Base::coord_type;
142 using depth_type =
typename Base::depth_type;
143 using pos_type =
typename Base::pos_type;
144 using offset_type =
typename Base::offset_type;
145 using length_type =
typename Base::length_type;
153 Map(Length leaf_node_length = Length(0.1),
155 :
Base(leaf_node_length, num_depth_levels)
160 Map(length_type leaf_node_length,
162 :
Map(Length(leaf_node_length), num_depth_levels)
166 Map(std::filesystem::path
const& file) :
Map() { read(file); }
168 Map(std::istream& in) :
Map() { read(in); }
172 Map(
Map const&) =
default;
176 template <
class... Maps2>
195 Map& operator=(
Map const&) =
default;
197 Map& operator=(
Map&&) =
default;
199 template <
class... Maps2>
212 [[nodiscard]]
static constexpr MapType mapTypes()
noexcept
214 return mapTypes(MapBasesISeq{});
217 [[nodiscard]]
static constexpr std::size_t numMapTypes()
noexcept
219 return MapBasesISeq::size();
222 [[nodiscard]]
static constexpr bool hasMapTypes(MapType map_types)
noexcept
224 return (mapTypes() & map_types) == map_types;
241 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
242 void propagate(NodeType
const&
node, MapType map_types = MapType::ALL)
251 auto const&
b = Base::treeInnerBlockConst(n.pos);
252 auto const c = Base::children(
b, n.offset);
259 onPropagateChildren(n, c, map_types);
261 if (onIsPrunable(c)) {
262 Base::pruneChildren(n, c);
267 class ExecutionPolicy,
268 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
269 void propagate(ExecutionPolicy&& policy, MapType map_types = MapType::ALL)
275 class ExecutionPolicy,
class NodeType,
276 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
277 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true>
279 MapType map_types = MapType::ALL)
288 auto const&
b = Base::treeInnerBlockConst(n.pos);
289 auto const c = Base::children(
b, n.offset);
295 propagate(std::forward<ExecutionPolicy>(policy), c, map_types,
false);
296 onPropagateChildren(n, c, map_types);
298 if (onIsPrunable(c)) {
299 Base::pruneChildren(n, c);
309 [[nodiscard]] MapHeader header(MapType map_types = MapType::ALL)
const
314 [[nodiscard]]
static bool isMap(std::filesystem::path
const& file)
316 return MapHeader::isMap(file);
319 [[nodiscard]]
static bool isMap(std::istream& in) {
return MapHeader::isMap(in); }
321 [[nodiscard]]
static bool isMap(ReadBuffer& in) {
return MapHeader::isMap(in); }
323 void read(std::filesystem::path
const& file, MapType map_types = MapType::ALL,
326 std::ifstream f = MapHeader::openRead(file);
330 void read(std::istream& in, MapType map_types = MapType::ALL,
bool propagate =
true)
332 readData(in, readHeader(in), map_types,
propagate);
335 void read(ReadBuffer& in, MapType map_types = MapType::ALL,
bool propagate =
true)
337 readData(in, readHeader(in), map_types,
propagate);
341 class ExecutionPolicy,
342 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
343 void read(ExecutionPolicy&& policy, std::filesystem::path
const& file,
344 MapType map_types = MapType::ALL,
bool propagate =
true)
346 std::ifstream f = MapHeader::openRead(file);
347 read(std::forward<ExecutionPolicy>(policy), f, map_types,
propagate);
351 class ExecutionPolicy,
352 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
353 void read(ExecutionPolicy&& policy, std::istream& in, MapType map_types = MapType::ALL,
356 readData(std::forward<ExecutionPolicy>(policy), in, readHeader(in), map_types,
361 class ExecutionPolicy,
362 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
363 void read(ExecutionPolicy&& policy, ReadBuffer& in, MapType map_types = MapType::ALL,
366 readData(std::forward<ExecutionPolicy>(policy), in, readHeader(in), map_types,
370 [[nodiscard]] MapHeader readHeader(std::filesystem::path
const& file)
const
372 return MapHeader{file};
375 [[nodiscard]] MapHeader readHeader(std::istream& in)
const {
return MapHeader{in}; }
377 [[nodiscard]] MapHeader readHeader(ReadBuffer& in)
const {
return MapHeader{in}; }
379 void readData(std::istream& in, MapHeader
const& header,
380 MapType map_types = MapType::ALL,
bool propagate =
true)
382 readData(execution::seq, in, header, map_types,
propagate);
385 void readData(ReadBuffer& in, MapHeader
const& header, MapType map_types = MapType::ALL,
388 readData(execution::seq, in, header, map_types,
propagate);
392 class ExecutionPolicy,
393 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
394 void readData(ExecutionPolicy&& policy, std::istream& in, MapHeader
const& header,
395 MapType map_types = MapType::ALL,
bool propagate =
true)
397 readDataImpl(std::forward<ExecutionPolicy>(policy), in, header, map_types,
propagate);
401 class ExecutionPolicy,
402 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
403 void readData(ExecutionPolicy&& policy, ReadBuffer& in, MapHeader
const& header,
404 MapType map_types = MapType::ALL,
bool propagate =
true)
406 readDataImpl(std::forward<ExecutionPolicy>(policy), in, header, map_types,
propagate);
409 template <
class Predicate = pred::Leaf,
410 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
411 void write(std::filesystem::path
const& file, Predicate
const& pred = pred::Leaf{},
412 MapType map_types = MapType::ALL)
const
414 write(execution::seq, file, pred, map_types);
417 template <
class Predicate = pred::Leaf,
418 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
419 void write(std::ostream& out, Predicate
const& pred = pred::Leaf{},
420 MapType map_types = MapType::ALL)
const
422 write(execution::seq, out, pred, map_types);
425 template <
class Predicate = pred::Leaf,
426 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
427 void write(WriteBuffer& out, Predicate
const& pred = pred::Leaf{},
428 MapType map_types = MapType::ALL)
const
430 write(execution::seq, out, pred, map_types);
433 template <
class Predicate = pred::Leaf,
434 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
435 [[nodiscard]] Buffer write(Predicate
const& pred = pred::Leaf{},
436 MapType map_types = MapType::ALL)
const
438 return write(execution::seq, pred, map_types);
442 class ExecutionPolicy,
class Predicate = pred::Leaf,
443 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
444 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
445 void write(ExecutionPolicy&& policy, std::filesystem::path
const& file,
446 Predicate
const& pred = pred::Leaf{}, MapType map_types = MapType::ALL)
const
448 std::ofstream f = MapHeader::openWrite(file);
449 return write(std::forward<ExecutionPolicy>(policy), f, pred, map_types);
453 class ExecutionPolicy,
class Predicate = pred::Leaf,
454 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
455 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
456 void write(ExecutionPolicy&& policy, std::ostream& out,
457 Predicate
const& pred = pred::Leaf{}, MapType map_types = MapType::ALL)
const
459 writeImpl(std::forward<ExecutionPolicy>(policy), out, pred, map_types,
true);
463 class ExecutionPolicy,
class Predicate = pred::Leaf,
464 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
465 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
466 void write(ExecutionPolicy&& policy, WriteBuffer& out,
467 Predicate
const& pred = pred::Leaf{}, MapType map_types = MapType::ALL)
const
469 writeImpl(std::forward<ExecutionPolicy>(policy), out, pred, map_types,
true);
473 class ExecutionPolicy,
class Predicate = pred::Leaf,
474 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
475 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
476 [[nodiscard]] Buffer write(ExecutionPolicy&& policy,
477 Predicate
const& pred = pred::Leaf{},
478 MapType map_types = MapType::ALL)
const
481 write(std::forward<ExecutionPolicy>(policy), buffer, pred, map_types);
485 template <
class Predicate = pred::Leaf,
486 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
487 [[nodiscard]] MapHeader writeData(std::filesystem::path
const& file,
488 Predicate
const& pred = pred::Leaf{},
489 MapType map_types = MapType::ALL)
const
491 return writeData(execution::seq, file, pred, map_types);
494 template <
class Predicate = pred::Leaf,
495 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
496 [[nodiscard]] MapHeader writeData(std::ostream& out,
497 Predicate
const& pred = pred::Leaf{},
498 MapType map_types = MapType::ALL)
const
500 return writeData(execution::seq, out, pred, map_types);
503 template <
class Predicate = pred::Leaf,
504 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
505 [[nodiscard]] MapHeader writeData(WriteBuffer& out,
506 Predicate
const& pred = pred::Leaf{},
507 MapType map_types = MapType::ALL)
const
509 return writeData(execution::seq, out, pred, map_types);
513 class ExecutionPolicy,
class Predicate = pred::Leaf,
514 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
515 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
516 [[nodiscard]] MapHeader writeData(ExecutionPolicy&& policy,
517 std::filesystem::path
const& file,
518 Predicate
const& pred = pred::Leaf{},
519 MapType map_types = MapType::ALL)
const
521 std::ofstream f = MapHeader::openWrite(file);
522 return writeData(std::forward<ExecutionPolicy>(policy), f, pred, map_types);
526 class ExecutionPolicy,
class Predicate = pred::Leaf,
527 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
528 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
529 [[nodiscard]] MapHeader writeData(ExecutionPolicy&& policy, std::ostream& out,
530 Predicate
const& pred = pred::Leaf{},
531 MapType map_types = MapType::ALL)
const
533 return writeImpl(std::forward<ExecutionPolicy>(policy), out, pred, map_types,
false);
537 class ExecutionPolicy,
class Predicate = pred::Leaf,
538 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
539 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
540 [[nodiscard]] MapHeader writeData(ExecutionPolicy&& policy, WriteBuffer& out,
541 Predicate
const& pred = pred::Leaf{},
542 MapType map_types = MapType::ALL)
const
544 return writeImpl(std::forward<ExecutionPolicy>(policy), out, pred, map_types,
false);
553 template <
class Predicate = pred::True,
554 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
555 void saveDotFile(std::filesystem::path
const& file,
556 Predicate
const& pred = pred::True{},
557 MapType map_types = MapType::ALL)
const
559 saveDotFile(
Base::node(), file, pred, map_types);
562 template <
class Predicate = pred::True,
563 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
564 void saveDotFile(std::ostream& out, Predicate
const& pred = pred::True{},
565 MapType map_types = MapType::ALL)
const
567 saveDotFile(
Base::node(), out, pred, map_types);
570 template <
class NodeType,
class Predicate = pred::True,
571 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
572 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
573 void saveDotFile(NodeType
node, std::filesystem::path
const& file,
574 Predicate
const& pred = pred::True{},
575 MapType map_types = MapType::ALL)
const
577 std::ofstream f = MapHeader::openWrite(file);
578 saveDotFile(
node, f, pred, map_types);
581 template <
class NodeType,
class Predicate = pred::True,
582 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
583 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
584 void saveDotFile(NodeType
node, std::ostream& out, Predicate
const& pred = pred::True{},
585 MapType map_types = MapType::ALL)
const
587 using Filter = pred::Filter<Predicate>;
591 std::string
const parent_shape =
"shape=polygon,sides=" + std::to_string(BF) +
' ';
593 out << std::boolalpha <<
"graph UFOMap {\n";
594 out <<
"fontname=\"Helvetica,Arial,sans-serif\"\n";
595 out <<
"node [fontname=\"Helvetica,Arial,sans-serif\" shape=ellipse color=lightblue2 "
597 out <<
"edge [fontname=\"Helvetica,Arial,sans-serif\"]\n";
599 Filter::init(pred, *
this);
600 bool valid_return = Base::exists(n) && Filter::returnable(pred, *
this, n);
601 bool valid_inner =
Base::isParent(n) && Filter::traversable(pred, *
this, n);
603 if (!valid_return && !valid_inner) {
609 std::to_string(
node.index.pos) +
'.' + std::to_string(
node.index.offset) +
'.' +
610 std::to_string(
node.code.depth()) +
'.' + std::to_string(
node.code.offset());
620 onDotFile(out, n.index, map_types);
627 out <<
" color=darkorange1";
632 saveDotFileRecurs(out, n,
id, pred, map_types, parent_shape);
646 gpuRelease(MapBasesISeq{});
650 [[nodiscard]] std::size_t gpuNumBuffers(MapType map_type)
const
652 return MapType::TREE == map_type ? Base::template gpuNumBuffers<TreeBlock>()
653 : gpuNumBuffers(map_type, MapBasesISeq{});
656 [[nodiscard]] std::size_t gpuNumLeafBuffers(MapType map_type)
const
658 return MapType::TREE == map_type ? Base::template gpuNumLeafBuffers<TreeBlock>()
659 : gpuNumLeafBuffers(map_type, MapBasesISeq{});
662 [[nodiscard]] std::size_t gpuNumInnerBuffers(MapType map_type)
const
664 return MapType::TREE == map_type ? Base::template gpuNumInnerBuffers<TreeBlock>()
665 : gpuNumInnerBuffers(map_type, MapBasesISeq{});
668 [[nodiscard]] WGPUBuffer gpuLeafBuffer(MapType map_type, std::size_t
index = 0)
const
670 return MapType::TREE == map_type ? Base::template gpuLeafBuffer<TreeBlock>(
index)
671 : gpuLeafBuffer(map_type,
index, MapBasesISeq{});
674 [[nodiscard]] WGPUBuffer gpuInnerBuffer(MapType map_type, std::size_t
index = 0)
const
676 return MapType::TREE == map_type ? Base::template gpuInnerBuffer<TreeBlock>(
index)
677 : gpuInnerBuffer(map_type,
index, MapBasesISeq{});
680 [[nodiscard]] std::size_t gpuLeafBufferSize(MapType map_type,
681 std::size_t
index = 0)
const
683 return MapType::TREE == map_type ? Base::template gpuLeafBufferSize<TreeBlock>(
index)
684 : gpuLeafBufferSize(map_type,
index, MapBasesISeq{});
687 [[nodiscard]] std::size_t gpuInnerBufferSize(MapType map_type,
688 std::size_t
index = 0)
const
690 return MapType::TREE == map_type
691 ? Base::template gpuInnerBufferSize<TreeBlock>(
index)
692 : gpuInnerBufferSize(map_type,
index, MapBasesISeq{});
695 void gpuRead(MapType map_types = MapType::ALL)
697 Base::template gpuRead<TreeBlock>();
698 gpuRead(map_types, MapBasesISeq{});
701 void gpuReadLeaf(MapType map_types = MapType::ALL)
703 Base::template gpuReadLeaf<TreeBlock>();
704 gpuReadLeaf(map_types, MapBasesISeq{});
707 void gpuReadInner(MapType map_types = MapType::ALL)
709 Base::template gpuReadInner<TreeBlock>();
710 gpuReadInner(map_types, MapBasesISeq{});
713 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
714 void gpuRead(Predicate
const& pred)
716 gpuRead(pred::predicate_map_type_v<Predicate>);
719 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
720 void gpuReadLeaf(Predicate
const& pred)
722 gpuReadLeaf(pred::predicate_map_type_v<Predicate>);
725 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
726 void gpuReadInner(Predicate
const& pred)
728 gpuReadInner(pred::predicate_map_type_v<Predicate>);
731 bool gpuWrite(MapType map_types = MapType::ALL)
733 bool updated = Base::template gpuWrite<TreeBlock>();
734 return gpuWrite(map_types, MapBasesISeq{}) || updated;
737 bool gpuWriteLeaf(MapType map_types = MapType::ALL)
739 bool updated = Base::template gpuWriteLeaf<TreeBlock>();
740 return gpuWriteLeaf(map_types, MapBasesISeq{}) || updated;
743 bool gpuWriteInner(MapType map_types = MapType::ALL)
745 bool updated = Base::template gpuWriteInner<TreeBlock>();
746 return gpuWriteInner(map_types, MapBasesISeq{}) || updated;
749 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
750 bool gpuWrite(Predicate
const& pred)
752 return gpuWrite(pred::predicate_map_type_v<Predicate>);
755 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
756 bool gpuWriteLeaf(Predicate
const& pred)
758 return gpuWriteLeaf(pred::predicate_map_type_v<Predicate>);
761 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
762 bool gpuWriteInner(Predicate
const& pred)
764 return gpuWriteInner(pred::predicate_map_type_v<Predicate>);
774 void onInitRoot() { onInitRoot(
Base::block(), MapBasesISeq{}); }
776 template <std::size_t... Is>
777 void onInitRoot(pos_type
block, std::index_sequence<Is...>)
779 return (onInitRoot<std::tuple_element_t<Is, MapBases>>(
block), ...);
783 void onInitRoot(pos_type
block)
785 Map::onInitRoot(
block);
788 void onInitLeafChildren(Index
node, pos_type children)
790 onInitLeafChildren(
node, children, MapBasesISeq{});
793 template <std::size_t... Is>
794 void onInitLeafChildren(Index
node, pos_type children, std::index_sequence<Is...>)
796 return (onInitLeafChildren<std::tuple_element_t<Is, MapBases>>(
node, children), ...);
800 void onInitLeafChildren(Index
node, pos_type children)
802 Map::onInitLeafChildren(
node, children);
805 void onInitInnerChildren(Index
node, pos_type children)
807 onInitInnerChildren(
node, children, MapBasesISeq{});
810 template <std::size_t... Is>
811 void onInitInnerChildren(Index
node, pos_type children, std::index_sequence<Is...>)
813 return (onInitInnerChildren<std::tuple_element_t<Is, MapBases>>(
node, children), ...);
817 void onInitInnerChildren(Index
node, pos_type children)
819 Map::onInitInnerChildren(
node, children);
822 void onPropagateChildren(Index
node, pos_type children, MapType map_types)
824 onPropagateChildren(
node, children, map_types, MapBasesISeq{});
827 template <std::size_t... Is>
828 void onPropagateChildren(Index
node, pos_type children, MapType map_types,
829 std::index_sequence<Is...>)
831 return (onPropagateChildren<std::tuple_element_t<Is, MapBases>>(
node, children,
837 void onPropagateChildren(Index
node, pos_type children, MapType map_types)
839 if (!isMapType<Map>(map_types)) {
843 Map::onPropagateChildren(
node, children);
846 [[nodiscard]]
bool onIsPrunable(pos_type
block)
const
851 template <std::size_t... Is>
852 [[nodiscard]]
bool onIsPrunable(pos_type
block, std::index_sequence<Is...>)
const
854 return (onIsPrunable<std::tuple_element_t<Is, MapBases>>(
block) && ...);
858 [[nodiscard]]
bool onIsPrunable(pos_type
block)
const
860 return Map::onIsPrunable(
block);
863 void onPruneLeafChildren(Index
node, pos_type children)
865 onPruneLeafChildren(
node, children, MapBasesISeq{});
868 template <std::size_t... Is>
869 void onPruneLeafChildren(Index
node, pos_type children, std::index_sequence<Is...>)
871 (onPruneLeafChildren<std::tuple_element_t<Is, MapBases>>(
node, children), ...);
875 void onPruneLeafChildren(Index
node, pos_type children)
877 Map::onPruneLeafChildren(
node, children);
880 void onPruneInnerChildren(Index
node, pos_type children)
882 onPruneInnerChildren(
node, children, MapBasesISeq{});
885 template <std::size_t... Is>
886 void onPruneInnerChildren(Index
node, pos_type children, std::index_sequence<Is...>)
888 (onPruneInnerChildren<std::tuple_element_t<Is, MapBases>>(
node, children), ...);
892 void onPruneInnerChildren(Index
node, pos_type children)
894 Map::onPruneInnerChildren(
node, children);
897 [[nodiscard]] std::size_t onSerializedSize(SerializedBlocks<BF>
const& blocks,
898 std::size_t num_nodes,
899 MapType map_types)
const
901 return onSerializedSize(blocks, num_nodes, map_types, MapBasesISeq{});
904 template <std::size_t... Is>
905 [[nodiscard]] std::size_t onSerializedSize(SerializedBlocks<BF>
const& blocks,
906 std::size_t num_nodes, MapType map_types,
907 std::index_sequence<Is...>)
const
909 return (onSerializedSize<std::tuple_element_t<Is, MapBases>>(blocks, num_nodes,
915 [[nodiscard]] std::size_t onSerializedSize(SerializedBlocks<BF>
const& blocks,
916 std::size_t num_nodes,
917 MapType map_types)
const
919 return isMapType<Map>(map_types) ? Map::onSerializedSize(blocks, num_nodes) : 0;
923 class ExecutionPolicy,
924 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
925 void onRead(ExecutionPolicy&& policy, ReadBuffer& in,
926 SerializedBlocks<BF>
const& blocks, MapType map_type,
927 std::uint64_t data_size)
929 onRead(std::forward<ExecutionPolicy>(policy), in, blocks, map_type, data_size,
934 class ExecutionPolicy, std::size_t... Is,
935 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
936 void onRead(ExecutionPolicy&& policy, ReadBuffer& in,
937 SerializedBlocks<BF>
const& blocks, MapType map_type,
938 std::uint64_t data_size, std::index_sequence<Is...>)
940 (onRead<std::tuple_element_t<Is, MapBases>>(policy, in, blocks, map_type,
946 class Map,
class ExecutionPolicy,
947 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
948 bool onRead(ExecutionPolicy&& policy, ReadBuffer& in,
949 SerializedBlocks<BF>
const& blocks, MapType map_type,
950 std::uint64_t data_size)
952 if (!isMapType<Map>(map_type)) {
956 Map::onRead(std::forward<ExecutionPolicy>(policy), in, blocks);
961 class ExecutionPolicy,
962 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
963 void onWrite(ExecutionPolicy&& policy, WriteBuffer& out,
964 SerializedBlocks<BF>
const& blocks, MapType map_type)
const
966 onWrite(std::forward<ExecutionPolicy>(policy), out, blocks, map_type, MapBasesISeq{});
970 class ExecutionPolicy, std::size_t... Is,
971 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
972 void onWrite(ExecutionPolicy&& policy, WriteBuffer& out,
973 SerializedBlocks<BF>
const& blocks, MapType map_type,
974 std::index_sequence<Is...>)
const
976 (onWrite<std::tuple_element_t<Is, MapBases>>(policy, out, blocks, map_type), ...);
980 class Map,
class ExecutionPolicy,
981 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
982 void onWrite(ExecutionPolicy&& policy, WriteBuffer& out,
983 SerializedBlocks<BF>
const& blocks, MapType map_type)
const
985 if (!isMapType<Map>(map_type)) {
989 Map::onWrite(std::forward<ExecutionPolicy>(policy), out, blocks);
992 void onDotFile(std::ostream& out, Index
node, MapType map_types)
const
997 out <<
"Modified: <font color='green'><b>true</b></font>";
999 out <<
"Modified: <font color='red'>false</font>";
1002 onDotFile(out,
node, map_types, MapBasesISeq{});
1005 template <std::size_t... Is>
1006 void onDotFile(std::ostream& out, Index
node, MapType map_types)
const
1008 (onDotFile<std::tuple_element_t<Is, MapBases>>(out,
node, map_types), ...);
1011 template <
class Map>
1012 void onDotFile(std::ostream& out, Index
node, MapType map_types)
const
1014 if (MapType::NONE == (mapType<Map>() & map_types)) {
1018 Map::onDotFile((out <<
"<br/>"),
node);
1027 template <std::size_t... Is>
1028 [[nodiscard]]
static constexpr MapType mapTypes(std::index_sequence<Is...>)
noexcept
1030 return (mapType<std::tuple_element_t<Is, MapBases>>() | ...);
1033 template <
class Map>
1034 [[nodiscard]]
static constexpr MapType mapType() noexcept
1039 template <
class Map>
1040 [[nodiscard]]
static constexpr bool isMapType(MapType map_type)
noexcept
1042 return mapType<Map>() == (mapType<Map>() & map_type);
1058 auto const&
b = Base::treeInnerBlockConst(
block);
1060 if (Base::modifiedNone(
b)) {
1064 for (offset_type i{}; BF > i; ++i) {
1066 auto c = Base::children(
b, i);
1073 onPropagateChildren(n, c, map_types);
1075 if (onIsPrunable(c)) {
1076 Base::pruneChildren(n, c);
1082 class ExecutionPolicy,
1083 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
1084 void propagate(ExecutionPolicy&& policy, pos_type
block, MapType map_types,
1092 auto const&
b = Base::treeInnerBlockConst(
block);
1094 if (Base::modifiedNone(
b)) {
1099 if (BF - 2u <= Base::modifiedCount(
b) && 2u < d) {
1101 [
this, policy,
block, map_types, is_parallel, &
b](offset_type i) {
1103 auto c = Base::children(
b, i);
1114 onPropagateChildren(n, c, map_types);
1116 if (onIsPrunable(c)) {
1117 Base::pruneChildren(n, c);
1121 for (offset_type i{}; BF > i; ++i) {
1123 auto c = Base::children(
b, i);
1129 propagate(policy, c, map_types, is_parallel);
1130 onPropagateChildren(n, c, map_types);
1132 if (onIsPrunable(c)) {
1133 Base::pruneChildren(n, c);
1145 template <
class ExecutionPolicy,
class Input>
1146 void readDataImpl(ExecutionPolicy&& policy, Input& in, MapHeader
const& header,
1149 if (Dim != header.leaf_node_length.size()) {
1150 throw std::runtime_error(
"Trying to read map with dimension " +
1151 std::to_string(header.leaf_node_length.size()) +
1152 " into a map with dimension " + std::to_string(Dim));
1155 Length leaf_node_length;
1156 for (std::size_t i{}; Dim > i; ++i) {
1157 leaf_node_length[i] = header.leaf_node_length[i];
1162 Base::clear(leaf_node_length, header.num_depth_levels);
1165 readMaps(policy, in, readBlocks(in, header), header, map_types);
1172 template <
class Input>
1173 [[nodiscard]] SerializedBlocks<BF> readBlocks(Input& in, MapHeader
const& header)
1175 std::vector<BitSet<BF>> tree(header.map_info[0].size);
1177 if (0 < header.map_info[0].size) {
1178 std::size_t
size = header.map_info[0].size *
sizeof(BitSet<BF>);
1179 if constexpr (std::is_base_of_v<std::istream, remove_cvref_t<Input>>) {
1180 in.read(
reinterpret_cast<char*
>(tree.data()),
size);
1181 }
else if constexpr (std::is_base_of_v<ReadBuffer, remove_cvref_t<Input>>) {
1182 in.read(tree.data(),
size);
1184 static_assert(dependent_false_v<Input>,
"Wrong input type");
1188 SerializedBlocks<BF> blocks;
1190 if (0 < header.num_blocks) {
1191 blocks.reserve(header.num_blocks);
1192 readBlocksRecurs(
Base::block(), tree.begin(), blocks);
1194 for (std::size_t i = 1; blocks.size() > i; ++i) {
1195 blocks[i].data_start = blocks[i - 1].data_start + blocks[i - 1].offsets.count();
1202 typename std::vector<BitSet<BF>>::const_iterator readBlocksRecurs(
1203 pos_type
block,
typename std::vector<BitSet<BF>>::const_iterator tree,
1204 SerializedBlocks<BF>& blocks)
1206 BitSet<BF>
const valid_return = *tree++;
1207 BitSet<BF>
const valid_inner = *tree++;
1208 BitSet<BF>
const valid_erase_children = valid_return & ~valid_inner;
1212 if (valid_return.any()) {
1213 blocks.emplace_back(0u,
block, valid_return);
1216 if (valid_inner.none() && valid_erase_children.none()) {
1220 for (offset_type i{}; BF > i; ++i) {
1221 if (valid_erase_children[i]) {
1222 Base::eraseChildren(Index(
block, i));
1226 for (offset_type i{}; BF > i; ++i) {
1227 if (valid_inner[i]) {
1228 tree = readBlocksRecurs(Base::createChildren(Index(
block, i)), tree, blocks);
1235 template <
class ExecutionPolicy>
1236 void readMaps(ExecutionPolicy&& policy, std::istream& in,
1237 SerializedBlocks<BF>
const& blocks, MapHeader
const& header,
1241 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1242 auto map_type = header.map_info[i].type;
1243 auto data_size = header.map_info[i].size;
1245 if (hasMapTypes(map_types & map_type)) {
1247 buffer.write(in, data_size);
1248 onRead(policy, buffer, blocks, map_type, data_size);
1251 in.seekg(
static_cast<std::istream::off_type
>(data_size), std::istream::cur);
1256 template <
class ExecutionPolicy>
1257 void readMaps(ExecutionPolicy&& policy, ReadBuffer& in,
1258 SerializedBlocks<BF>
const& blocks, MapHeader
const& header,
1261 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1262 auto map_type = header.map_info[i].type;
1263 auto data_size = header.map_info[i].size;
1264 auto pos = in.readPos();
1266 if (hasMapTypes(map_types & map_type)) {
1267 onRead(policy, in, blocks, map_type, data_size);
1271 in.readSeek(pos + data_size);
1298 template <
class ExecutionPolicy,
class Output,
class Predicate>
1299 MapHeader writeImpl(ExecutionPolicy&& policy,
Output& out, Predicate
const& pred,
1300 MapType map_types,
bool write_header)
const
1302 auto [tree, blocks] = writeBlocks(pred);
1304 for (std::size_t i = 1; blocks.size() > i; ++i) {
1305 blocks[i].data_start = blocks[i - 1].data_start + blocks[i - 1].offsets.count();
1308 MapHeader h = header(map_types);
1309 h.num_blocks = blocks.size();
1310 h.num_nodes = blocks.back().data_start + blocks.back().offsets.count();
1311 h.map_info[0].size = tree.size();
1312 for (std::size_t i = 1; h.map_info.size() > i; ++i) {
1313 h.map_info[i].size = onSerializedSize(blocks, h.num_nodes, h.map_info[i].type);
1320 if (!tree.empty()) {
1321 std::size_t
size = tree.size() *
sizeof(BitSet<BF>);
1322 if constexpr (std::is_base_of_v<std::ostream, remove_cvref_t<Output>>) {
1323 out.write(
reinterpret_cast<char*
>(tree.data()),
size);
1324 }
else if constexpr (std::is_base_of_v<WriteBuffer, remove_cvref_t<Output>>) {
1325 out.write(tree.data(),
size);
1327 static_assert(dependent_false_v<Output>,
"Wrong output type");
1331 if (!blocks.empty()) {
1332 writeMaps(std::forward<ExecutionPolicy>(policy), out, blocks, h);
1338 template <
class Predicate>
1339 [[nodiscard]] std::pair<std::vector<BitSet<BF>>, SerializedBlocks<BF>> writeBlocks(
1340 Predicate pred)
const
1342 using P = remove_cvref_t<Predicate>;
1343 using Filter = pred::Filter<P>;
1344 using L = pred::Leaf;
1345 using M = pred::Modified<false>;
1346 using P1 =
decltype(std::declval<L>() && std::declval<M>());
1347 using P2 =
decltype(std::declval<M>() && std::declval<L>());
1349 std::pair<std::vector<BitSet<BF>>, SerializedBlocks<BF>> res;
1351 auto& tree = res.first;
1352 auto& blocks = res.second;
1354 if constexpr (contains_type_v<P, P1, P2>) {
1360 bool valid_return = leaf &&
modified;
1361 bool valid_inner = !leaf &&
modified;
1363 tree.emplace_back(valid_return ? 1u : 0u);
1364 tree.emplace_back(valid_inner ? 1u : 0u);
1367 blocks.emplace_back(0u, root.pos, BitSet<BF>(1u));
1368 }
else if (valid_inner) {
1369 writeBlocksModifiedRecurs(Base::children(root), tree, blocks);
1372 Filter::init(pred, *
this);
1376 bool valid_return = Filter::returnable(pred, *
this, root);
1378 Base::isParent(root.index) && Filter::traversable(pred, *
this, root);
1380 tree.emplace_back(valid_return ? 1u : 0u);
1381 tree.emplace_back(valid_inner ? 1u : 0u);
1384 blocks.emplace_back(0u, root.index.pos, BitSet<BF>(1u));
1387 writeBlocksRecurs(root, pred, tree, blocks);
1391 if (blocks.empty()) {
1398 template <
class Predicate>
1399 bool writeBlocksRecurs(Node parent, Predicate
const& pred,
1400 std::vector<BitSet<BF>>& tree,
1401 SerializedBlocks<BF>& blocks)
const
1403 using P = remove_cvref_t<Predicate>;
1404 using Filter = pred::Filter<P>;
1406 auto const&
block = Base::TreeInnerBlock(parent.index.pos);
1407 auto const c = Base::children(
block, parent.index.offset);
1411 for (offset_type i{}; BF > i; ++i) {
1413 vr[i] = Filter::returnable(pred, *
this,
node);
1421 blocks.emplace_back(0u, c, vr);
1427 std::array<Node, BF>
node;
1428 for (offset_type i{}; BF > i; ++i) {
1430 node[i].index = Index(c, i);
1431 vr[i] = Filter::returnable(pred, *
this,
node[i]);
1435 if (vr.none() && vi.none()) {
1439 std::size_t
const tree_size_before = tree.size();
1440 tree.emplace_back(vr);
1441 BitSet<BF>& valid_inner = tree.emplace_back(vi);
1444 blocks.emplace_back(0u,
block, vr);
1451 for (offset_type i{}; BF > i; ++i) {
1452 vi[i] = vi[i] && writeNodesRecurs(
node[i], pred, tree, blocks);
1457 if (vr.any() || vi.any()) {
1461 tree.resize(tree_size_before);
1465 bool writeBlocksModifiedRecurs(pos_type
block, std::vector<BitSet<BF>>& tree,
1466 SerializedBlocks<BF>& blocks)
const
1475 blocks.emplace_back(0u,
block, m);
1479 auto const&
b = Base::treeInnerBlock(
block);
1481 auto const& c = Base::children(
b);
1484 for (offset_type i{}; BF > i; ++i) {
1488 BitSet<BF>
const vr = leaf & m;
1489 BitSet<BF> vi = ~leaf & m;
1491 if (vr.none() && vi.none()) {
1495 std::size_t
const tree_size_before = tree.size();
1496 tree.emplace_back(vr);
1497 BitSet<BF>& valid_inner = tree.emplace_back(vi);
1500 blocks.emplace_back(0u,
block, vr);
1507 for (offset_type i{}; BF > i; ++i) {
1508 vi[i] = vi[i] && writeBlocksModifiedRecurs(c[i], tree, blocks);
1513 if (vr.any() || vi.any()) {
1517 tree.resize(tree_size_before);
1521 template <
class ExecutionPolicy>
1522 void writeMaps(ExecutionPolicy&& policy, std::ostream& out,
1523 SerializedBlocks<BF>
const& blocks, MapHeader
const& header)
const
1525 if (blocks.empty()) {
1529 std::uint64_t max_size{};
1530 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1531 max_size = std::max(max_size, header.map_info[i].size);
1535 buffer.reserve(max_size);
1537 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1539 onWrite(policy, buffer, blocks, header.map_info[i].type);
1540 if (!buffer.empty()) {
1541 buffer.read(out, buffer.size());
1547 template <
class ExecutionPolicy>
1548 void writeMaps(ExecutionPolicy&& policy, WriteBuffer& out,
1549 SerializedBlocks<BF>
const& blocks, MapHeader
const& header)
const
1551 if (blocks.empty()) {
1555 std::size_t total_size{};
1556 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1557 total_size += header.map_info[i].size;
1560 out.reserve(out.size() + total_size);
1562 for (std::size_t i = 1; header.map_info.size() > i; ++i) {
1563 onWrite(policy, out, blocks, header.map_info[i].type);
1574 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
1575 void saveDotFileRecurs(std::ostream& out, Node
node, std::string
const&
id,
1576 Predicate
const& pred, MapType map_types,
1577 std::string
const& parent_shape)
const
1579 using Filter = pred::Filter<Predicate>;
1581 for (std::size_t i{}; BF > i; ++i) {
1583 bool valid_return = Filter::returnable(pred, *
this,
child);
1586 if (!valid_return && !valid_inner) {
1590 std::string child_id = std::to_string(
child.index.pos) +
'.' +
1591 std::to_string(
child.index.offset) +
'.' +
1592 std::to_string(
child.code.depth()) +
'.' +
1593 std::to_string(
child.code.offset());
1594 out << child_id <<
" [";
1597 out << parent_shape;
1604 onDotFile(out,
child.index, map_types);
1611 out <<
" color=darkorange1";
1614 out <<
id <<
" -- " << child_id <<
'\n';
1617 saveDotFileRecurs(out,
child, child_id, pred, map_types, parent_shape);
1628 template <std::size_t... Is>
1629 void gpuRelease(std::index_sequence<Is...>)
1631 (gpuRelease<std::tuple_element_t<Is, MapBases>>(), ...);
1634 template <
class Map>
1637 Map::onGpuRelease();
1640 template <std::size_t... Is>
1641 [[nodiscard]] std::size_t gpuNumBuffers(MapType map_type,
1642 std::index_sequence<Is...>)
const
1644 return std::max({gpuNumBuffers<std::tuple_element_t<Is, MapBases>>(map_type)...});
1647 template <
class Map>
1648 [[nodiscard]] std::size_t gpuNumBuffers(MapType map_type)
const
1650 return isMapType<Map>(map_type) ? Base::template gpuNumBuffers<typename Map::Block>()
1654 template <std::size_t... Is>
1655 [[nodiscard]] std::size_t gpuNumLeafBuffers(MapType map_type,
1656 std::index_sequence<Is...>)
const
1658 return std::max({gpuNumLeafBuffers<std::tuple_element_t<Is, MapBases>>(map_type)...});
1661 template <
class Map>
1662 [[nodiscard]] std::size_t gpuNumLeafBuffers(MapType map_type)
const
1664 return isMapType<Map>(map_type)
1665 ? Base::template gpuNumLeafBuffers<typename Map::Block>()
1669 template <std::size_t... Is>
1670 [[nodiscard]] std::size_t gpuNumInnerBuffers(MapType map_type,
1671 std::index_sequence<Is...>)
const
1674 {gpuNumInnerBuffers<std::tuple_element_t<Is, MapBases>>(map_type)...});
1677 template <
class Map>
1678 [[nodiscard]] std::size_t gpuNumInnerBuffers(MapType map_type)
const
1680 return isMapType<Map>(map_type)
1681 ? Base::template gpuNumInnerBuffers<typename Map::Block>()
1685 template <std::size_t... Is>
1686 [[nodiscard]] WGPUBuffer gpuLeafBuffer(MapType map_type, std::size_t
index,
1687 std::index_sequence<Is...>)
const
1690 {gpuLeafBuffer<std::tuple_element_t<Is, MapBases>>(map_type,
index)...});
1693 template <
class Map>
1694 [[nodiscard]] WGPUBuffer gpuLeafBuffer(MapType map_type, std::size_t
index)
const
1696 return isMapType<Map>(map_type)
1697 ? Base::template gpuLeafBuffer<typename Map::Block>(
index)
1701 template <std::size_t... Is>
1702 [[nodiscard]] WGPUBuffer gpuInnerBuffer(MapType map_type, std::size_t
index,
1703 std::index_sequence<Is...>)
const
1706 {gpuInnerBuffer<std::tuple_element_t<Is, MapBases>>(map_type,
index)...});
1709 template <
class Map>
1710 [[nodiscard]] WGPUBuffer gpuInnerBuffer(MapType map_type, std::size_t
index)
const
1712 return isMapType<Map>(map_type)
1713 ? Base::template gpuInnerBuffer<typename Map::Block>(
index)
1717 template <std::size_t... Is>
1718 [[nodiscard]] std::size_t gpuLeafBufferSize(MapType map_type, std::size_t
index,
1719 std::index_sequence<Is...>)
const
1722 {gpuLeafBufferSize<std::tuple_element_t<Is, MapBases>>(map_type,
index)...});
1725 template <
class Map>
1726 [[nodiscard]] std::size_t gpuLeafBufferSize(MapType map_type, std::size_t
index)
const
1728 return isMapType<Map>(map_type)
1729 ? Base::template gpuLeafBufferSize<typename Map::Block>(
index)
1733 template <std::size_t... Is>
1734 [[nodiscard]] std::size_t gpuInnerBufferSize(MapType map_type, std::size_t
index,
1735 std::index_sequence<Is...>)
const
1738 {gpuInnerBufferSize<std::tuple_element_t<Is, MapBases>>(map_type,
index)...});
1741 template <
class Map>
1742 [[nodiscard]] std::size_t gpuInnerBufferSize(MapType map_type, std::size_t
index)
const
1744 return isMapType<Map>(map_type)
1745 ? Base::template gpuInnerBufferSize<typename Map::Block>(
index)
1749 template <std::size_t... Is>
1750 void gpuRead(MapType map_types, std::index_sequence<Is...>)
1752 (gpuRead<std::tuple_element_t<Is, MapBases>>(map_types), ...);
1755 template <
class Map>
1756 void gpuRead(MapType map_types)
1758 if (!isMapType<Map>(map_types)) {
1763 Base::template gpuRead<typename Map::Block>();
1766 template <std::size_t... Is>
1767 void gpuReadLeaf(MapType map_types, std::index_sequence<Is...>)
1769 (gpuReadLeaf<std::tuple_element_t<Is, MapBases>>(map_types), ...);
1772 template <
class Map>
1773 void gpuReadLeaf(MapType map_types)
1775 if (!isMapType<Map>(map_types)) {
1779 Map::onGpuReadLeaf();
1780 Base::template gpuReadLeaf<typename Map::Block>();
1783 template <std::size_t... Is>
1784 void gpuReadInner(MapType map_types, std::index_sequence<Is...>)
1786 (gpuReadLeaf<std::tuple_element_t<Is, MapBases>>(map_types), ...);
1789 template <
class Map>
1790 void gpuReadInner(MapType map_types)
1792 if (!isMapType<Map>(map_types)) {
1796 Map::onGpuReadInner();
1797 Base::template gpuReadInner<typename Map::Block>();
1800 template <std::size_t... Is>
1801 bool gpuWrite(MapType map_types, std::index_sequence<Is...>)
1803 return (gpuWrite<std::tuple_element_t<Is, MapBases>>(map_types) | ...);
1806 template <
class Map>
1807 bool gpuWrite(MapType map_types)
1809 if (!isMapType<Map>(map_types)) {
1814 return Base::template gpuWrite<typename Map::Block>();
1817 template <std::size_t... Is>
1818 bool gpuWriteLeaf(MapType map_types, std::index_sequence<Is...>)
1820 return (gpuWriteLeaf<std::tuple_element_t<Is, MapBases>>(map_types) | ...);
1823 template <
class Map>
1824 bool gpuWriteLeaf(MapType map_types)
1826 if (!isMapType<Map>(map_types)) {
1830 Map::onGpuWriteLeaf();
1831 return Base::template gpuWriteLeaf<typename Map::Block>();
1834 template <std::size_t... Is>
1835 bool gpuWriteInner(MapType map_types, std::index_sequence<Is...>)
1837 return (gpuWriteLeaf<std::tuple_element_t<Is, MapBases>>(map_types) | ...);
1840 template <
class Map>
1841 bool gpuWriteInner(MapType map_types)
1843 if (!isMapType<Map>(map_types)) {
1847 Map::onGpuWriteInner();
1848 return Base::template gpuWriteInner<typename Map::Block>();