Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions include/prtree/core/detail/bounding_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@

#include "prtree/core/detail/types.h"

using Real = float;

template <int D = 2> class BB {
template <int D = 2, typename Real = float> class BB {
private:
Real values[2 * D];

Expand Down
16 changes: 8 additions & 8 deletions include/prtree/core/detail/data_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@
#include "prtree/core/detail/types.h"

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int D = 2> class DataType {
template <IndexType T, int D = 2, typename Real = float> class DataType {
public:
BB<D> second;
BB<D, Real> second;
T first;

DataType() noexcept = default;

DataType(const T &f, const BB<D> &s) {
DataType(const T &f, const BB<D, Real> &s) {
first = f;
second = s;
}

DataType(T &&f, BB<D> &&s) noexcept {
DataType(T &&f, BB<D, Real> &&s) noexcept {
first = std::move(f);
second = std::move(s);
}
Expand All @@ -39,9 +39,9 @@ template <IndexType T, int D = 2> class DataType {
template <class Archive> void serialize(Archive &ar) { ar(first, second); }
};

template <class T, int D = 2>
void clean_data(DataType<T, D> *b, DataType<T, D> *e) {
for (DataType<T, D> *it = e - 1; it >= b; --it) {
it->~DataType<T, D>();
template <class T, int D = 2, typename Real = float>
void clean_data(DataType<T, D, Real> *b, DataType<T, D, Real> *e) {
for (DataType<T, D, Real> *it = e - 1; it >= b; --it) {
it->~DataType<T, D, Real>();
}
}
66 changes: 33 additions & 33 deletions include/prtree/core/detail/nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
#include "prtree/core/detail/types.h"

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class PRTreeLeaf {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class PRTreeLeaf {
public:
BB<D> mbb;
svec<DataType<T, D>, B> data;
BB<D, Real> mbb;
svec<DataType<T, D, Real>, B> data;

PRTreeLeaf() { mbb = BB<D>(); }
PRTreeLeaf() { mbb = BB<D, Real>(); }

PRTreeLeaf(const Leaf<T, B, D> &leaf) {
PRTreeLeaf(const Leaf<T, B, D, Real> &leaf) {
mbb = leaf.mbb;
data = leaf.data;
}
Expand All @@ -38,7 +38,7 @@ template <IndexType T, int B = 6, int D = 2> class PRTreeLeaf {
}
}

void operator()(const BB<D> &target, vec<T> &out) const {
void operator()(const BB<D, Real> &target, vec<T> &out) const {
if (mbb(target)) {
for (const auto &x : data) {
if (x.second(target)) {
Expand All @@ -48,7 +48,7 @@ template <IndexType T, int B = 6, int D = 2> class PRTreeLeaf {
}
}

void del(const T &key, const BB<D> &target) {
void del(const T &key, const BB<D, Real> &target) {
if (mbb(target)) {
auto remove_it =
std::remove_if(data.begin(), data.end(), [&](auto &datum) {
Expand All @@ -58,21 +58,21 @@ template <IndexType T, int B = 6, int D = 2> class PRTreeLeaf {
}
}

void push(const T &key, const BB<D> &target) {
void push(const T &key, const BB<D, Real> &target) {
data.emplace_back(key, target);
update_mbb();
}

template <class Archive> void save(Archive &ar) const {
vec<DataType<T, D>> _data;
vec<DataType<T, D, Real>> _data;
for (const auto &datum : data) {
_data.push_back(datum);
}
ar(mbb, _data);
}

template <class Archive> void load(Archive &ar) {
vec<DataType<T, D>> _data;
vec<DataType<T, D, Real>> _data;
ar(mbb, _data);
for (const auto &datum : _data) {
data.push_back(datum);
Expand All @@ -81,63 +81,63 @@ template <IndexType T, int B = 6, int D = 2> class PRTreeLeaf {
};

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class PRTreeNode {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class PRTreeNode {
public:
BB<D> mbb;
std::unique_ptr<Leaf<T, B, D>> leaf;
std::unique_ptr<PRTreeNode<T, B, D>> head, next;
BB<D, Real> mbb;
std::unique_ptr<Leaf<T, B, D, Real>> leaf;
std::unique_ptr<PRTreeNode<T, B, D, Real>> head, next;

PRTreeNode() {}
PRTreeNode(const BB<D> &_mbb) { mbb = _mbb; }
PRTreeNode(const BB<D, Real> &_mbb) { mbb = _mbb; }

PRTreeNode(BB<D> &&_mbb) noexcept { mbb = std::move(_mbb); }
PRTreeNode(BB<D, Real> &&_mbb) noexcept { mbb = std::move(_mbb); }

PRTreeNode(Leaf<T, B, D> *l) {
leaf = std::make_unique<Leaf<T, B, D>>();
PRTreeNode(Leaf<T, B, D, Real> *l) {
leaf = std::make_unique<Leaf<T, B, D, Real>>();
mbb = l->mbb;
leaf->mbb = std::move(l->mbb);
leaf->data = std::move(l->data);
}

bool operator()(const BB<D> &target) { return mbb(target); }
bool operator()(const BB<D, Real> &target) { return mbb(target); }
};

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class PRTreeElement {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class PRTreeElement {
public:
BB<D> mbb;
std::unique_ptr<PRTreeLeaf<T, B, D>> leaf;
BB<D, Real> mbb;
std::unique_ptr<PRTreeLeaf<T, B, D, Real>> leaf;
bool is_used = false;

PRTreeElement() {
mbb = BB<D>();
mbb = BB<D, Real>();
is_used = false;
}

PRTreeElement(const PRTreeNode<T, B, D> &node) {
mbb = BB<D>(node.mbb);
PRTreeElement(const PRTreeNode<T, B, D, Real> &node) {
mbb = BB<D, Real>(node.mbb);
if (node.leaf) {
Leaf<T, B, D> tmp_leaf = Leaf<T, B, D>(*node.leaf.get());
leaf = std::make_unique<PRTreeLeaf<T, B, D>>(tmp_leaf);
Leaf<T, B, D, Real> tmp_leaf = Leaf<T, B, D, Real>(*node.leaf.get());
leaf = std::make_unique<PRTreeLeaf<T, B, D, Real>>(tmp_leaf);
}
is_used = true;
}

bool operator()(const BB<D> &target) { return is_used && mbb(target); }
bool operator()(const BB<D, Real> &target) { return is_used && mbb(target); }

template <class Archive> void serialize(Archive &archive) {
archive(mbb, leaf, is_used);
}
};

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2>
template <IndexType T, int B = 6, int D = 2, typename Real = float>
void bfs(
const std::function<void(std::unique_ptr<PRTreeLeaf<T, B, D>> &)> &func,
vec<PRTreeElement<T, B, D>> &flat_tree, const BB<D> target) {
const std::function<void(std::unique_ptr<PRTreeLeaf<T, B, D, Real>> &)> &func,
vec<PRTreeElement<T, B, D, Real>> &flat_tree, const BB<D, Real> target) {
queue<size_t> que;
auto qpush_if_intersect = [&](const size_t &i) {
PRTreeElement<T, B, D> &r = flat_tree[i];
PRTreeElement<T, B, D, Real> &r = flat_tree[i];
// std::cout << "i " << (long int) i << " : " << (bool) r.leaf << std::endl;
if (r(target)) {
// std::cout << " is pushed" << std::endl;
Expand All @@ -151,7 +151,7 @@ void bfs(
size_t idx = que.front();
// std::cout << "idx: " << (long int) idx << std::endl;
que.pop();
PRTreeElement<T, B, D> &elem = flat_tree[idx];
PRTreeElement<T, B, D, Real> &elem = flat_tree[idx];

if (elem.leaf) {
// std::cout << "func called for " << (long int) idx << std::endl;
Expand Down
56 changes: 28 additions & 28 deletions include/prtree/core/detail/pseudo_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@
#include "prtree/core/detail/types.h"

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class Leaf {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class Leaf {
public:
BB<D> mbb;
svec<DataType<T, D>, B> data; // You can swap when filtering
BB<D, Real> mbb;
svec<DataType<T, D, Real>, B> data; // You can swap when filtering
int axis = 0;

// T is type of keys(ids) which will be returned when you post a query.
Leaf() { mbb = BB<D>(); }
Leaf() { mbb = BB<D, Real>(); }
Leaf(const int _axis) {
axis = _axis;
mbb = BB<D>();
mbb = BB<D, Real>();
}

void set_axis(const int &_axis) { axis = _axis; }

void push(const T &key, const BB<D> &target) {
void push(const T &key, const BB<D, Real> &target) {
data.emplace_back(key, target);
update_mbb();
}
Expand All @@ -46,15 +46,15 @@ template <IndexType T, int B = 6, int D = 2> class Leaf {
}
}

bool filter(DataType<T, D> &value) { // false means given value is ignored
bool filter(DataType<T, D, Real> &value) { // false means given value is ignored
// Phase 2: C++20 requires explicit 'this' capture
auto comp = [this](const auto &a, const auto &b) noexcept {
return a.second.val_for_comp(axis) < b.second.val_for_comp(axis);
};

if (data.size() < B) { // if there is room, just push the candidate
auto iter = std::lower_bound(data.begin(), data.end(), value, comp);
DataType<T, D> tmp_value = DataType<T, D>(value);
DataType<T, D, Real> tmp_value = DataType<T, D, Real>(value);
data.insert(iter, std::move(tmp_value));
mbb += value.second;
return true;
Expand All @@ -76,9 +76,9 @@ template <IndexType T, int B = 6, int D = 2> class Leaf {
};

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class PseudoPRTreeNode {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class PseudoPRTreeNode {
public:
Leaf<T, B, D> leaves[2 * D];
Leaf<T, B, D, Real> leaves[2 * D];
std::unique_ptr<PseudoPRTreeNode> left, right;

PseudoPRTreeNode() {
Expand All @@ -98,7 +98,7 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTreeNode {
archive(left, right, leaves);
}

void address_of_leaves(vec<Leaf<T, B, D> *> &out) {
void address_of_leaves(vec<Leaf<T, B, D, Real> *> &out) {
for (auto &leaf : leaves) {
if (leaf.data.size() > 0) {
out.emplace_back(&leaf);
Expand All @@ -120,20 +120,20 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTreeNode {
};

// Phase 8: Apply C++20 concept constraints
template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {
template <IndexType T, int B = 6, int D = 2, typename Real = float> class PseudoPRTree {
public:
std::unique_ptr<PseudoPRTreeNode<T, B, D>> root;
vec<Leaf<T, B, D> *> cache_children;
std::unique_ptr<PseudoPRTreeNode<T, B, D, Real>> root;
vec<Leaf<T, B, D, Real> *> cache_children;
const int nthreads = std::max(1, (int)std::thread::hardware_concurrency());

PseudoPRTree() { root = std::make_unique<PseudoPRTreeNode<T, B, D>>(); }
PseudoPRTree() { root = std::make_unique<PseudoPRTreeNode<T, B, D, Real>>(); }

template <class iterator> PseudoPRTree(const iterator &b, const iterator &e) {
if (!root) {
root = std::make_unique<PseudoPRTreeNode<T, B, D>>();
root = std::make_unique<PseudoPRTreeNode<T, B, D, Real>>();
}
construct(root.get(), b, e, 0);
clean_data<T, D>(b, e);
clean_data<T, D, Real>(b, e);
}

template <class Archive> void serialize(Archive &archive) {
Expand All @@ -142,7 +142,7 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {
}

template <class iterator>
void construct(PseudoPRTreeNode<T, B, D> *node, const iterator &b,
void construct(PseudoPRTreeNode<T, B, D, Real> *node, const iterator &b,
const iterator &e, const int depth) {
if (e - b > 0 && node != nullptr) {
bool use_recursive_threads = std::pow(2, depth + 1) <= nthreads;
Expand All @@ -152,20 +152,20 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {

vec<std::thread> threads;
threads.reserve(2);
PseudoPRTreeNode<T, B, D> *node_left, *node_right;
PseudoPRTreeNode<T, B, D, Real> *node_left, *node_right;

const int axis = depth % (2 * D);
auto ee = node->filter(b, e);
auto m = b;
std::advance(m, (ee - b) / 2);
std::nth_element(b, m, ee,
[axis](const DataType<T, D> &lhs,
const DataType<T, D> &rhs) noexcept {
[axis](const DataType<T, D, Real> &lhs,
const DataType<T, D, Real> &rhs) noexcept {
return lhs.second[axis] < rhs.second[axis];
});

if (m - b > 0) {
node->left = std::make_unique<PseudoPRTreeNode<T, B, D>>(axis);
node->left = std::make_unique<PseudoPRTreeNode<T, B, D, Real>>(axis);
node_left = node->left.get();
if (use_recursive_threads) {
threads.push_back(
Expand All @@ -175,7 +175,7 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {
}
}
if (ee - m > 0) {
node->right = std::make_unique<PseudoPRTreeNode<T, B, D>>(axis);
node->right = std::make_unique<PseudoPRTreeNode<T, B, D, Real>>(axis);
node_right = node->right.get();
if (use_recursive_threads) {
threads.push_back(
Expand All @@ -191,7 +191,7 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {

auto get_all_leaves(const int hint) {
if (cache_children.empty()) {
using U = PseudoPRTreeNode<T, B, D>;
using U = PseudoPRTreeNode<T, B, D, Real>;
cache_children.reserve(hint);
auto node = root.get();
queue<U *> que;
Expand All @@ -210,15 +210,15 @@ template <IndexType T, int B = 6, int D = 2> class PseudoPRTree {
return cache_children;
}

std::pair<DataType<T, D> *, DataType<T, D> *> as_X(void *placement,
std::pair<DataType<T, D, Real> *, DataType<T, D, Real> *> as_X(void *placement,
const int hint) {
DataType<T, D> *b, *e;
DataType<T, D, Real> *b, *e;
auto children = get_all_leaves(hint);
T total = children.size();
b = reinterpret_cast<DataType<T, D> *>(placement);
b = reinterpret_cast<DataType<T, D, Real> *>(placement);
e = b + total;
for (T i = 0; i < total; i++) {
new (b + i) DataType<T, D>{i, children[i]->mbb};
new (b + i) DataType<T, D, Real>{i, children[i]->mbb};
}
return {b, e};
}
Expand Down
Loading