diff --git a/src/include/lattice.h b/src/include/lattice.h index 6b571a3..4544132 100644 --- a/src/include/lattice.h +++ b/src/include/lattice.h @@ -13,7 +13,7 @@ namespace pivot { -template struct box; +template struct box; /** * @brief Represents a closed interval [left_, right_]. @@ -39,7 +39,7 @@ struct interval { /** * @brief Represents a Dim-dimensional point. */ -template class point : boost::multipliable, int> { +template class point : boost::multipliable, int> { public: point() = default; @@ -77,10 +77,10 @@ template class point : boost::multipliable, int> { std::array coords_{}; }; -template point(std::array) -> point; +template point(std::array) -> point; /** @brief Represents a Dim-dimensional box. */ -template struct box : boost::additive, point> { +template struct box : boost::additive, point> { std::array intervals_; box() = delete; @@ -94,7 +94,7 @@ template struct box : boost::additive, point> { * in the sense that the input sequences of points (p0, ...) is effectively translated by e0 - p0 * prior to the box's construction. In other words, the box will always have a vertex at e0. */ - box(std::span> points); + box(std::span> points); bool operator==(const box &b) const; @@ -105,9 +105,9 @@ template struct box : boost::additive, point> { bool empty() const; /** @brief Action of a point (understood as a vector) on a box */ - box &operator+=(const point &b); + box &operator+=(const point &b); - box &operator-=(const point &b); + box &operator-=(const point &b); /** * @brief Returns the "union" of two boxes. @@ -129,7 +129,7 @@ template struct box : boost::additive, point> { std::string to_string() const; }; -template box(std::array, N>) -> box; +template box(std::array, N>) -> box; struct point_hash { int num_steps_; @@ -138,7 +138,7 @@ struct point_hash { // This hashing method, which exploits the known range of values that can be taken by the // sequence of points in a walk, ppears to result in better performance than other methods tested. - template std::size_t operator()(const point &p) const; + template std::size_t operator()(const point &p) const; }; /** @@ -156,7 +156,7 @@ struct point_hash { * entries of S by S(i). Note that P e(i) = e(P(i)) and S e(i) = S(i) e(i), where e(i) * is the i-th standard unit vector. */ -template class transform { +template class transform { public: /** @brief Constructs the identity transformation. */ @@ -174,7 +174,7 @@ template class transform { * * Note that the resulting pivot transformation is not uniquely defined by the inputs. */ - transform(const point &p, const point &q); + transform(const point &p, const point &q); /** @brief Produce a uniformly random transfom.*/ template static transform rand(Gen &gen) { @@ -203,7 +203,7 @@ template class transform { * * which means the P(i)-th component of the result is S(P(i)) p[i]. */ - point operator*(const point &p) const; + point operator*(const point &p) const; /** * @brief Composes two transforms. @@ -238,7 +238,7 @@ template class transform { * which means the P(i)-th interval from which SP(B) is constructed has bounds S(P(i)) a[i] and * S(P(i)) b[i]. */ - box operator*(const box &b) const; + box operator*(const box &b) const; /** @brief Returns true if the transform is the identity. */ bool is_identity() const; diff --git a/src/include/utils.h b/src/include/utils.h index 1ea524a..b5e6099 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -4,10 +4,10 @@ namespace pivot { -template std::vector> from_csv(const std::string &path); +template std::vector> from_csv(const std::string &path); -template void to_csv(const std::string &path, const std::vector> &points); +template void to_csv(const std::string &path, const std::vector> &points); -template std::vector> line(int num_steps); +template std::vector> line(int num_steps); } // namespace pivot diff --git a/src/include/walk.h b/src/include/walk.h index 9be21d7..636cf31 100644 --- a/src/include/walk.h +++ b/src/include/walk.h @@ -11,10 +11,10 @@ namespace pivot { -template class walk : public walk_base { +template class walk : public walk_base { public: - walk(const std::vector> &steps, std::optional seed = std::nullopt); + walk(const std::vector> &steps, std::optional seed = std::nullopt); walk(int num_steps, std::optional seed = std::nullopt); walk(const std::string &path, std::optional seed = std::nullopt); @@ -24,15 +24,15 @@ template class walk : public walk_base { ~walk() = default; - point operator[](int i) const { return steps_[i]; } + point operator[](int i) const { return steps_[i]; } int num_steps() const { return steps_.size(); } - point endpoint() const override { return steps_.back(); } + point endpoint() const override { return steps_.back(); } - std::optional>> try_pivot(int step, const transform &trans) const; + std::optional>> try_pivot(int step, const transform &trans) const; - std::pair>>> try_rand_pivot() const; + std::pair>>> try_rand_pivot() const; bool rand_pivot(bool fast = false) override; @@ -43,15 +43,15 @@ template class walk : public walk_base { void export_csv(const std::string &path) const override; protected: - std::vector> steps_; - boost::unordered_flat_map, int, point_hash> occupied_; + std::vector> steps_; + boost::unordered_flat_map, int, point_hash> occupied_; mutable std::mt19937 rng_; mutable std::uniform_int_distribution dist_; - void do_pivot(int step, std::vector> &new_points); + void do_pivot(int step, std::vector> &new_points); - point pivot_point(int step, int i, const transform &trans) const; + point pivot_point(int step, int i, const transform &trans) const; }; } // namespace pivot diff --git a/src/include/walk_base.h b/src/include/walk_base.h index fdb0e87..36ee01e 100644 --- a/src/include/walk_base.h +++ b/src/include/walk_base.h @@ -4,7 +4,7 @@ namespace pivot { -template class walk_base { +template class walk_base { public: virtual ~walk_base() = default; @@ -15,7 +15,7 @@ template class walk_base { virtual void export_csv(const std::string &path) const = 0; - virtual point endpoint() const = 0; + virtual point endpoint() const = 0; }; } // namespace pivot diff --git a/src/include/walk_node.h b/src/include/walk_node.h index 038c7c2..2f4ec31 100644 --- a/src/include/walk_node.h +++ b/src/include/walk_node.h @@ -10,18 +10,19 @@ namespace pivot { /* FORWARD REFERENCES */ -template class walk_node; +template class walk_node; -template -bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, - const point &r_anchor, const transform &l_symm, const transform &r_symm); +template +bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, + const point &r_anchor, const transform &l_symm, + const transform &r_symm); -template class walk_tree; +template class walk_tree; /* WALK NODE */ /** @brief Represents a node in a walk tree. */ -template class walk_node { +template class walk_node { public: /* CONSTRUCTORS, DESTRUCTOR */ @@ -33,7 +34,7 @@ template class walk_node { * * @return The root of the walk tree. */ - static walk_node *pivot_rep(const std::vector> &steps, walk_node *buf = nullptr); + static walk_node *pivot_rep(const std::vector> &steps, walk_node *buf = nullptr); /** @brief Returns the root of a walk tree for the balanced representation of a walk given by a sequence of points. * @@ -42,7 +43,7 @@ template class walk_node { * * @return The root of the walk tree. */ - static walk_node *balanced_rep(const std::vector> &steps, walk_node *buf = nullptr); + static walk_node *balanced_rep(const std::vector> &steps, walk_node *buf = nullptr); /** @brief Copies the given node but none of the nodes it links to. */ walk_node(const walk_node &w) = default; @@ -57,11 +58,11 @@ template class walk_node { int id() const { return id_; } - const box &bbox() const { return bbox_; } + const box &bbox() const { return bbox_; } - const point &endpoint() const { return end_; } + const point &endpoint() const { return end_; } - const transform &symm() const { return symm_; } + const transform &symm() const { return symm_; } walk_node *left() const { return left_; } @@ -125,7 +126,7 @@ template class walk_node { * * @return Whether the transform creates an intersection. */ - bool shuffle_intersect(const transform &t, std::optional is_left_child); + bool shuffle_intersect(const transform &t, std::optional is_left_child); /** * @brief Checks if the current walk has an intersection via a top-down algorithm. @@ -136,7 +137,7 @@ template class walk_node { /* OTHER FUNCTIONS */ - std::vector> steps() const; + std::vector> steps() const; void todot(const std::string &path) const; @@ -146,15 +147,16 @@ template class walk_node { walk_node *parent_{}; walk_node *left_{}; walk_node *right_{}; - transform symm_; - box bbox_; - point end_; + transform symm_; + box bbox_; + point end_; - friend class walk_tree; + friend class walk_tree; /* CONVENIENCE METHODS */ - walk_node(int id, int num_sites, const transform &symm, const box &bbox, const point &end); + walk_node(int id, int num_sites, const transform &symm, const box &bbox, + const point &end); void set_left(walk_node *left) { left_ = left; @@ -185,15 +187,15 @@ template class walk_node { Agnode_t *todot(Agraph_t *g, const cgraph_t &cgraph) const; // recursive helper - static walk_node *balanced_rep(std::span> steps, int start, const transform &glob_symm, - walk_node *buf); + static walk_node *balanced_rep(std::span> steps, int start, + const transform &glob_symm, walk_node *buf); - bool shuffle_intersect(const transform &t, std::optional was_left_child, + bool shuffle_intersect(const transform &t, std::optional was_left_child, std::optional is_left_child); - template - friend bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, - const point &r_anchor, const transform &l_symm, const transform &r_symm); + template + friend bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, + const point &r_anchor, const transform &l_symm, const transform &r_symm); }; } // namespace pivot diff --git a/src/include/walk_tree.h b/src/include/walk_tree.h index 1afb8ed..63af7c5 100644 --- a/src/include/walk_tree.h +++ b/src/include/walk_tree.h @@ -10,10 +10,10 @@ namespace pivot { -template class walk_node; +template class walk_node; /** @brief Represents an entire saw-tree (as per Clisby's 2010 paper). */ -template class walk_tree : public walk_base { +template class walk_tree : public walk_base { public: /* CONSTRUCTORS, DESTRUCTOR */ @@ -56,7 +56,7 @@ template class walk_tree : public walk_base { * * @warning It is not recommended to set balanced=false. */ - walk_tree(const std::vector> &steps, std::optional seed = std::nullopt, + walk_tree(const std::vector> &steps, std::optional seed = std::nullopt, bool balanced = true); /**@brief Deallocates the entire tree and every node it contains. */ @@ -64,9 +64,9 @@ template class walk_tree : public walk_base { /* GETTERS, SETTERS, SIMPLE UTILITIES */ - walk_node *root() const; + walk_node *root() const; - point endpoint() const override; + point endpoint() const override; bool is_leaf() const; @@ -84,7 +84,7 @@ template class walk_tree : public walk_base { * * @return reference to the node */ - walk_node &find_node(int n); + walk_node &find_node(int n); /* HIGH-LEVEL FUNCTIONS (see Clisby (2010), Section 2.7) */ @@ -99,7 +99,7 @@ template class walk_tree : public walk_base { * * @return Whether the pivot was successful. */ - bool try_pivot(int n, const transform &r); + bool try_pivot(int n, const transform &r); /** * @brief Attempt to pivot the walk about the given lattice site using Clisby's Attempt_pivot_fast function. @@ -112,7 +112,7 @@ template class walk_tree : public walk_base { * * @return Whether the pivot was successful. */ - bool try_pivot_fast(int n, const transform &r); + bool try_pivot_fast(int n, const transform &r); /** * @brief Attempts to pivot the walk about a randomly chosen lattice site with a random transform. @@ -130,7 +130,7 @@ template class walk_tree : public walk_base { * * @return Sequence of lattice sites. */ - std::vector> steps() const; + std::vector> steps() const; /** * @brief Check whether the walk is self-avoiding using a naive algorithm. @@ -149,10 +149,10 @@ template class walk_tree : public walk_base { void todot(const std::string &path) const; private: - std::unique_ptr> root_; + std::unique_ptr> root_; std::mt19937 rng_; std::uniform_int_distribution dist_; // distribution for choosing a random lattice site - walk_node *buf_; // buffer into which nodes are allocated (used for fast node lookup by id) + walk_node *buf_; // buffer into which nodes are allocated (used for fast node lookup by id) }; } // namespace pivot diff --git a/src/lattice/box.hpp b/src/lattice/box.hpp index 2b93179..bf6de71 100644 --- a/src/lattice/box.hpp +++ b/src/lattice/box.hpp @@ -24,7 +24,7 @@ std::string interval::to_string() const { return result; } -template box &box::operator+=(const point &p) { +template box &box::operator+=(const point &p) { for (int i = 0; i < Dim; ++i) { intervals_[i].left_ += p[i]; intervals_[i].right_ += p[i]; @@ -32,7 +32,7 @@ template box &box::operator+=(const point &p) { return *this; } -template box &box::operator-=(const point &b) { +template box &box::operator-=(const point &b) { for (int i = 0; i < Dim; ++i) { intervals_[i].left_ -= b[i]; intervals_[i].right_ -= b[i]; @@ -40,9 +40,9 @@ template box &box::operator-=(const point &b) { return *this; } -template box::box(const std::array &intervals) : intervals_(intervals) {} +template box::box(const std::array &intervals) : intervals_(intervals) {} -template box::box(std::span> points) { +template box::box(std::span> points) { std::array min; std::array max; min.fill(std::numeric_limits::max()); @@ -60,17 +60,17 @@ template box::box(std::span> points) { } } -template bool box::operator==(const box &b) const { return intervals_ == b.intervals_; } +template bool box::operator==(const box &b) const { return intervals_ == b.intervals_; } -template bool box::operator!=(const box &b) const { return intervals_ != b.intervals_; } +template bool box::operator!=(const box &b) const { return intervals_ != b.intervals_; } -template interval box::operator[](int i) const { return intervals_[i]; } +template interval box::operator[](int i) const { return intervals_[i]; } -template bool box::empty() const { +template bool box::empty() const { return std::any_of(intervals_.begin(), intervals_.end(), [](const interval &i) { return i.empty(); }); } -template box box::operator|(const box &b) const { +template box box::operator|(const box &b) const { std::array intervals; for (int i = 0; i < Dim; ++i) { intervals[i] = interval(std::min(intervals_[i].left_, b.intervals_[i].left_), @@ -79,7 +79,7 @@ template box box::operator|(const box &b) const { return box(intervals); } -template box box::operator&(const box &b) const { +template box box::operator&(const box &b) const { std::array intervals; for (int i = 0; i < Dim; ++i) { intervals[i] = interval(std::max(intervals_[i].left_, b.intervals_[i].left_), @@ -88,7 +88,7 @@ template box box::operator&(const box &b) const { return box(intervals); } -template std::string box::to_string() const { +template std::string box::to_string() const { std::string s = ""; for (int i = 0; i < Dim - 1; ++i) { s += intervals_[i].to_string() + " x "; diff --git a/src/lattice/point.hpp b/src/lattice/point.hpp index 8264ed1..ddc44ce 100644 --- a/src/lattice/point.hpp +++ b/src/lattice/point.hpp @@ -4,17 +4,17 @@ namespace pivot { -template point::point(const std::array &coords) : coords_(coords) {} +template point::point(const std::array &coords) : coords_(coords) {} -template point point::unit(int i) { - point result; +template point point::unit(int i) { + point result; result.coords_[i] = 1; return result; } -template int point::operator[](int i) const { return coords_[i]; } +template int point::operator[](int i) const { return coords_[i]; } -template bool point::operator==(const point &p) const { +template bool point::operator==(const point &p) const { // Faster than using std::equal, at least for small arrays // https://stackoverflow.com/questions/39262496/why-is-stdequal-much-slower-than-a-hand-rolled-loop-for-two-small-stdarray for (int i = 0; i < Dim; ++i) { @@ -25,9 +25,9 @@ template bool point::operator==(const point &p) const { return true; } -template bool point::operator!=(const point &p) const { return !(*this == p); } +template bool point::operator!=(const point &p) const { return !(*this == p); } -template point point::operator+(const point &p) const { +template point point::operator+(const point &p) const { std::array sum; for (int i = 0; i < Dim; ++i) { sum[i] = coords_[i] + p.coords_[i]; @@ -35,7 +35,7 @@ template point point::operator+(const point &p) const { return point(sum); } -template point point::operator-(const point &p) const { +template point point::operator-(const point &p) const { std::array diff; for (int i = 0; i < Dim; ++i) { diff[i] = coords_[i] - p.coords_[i]; @@ -43,14 +43,14 @@ template point point::operator-(const point &p) const { return point(diff); } -template point &point::operator*=(int k) { +template point &point::operator*=(int k) { for (int i = 0; i < Dim; ++i) { coords_[i] *= k; } return *this; } -template int point::norm() const { +template int point::norm() const { int sum = 0; for (int i = 0; i < Dim; ++i) { sum += coords_[i] * coords_[i]; @@ -58,7 +58,7 @@ template int point::norm() const { return sum; } -template std::string point::to_string() const { +template std::string point::to_string() const { std::string s = "("; for (int i = 0; i < Dim - 1; ++i) { s += std::to_string(coords_[i]) + ", "; @@ -74,7 +74,7 @@ template std::string point::to_string() const { point_hash::point_hash(int num_steps) : num_steps_(num_steps) {} -template std::size_t point_hash::operator()(const point &p) const { +template std::size_t point_hash::operator()(const point &p) const { std::size_t hash = 0; for (int i = 0; i < Dim; ++i) { hash = num_steps_ + p[i] + 2 * num_steps_ * hash; diff --git a/src/lattice/transform.hpp b/src/lattice/transform.hpp index 7b035c0..1fe7fde 100644 --- a/src/lattice/transform.hpp +++ b/src/lattice/transform.hpp @@ -4,20 +4,21 @@ namespace pivot { -template transform::transform() { +template transform::transform() { for (int i = 0; i < Dim; ++i) { perm_[i] = i; // trivial permutation signs_[i] = 1; // standard orientations (no flips) } } -template -transform::transform(const std::array &perm, const std::array &signs) +template +transform::transform(const std::array &perm, const std::array &signs) : perm_(perm), signs_(signs) {} -template transform::transform(const point &p, const point &q) : transform() { +template +transform::transform(const point &p, const point &q) : transform() { // The input points should differ by 1 in a single coordinate. Start by finding this coordinate or fail. - point diff = q - p; + point diff = q - p; int idx = -1; for (int i = 0; i < Dim; ++i) { if (std::abs(diff[i]) == 1) { @@ -39,25 +40,26 @@ template transform::transform(const point &p, const point transform transform::rand() { +template transform transform::rand() { static std::random_device rd; static std::mt19937 gen(rd()); return rand(gen); } -template bool transform::operator==(const transform &t) const { +template bool transform::operator==(const transform &t) const { return perm_ == t.perm_ && signs_ == t.signs_; } -template point transform::operator*(const point &p) const { +template point transform::operator*(const point &p) const { std::array coords; for (int i = 0; i < Dim; ++i) { coords[perm_[i]] = signs_[perm_[i]] * p[i]; } - return point(coords); + return point(coords); } -template transform transform::operator*(const transform &t) const { +template +transform transform::operator*(const transform &t) const { std::array perm; std::array signs; for (int i = 0; i < Dim; ++i) { @@ -67,17 +69,17 @@ template transform transform::operator*(const transform return transform(perm, signs); } -template box transform::operator*(const box &b) const { +template box transform::operator*(const box &b) const { std::array intervals; for (int i = 0; i < Dim; ++i) { int x = signs_[perm_[i]] * b.intervals_[i].left_; int y = signs_[perm_[i]] * b.intervals_[i].right_; intervals[perm_[i]] = interval(std::min(x, y), std::max(x, y)); } - return box(intervals); + return box(intervals); } -template bool transform::is_identity() const { +template bool transform::is_identity() const { for (int i = 0; i < Dim; ++i) { if (perm_[i] != i || signs_[i] != 1) { return false; @@ -86,7 +88,7 @@ template bool transform::is_identity() const { return true; } -template transform transform::inverse() const { +template transform transform::inverse() const { std::array perm; std::array signs; for (int i = 0; i < Dim; ++i) { @@ -96,7 +98,7 @@ template transform transform::inverse() const { return transform(perm, signs); } -template std::array, Dim> transform::to_matrix() const { +template std::array, Dim> transform::to_matrix() const { std::array, Dim> matrix = {}; for (int i = 0; i < Dim; ++i) { matrix[perm_[i]][i] = signs_[perm_[i]]; @@ -104,7 +106,7 @@ template std::array, Dim> transform::to_matr return matrix; } -template std::string transform::to_string() const { +template std::string transform::to_string() const { auto matrix = to_matrix(); std::string s = "["; for (int i = 0; i < Dim; ++i) { diff --git a/src/loop.h b/src/loop.h index 8987a79..e37fe3d 100644 --- a/src/loop.h +++ b/src/loop.h @@ -6,15 +6,15 @@ #include "walk.h" #include "walk_tree.h" -template +template int main_loop(int num_steps, int iters, bool naive, bool fast, int seed, bool require_success, bool verify, const std::string &in_path, const std::string &out_dir) { std::unique_ptr> w; if (naive) { if (in_path.empty()) { - w = std::make_unique>(num_steps, seed); + w = std::make_unique>(num_steps, seed); } else { - w = std::make_unique>(in_path, seed); + w = std::make_unique>(in_path, seed); } } else { if (in_path.empty()) { diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 05975f1..cb82d0a 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -8,9 +8,9 @@ namespace pivot { -template std::vector> from_csv(const std::string &path) { +template std::vector> from_csv(const std::string &path) { std::ifstream file(path); - std::vector> points; + std::vector> points; std::string line; while (std::getline(file, line)) { std::array coords; @@ -23,12 +23,13 @@ template std::vector> from_csv(const std::string &path) { coords[i] = std::stoi(line.substr(start, end - start)); start = end + 1; } - points.push_back(point(coords)); + points.push_back(point(coords)); } return points; } -template void to_csv(const std::string &path, const std::vector> &points) { +template +void to_csv(const std::string &path, const std::vector> &points) { // TODO: check path exists std::ofstream file(path); for (const auto &p : points) { @@ -39,17 +40,18 @@ template void to_csv(const std::string &path, const std::vector std::vector> line(int num_steps) { - std::vector> steps(num_steps); +template std::vector> line(int num_steps) { + std::vector> steps(num_steps); for (int i = 0; i < num_steps; ++i) { - steps[i] = (i + 1) * point::unit(0); + steps[i] = (i + 1) * point::unit(0); } return steps; } -#define FROM_CSV_INST(z, n, data) template std::vector> from_csv(const std::string &path); -#define TO_CSV_INST(z, n, data) template void to_csv(const std::string &path, const std::vector> &points); -#define LINE_INST(z, n, data) template std::vector> line(int num_steps); +#define FROM_CSV_INST(z, n, data) template std::vector> from_csv(const std::string &path); +#define TO_CSV_INST(z, n, data) \ + template void to_csv(const std::string &path, const std::vector> &points); +#define LINE_INST(z, n, data) template std::vector> line(int num_steps); // cppcheck-suppress syntaxError BOOST_PP_REPEAT_FROM_TO(1, DIMS_UB, TO_CSV_INST, ~) diff --git a/src/walks/node/ctors.hpp b/src/walks/node/ctors.hpp index fd71c4d..8c98b44 100644 --- a/src/walks/node/ctors.hpp +++ b/src/walks/node/ctors.hpp @@ -2,27 +2,29 @@ namespace pivot { -template -walk_node::walk_node(int id, int num_sites, const transform &symm, const box &bbox, - const point &end) +template +walk_node::walk_node(int id, int num_sites, const transform &symm, const box &bbox, + const point &end) : id_(id), num_sites_(num_sites), symm_(symm), bbox_(bbox), end_(end) {} -template walk_node *walk_node::pivot_rep(const std::vector> &steps, walk_node *buf) { +template +walk_node *walk_node::pivot_rep(const std::vector> &steps, walk_node *buf) { int num_sites = steps.size(); if (num_sites < 2) { throw std::invalid_argument("num_sites must be at least 2"); } - walk_node *root = - buf ? new (buf) walk_node(1, num_sites, transform(steps[0], steps[1]), box(steps), steps[num_sites - 1]) - : new walk_node(1, num_sites, transform(steps[0], steps[1]), box(steps), steps[num_sites - 1]); + walk_node *root = + buf ? new (buf) + walk_node(1, num_sites, transform(steps[0], steps[1]), box(steps), steps[num_sites - 1]) + : new walk_node(1, num_sites, transform(steps[0], steps[1]), box(steps), steps[num_sites - 1]); auto node = root; for (int i = 0; i < num_sites - 2; ++i) { auto id = i + 2; - node->right_ = buf ? new (buf + id - 1) - walk_node(id, num_sites - i - 1, transform(steps[i + 1], steps[i + 2]), - box(std::span>(steps).subspan(i + 1)), steps[num_sites - 1]) + node->right_ = buf ? new (buf + id - 1) walk_node(id, num_sites - i - 1, transform(steps[i + 1], steps[i + 2]), + box(std::span>(steps).subspan(i + 1)), + steps[num_sites - 1]) : new walk_node(i + 2, num_sites - i - 1, transform(steps[i + 1], steps[i + 2]), - box(std::span>(steps).subspan(i + 1)), + box(std::span>(steps).subspan(i + 1)), steps[num_sites - 1]); // TODO: double-check this node->right_->parent_ = node; node = node->right_; @@ -30,14 +32,16 @@ template walk_node *walk_node::pivot_rep(const std::vector

-walk_node *walk_node::balanced_rep(const std::vector> &steps, walk_node *buf) { - return balanced_rep(steps, 1, transform(), buf); +template +walk_node *walk_node::balanced_rep(const std::vector> &steps, + walk_node *buf) { + return balanced_rep(steps, 1, transform(), buf); } -template -walk_node *walk_node::balanced_rep(std::span> steps, int start, - const transform &glob_symm, walk_node *buf) { +template +walk_node *walk_node::balanced_rep(std::span> steps, int start, + const transform &glob_symm, + walk_node *buf) { int num_sites = steps.size(); if (num_sites < 1) { throw std::invalid_argument("num_sites must be at least 1"); @@ -54,8 +58,8 @@ walk_node *walk_node::balanced_rep(std::span> steps, auto abs_symm = transform(steps[n - 1], steps[n]); auto glob_inv = glob_symm.inverse(); auto rel_symm = glob_inv * abs_symm; - auto rel_end = glob_inv * (steps.back() - steps.front()) + point::unit(0); - auto rel_box = point::unit(0) + glob_inv * (box(steps) - point::unit(0)); + auto rel_end = glob_inv * (steps.back() - steps.front()) + point::unit(0); + auto rel_box = point::unit(0) + glob_inv * (box(steps) - point::unit(0)); int id = start + n - 1; walk_node *root = buf ? new (buf + id - 1) walk_node(id, num_sites, rel_symm, rel_box, rel_end) : new walk_node(id, num_sites, rel_symm, rel_box, rel_end); @@ -71,20 +75,20 @@ walk_node *walk_node::balanced_rep(std::span> steps, return root; } -template walk_node walk_node::create_leaf() { +template walk_node walk_node::create_leaf() { std::array intervals; intervals[0] = interval(1, 1); for (int i = 1; i < Dim; ++i) { intervals[i] = interval(0, 0); } - return walk_node(0, 1, transform(), box(intervals), point::unit(0)); + return walk_node(0, 1, transform(), box(intervals), point::unit(0)); } -template walk_node &walk_node::leaf() { - static walk_node leaf = create_leaf(); +template walk_node &walk_node::leaf() { + static walk_node leaf = create_leaf(); return leaf; } -template walk_node::~walk_node() = default; +template walk_node::~walk_node() = default; } // namespace pivot diff --git a/src/walks/node/graphviz.hpp b/src/walks/node/graphviz.hpp index 1102304..189b225 100644 --- a/src/walks/node/graphviz.hpp +++ b/src/walks/node/graphviz.hpp @@ -2,7 +2,7 @@ namespace pivot { -template void walk_node::todot(const std::string &path) const { +template void walk_node::todot(const std::string &path) const { gvc_t &gvc = gvc_t::load(); cgraph_t &cgraph = cgraph_t::load(); @@ -20,7 +20,7 @@ template void walk_node::todot(const std::string &path) const { gvc.gvFreeContext(context); } -template Agnode_t *walk_node::todot(Agraph_t *g, const cgraph_t &cgraph) const { +template Agnode_t *walk_node::todot(Agraph_t *g, const cgraph_t &cgraph) const { auto name = std::to_string(id_); Agnode_t *node = cgraph.agnode(g, (char *)name.c_str(), 1); if (cgraph.agset((void *)node, (char *)"shape", (char *)"box") != 0) { diff --git a/src/walks/node/pivot.hpp b/src/walks/node/pivot.hpp index 6465da2..35103d3 100644 --- a/src/walks/node/pivot.hpp +++ b/src/walks/node/pivot.hpp @@ -7,7 +7,7 @@ namespace pivot { // Note: A detail missing from Clisby's paper regarding tree rotations is that parent pointers must be updated, // except when the rotation is called from shuffle_intersect. -template walk_node *walk_node::rotate_left(bool set_parent) { +template walk_node *walk_node::rotate_left(bool set_parent) { if (right_->is_leaf()) { throw std::invalid_argument("can't rotate left on a leaf node"); } @@ -41,7 +41,7 @@ template walk_node *walk_node::rotate_left(bool set_parent) return this; } -template walk_node *walk_node::rotate_right(bool set_parent) { +template walk_node *walk_node::rotate_right(bool set_parent) { if (left_->is_leaf()) { throw std::invalid_argument("can't rotate right on a leaf node"); } @@ -75,7 +75,7 @@ template walk_node *walk_node::rotate_right(bool set_parent) return this; } -template void walk_node::merge() { +template void walk_node::merge() { num_sites_ = left_->num_sites_ + right_->num_sites_; bbox_ = left_->bbox_ | (left_->end_ + symm_ * right_->bbox_); @@ -84,7 +84,7 @@ template void walk_node::merge() { /* USER LEVEL OPERATIONS */ -template walk_node *walk_node::shuffle_up(int id) { +template walk_node *walk_node::shuffle_up(int id) { if (id < left_->num_sites_) { left_->shuffle_up(id); rotate_right(); @@ -96,7 +96,7 @@ template walk_node *walk_node::shuffle_up(int id) { return this; } -template walk_node *walk_node::shuffle_down() { +template walk_node *walk_node::shuffle_down() { int id = std::floor((num_sites_ + 1) / 2.0); if (id < left_->num_sites_) { rotate_right(); @@ -109,13 +109,14 @@ template walk_node *walk_node::shuffle_down() { return this; } -template bool walk_node::intersect() const { - return ::pivot::intersect(left_, right_, point(), left_->end_, transform(), symm_); +template bool walk_node::intersect() const { + return ::pivot::intersect(left_, right_, point(), left_->end_, transform(), symm_); } -template -bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, - const point &r_anchor, const transform &l_symm, const transform &r_symm) { +template +bool intersect(const walk_node *l_walk, const walk_node *r_walk, const point &l_anchor, + const point &r_anchor, const transform &l_symm, + const transform &r_symm) { auto l_box = l_anchor + l_symm * l_walk->bbox_; auto r_box = r_anchor + r_symm * r_walk->bbox_; if ((l_box & r_box).empty()) { @@ -137,27 +138,29 @@ bool intersect(const walk_node *l_walk, const walk_node *r_walk, const } } -template bool walk_node::shuffle_intersect(const transform &t, std::optional is_left_child) { +template +bool walk_node::shuffle_intersect(const transform &t, std::optional is_left_child) { return shuffle_intersect(t, std::nullopt, is_left_child); } -template -bool walk_node::shuffle_intersect(const transform &t, std::optional was_left_child, - std::optional is_left_child) { +template +bool walk_node::shuffle_intersect(const transform &t, std::optional was_left_child, + std::optional is_left_child) { /* BASE CASE */ if (was_left_child.has_value()) { if (was_left_child.value()) { - if (::pivot::intersect(left_, right_->right_, point(), left_->end_ + symm_ * t * right_->left_->end_, - transform(), symm_ * t * right_->symm_)) { + if (::pivot::intersect(left_, right_->right_, point(), left_->end_ + symm_ * t * right_->left_->end_, + transform(), symm_ * t * right_->symm_)) { return true; } } else { - if (::pivot::intersect(left_->left_, right_, point(), left_->end_, transform(), symm_ * t)) { + if (::pivot::intersect(left_->left_, right_, point(), left_->end_, transform(), + symm_ * t)) { return true; } } } else { - if (::pivot::intersect(left_, right_, point(), left_->end_, transform(), symm_ * t)) { + if (::pivot::intersect(left_, right_, point(), left_->end_, transform(), symm_ * t)) { return true; } } diff --git a/src/walks/node/walk_node.cpp b/src/walks/node/walk_node.cpp index c301d3f..fcf3ac6 100644 --- a/src/walks/node/walk_node.cpp +++ b/src/walks/node/walk_node.cpp @@ -10,7 +10,7 @@ namespace pivot { -template bool walk_node::operator==(const walk_node &other) const { +template bool walk_node::operator==(const walk_node &other) const { if (is_leaf() && other.is_leaf()) { return true; } @@ -18,10 +18,12 @@ template bool walk_node::operator==(const walk_node &other) const end_ == other.end_ && *left_ == *other.left_ && *right_ == *other.right_; } -template bool walk_node::is_leaf() const { return left_ == nullptr && right_ == nullptr; } +template bool walk_node::is_leaf() const { + return left_ == nullptr && right_ == nullptr; +} -template std::vector> walk_node::steps() const { - std::vector> result; +template std::vector> walk_node::steps() const { + std::vector> result; if (is_leaf()) { result.push_back(end_); return result; diff --git a/src/walks/walk.cpp b/src/walks/walk.cpp index 52600a7..0f4a184 100644 --- a/src/walks/walk.cpp +++ b/src/walks/walk.cpp @@ -6,8 +6,8 @@ namespace pivot { -template -walk::walk(const std::vector> &steps, std::optional seed) +template +walk::walk(const std::vector> &steps, std::optional seed) : steps_(steps), occupied_(steps.size(), point_hash(steps.size())) { for (int i = 0; i < num_steps(); ++i) { occupied_[steps_[i]] = i; @@ -17,19 +17,21 @@ walk::walk(const std::vector> &steps, std::optional(0, num_steps() - 1); } -template -walk::walk(int num_steps, std::optional seed) : walk(line(num_steps), seed) {} +template +walk::walk(int num_steps, std::optional seed) : walk(line(num_steps), seed) {} -template -walk::walk(const std::string &path, std::optional seed) : walk(from_csv(path), seed) {} +template +walk::walk(const std::string &path, std::optional seed) + : walk(from_csv(path), seed) {} -template -std::optional>> walk::try_pivot(int step, const transform &trans) const { +template +std::optional>> walk::try_pivot(int step, + const transform &trans) const { if (trans.is_identity()) { return {}; } - std::vector> new_points(num_steps() - step - 1); + std::vector> new_points(num_steps() - step - 1); for (int i = step + 1; i < num_steps(); ++i) { auto q = pivot_point(step, i, trans); auto it = occupied_.find(q); @@ -41,13 +43,14 @@ std::optional>> walk::try_pivot(int step, const tran return new_points; } -template std::pair>>> walk::try_rand_pivot() const { +template +std::pair>>> walk::try_rand_pivot() const { auto step = dist_(rng_); - auto r = transform::rand(rng_); + auto r = transform::rand(rng_); return {step, try_pivot(step, r)}; } -template bool walk::rand_pivot(bool fast) { +template bool walk::rand_pivot(bool fast) { if (fast) { // TODO: implement Kennedy algorithm throw std::invalid_argument("fast pivot not implemented for naive walk"); } @@ -60,14 +63,14 @@ template bool walk::rand_pivot(bool fast) { return true; } -template bool walk::rand_pivot(int num_workers) { +template bool walk::rand_pivot(int num_workers) { if (num_workers == 0) { return rand_pivot(); } std::vector steps(num_workers); - std::vector>>> proposals(num_workers); - std::vector>>>>> futures(num_workers); + std::vector>>> proposals(num_workers); + std::vector>>>>> futures(num_workers); for (int i = 0; i < num_workers; ++i) { futures[i] = std::async(&walk::try_rand_pivot, this); } @@ -89,7 +92,7 @@ template bool walk::rand_pivot(int num_workers) { return success; } -template bool walk::self_avoiding() const { +template bool walk::self_avoiding() const { for (int i = 0; i < num_steps(); ++i) { for (int j = i + 1; j < num_steps(); ++j) { if (steps_[i] == steps_[j]) { @@ -100,9 +103,11 @@ template bool walk::self_avoiding() const { return true; } -template void walk::export_csv(const std::string &path) const { return to_csv(path, steps_); } +template void walk::export_csv(const std::string &path) const { + return to_csv(path, steps_); +} -template void walk::do_pivot(int step, std::vector> &new_points) { +template void walk::do_pivot(int step, std::vector> &new_points) { for (auto it = steps_.begin() + step + 1; it != steps_.end(); ++it) { occupied_.erase(*it); } @@ -112,12 +117,13 @@ template void walk::do_pivot(int step, std::vector> &n } } -template point walk::pivot_point(int step, int i, const transform &trans) const { +template +point walk::pivot_point(int step, int i, const transform &trans) const { auto p = steps_[step]; return p + trans * (steps_[i] - p); } -#define WALK_INST(z, n, data) template class walk; +#define WALK_INST(z, n, data) template class walk; // cppcheck-suppress syntaxError BOOST_PP_REPEAT_FROM_TO(1, DIMS_UB, WALK_INST, ~) diff --git a/src/walks/walk_tree.cpp b/src/walks/walk_tree.cpp index 44a12c8..39380b6 100644 --- a/src/walks/walk_tree.cpp +++ b/src/walks/walk_tree.cpp @@ -13,34 +13,35 @@ namespace pivot { /* CONSTRUCTORS, DESTRUCTOR */ -template -walk_tree::walk_tree(int num_sites, std::optional seed, bool balanced) - : walk_tree(line(num_sites), seed, balanced) {} +template +walk_tree::walk_tree(int num_sites, std::optional seed, bool balanced) + : walk_tree(line(num_sites), seed, balanced) {} -template -walk_tree::walk_tree(const std::string &path, std::optional seed, bool balanced) - : walk_tree(from_csv(path), seed, balanced) {} +template +walk_tree::walk_tree(const std::string &path, std::optional seed, bool balanced) + : walk_tree(from_csv(path), seed, balanced) {} -template -walk_tree::walk_tree(const std::vector> &steps, std::optional seed, bool balanced) { +template +walk_tree::walk_tree(const std::vector> &steps, std::optional seed, + bool balanced) { if (steps.size() < 2) { throw std::invalid_argument("walk must have at least 2 sites (1 step)"); } buf_ = nullptr; if (balanced) { - size_t buf_size = sizeof(walk_node) * (steps.size() - 1); - constexpr auto alignment = std::align_val_t(alignof(walk_node)); - buf_ = static_cast *>(::operator new[](buf_size, alignment)); + size_t buf_size = sizeof(walk_node) * (steps.size() - 1); + constexpr auto alignment = std::align_val_t(alignof(walk_node)); + buf_ = static_cast *>(::operator new[](buf_size, alignment)); } - root_ = balanced ? std::unique_ptr>(walk_node::balanced_rep(steps, buf_)) - : std::unique_ptr>(walk_node::pivot_rep(steps, buf_)); + root_ = balanced ? std::unique_ptr>(walk_node::balanced_rep(steps, buf_)) + : std::unique_ptr>(walk_node::pivot_rep(steps, buf_)); rng_ = std::mt19937(seed.value_or(std::random_device()())); dist_ = std::uniform_int_distribution(1, steps.size() - 1); } -template walk_tree::~walk_tree() { - std::stack *> nodes; +template walk_tree::~walk_tree() { + std::stack *> nodes; nodes.push(root_.release()); while (!nodes.empty()) { auto curr = nodes.top(); @@ -55,32 +56,32 @@ template walk_tree::~walk_tree() { } if (buf_) { - ::operator delete[](buf_, std::align_val_t(alignof(walk_node))); + ::operator delete[](buf_, std::align_val_t(alignof(walk_node))); } } /* GETTERS, SETTERS, SIMPLE UTILITIES */ -template walk_node *walk_tree::root() const { return root_.get(); } +template walk_node *walk_tree::root() const { return root_.get(); } -template point walk_tree::endpoint() const { return root_->endpoint(); } +template point walk_tree::endpoint() const { return root_->endpoint(); } -template bool walk_tree::is_leaf() const { return root_->is_leaf(); } +template bool walk_tree::is_leaf() const { return root_->is_leaf(); } /* PRIMITIVE OPERATIONS */ -template walk_node &walk_tree::find_node(int n) { +template walk_node &walk_tree::find_node(int n) { if (!buf_) { throw std::runtime_error("find_node can only be used on trees initialized with balanced=true"); } - walk_node &result = buf_[n - 1]; + walk_node &result = buf_[n - 1]; assert(result.id_ == n); return result; } /* HIGH-LEVEL FUNCTIONS */ -template bool walk_tree::try_pivot(int n, const transform &r) { +template bool walk_tree::try_pivot(int n, const transform &r) { if (r.is_identity()) { return false; } @@ -98,13 +99,13 @@ template bool walk_tree::try_pivot(int n, const transform &r return success; } -template bool walk_tree::try_pivot_fast(int n, const transform &t) { +template bool walk_tree::try_pivot_fast(int n, const transform &t) { if (t.is_identity()) { return false; } - walk_node *w = &find_node(n); // TODO: a pointer seems to be needed, but why? - walk_node w_copy(*w); + walk_node *w = &find_node(n); // TODO: a pointer seems to be needed, but why? + walk_node w_copy(*w); auto success = !w_copy.shuffle_intersect(t, w->is_left_child()); if (success) { root_->shuffle_up(n); @@ -115,17 +116,19 @@ template bool walk_tree::try_pivot_fast(int n, const transform bool walk_tree::rand_pivot(bool fast) { +template bool walk_tree::rand_pivot(bool fast) { auto site = dist_(rng_); - auto r = transform::rand(rng_); + auto r = transform::rand(rng_); return fast ? try_pivot_fast(site, r) : try_pivot(site, r); } /* OTHER FUNCTIONS */ -template std::vector> walk_tree::steps() const { return root_->steps(); } +template std::vector> walk_tree::steps() const { + return root_->steps(); +} -template bool walk_tree::self_avoiding() const { +template bool walk_tree::self_avoiding() const { auto steps = this->steps(); for (size_t i = 0; i < steps.size(); ++i) { for (size_t j = i + 1; j < steps.size(); ++j) { @@ -137,9 +140,11 @@ template bool walk_tree::self_avoiding() const { return true; } -template void walk_tree::export_csv(const std::string &path) const { return to_csv(path, steps()); } +template void walk_tree::export_csv(const std::string &path) const { + return to_csv(path, steps()); +} -template void walk_tree::todot(const std::string &path) const { root_->todot(path); } +template void walk_tree::todot(const std::string &path) const { root_->todot(path); } /* TEMPLATE INSTANTIATION */