114 static constexpr TreeIndex::offset_type
const BF = Data::BF;
119 using modified_type =
typename LeafBlock::modified_type;
121 static constexpr modified_type
const MODIFIED_ALL_SET =
122 static_cast<modified_type
>(~(~0u << BF));
123 static constexpr modified_type
const MODIFIED_NONE_SET = {};
130 using coord_type = float;
131 using length_type = double;
132 using depth_type = std::uint32_t;
145 using pos_type =
typename Index::pos_type;
146 using offset_type =
typename Index::offset_type;
147 using code_type =
typename Code::code_type;
148 using key_type =
typename Key::key_type;
154 template <
class Predicate>
158 template <
class Geometry>
162 template <
class Predicate,
class Geometry>
167 template <
class Predicate>
171 template <
class Geometry>
175 template <
class Predicate,
class Geometry>
176 using ConstQueryNearest =
177 IteratorWrapper<const_query_nearest_iterator_pred_geom<Predicate, Geometry>,
183 contains_convertible_type<remove_cvref_t<T>, Index, Node, Code, Key, Coord>,
184 std::is_constructible<remove_cvref_t<T>, Coord>> {
211 [[nodiscard]]
static constexpr std::size_t
dimensions() noexcept {
return Dim; }
218 [[nodiscard]] std::size_t
size()
const
221 return Data::size() * BF - (BF - 1);
229 void reserve(std::size_t num_nodes) { Data::reserve((num_nodes + BF - 1) / BF); }
241 void clear(Length
const& leaf_node_length, depth_type num_depth_levels)
243 init(leaf_node_length, num_depth_levels);
247 void clear(length_type
const& leaf_node_length, depth_type num_depth_levels)
249 clear(Length(leaf_node_length), num_depth_levels);
263 return num_depth_levels_;
280 return Code::maxDepth() + 1;
313 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
314 [[nodiscard]]
constexpr depth_type
depth(NodeType
node)
const
316 using T = remove_cvref_t<NodeType>;
317 if constexpr (std::is_same_v<T, Index>) {
319 }
else if constexpr (std::is_same_v<T, Node>) {
321 }
else if constexpr (std::is_same_v<T, Code>) {
323 }
else if constexpr (std::is_same_v<T, Key>) {
325 }
else if constexpr (std::is_same_v<T, Coord>) {
356 return node_half_length_[
depth + 1];
365 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
395 return node_half_length_[
depth];
407 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
439 return node_half_length_reciprocal_[
depth + 1];
451 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
486 return node_half_length_reciprocal_[
depth];
499 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
522 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
538 for (std::size_t i{}; p.
size() > i; ++i) {
539 p[i] = std::nextafter(p[i], c[i]);
550 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
556 for (std::size_t i{}; p.
size() > i; ++i) {
557 p[i] = std::nextafter(p[i], c[i]);
574 for (std::size_t i{};
max.
size() > i; ++i) {
575 max[i] = std::nextafter(
max[i], c[i]);
586 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
594 for (std::size_t i{};
max.
size() > i; ++i) {
595 max[i] = std::nextafter(
max[i], c[i]);
614 for (std::size_t i{}; coord.
size() > i; ++i) {
615 if (-hl[i] > coord[i] || hl[i] <= coord[i]) {
645 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
648 using T = remove_cvref_t<NodeType>;
649 if constexpr (std::is_same_v<T, Key>) {
654 if (
depth() == node_depth) {
661 std::int_fast64_t hmv =
662 static_cast<std::int_fast64_t
>(half_max_value_ >> node_depth);
665 cast<coord_type>((cast<length_type>(cast<std::int_fast64_t>(
node) - hmv) +
666 static_cast<length_type
>(0.5)) *
669 return Coord(coord, node_depth);
681 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
710 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
726 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
728 std::size_t
axis)
const
743 [[nodiscard]]
constexpr pos_type
block() const noexcept
745 return Data::addInnerType(0);
755 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
770 [[nodiscard]]
constexpr offset_type
offset() const noexcept {
return 0; }
779 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
782 using T = remove_cvref_t<NodeType>;
783 if constexpr (std::is_same_v<T, Index>) {
785 }
else if constexpr (std::is_same_v<T, Node>) {
787 }
else if constexpr (contains_type_v<T, Code, Key>) {
788 return node.offset();
808 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
809 [[nodiscard]]
constexpr Index
index(NodeType
node)
const
813 using T = remove_cvref_t<NodeType>;
814 if constexpr (std::is_same_v<T, Index>) {
816 }
else if constexpr (std::is_same_v<T, Code>) {
818 depth_type
const min_depth =
depth(
node);
819 for (depth_type d =
depth(); min_depth < d; --d) {
827 }
else if constexpr (contains_type_v<T, Node, Key, Coord>) {
851 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
854 using T = remove_cvref_t<NodeType>;
855 if constexpr (std::is_same_v<T, Index>) {
857 }
else if constexpr (std::is_same_v<T, Node>) {
859 }
else if constexpr (std::is_same_v<T, Code>) {
861 }
else if constexpr (contains_type_v<T, Key, Coord>) {
881 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
884 return this->
node(node);
891 [[nodiscard]] Code code()
const {
return Code(std::array<code_type, 3>{},
depth()); }
893 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
894 [[nodiscard]] Code code(NodeType
node)
const
896 using T = remove_cvref_t<NodeType>;
897 if constexpr (std::is_same_v<T, Index>) {
905 ret.setOffset(d,
node.offset);
910 }
else if constexpr (std::is_same_v<T, Node>) {
912 }
else if constexpr (std::is_same_v<T, Code>) {
914 }
else if constexpr (std::is_same_v<T, Key>) {
916 }
else if constexpr (std::is_same_v<T, Coord>) {
917 return code(key(
node));
919 return code(convert(
node));
923 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
924 [[nodiscard]] std::optional<Code> codeChecked(NodeType
node)
const
933 [[nodiscard]] Key key()
const {
return Key(Vec<Dim, key_type>(0),
depth()); }
935 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
936 [[nodiscard]] Key key(NodeType
node)
const
938 using T = remove_cvref_t<NodeType>;
939 if constexpr (std::is_same_v<T, Code>) {
941 }
else if constexpr (std::is_same_v<T, Key>) {
943 }
else if constexpr (std::is_same_v<T, Coord>) {
952 auto k = cast<key_type>(
953 cast<std::make_signed_t<key_type>>(
floor(cast<length_type>(p) * lr))) +
956 return Key(k >> d, d);
957 }
else if constexpr (contains_type_v<T, Index, Node>) {
958 return key(code(
node));
960 return key(convert(
node));
964 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
965 [[nodiscard]] std::optional<Key> keyChecked(NodeType
node)
const
989 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
996 void modifiedSet(
bool value) {
return value ? modifiedSet() : modifiedReset(); }
998 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
999 void modifiedSet(NodeType
node,
bool value)
1001 return value ? modifiedSet(
node) : modifiedReset(
node);
1004 void modifiedSet() { modifiedSet(
index()); }
1006 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1007 void modifiedSet(NodeType
node)
1010 auto n = create(
node);
1011 modifiedSet(n.pos, n.offset);
1013 modifiedSetChildren(n);
1017 void modifiedReset() { modifiedReset(
index()); }
1019 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1020 void modifiedReset(NodeType
node)
1022 if (!exists(
node)) {
1027 modifiedReset(n.pos, n.offset);
1029 modifiedResetChildren(n);
1041 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1042 Index create(NodeType
node)
1046 using T = remove_cvref_t<NodeType>;
1047 if constexpr (std::is_same_v<T, Index>) {
1048 modifiedSetParents(
node);
1051 Code code = this->code(
node);
1052 auto wanted_depth =
depth(code);
1053 auto cur_node =
index();
1054 auto cur_depth =
depth();
1055 while (wanted_depth < cur_depth) {
1056 cur_node = createChild(cur_node, code.offset(--cur_depth));
1062 template <
class InputIt,
class OutputIt>
1063 OutputIt create(InputIt first, InputIt last, OutputIt d_first)
1065 using T = remove_cvref_t<typename std::iterator_traits<InputIt>::value_type>;
1067 if constexpr (std::is_same_v<T, Index>) {
1068 return std::transform(first, last, d_first,
1069 [
this](Index
node) {
return create(
node); });
1072 Code node_code = this->code();
1074 return std::transform(first, last, d_first,
1075 [
this, &
node, &node_code](
auto const& x) {
1076 Code d_code = code(x);
1077 depth_type d = Code::depthWhereEqual(node_code, d_code);
1081 for (depth_type d_depth =
depth(d_code); d_depth < d; --d) {
1082 node = createChild(
node, d_code.offset(d - 1));
1090 template <
class InputIt>
1091 std::vector<Index> create(InputIt first, InputIt last)
1093 std::vector<Index> nodes;
1094 create(first, last, std::back_inserter(nodes));
1099 class Range,
class OutputIt,
1100 std::enable_if_t<!is_node_type_v<Range> && !execution::is_execution_policy_v<Range>,
1102 OutputIt create(Range
const& r, OutputIt d_first)
1106 return create(begin(r), end(r), d_first);
1109 template <
class Range, std::enable_if_t<!is_node_type_v<Range>,
bool> = true>
1110 std::vector<Index> create(Range
const& r)
1112 std::vector<Index> nodes;
1113 create(r, std::back_inserter(nodes));
1120 class ExecutionPolicy,
class RandomIt1,
class RandomIt2,
1121 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
1122 RandomIt2 create(ExecutionPolicy&& policy, RandomIt1 first, RandomIt1 last,
1125 using T = remove_cvref_t<typename std::iterator_traits<RandomIt1>::value_type>;
1127 if constexpr (std::is_same_v<T, Index>) {
1128 return ufo::transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
1129 [
this](Index
node) {
1130 modifiedSetParentsThreadSafe(
node);
1140 static std::size_t create_call_num{};
1143 return transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
1144 [
this, ccn = create_call_num](
auto const& x) {
1146 thread_local Code node_code = code();
1148 thread_local std::size_t thread_create_call_num = 1;
1149 if (ccn != thread_create_call_num) {
1150 thread_create_call_num = ccn;
1155 Code d_code = code(x);
1156 depth_type d = Code::depthWhereEqual(node_code, d_code);
1160 for (depth_type d_depth =
depth(d_code); d_depth < d; --d) {
1161 node = createChildThreadSafe(
node, d_code.offset(d - 1));
1170 class ExecutionPolicy,
class RandomIt,
1171 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
1172 std::vector<Index> create(ExecutionPolicy&& policy, RandomIt first, RandomIt last)
1174 __block std::vector<Index> nodes(std::distance(first, last));
1175 create(std::forward<ExecutionPolicy>(policy), first, last, nodes.begin());
1180 class ExecutionPolicy,
class Range,
class RandomIt,
1181 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
1182 std::enable_if_t<!is_node_type_v<Range>,
bool> =
true>
1183 RandomIt create(ExecutionPolicy&& policy, Range
const& r, RandomIt d_first)
1187 return create(std::forward<ExecutionPolicy>(policy), begin(r), end(r), d_first);
1191 class ExecutionPolicy,
class Range,
1192 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true,
1193 std::enable_if_t<!is_node_type_v<Range>,
bool> =
true>
1194 std::vector<Index> create(ExecutionPolicy&& policy, Range
const& r)
1197 __block std::vector<Index> nodes(
size(r));
1198 create(std::forward<ExecutionPolicy>(policy), r, nodes.begin());
1208 void eraseChildren() { eraseChildren(
index()); }
1210 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1211 void eraseChildren(NodeType
node)
1213 using T = remove_cvref_t<NodeType>;
1214 if constexpr (std::is_same_v<T, Index>) {
1219 auto c = children(
node);
1220 for (offset_type i{}; BF > i; ++i) {
1221 eraseChildren(Index(c, i));
1224 pruneChildren(
node, c);
1225 }
else if constexpr (contains_type_v<T, Node, Code>) {
1226 if (!exists(
node)) {
1231 }
else if constexpr (contains_type_v<T, Key, Coord>) {
1232 eraseChildren(code(
node));
1234 eraseChildren(convert(
node));
1259 return Data::leaf(
block);
1270 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1273 using T = remove_cvref_t<NodeType>;
1274 if constexpr (std::is_same_v<T, Index>) {
1291 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1307 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1319 [[nodiscard]]
constexpr bool isRoot(pos_type
block)
const
1330 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1333 using T = remove_cvref_t<NodeType>;
1334 if constexpr (std::is_same_v<T, Index>) {
1336 }
else if constexpr (std::is_same_v<T, Node>) {
1337 return isRoot(
node.code);
1338 }
else if constexpr (std::is_same_v<T, Code>) {
1339 return code() ==
node;
1340 }
else if constexpr (std::is_same_v<T, Key>) {
1341 return key() ==
node;
1342 }
else if constexpr (std::is_same_v<T, Coord>) {
1343 return isRoot(key(
node));
1345 return isRoot(convert(
node));
1369 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1372 using T = remove_cvref_t<NodeType>;
1373 if constexpr (std::is_same_v<T, Index>) {
1375 }
else if constexpr (std::is_same_v<T, Node>) {
1377 }
else if constexpr (std::is_same_v<T, Code>) {
1379 }
else if constexpr (std::is_same_v<T, Key>) {
1380 auto const mv = (2 * half_max_value_) >>
depth(
node);
1381 for (std::size_t i{};
node.size() != i; ++i) {
1388 }
else if constexpr (std::is_same_v<T, Coord>) {
1401 [[nodiscard]]
bool exists(pos_type
block)
const
1412 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1415 using T = remove_cvref_t<NodeType>;
1416 if constexpr (std::is_same_v<T, Index>) {
1417 return exists(
node.pos);
1418 }
else if constexpr (contains_type_v<T, Node, Code, Key, Coord>) {
1421 return exists(convert(
node));
1431 [[nodiscard]] std::array<pos_type, BF>
const& children(pos_type
block)
const
1434 return treeInnerBlock(
block).children;
1437 [[nodiscard]] pos_type children(Index
node)
const
1439 return children(
node.pos)[
node.offset];
1449 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1455 using T = remove_cvref_t<NodeType>;
1456 if constexpr (std::is_same_v<T, Index>) {
1458 }
else if constexpr (std::is_same_v<T, Node>) {
1460 }
else if constexpr (contains_type_v<T, Code, Key>) {
1462 }
else if constexpr (std::is_same_v<T, Coord>) {
1465 auto child_depth =
node.depth - depth_type(1);
1479 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1482 using T = remove_cvref_t<NodeType>;
1483 if constexpr (std::is_same_v<T, Index>) {
1486 }
else if constexpr (contains_type_v<T, Node, Code, Key, Coord>) {
1498 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1499 [[nodiscard]]
auto sibling(NodeType
node, offset_type
offset)
const
1501 assert(!isRoot(
node));
1504 using T = remove_cvref_t<NodeType>;
1505 if constexpr (std::is_same_v<T, Index>) {
1507 }
else if constexpr (std::is_same_v<T, Node>) {
1509 }
else if constexpr (contains_type_v<T, Code, Key>) {
1511 }
else if constexpr (std::is_same_v<T, Coord>) {
1518 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1519 [[nodiscard]]
auto siblingChecked(NodeType
node, offset_type
offset)
const
1529 [[nodiscard]] Index parent(pos_type
block)
const
1531 assert(!isRoot(
block));
1533 : parent(treeInnerBlock(
block));
1536 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1537 [[nodiscard]]
auto parent(NodeType
node)
const
1539 assert(!isRoot(
node));
1541 using T = remove_cvref_t<NodeType>;
1542 if constexpr (std::is_same_v<T, Index>) {
1543 return parent(
node.pos);
1544 }
else if constexpr (std::is_same_v<T, Node>) {
1545 return Node(parent(
node.code),
node.index);
1546 }
else if constexpr (contains_type_v<T, Code, Key>) {
1547 return node.parent();
1548 }
else if constexpr (std::is_same_v<T, Coord>) {
1551 return parent(convert(
node));
1555 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1556 [[nodiscard]]
auto parentChecked(NodeType
node)
const
1558 return !isRoot(
node) ? std::optional(parent(
node)) :
std::nullopt;
1565 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1566 [[nodiscard]]
auto ancestor(NodeType
node, depth_type
depth)
const
1570 assert(this->
depth() >= depth);
1572 depth_type cur_depth = this->
depth(node);
1574 if (cur_depth >=
depth) {
1578 using T = remove_cvref_t<NodeType>;
1579 if constexpr (std::is_same_v<T, Index>) {
1580 node = 0 == cur_depth ? parent(treeLeafBlock(
node.pos))
1581 : parent(treeInnerBlock(
node.pos));
1583 for (++cur_depth; cur_depth <
depth; ++cur_depth) {
1584 node = parent(treeInnerBlock(
node.pos));
1588 }
else if constexpr (std::is_same_v<T, Node>) {
1590 }
else if constexpr (contains_type_v<T, Code, Key>) {
1592 }
else if constexpr (std::is_same_v<T, Coord>) {
1599 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1600 [[nodiscard]]
auto ancestorChecked(NodeType
node, depth_type
depth)
const
1603 this->
depth() >= depth
1615 template <
class UnaryFun,
1616 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Index>,
bool> =
true>
1630 template <
class NodeType,
class UnaryFun,
1631 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1632 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Index>,
bool> =
true>
1637 if (!exists(
node)) {
1642 pos_type
const start = cur.pos;
1645 cur =
child(cur, 0);
1648 while (start != cur.pos) {
1649 if (BF - 1 <= cur.offset) {
1650 cur = parent(cur.pos);
1654 cur =
child(cur, 0);
1669 template <
class UnaryFun,
class Predicate,
1670 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Node>,
bool> =
true,
1671 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1672 void traverse(UnaryFun f, Predicate
const& pred,
bool only_exists =
true)
const
1686 template <
class NodeType,
class UnaryFun,
class Predicate,
1687 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1688 std::enable_if_t<std::is_invocable_v<UnaryFun, Node>,
bool> =
true,
1689 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1690 void traverse(NodeType
node, UnaryFun f, Predicate pred,
bool only_exists =
true)
const
1696 Filter::init(pred,
derived());
1699 auto fun = [
this, f, &pred](
Node node) {
1706 if (!exists(
node)) {
1711 pos_type
const start = cur.index.pos;
1714 cur.code = cur.code.firstBorn();
1715 cur.index =
child(cur.index, 0);
1718 while (start != cur.index.pos) {
1719 if (BF - 1 <= cur.index.offset) {
1720 cur.code = cur.code.parent();
1721 cur.index = parent(cur.index.pos);
1723 cur.code = cur.code.nextSibling();
1726 cur.code = cur.code.firstBorn();
1727 cur.index =
child(cur.index, 0);
1732 auto fun = [
this, f, &pred](
Node node) {
1740 depth_type
const start = cur.code.depth();
1743 cur.code = cur.code.firstborn();
1744 cur.index =
isParent(cur.index) ?
child(cur.index, 0) : cur.index;
1747 while (start != cur.code.depth()) {
1748 if (BF - 1 <= cur.code.offset()) {
1749 cur.code = cur.code.parent();
1751 cur.code.depth() >
depth(cur.index) ? parent(cur.index.pos) : cur.index;
1753 cur.code = cur.code.nextSibling();
1754 cur.index.offset += cur.code.depth() ==
depth(cur.index) ? 1 : 0;
1756 cur.code = cur.code.firstborn();
1757 cur.index =
isParent(cur.index) ?
child(cur.index, 0) : cur.index;
1774 [[nodiscard]] const_iterator begin(
bool only_leaves =
true,
1775 bool only_exists =
true)
const
1777 return begin(
node(), only_leaves, only_exists);
1780 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
1781 [[nodiscard]] const_iterator begin(NodeType
node,
bool only_leaves =
true,
1782 bool only_exists =
true)
const
1784 return const_iterator(&
derived(), this->
node(node), only_leaves, only_exists);
1787 [[nodiscard]] const_iterator end()
const {
return const_iterator(); }
1793 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
1794 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
1795 Predicate
const& pred,
bool only_exists =
true,
bool early_stopping =
false)
const
1797 return beginQuery(
node(), pred, only_exists, early_stopping);
1800 template <
class NodeType,
class Predicate,
1801 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1802 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1803 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
1804 NodeType
node, Predicate
const& pred,
bool only_exists =
true,
1805 bool early_stopping =
false)
const
1807 return const_query_iterator_pred<remove_cvref_t<Predicate>>(
1808 &
derived(), this->
node(node), pred, only_exists, early_stopping);
1811 [[nodiscard]] const_query_iterator endQuery()
const {
return const_query_iterator(); }
1817 template <
class Geometry>
1818 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
1819 Geometry
const& geometry,
double epsilon = 0.0,
bool only_leaves =
true,
1820 bool only_exists =
true)
const
1822 return beginNearest(
node(), geometry, epsilon, only_leaves, only_exists);
1825 template <
class NodeType,
class Geometry,
1826 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true>
1827 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
1828 NodeType
node, Geometry
const& geometry,
double epsilon = 0.0,
1829 bool only_leaves =
true,
bool only_exists =
true)
const
1831 return const_nearest_iterator_geom<Geometry>(&
derived(), this->
node(node), geometry,
1832 epsilon, only_leaves, only_exists);
1835 [[nodiscard]] const_nearest_iterator endNearest()
const
1837 return const_nearest_iterator();
1844 template <
class Predicate,
class Geometry,
1845 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1846 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
1847 beginQueryNearest(Predicate
const& pred, Geometry
const& geometry,
double epsilon = 0.0,
1848 bool only_exists =
true,
bool early_stopping =
false)
const
1850 return beginQueryNearest(
node(), pred, geometry, epsilon, only_exists,
1854 template <
class NodeType,
class Predicate,
class Geometry,
1855 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1856 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1857 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
1858 beginQueryNearest(NodeType
node, Predicate
const& pred, Geometry
const& geometry,
1859 double epsilon = 0.0,
bool only_exists =
true,
1860 bool early_stopping =
false)
const
1862 return const_query_nearest_iterator_pred_geom<Predicate, Geometry>(
1863 &
derived(), this->
node(node), pred, geometry, epsilon, only_exists,
1867 [[nodiscard]] const_query_nearest_iterator endQueryNearest()
const
1869 return const_query_nearest_iterator();
1882 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
1883 [[nodiscard]] ConstQuery<Predicate> query(Predicate
const& pred,
1884 bool only_exists =
true,
1885 bool early_stopping =
false)
const
1887 return query(
node(), pred, only_exists, early_stopping);
1890 template <
class NodeType,
class Predicate,
1891 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1892 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1893 [[nodiscard]] ConstQuery<Predicate> query(NodeType
node, Predicate
const& pred,
1894 bool only_exists =
true,
1895 bool early_stopping =
false)
const
1897 return ConstQuery<Predicate>(beginQuery(
node, pred, only_exists, early_stopping),
1901 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
1902 [[nodiscard]] ConstQuery<Predicate> operator()(Predicate
const& pred,
1903 bool only_exists =
true,
1904 bool early_stopping =
false)
const
1906 return query(pred, only_exists, early_stopping);
1909 template <
class NodeType,
class Predicate,
1910 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1911 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1912 [[nodiscard]] ConstQuery<Predicate> operator()(NodeType
node, Predicate
const& pred,
1913 bool only_exists =
true,
1914 bool early_stopping =
false)
const
1916 return query(
node, pred, only_exists, early_stopping);
1923 template <
class Geometry>
1924 [[nodiscard]] ConstNearest<Geometry> nearest(Geometry
const& geometry,
1925 double epsilon = 0.0,
1926 bool only_leaves =
true,
1927 bool only_exists =
true)
const
1929 return nearest(
node(), geometry, epsilon, only_leaves, only_exists);
1932 template <
class NodeType,
class Geometry,
1933 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true>
1934 [[nodiscard]] ConstNearest<Geometry> nearest(NodeType
node, Geometry
const& geometry,
1935 double epsilon = 0.0,
1936 bool only_leaves =
true,
1937 bool only_exists =
true)
const
1939 return ConstNearest<Geometry>(
1940 beginNearest(
node, geometry, epsilon, only_leaves, only_exists), endNearest());
1947 template <
class Predicate,
class Geometry,
1948 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1949 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
1950 Predicate
const& pred, Geometry
const& geometry,
double epsilon = 0.0,
1951 bool only_exists =
true,
bool early_stopping =
false)
const
1953 return queryNearest(
node(), pred, geometry, epsilon, only_exists, early_stopping);
1956 template <
class NodeType,
class Predicate,
class Geometry,
1957 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1958 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1959 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
1960 NodeType
node, Predicate
const& pred, Geometry
const& geometry,
1961 double epsilon = 0.0,
bool only_exists =
true,
bool early_stopping =
false)
const
1963 return ConstQueryNearest<Predicate, Geometry>(
1964 beginQueryNearest(
node, pred, geometry, epsilon, only_exists, early_stopping),
1976 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
1977 [[nodiscard]] TraceResult trace(Ray
const& ray, Predicate
const& pred,
1978 float min_dist = 0.0f,
1979 float max_dist = std::numeric_limits<float>::max(),
1980 bool only_exists =
true)
const
1982 return trace(
node(), ray, pred, min_dist, max_dist, only_exists);
1985 template <
class NodeType,
class Predicate,
1986 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
1987 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
1988 [[nodiscard]] TraceResult trace(NodeType
node, Ray
const& ray, Predicate pred,
1989 float min_dist = 0.0f,
1990 float max_dist = std::numeric_limits<float>::max(),
1991 bool only_exists =
true)
const
1995 using Filter = pred::Filter<Predicate>;
1997 Filter::init(pred,
derived());
2001 return TraceResult{Node(), -1.0f};
2004 auto params = traceInit(n, ray);
2005 return trace(n, params, pred, min_dist, max_dist, only_exists);
2008 template <
class InputIt,
class OutputIt,
class Predicate,
2009 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
2010 OutputIt trace(InputIt first, InputIt last, OutputIt d_first, Predicate
const& pred,
2011 float min_dist = 0.0f,
2012 float max_dist = std::numeric_limits<float>::max(),
2013 bool only_exists =
true)
const
2015 return trace(
node(), first, last, d_first, pred, min_dist, max_dist, only_exists);
2018 template <
class NodeType,
class InputIt,
class OutputIt,
class Predicate,
2019 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2020 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
2021 OutputIt trace(NodeType
node, InputIt first, InputIt last, OutputIt d_first,
2022 Predicate
const& pred,
float min_dist = 0.0f,
2023 float max_dist = std::numeric_limits<float>::max(),
2024 bool only_exists =
true)
const
2029 template <
class InputIt,
class Predicate,
2030 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
2031 [[nodiscard]] std::vector<TraceResult> trace(
2032 InputIt first, InputIt last, Predicate
const& pred,
float min_dist = 0.0f,
2033 float max_dist = std::numeric_limits<float>::max(),
bool only_exists =
true)
const
2035 return trace(
node(), first, last, pred, min_dist, max_dist, only_exists);
2038 template <
class NodeType,
class InputIt,
class Predicate,
2039 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2040 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
2041 [[nodiscard]] std::vector<TraceResult> trace(
2042 NodeType
node, InputIt first, InputIt last, Predicate
const& pred,
2043 float min_dist = 0.0f,
float max_dist = std::numeric_limits<float>::max(),
2044 bool only_exists =
true)
const
2046 std::vector<TraceResult> res;
2047 trace(
node, first, last, std::back_inserter(res), pred, min_dist, max_dist,
2053 class ExecutionPolicy,
class RandomIt1,
class RandomIt2,
class Predicate,
2054 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
2055 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
2056 RandomIt2 trace(ExecutionPolicy&& policy, RandomIt1 first, RandomIt1 last,
2057 RandomIt2 d_first, Predicate
const& pred,
float min_dist = 0.0f,
2058 float max_dist = std::numeric_limits<float>::max(),
2059 bool only_exists =
true)
const
2061 return trace(std::forward<ExecutionPolicy>(policy),
index(), first, last, d_first,
2062 pred, min_dist, max_dist, only_exists);
2066 class ExecutionPolicy,
class NodeType,
class RandomIt1,
class RandomIt2,
2067 class Predicate, std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2068 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
2069 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
2070 RandomIt2 trace(ExecutionPolicy&& policy, NodeType
node, RandomIt1 first,
2071 RandomIt1 last, RandomIt2 d_first, Predicate pred,
2072 float min_dist = 0.0f,
2073 float max_dist = std::numeric_limits<float>::max(),
2074 bool only_exists =
true)
const
2078 using Filter = pred::Filter<Predicate>;
2080 Filter::init(pred,
derived());
2082 Node n = this->
node(node);
2084 for (; last != first; ++first, ++d_first) {
2085 *d_first = TraceResult{Node(), -1.0f};
2093 return transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
2094 [&](Ray
const& ray) {
2095 auto params = traceInit(ray,
center, half_length);
2096 return trace(n, params, pred, min_dist, max_dist, only_exists);
2101 class ExecutionPolicy,
class RandomIt,
class Predicate,
2102 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
2103 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
2104 [[nodiscard]] std::vector<TraceResult> trace(
2105 ExecutionPolicy&& policy, RandomIt first, RandomIt last, Predicate
const& pred,
2106 float min_dist = 0.0f,
float max_dist = std::numeric_limits<float>::max(),
2107 bool only_exists =
true)
const
2109 return trace(std::forward<ExecutionPolicy>(policy),
index(), first, last, pred,
2110 min_dist, max_dist, only_exists);
2114 class ExecutionPolicy,
class NodeType,
class RandomIt,
class Predicate,
2115 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2116 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
2117 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
2118 [[nodiscard]] std::vector<TraceResult> trace(
2119 ExecutionPolicy&& policy, NodeType
node, RandomIt first, RandomIt last,
2120 Predicate
const& pred,
float min_dist = 0.0f,
2121 float max_dist = std::numeric_limits<float>::max(),
bool only_exists =
true)
const
2123 __block std::vector<TraceResult> res(std::distance(first, last));
2124 trace(std::forward<ExecutionPolicy>(policy),
node, first, last, res.begin(), pred,
2125 min_dist, max_dist, only_exists);
2135 template <
class Derived2, std::size_t Dim2,
class... Blocks2>
2136 friend bool operator==(Tree<Derived2, Dim2, Blocks2...>
const& lhs,
2137 Tree<Derived2, Dim2, Blocks2...>
const& rhs);
2139 template <
class Derived2, std::size_t Dim2,
class... Blocks2>
2140 friend bool operator!=(Tree<Derived2, Dim2, Blocks2...>
const& lhs,
2141 Tree<Derived2, Dim2, Blocks2...>
const& rhs);
2150 Tree(Length leaf_node_length, depth_type num_depth_levels)
2152 init(leaf_node_length, num_depth_levels);
2156 Tree(length_type leaf_node_length, depth_type num_depth_levels)
2157 : Tree(Length(leaf_node_length), num_depth_levels)
2161 Tree(Tree
const&) =
default;
2163 Tree(Tree&&) =
default;
2179 Tree& operator=(Tree
const&) =
default;
2181 Tree& operator=(Tree&&) =
default;
2189 void init(Length leaf_node_length, depth_type num_depth_levels)
2193 throw std::invalid_argument(
"'num_depth_levels' has to be in range [" +
2196 std::to_string(+num_depth_levels) +
"' was supplied.");
2199 if (length_type(0) >=
ufo::min(leaf_node_length) || !
isfinite(leaf_node_length)) {
2200 std::stringstream ss;
2201 ss << leaf_node_length;
2202 throw std::invalid_argument(
2203 "'leaf_node_length' has to be finite and greater than zero, '" + ss.str() +
2206 if (!
isnormal(
ldexp(leaf_node_length, num_depth_levels - 1))) {
2207 std::stringstream ss;
2208 ss <<
ldexp(leaf_node_length, num_depth_levels - 1);
2209 throw std::invalid_argument(
2210 "'leaf_node_length * 2^(num_depth_levels - 1)' has to be finite and greater "
2212 ss.str() +
"' was supplied.");
2214 if (length_type(0) >=
ufo::min(length_type(1) /
ldexp(leaf_node_length, -1))) {
2215 std::stringstream ss;
2216 ss << (length_type(1) /
ldexp(leaf_node_length, -1));
2217 throw std::invalid_argument(
2218 "The reciprocal of half 'leaf_node_length' (i.e., 1 / (leaf_node_length / "
2219 "2)) has to be a greater than zero, '" +
2220 ss.str() +
"' was supplied.");
2223 num_depth_levels_ = num_depth_levels;
2224 half_max_value_ = key_type(1) << (num_depth_levels - 2);
2227 for (
int i{}; node_half_length_.size() > i; ++i) {
2228 node_half_length_[i] =
ldexp(leaf_node_length, i - 1);
2229 node_half_length_reciprocal_[i] = length_type(1) / node_half_length_[i];
2244 [[nodiscard]]
constexpr Derived&
derived() {
return *
static_cast<Derived*
>(
this); }
2251 [[nodiscard]]
constexpr Derived
const&
derived()
const
2253 return *
static_cast<Derived const*
>(
this);
2264 pos_type p = Data::innerCreate();
2265 InnerBlock&
block = treeInnerBlock(p);
2266 block.children.fill(Index::NULL_POS);
2267 block.parent_block = Index::NULL_POS;
2268 block.parent_offset = {};
2270 block.modified = MODIFIED_NONE_SET;
2279 [[nodiscard]] LeafBlock& treeLeafBlock(pos_type
block)
2282 return Data::template leafBlock<LeafBlock>(
block);
2285 [[nodiscard]] LeafBlock
const& treeLeafBlock(pos_type
block)
const
2288 return Data::template leafBlock<LeafBlock>(
block);
2291 [[nodiscard]] LeafBlock
const& treeLeafBlockConst(pos_type
block)
const
2294 return treeLeafBlock(
block);
2297 [[nodiscard]] InnerBlock& treeInnerBlock(pos_type
block)
2300 return Data::template innerBlock<InnerBlock>(
block);
2303 [[nodiscard]] InnerBlock
const& treeInnerBlock(pos_type
block)
const
2306 return Data::template innerBlock<InnerBlock>(
block);
2309 [[nodiscard]] InnerBlock
const& treeInnerBlockConst(pos_type
block)
const
2312 return treeInnerBlock(
block);
2321 template <
class UpdateFun,
2322 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2324 void recursUp(Index
node, UpdateFun update_f)
2326 assert(exists(
node));
2328 offset_type children =
node.pos;
2332 children =
node.pos;
2333 node = parent(treeInnerBlockConst(
node.pos));
2337 template <
class UpdateFun,
2338 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2340 void recursDown(pos_type
block, UpdateFun update_f)
2342 assert(exists(
block));
2348 InnerBlock
const&
b = treeInnerBlockConst(
block);
2349 for (offset_type i{}; BF > i; ++i) {
2350 if (pos_type c = children(
b, i);
valid(c) && update_f(Index(
block, i), c)) {
2351 recursDown(c, update_f);
2356 template <
class UpdateFun,
2357 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2359 void recursDown(Index
node, UpdateFun update_f)
2361 assert(exists(
node));
2367 if (pos_type c = children(
node);
valid(c) && update_f(
node, c)) {
2368 recursDown(c, update_f);
2373 class NodeFun,
class BlockFun,
class UpdateFun,
2374 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>,
bool> =
true,
2375 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>,
bool> =
true,
2376 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
bool> =
2378 void recursLeaves(pos_type
block, NodeFun node_f, BlockFun block_f, UpdateFun update_f)
2380 assert(exists(
block));
2383 modifiedSet(treeLeafBlock(
block));
2388 InnerBlock&
b = treeInnerBlock(
block);
2396 for (offset_type i{}; BF > i; ++i) {
2398 if (pos_type c = children(
b, i);
valid(c)) {
2399 recursLeaves(c, node_f, block_f, update_f);
2408 class NodeType,
class NodeFun,
class BlockFun,
class UpdateFun,
2409 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2410 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>,
bool> =
true,
2411 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>,
bool> =
true,
2412 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
bool> =
2414 void recursLeaves(NodeType
node, NodeFun node_f, BlockFun block_f, UpdateFun update_f,
2417 Index n = createThreadSafe(
node);
2420 modifiedSet(treeLeafBlock(n.pos), n.offset);
2423 InnerBlock&
block = treeInnerBlock(n.pos);
2424 modifiedSet(
block, n.offset);
2426 if (pos_type c = children(
block, n.offset);
valid(c)) {
2427 recursLeaves(c, node_f, block_f, update_f);
2435 recursUp(n, update_f);
2441 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>,
bool> =
true>
2442 void recursParentFirst(pos_type
block, BlockFun block_f)
2444 assert(exists(
block));
2449 modifiedSet(treeLeafBlock(
block));
2453 InnerBlock&
b = treeInnerBlock(
block);
2456 for (offset_type i{}; BF > i; ++i) {
2457 if (pos_type c = children(
b, i);
valid(c)) {
2458 recursParentFirst(c, block_f);
2464 class NodeType,
class NodeFun,
class BlockFun,
class UpdateFun,
2465 std::enable_if_t<is_node_type_v<NodeType>,
bool> =
true,
2466 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>,
bool> =
true,
2467 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>,
bool> =
true,
2468 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
bool> =
2470 void recursParentFirst(NodeType
node, NodeFun node_f, BlockFun block_f,
2471 UpdateFun update_f,
bool propagate)
2473 Index n = createThreadSafe(
node);
2478 modifiedSet(treeLeafBlock(n.pos), n.offset);
2480 InnerBlock&
block = treeInnerBlock(n.pos);
2481 modifiedSet(
block, n.offset);
2483 if (pos_type c = children(
block, n.offset);
valid(c)) {
2484 recursParentFirst(c, block_f);
2489 recursUp(n, update_f);
2499 [[nodiscard]]
bool allLeaf([[maybe_unused]] LeafBlock
const&
block)
const
2504 [[nodiscard]]
bool allLeaf(InnerBlock
const&
block)
const
2506 return std::all_of(
block.children.begin(),
block.children.end(),
2507 [](pos_type e) { return Index::MAX_VALID_POS < e; });
2521 [[nodiscard]]
bool anyLeaf([[maybe_unused]] LeafBlock
const&
block)
const
2526 [[nodiscard]]
bool anyLeaf(InnerBlock
const&
block)
const
2528 return std::any_of(
block.children.begin(),
block.children.end(),
2529 [](pos_type e) { return Index::MAX_VALID_POS < e; });
2597 half_length /= length_type(2);
2599 center[i] += (
child & offset_type(1u << i)) ? half_length[i] : -half_length[i];
2621 center[i] += (
index & offset_type(1u << i)) ? -half_length[i] : half_length[i];
2632 void initLeafChildren(Index
node, InnerBlock
const&
block, pos_type children)
2634 LeafBlock& cb = treeLeafBlock(children);
2635 cb.parent_block =
node.pos;
2636 cb.parent_offset =
static_cast<std::uint8_t
>(
node.offset);
2642 void initInnerChildren(Index
node, InnerBlock
const&
block, pos_type children)
2644 InnerBlock& cb = treeInnerBlock(children);
2645 cb.children.fill(Index::NULL_POS);
2646 cb.parent_block =
node.pos;
2647 cb.parent_offset =
static_cast<std::uint8_t
>(
node.offset);
2648 cb.depth =
static_cast<std::uint8_t
>(
block.depth - 1);
2654 pos_type createChildren(Index
node)
2658 InnerBlock&
block = treeInnerBlock(
node.pos);
2660 pos_type c = children(
block,
node.offset);
2661 assert(Index::PROCESSING_POS != c);
2663 if (Index::NULL_POS == c) {
2664 if (1 ==
block.depth) {
2665 c = Data::leafCreate();
2668 c = Data::innerCreate();
2680 pos_type createChildrenThreadSafe(Index
node)
2684 InnerBlock&
block = treeInnerBlock(
node.pos);
2686 auto cr = std::atomic_ref(
block.children[
node.offset]);
2688 pos_type c = Index::NULL_POS;
2689 if (cr.compare_exchange_strong(c, Index::PROCESSING_POS, std::memory_order_relaxed)) {
2690 if (1 ==
block.depth) {
2691 c = Data::leafCreateThreadSafe();
2694 c = Data::innerCreateThreadSafe();
2698 modifiedSetThreadSafe(
block,
node.offset);
2700 cr.store(c, std::memory_order_release);
2702 }
else if (
valid(c)) {
2703 modifiedSetThreadSafe(
block,
node.offset);
2705 cr.wait(Index::PROCESSING_POS, std::memory_order_relaxed);
2706 c = cr.load(std::memory_order_acquire);
2739 Index createChild(Index
node, offset_type child_offset)
2742 assert(BF > child_offset);
2744 return Index(createChildren(
node), child_offset);
2747 Index createChildThreadSafe(Index
node, offset_type child_offset)
2750 assert(BF > child_offset);
2752 return Index(createChildrenThreadSafe(
node), child_offset);
2755 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
2756 Index createThreadSafe(NodeType
node)
2760 using T = remove_cvref_t<NodeType>;
2761 if constexpr (std::is_same_v<T, Index>) {
2762 assert(exists(
node));
2763 modifiedSetParentsThreadSafe(
node);
2766 Code code = this->code(
node);
2767 auto wanted_depth =
depth(code);
2768 auto cur_node =
index();
2769 auto cur_depth =
depth();
2770 while (wanted_depth < cur_depth) {
2771 cur_node = createChildThreadSafe(cur_node, code.offset(--cur_depth));
2783 void pruneChildren(Index
node) { pruneChildren(
node, children(
node)); }
2785 void pruneChildren(Index
node, pos_type children)
2789 InnerBlock&
block = treeInnerBlock(
node.pos);
2790 block.children[
node.offset] = Index::NULL_POS;
2796 treeLeafBlock(children).parent_block = Index::INVALID_POS;
2797 Data::leafErase(children);
2800 treeInnerBlock(children).parent_block = Index::INVALID_POS;
2801 Data::innerErase(children);
2815 template <
bool OnlyDistance =
false,
bool FastAsSonic =
false,
class ValueFun,
2817 [[nodiscard]] std::conditional_t<OnlyDistance, float, std::pair<float, Index>> nearest(
2818 Index
node, NearestSearchAlgorithm search_alg, ValueFun value_f, InnerFun inner_f,
2819 float max_dist,
float epsilon)
const
2825 std::conditional_t<OnlyDistance, float, std::pair<float, Index>> closest{};
2826 if constexpr (OnlyDistance) {
2829 closest.first = max_dist;
2833 auto cb = children(
node);
2834 auto cd =
depth(cb);
2839 closest = nearestDepthFirst<OnlyDistance, FastAsSonic>(cb, cd, max_dist, epsilon,
2854 if constexpr (!FastAsSonic) {
2855 max_dist = value_f(
node);
2857 assert(!std::isnan(max_dist));
2858 if constexpr (OnlyDistance) {
2859 return UFO_MIN(closest, max_dist);
2861 return closest.first < max_dist ? closest : std::pair{max_dist,
node};
2865 template <
class Predicate,
class ValueFun,
class InnerFun,
2866 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
2867 [[nodiscard]] std::pair<float, Index> nearest(Index
node, Predicate pred,
2868 NearestSearchAlgorithm search_alg,
2869 ValueFun value_f, InnerFun inner_f,
2870 float max_dist,
float epsilon)
const
2872 using Filter = pred::Filter<Predicate>;
2874 Filter::init(pred,
derived());
2876 auto wrapped_value_f = [value_f, &pred](Index
node) ->
float {
2877 return Filter::returnable(pred) ? value_f(
node)
2878 :
std::numeric_limits<float>::infinity();
2881 auto wrapped_inner_f = [inner_f, &pred](Index
node) ->
float {
2882 return Filter::traversable(pred) ? inner_f(
node)
2883 :
std::numeric_limits<float>::infinity();
2886 return nearest(
node, search_alg, wrapped_value_f, wrapped_inner_f, max_dist, epsilon);
2889 template <
bool OnlyDistance,
bool FastAsSonic,
class ValueFun,
class InnerFun>
2890 [[nodiscard]] std::conditional_t<OnlyDistance, float, std::pair<float, Index>>
2891 nearestDepthFirst(pos_type
block, depth_type
depth,
float c_dist,
float epsilon,
2892 ValueFun value_f, InnerFun inner_f)
const
2894 struct StackElement {
2895 using Container = std::array<std::pair<float, pos_type>, BF>;
2896 using Iterator =
typename Container::iterator;
2898 Container container;
2901 [[nodiscard]]
constexpr float&
distance() {
return it->first; }
2903 [[nodiscard]]
constexpr float const&
distance()
const {
return it->first; }
2905 [[nodiscard]]
constexpr pos_type& block() {
return it->second; }
2907 [[nodiscard]]
constexpr pos_type
const& block()
const {
return it->second; }
2909 constexpr void start() { it = container.begin(); }
2911 [[nodiscard]]
constexpr bool empty() {
return container.end() == it; }
2913 [[nodiscard]]
constexpr bool empty()
const {
return container.end() == it; }
2915 StackElement& operator++()
2921 constexpr void sort()
2923 if constexpr (2 == BF) {
2924 UFO_SORT_ASCENDING_PAIR_FIRST_2(container);
2925 }
else if constexpr (4 == BF) {
2926 UFO_SORT_ASCENDING_PAIR_FIRST_4(container);
2927 }
else if constexpr (8 == BF) {
2928 UFO_SORT_ASCENDING_PAIR_FIRST_8(container);
2929 }
else if constexpr (16 == BF) {
2930 UFO_SORT_ASCENDING_PAIR_FIRST_16(container);
2932 std::sort(container.begin(), container.end(),
2933 [](
auto a,
auto b) { return a.first < b.first; });
2943 stack[
depth].it = std::prev(stack[
depth].container.end());
2948 stack[
depth].distance() = 0.0f;
2950 std::conditional_t<OnlyDistance, bool, Index> c_node;
2952 std::array<std::conditional_t<OnlyDistance, float, std::pair<float, offset_type>>, BF>
2955 for (depth_type max_depth =
depth + 1; max_depth >
depth;) {
2956 StackElement& se = stack[
depth];
2958 if (se.empty() || c_dist - epsilon <= se.distance()) {
2966 StackElement& cur = stack[
depth - 1u];
2970 for (std::size_t i{}; BF > i; ++i) {
2972 cur.container[i].first = inner_f(
node);
2973 assert(!std::isnan(cur.container[i].first));
2974 cur.container[i].second = children(
node);
2976 if constexpr (!FastAsSonic) {
2977 if constexpr (OnlyDistance) {
2978 d[i] = value_f(
node);
2979 assert(!std::isnan(d[i]));
2981 d[i].first = value_f(
node);
2982 assert(!std::isnan(d[i].first));
2988 if constexpr (!FastAsSonic) {
2989 if constexpr (OnlyDistance) {
2990 if constexpr (2 == BF) {
2992 }
else if constexpr (4 == BF) {
2994 }
else if constexpr (8 == BF) {
2996 }
else if constexpr (16 == BF) {
2999 for (std::size_t i = 1; BF > i; ++i) {
3000 d[0] = UFO_MIN(d[0], d[i]);
3004 c_dist = c_dist <= d[0] ? c_dist : d[0];
3006 if constexpr (2 == BF) {
3007 UFO_MIN_PAIR_FIRST_2(d);
3008 }
else if constexpr (4 == BF) {
3009 UFO_MIN_PAIR_FIRST_4(d);
3010 }
else if constexpr (8 == BF) {
3011 UFO_MIN_PAIR_FIRST_8(d);
3012 }
else if constexpr (16 == BF) {
3013 UFO_MIN_PAIR_FIRST_16(d);
3015 for (std::size_t i = 1; BF > i; ++i) {
3016 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3020 c_node = c_dist <= d[0].first ? c_node : Index{
block, d[0].second};
3021 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3026 for (
auto [dist, child_block] : cur.container) {
3027 if (c_dist <= dist + epsilon) {
3031 if constexpr (OnlyDistance) {
3032 for (offset_type i{}; BF > i; ++i) {
3033 d[i] = value_f(Index(child_block, i));
3034 assert(!std::isnan(d[i]));
3037 if constexpr (2 == BF) {
3039 }
else if constexpr (4 == BF) {
3041 }
else if constexpr (8 == BF) {
3043 }
else if constexpr (16 == BF) {
3046 for (std::size_t i = 1; BF > i; ++i) {
3047 d[0] = UFO_MIN(d[0], d[i]);
3051 c_dist = c_dist <= d[0] ? c_dist : d[0];
3053 for (offset_type i{}; BF > i; ++i) {
3054 d[i].first = value_f(Index(child_block, i));
3055 assert(!std::isnan(d[i].first));
3059 if constexpr (2 == BF) {
3060 UFO_MIN_PAIR_FIRST_2(d);
3061 }
else if constexpr (4 == BF) {
3062 UFO_MIN_PAIR_FIRST_4(d);
3063 }
else if constexpr (8 == BF) {
3064 UFO_MIN_PAIR_FIRST_8(d);
3065 }
else if constexpr (16 == BF) {
3066 UFO_MIN_PAIR_FIRST_16(d);
3068 for (std::size_t i = 1; BF > i; ++i) {
3069 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3073 c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3074 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3083 if constexpr (OnlyDistance) {
3086 return {c_dist, c_node};
3090 template <
class ValueFun,
class InnerFun>
3091 [[nodiscard]] std::pair<float, Index> nearestDepthFirst(pos_type
block,
3092 depth_type
depth,
float c_dist,
3094 InnerFun inner_f)
const
3097 std::array<std::pair<std::size_t, std::array<std::pair<float, pos_type>, BF>>,
3101 stack[
depth].first = BF - 1u;
3102 stack[
depth].second[BF - 1].first = 0.0f;
3107 for (depth_type max_depth =
depth + 1; max_depth >
depth;) {
3108 auto& [idx, c] = stack[
depth];
3110 if (BF <= idx || c_dist <= c[idx].first) {
3115 block = c[idx].second;
3118 stack[
depth - 1].first = 0;
3119 auto& candidates = stack[
depth - 1].second;
3121 for (std::size_t i{}; BF > i; ++i) {
3123 candidates[i].first = inner_f(
node);
3124 assert(!std::isnan(candidates[i].first));
3125 candidates[i].second = children(
node);
3129 std::array<std::pair<float, offset_type>, BF> d;
3130 for (
auto [dist, child_block] : candidates) {
3131 if (c_dist <= dist) {
3135 for (offset_type i{}; BF > i; ++i) {
3136 d[i].first = value_f(Index(child_block, i));
3137 assert(!std::isnan(d[i].first));
3141 if constexpr (2 == BF) {
3142 UFO_MIN_PAIR_FIRST_2(d);
3143 }
else if constexpr (4 == BF) {
3144 UFO_MIN_PAIR_FIRST_4(d);
3145 }
else if constexpr (8 == BF) {
3146 UFO_MIN_PAIR_FIRST_8(d);
3147 }
else if constexpr (16 == BF) {
3148 UFO_MIN_PAIR_FIRST_16(d);
3150 for (std::size_t i = 1; BF > i; ++i) {
3151 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3155 c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3156 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3159 if constexpr (2 == BF) {
3160 UFO_SORT_ASCENDING_PAIR_FIRST_2(candidates);
3161 }
else if constexpr (4 == BF) {
3162 UFO_SORT_ASCENDING_PAIR_FIRST_4(candidates);
3163 }
else if constexpr (8 == BF) {
3164 UFO_SORT_ASCENDING_PAIR_FIRST_8(candidates);
3165 }
else if constexpr (16 == BF) {
3166 UFO_SORT_ASCENDING_PAIR_FIRST_16(candidates);
3168 std::sort(candidates.begin(), candidates.end(),
3169 [](
auto a,
auto b) { return a.first < b.first; });
3175 return {c_dist, c_node};
3405 : node(node), cur_node(cur_node), t0(t0), t1(t1), tm(tm)
3410 template <
class NodeType, std::enable_if_t<is_node_type_v<NodeType>,
bool> = true>
3416 [[nodiscard]]
static constexpr TraceParams traceInit(
Ray const& ray,
3418 Length half_length)
noexcept
3423 for (std::size_t i{}; Dim > i; ++i) {
3426 auto a =
center[i] - half_length[i] - origin;
3427 auto b =
center[i] + half_length[i] - origin;
3433 params.a |= unsigned(0 > ray.
direction[i]) << i;
3439 [[nodiscard]]
static constexpr inline unsigned firstNode(Point
const& tm,
3440 float const t)
noexcept
3442 unsigned node =
static_cast<unsigned>(tm[0] < t);
3443 for (
unsigned i = 1; Dim > i; ++i) {
3444 node |=
static_cast<unsigned>(tm[i] < t) << i;
3449 [[nodiscard]]
static constexpr inline unsigned newNode(
unsigned cur,
3450 unsigned dim)
noexcept
3453 unsigned x = 1u << dim;
3454 return ((cur & x) << Dim) | cur | x;
3457 template <
class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>,
bool> = true>
3458 [[nodiscard]]
constexpr TraceResult trace(Node
node, TraceParams
const& params,
3459 Predicate
const& pred,
float const near_clip,
3460 float const far_clip,
bool only_exists)
const
3464 using Filter = pred::Filter<Predicate>;
3466 auto returnable = [
this, near_clip, far_clip, &pred](Node
const&
node,
float min_dist,
3468 return near_clip <= max_dist && far_clip >= min_dist &&
3472 auto traversable = [
this, near_clip, far_clip, &pred](
3473 Node
const&
node,
float min_dist,
float max_dist) {
3474 return near_clip <= max_dist && far_clip >= min_dist &&
isParent(
node.index) &&
3478 constexpr auto const new_node_lut = []() {
3479 std::array<std::array<unsigned, Dim>, BF> lut{};
3480 for (
unsigned cur{}; BF != cur; ++cur) {
3481 for (
unsigned dim{}; Dim != dim; ++dim) {
3482 lut[cur][dim] = newNode(cur, dim);
3488 auto t0 = params.t0;
3489 auto t1 = params.t1;
3490 auto tm = (t0 + t1) * 0.5f;
3496 if (min_dist >= max_dist || near_clip > max_dist || far_clip < min_dist) {
3497 return TraceResult{Node(),
3499 std::numeric_limits<float>::infinity()};
3500 }
else if (returnable(
node, min_dist, max_dist)) {
3501 float distance = std::max(near_clip, min_dist);
3503 }
else if (!traversable(
node, min_dist, max_dist)) {
3504 return TraceResult{Node(),
3506 std::numeric_limits<float>::infinity()};
3509 unsigned cur_node = firstNode(tm, min_dist);
3512 stack[0] = TraceStackElement{
node, cur_node, t0, t1, tm};
3514 for (
int idx{}; 0 <= idx;) {
3515 node = stack[idx].node;
3516 cur_node = stack[idx].cur_node;
3526 for (
unsigned i{}; Dim > i; ++i) {
3527 t0[i] = (cur_node & (1u << i)) ? tm[i] : t0[i];
3528 t1[i] = (cur_node & (1u << i)) ? t1[i] : tm[i];
3531 stack[idx].cur_node = new_node_lut[cur_node][
minIndex(t1)];
3532 idx -= BF <= stack[idx].cur_node;
3537 if (returnable(
node, min_dist, max_dist)) {
3538 float distance = std::max(near_clip, min_dist);
3540 }
else if (!traversable(
node, min_dist, max_dist)) {
3544 tm = (t0 + t1) * 0.5f;
3546 unsigned cur_node = firstNode(tm, min_dist);
3548 stack[++idx] = TraceStackElement{
node, cur_node, t0, t1, tm};
3551 return TraceResult{Node(), std::numeric_limits<float>::infinity()};
3555 template <
class NodeType>
3556 [[nodiscard]]
constexpr auto convert(NodeType
node)
const
3558 using T = remove_cvref_t<NodeType>;
3559 if constexpr (std::is_convertible_v<T, Index>) {
3560 return static_cast<Index
>(
node);
3561 }
else if constexpr (std::is_convertible_v<T, Node>) {
3562 return static_cast<Node
>(
node);
3563 }
else if constexpr (std::is_convertible_v<T, Code>) {
3564 return static_cast<Code
>(
node);
3565 }
else if constexpr (std::is_convertible_v<T, Key>) {
3566 return static_cast<Key
>(
node);
3567 }
else if constexpr (std::is_convertible_v<T, Coord>) {
3568 return static_cast<Coord
>(
node);
3569 }
else if constexpr (std::is_constructible_v<T, Coord>) {
3572 static_assert(is_node_type_v<NodeType>,
"Not one of the supported node types.");
3582 [[nodiscard]]
int modifiedCount(LeafBlock
const&
block)
const
3587 [[nodiscard]]
int modifiedCount(InnerBlock
const&
block)
const
3592 [[nodiscard]]
bool modifiedAll(LeafBlock
const&
block)
const
3597 [[nodiscard]]
bool modifiedAll(InnerBlock
const&
block)
const
3602 [[nodiscard]]
bool modifiedNone(LeafBlock
const&
block)
const
3607 [[nodiscard]]
bool modifiedNone(InnerBlock
const&
block)
const
3630 [[nodiscard]] modified_type
modified(LeafBlock
const&
block)
const
3632 return block.modified;
3637 [[nodiscard]] modified_type
modified(InnerBlock
const&
block)
const
3639 return block.modified;
3654 void modifiedSet(LeafBlock&
block, offset_type
offset)
3659 void modifiedSet(InnerBlock&
block, offset_type
offset)
3664 void modifiedSet(pos_type
block, offset_type
offset)
3674 void modifiedSet(pos_type
block)
3677 : modifiedSet(treeInnerBlock(
block));
3680 void modifiedSetThreadSafe(LeafBlock&
block, offset_type
offset)
3683 m.fetch_or(
static_cast<modified_type
>(1u <<
offset), std::memory_order_relaxed);
3686 void modifiedSetThreadSafe(InnerBlock&
block, offset_type
offset)
3689 m.fetch_or(
static_cast<modified_type
>(1u <<
offset), std::memory_order_relaxed);
3692 void modifiedSetThreadSafe(pos_type
block, offset_type
offset)
3695 : modifiedSetThreadSafe(treeInnerBlock(
block),
offset);
3698 void modifiedSetThreadSafe(LeafBlock&
block)
3701 m.store(MODIFIED_ALL_SET, std::memory_order_relaxed);
3704 void modifiedSetThreadSafe(InnerBlock&
block)
3707 m.store(MODIFIED_ALL_SET, std::memory_order_relaxed);
3710 void modifiedSetThreadSafe(pos_type
block)
3713 : modifiedSetThreadSafe(treeInnerBlock(
block));
3716 void modifiedReset(LeafBlock&
block, offset_type
offset)
3721 void modifiedReset(InnerBlock&
block, offset_type
offset)
3726 void modifiedReset(pos_type
block, offset_type
offset)
3736 void modifiedReset(pos_type
block)
3739 : modifiedSet(treeInnerBlock(
block));
3742 void modifiedSetParents(Index
node)
3744 if (Index p = parent(
node);
3745 !
valid(p) ||
modified(treeInnerBlockConst(p.pos), p.offset)) {
3749 recursUp(
node, [
this](Index parent, [[maybe_unused]] pos_type children) ->
bool {
3750 modified_type& m =
modified(treeInnerBlock(parent.pos));
3751 modified_type prev = m;
3752 m |=
static_cast<modified_type
>(1u << parent.offset);
3757 void modifiedSetParentsThreadSafe(Index
node)
3759 if (Index p = parent(
node);
3760 !
valid(p) ||
modified(treeInnerBlockConst(p.pos), p.offset)) {
3764 recursUp(
node, [
this](Index parent, [[maybe_unused]] pos_type children) ->
bool {
3765 auto m = std::atomic_ref(
modified(treeInnerBlock(parent.pos)));
3766 modified_type v =
static_cast<modified_type
>(1u << parent.offset);
3767 return v != (m.fetch_or(v, std::memory_order_relaxed) & v);
3771 void modifiedSetChildren(Index
node)
3773 recursDown(
node, [
this]([[maybe_unused]] Index parent, pos_type children) ->
bool {
3775 modifiedSet(treeLeafBlock(children));
3778 modified_type& m =
modified(treeInnerBlock(children));
3779 modified_type prev = m;
3780 m = MODIFIED_ALL_SET;
3786 void modifiedResetChildren(Index
node)
3788 recursDown(
node, [
this]([[maybe_unused]] Index parent, pos_type children) ->
bool {
3790 modifiedReset(treeLeafBlock(children));
3793 modified_type& m =
modified(treeInnerBlock(children));
3794 modified_type prev = m;
3795 m = MODIFIED_NONE_SET;
3807 [[nodiscard]] std::array<pos_type, BF>
const& children(InnerBlock
const&
block)
const
3809 return block.children;
3812 [[nodiscard]] pos_type children(InnerBlock
const&
block, offset_type
offset)
const
3823 [[nodiscard]] Index parent(LeafBlock
const&
block)
const
3825 return Index(
block.parent_block,
block.parent_offset);
3828 [[nodiscard]] Index parent(InnerBlock
const&
block)
const
3830 return Index(
block.parent_block,
block.parent_offset);
3835 depth_type num_depth_levels_;
3837 key_type half_max_value_;