16template<
typename T,
typename Spacetree>
18 { t(node) } -> std::same_as<void>;
21template<
typename T,
typename Spacetree>
23 { t(node, ctx) } -> std::same_as<void>;
26template<
typename T,
typename Spacetree>
29template<
typename T,
typename Spacetree,
typename Val>
31 { t(node, val) } -> std::same_as<void>;
34template<
typename T,
typename Spacetree,
typename Val>
36 { t(node, val, ctx) } -> std::same_as<void>;
39template<
typename T,
typename Spacetree,
typename Val>
43template<
typename Spacetree,
typename =
void>
46template<
typename Spacetree>
51template<
typename _Geometry,
typename _Item,
int THRESHOLD = 64,
int SPLIT_FACTOR = 2,
typename _TaskBackend = ThreadPoolTaskBackend>
52struct Spacetree :
public LinkedGrid<_Geometry, SPLIT_FACTOR, Spacetree<_Geometry, _Item, THRESHOLD, SPLIT_FACTOR, _TaskBackend>> {
55 using Geo = _Geometry;
68 template<
int LEVEL = 4>
71 template<
int LEVEL = 4>
88 this->items = std::move(other.items);
96 while (node->subtrees) {
97 auto subtreeIdx = node->
range.splitIdx(SPLIT_FACTOR, p);
98 node = node->subtrees + subtreeIdx;
107 while (node->subtrees) {
108 auto subtreeIdx = node->
range.splitIdx(SPLIT_FACTOR, region.low);
109 auto *nodeCandidate = node->subtrees + subtreeIdx;
110 if (nodeCandidate->range.containsEx(region.high)) node = nodeCandidate;
118 auto itemPos = item._x;
120 auto *inRangeNode =
this;
121 while (!inRangeNode->range.contains(itemPos)) {
122 inRangeNode = inRangeNode->parent;
123 if (!inRangeNode) [[unlikely]] {
128 auto *leafNode = inRangeNode->findLeaf(itemPos);
130 if (leafNode->items.size() == THRESHOLD) [[unlikely]] {
131 leafNode->splitIntoSubtrees();
132 leafNode = leafNode->findLeaf(itemPos);
135 leafNode->pushItem(item);
143 this->items.push_back(p);
147 auto *fullTree =
this;
150 assert(fullTree->items.size() == THRESHOLD)
154 char idxs[THRESHOLD];
156 for (
int i = 0; i < THRESHOLD; i++) {
157 auto pos = fullTree->items[i]._x;
158 auto quartIdx = fullTree->range.splitIdx(SPLIT_FACTOR, pos);
162 for (
int i = 0; i < THRESHOLD; i++) {
163 auto *subtree = fullTree->subtrees + idxs[i];
164 subtree->items.push_back(fullTree->items[i]);
170 auto *
subtrees = fullTree->subtrees;
177 }
while (fullTree && fullTree->level < 128);
181 auto *currSubtree =
this;
183 if (refined && this->range.contains(
range)) {
188 while (!currSubtree->range.contains(
range) & (currSubtree->parent !=
nullptr)) {
189 currSubtree = currSubtree->parent;
195 template<StatelessOnNodeCallback<Spacetree> Callback,
typename Iter = LeafsIterator>
197 auto iter = Iter(
this);
198 this->
onNode(F, iter, numThreads);
201 template<StatelessOnNodeCallback<Spacetree> Callback,
typename Iter>
202 void onNode(Callback F, Iter iter,
u32 numThreads = 0) {
203 auto taskGenerator =
Lambda([](
auto &iter,
auto &callback) {
204 auto nodeOpt = iter.next();
206 auto task =
Lambda([](
auto *node,
auto *callback,
auto &ctx) {
207 (*callback)(node, ctx);
208 }, nodeOpt.value_or(
nullptr), &callback);
209 return (nodeOpt) ? std::optional(task) : std::nullopt;
211 auto task =
Lambda([](
auto *node,
auto *callback) {
213 }, nodeOpt.value_or(
nullptr), &callback);
214 return (nodeOpt) ? std::optional(task) : std::nullopt;
215 }
else static_assert(
false);
218 TaskBackend::runSerialGenerator(taskGenerator, numThreads);
221 template<
typename StateInitF, StatefulOnNodeCallback<Spacetree, std::invoke_result_t<StateInitF>> Callback,
typename Iter = LeafsIterator>
222 auto onNode(Callback F, StateInitF stateInitF,
u32 numThreads = 0) {
223 auto iter = Iter(
this);
224 return this->
onNode(F, stateInitF, iter, numThreads);
227 template<
typename StateInitF, StatefulOnNodeCallback<Spacetree, std::invoke_result_t<StateInitF>> Callback,
typename Iter>
228 auto onNode(Callback F, StateInitF stateInitF, Iter iter,
u32 numThreads = 0) {
229 using ValueType = std::invoke_result_t<StateInitF>;
231 auto taskGenerator =
Lambda([](
auto &iter,
auto &callback) {
232 auto nodeOpt = iter.next();
234 auto task =
Lambda([](
auto *node,
auto *callback,
auto &acc,
auto &ctx) {
235 (*callback)(node, acc, ctx);
236 }, nodeOpt.value_or(
nullptr), &callback);
237 return (nodeOpt) ? std::optional(task) : std::nullopt;
239 auto task =
Lambda([](
auto *node,
auto *callback,
auto &acc) {
240 (*callback)(node, acc);
241 }, nodeOpt.value_or(
nullptr), &callback);
242 return (nodeOpt) ? std::optional(task) : std::nullopt;
243 }
else static_assert(
false);
246 return TaskBackend::runSerialGenerator(taskGenerator, stateInitF, numThreads);
266 return Geo::template PowerN<SPLIT_FACTOR>();
LinkedGrid & operator=(LinkedGrid &&other) noexcept
Region< dim, fp, topBoundaryInclusive > Region
Spacetree(Geo::Region range, Spacetree *parent, Geo::RowMajorIdx idx, int level)
static constexpr u32 getMaxChildren()
void onNode(Callback F, u32 numThreads=0)
Spacetree(Geo::Region range)
auto onNode(Callback F, StateInitF stateInitF, Iter iter, u32 numThreads=0)
static constexpr int CAPACITY
auto onNode(Callback F, StateInitF stateInitF, u32 numThreads=0)
void onNode(Callback F, Iter iter, u32 numThreads=0)
Spacetree * findLeaf(const Geo::Point &p)
Spacetree * getRegionParent(const Geo::Region &range, bool refined=false)
Spacetree * insert(Item item)
IterationOrderSelector< Spacetree >::type IterOrder
Spacetree & operator=(Spacetree &&other) noexcept
Spacetree * findChildNode(const Geo::Region ®ion)
Spacetree(Spacetree &&other) noexcept