diff --git a/tc/include/tc/core.hpp b/tc/include/tc/core.hpp index 7c3f42a..d4852ba 100644 --- a/tc/include/tc/core.hpp +++ b/tc/include/tc/core.hpp @@ -11,18 +11,9 @@ namespace tc { using Mult = std::uint16_t; constexpr Mult FREE = 0; - /** - * @brief Mapping from "global" generator names or objects to indexes used for value lookup. - * @tparam Gen_ - */ - template - struct Index; - /** * @brief Complete representation of a quotient group. Describes the action of each generator on each coset. - * @tparam Gen_ */ - template struct Cosets; /** @@ -42,7 +33,6 @@ namespace tc { * @see * Coxeter Group (Wikipedia) */ - template struct Group; /** @@ -52,33 +42,7 @@ namespace tc { template struct Path; - template<> - struct Index<> { - size_t operator()(size_t const &idx) const { - return idx; - } - }; - - template - struct Index { - using Gen = Gen_; - - std::vector _gens{}; - - explicit Index(std::vector gens) : _gens(gens) {} - - template - Index(It begin, It end) : _gens(begin, end) {} - - size_t operator()(Gen const &gen) const { - auto it = std::find(_gens.begin(), _gens.end(), gen); - assert(it != _gens.end()); - return it - _gens.begin(); - } - }; - - template<> - struct Cosets<> { + struct Cosets { static constexpr size_t UNSET = std::numeric_limits::max(); private: @@ -108,7 +72,7 @@ namespace tc { [[nodiscard]] size_t size() const; - friend Group<>; // only constructible via Group<>::solve + friend Group; // only constructible via Group<>::solve private: explicit Cosets(size_t rank); @@ -122,8 +86,7 @@ namespace tc { [[nodiscard]] bool isset(size_t idx) const; }; - template<> - struct Group<> { + struct Group { using Rel = std::tuple; private: @@ -147,7 +110,7 @@ namespace tc { [[nodiscard]] Group sub(std::vector const &idxs) const; - [[nodiscard]] Cosets<> solve(std::vector const &idxs = {}, size_t bound = SIZE_MAX) const; + [[nodiscard]] Cosets solve(std::vector const &idxs = {}, size_t bound = SIZE_MAX) const; }; template<> @@ -160,7 +123,7 @@ namespace tc { public: // todo be smarter about move semantics - explicit Path(Cosets<> const &cosets) : _data() { + explicit Path(Cosets const &cosets) : _data() { _data.resize(cosets.order()); std::vector complete(cosets.order(), false); @@ -206,101 +169,21 @@ namespace tc { } }; - template - struct Cosets : public Cosets<> { - using Gen = Gen_; - - private: - Index _index; - - friend Path; - - public: - Cosets(Cosets<> g, std::vector gens) : Cosets<>(g), _index(gens) {} - - void set(size_t coset, Gen const &gen, size_t target) { - Cosets<>::set(coset, _index(gen), target); - } - - [[nodiscard]] size_t get(size_t coset, Gen const &gen) const { - return Cosets<>::get(coset, _index(gen)); - } - - [[nodiscard]] bool isset(size_t coset, Gen const &gen) const { - return Cosets<>::isset(coset, _index(gen)); - } - - [[nodiscard]] std::vector gens() const { - return _index._gens; - } - - private: - Cosets(size_t rank, std::vector gens) : Cosets<>(rank), _index(gens) {} - }; - - template - struct Group : public Group<> { - using Gen = Gen_; - using Rel = std::tuple; - - private: - Index _index; - - public: - Group(Group const &) = default; - - Group(Group &&) noexcept = default; - - Group(Group<> g, std::vector gens) : Group<>(g), _index(gens) {} - - Group(size_t rank, std::vector gens) : Group<>(rank), _index(gens) {} - - ~Group() = default; - - void set(Gen const &u, Gen const &v, Mult m) { - Group<>::set(_index(u), _index(v), m); - } - - [[nodiscard]] Mult get(Gen const &u, Gen const &v) const { - return Group<>::get(_index(u), _index(v)); - } - - [[nodiscard]] std::vector gens() const { - return _index._gens; - } - - [[nodiscard]] Group sub(std::vector const &gens) const { - std::vector idxs(gens.size()); - std::transform(gens.begin(), gens.end(), idxs.begin(), _index); - return Group(Group<>::sub(idxs), gens); - } - - [[nodiscard]] Cosets solve(std::vector const &gens = {}, size_t bound = SIZE_MAX) const { - std::vector idxs(gens.size()); - std::transform(gens.begin(), gens.end(), idxs.begin(), _index); - - return Cosets(Group<>::solve(idxs, bound), _index._gens); - } - }; - template struct Path : public Path<> { using Gen = Gen_; private: - Index _index; + std::vector _index; public: - // todo be smarter about move semantics - explicit Path(Cosets const &cosets) : Path<>(cosets), _index(cosets._index) {} - template - Path(Cosets<> const &cosets, T const &gens) - : Path<>(cosets), _index(gens.begin(), gens.end()) {} + Path(Cosets const &cosets, T &&gens) + : Path<>(cosets), _index(std::forward(gens).begin(), std::forward(gens).end()) {} template void walk(Elem const &start, BinaryOp op, It out) { - Path<>::walk(start, op, out, _index._gens.begin()); + Path<>::walk(start, op, out, _index.begin()); } }; } diff --git a/tc/include/tc/groups.hpp b/tc/include/tc/groups.hpp index 2a52119..aeaa0e5 100644 --- a/tc/include/tc/groups.hpp +++ b/tc/include/tc/groups.hpp @@ -10,14 +10,14 @@ namespace tc { * Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c] * @param mults: The sequence of multiplicites between adjacent generators. */ - Group<> schlafli(const std::vector &mults); + Group schlafli(const std::vector &mults); - Group<> coxeter(const std::string &symbol); + Group coxeter(const std::string &symbol); - Group<> vcoxeter(const std::string &symbol, const std::vector &values); + Group vcoxeter(const std::string &symbol, const std::vector &values); template - Group<> coxeter(const std::string &symbol, const Args &... args) { + Group coxeter(const std::string &symbol, const Args &... args) { std::vector values = {{args...}}; return vcoxeter(symbol, values); } diff --git a/tc/src/cosets.cpp b/tc/src/cosets.cpp index d91ab55..5375204 100644 --- a/tc/src/cosets.cpp +++ b/tc/src/cosets.cpp @@ -1,54 +1,54 @@ #include namespace tc { - Cosets<>::Cosets(size_t rank) + Cosets::Cosets(size_t rank) : _rank(rank), _order(0), _complete(false), _data() {} - void Cosets<>::set(size_t coset, size_t gen, size_t target) { + void Cosets::set(size_t coset, size_t gen, size_t target) { set(coset * rank() + gen, target); } - [[nodiscard]] size_t Cosets<>::get(size_t coset, size_t gen) const { + [[nodiscard]] size_t Cosets::get(size_t coset, size_t gen) const { return get(coset * rank() + gen); } - [[nodiscard]] bool Cosets<>::isset(size_t coset, size_t gen) const { + [[nodiscard]] bool Cosets::isset(size_t coset, size_t gen) const { return isset(coset * rank() + gen); } - [[nodiscard]] size_t Cosets<>::rank() const { + [[nodiscard]] size_t Cosets::rank() const { return _rank; } - [[nodiscard]] size_t Cosets<>::order() const { + [[nodiscard]] size_t Cosets::order() const { return _order; } - [[nodiscard]] bool Cosets<>::complete() const { + [[nodiscard]] bool Cosets::complete() const { return _complete; } - [[nodiscard]] size_t Cosets<>::size() const { + [[nodiscard]] size_t Cosets::size() const { return _data.size(); } - void Cosets<>::add_row() { + void Cosets::add_row() { _data.resize(_data.size() + rank(), UNSET); _order++; } - void Cosets<>::set(size_t idx, size_t target) { + void Cosets::set(size_t idx, size_t target) { size_t coset = idx / rank(); size_t gen = idx % rank(); _data[idx] = target; _data[target * rank() + gen] = coset; } - [[nodiscard]] size_t Cosets<>::get(size_t idx) const { + [[nodiscard]] size_t Cosets::get(size_t idx) const { return _data[idx]; } - [[nodiscard]] bool Cosets<>::isset(size_t idx) const { + [[nodiscard]] bool Cosets::isset(size_t idx) const { return get(idx) != UNSET; } diff --git a/tc/src/group.cpp b/tc/src/group.cpp index 9866c02..38ad0cb 100644 --- a/tc/src/group.cpp +++ b/tc/src/group.cpp @@ -3,13 +3,13 @@ #include namespace tc { - Group<>::Group(size_t rank) : _rank(rank), _mults(_rank * _rank, 2) { + Group::Group(size_t rank) : _rank(rank), _mults(_rank * _rank, 2) { for (int idx = 0; idx < rank; ++idx) { set(idx, idx, 1); } } - void Group<>::set(size_t u, size_t v, Mult m) { + void Group::set(size_t u, size_t v, Mult m) { assert(u < rank()); assert(v < rank()); @@ -17,19 +17,19 @@ namespace tc { _mults[v * rank() + u] = m; } - [[nodiscard]] Mult Group<>::get(size_t u, size_t v) const { + [[nodiscard]] Mult Group::get(size_t u, size_t v) const { assert(u < rank()); assert(v < rank()); return _mults[u * rank() + v]; } - [[nodiscard]] size_t Group<>::rank() const { + [[nodiscard]] size_t Group::rank() const { return _rank; } - [[nodiscard]] Group<> Group<>::sub(std::vector const &idxs) const { - Group<> res(idxs.size()); + [[nodiscard]] Group Group::sub(std::vector const &idxs) const { + Group res(idxs.size()); for (int i = 0; i < idxs.size(); ++i) { for (int j = i; j < idxs.size(); ++j) { diff --git a/tc/src/groups.cpp b/tc/src/groups.cpp index dab2cb8..34d9edd 100644 --- a/tc/src/groups.cpp +++ b/tc/src/groups.cpp @@ -5,15 +5,15 @@ #include namespace tc { - Group<> schlafli(const std::vector &mults) { - Group<> res(mults.size() + 1); + Group schlafli(const std::vector &mults) { + Group res(mults.size() + 1); for (size_t i = 0; i < mults.size(); ++i) { res.set(i, i + 1, mults[i]); } return res; } - Group<> vcoxeter(const std::string &symbol, const std::vector &values) { + Group vcoxeter(const std::string &symbol, const std::vector &values) { fmt::dynamic_format_arg_store ds; for (const auto &value: values) { diff --git a/tc/src/lang.cpp b/tc/src/lang.cpp index 3b102cb..33827b1 100644 --- a/tc/src/lang.cpp +++ b/tc/src/lang.cpp @@ -14,7 +14,7 @@ struct Graph { size_t rank{}; - std::vector::Rel> edges{}; + std::vector edges{}; }; struct Op { @@ -287,10 +287,10 @@ Graph eval(const std::vector &ops) { } namespace tc { - Group<> coxeter(const std::string &symbol) { + Group coxeter(const std::string &symbol) { auto ops = compile(symbol); auto diagram = eval(ops); - Group<> res(diagram.rank); + Group res(diagram.rank); for (const auto &[i, j, m]: diagram.edges) { res.set(i, j, m); } diff --git a/tc/src/solve.cpp b/tc/src/solve.cpp index 779deed..cfa7449 100644 --- a/tc/src/solve.cpp +++ b/tc/src/solve.cpp @@ -20,10 +20,10 @@ namespace tc { }; struct Tables { - std::vector::Rel> rels; + std::vector rels; std::vector> rows; - explicit Tables(std::vector::Rel> rels) + explicit Tables(std::vector rels) : rels(std::move(rels)), rows() { } @@ -36,9 +36,9 @@ namespace tc { } }; - [[nodiscard]] Cosets<> Group<>::solve(std::vector const &idxs, size_t bound) const { + [[nodiscard]] Cosets Group::solve(std::vector const &idxs, size_t bound) const { // region Initialize Cosets Table - Cosets<> cosets(rank()); + Cosets cosets(rank()); cosets.add_row(); if (rank() == 0) { @@ -53,7 +53,7 @@ namespace tc { // endregion // region Initialize Relation Tables - std::vector::Rel> rels; + std::vector rels; for (int i = 0; i < rank(); ++i) { for (int j = i + 1; j < rank(); ++j) { // The algorithm only works for Coxeter groups; multiplicities m_ii=1 are assumed. Relation tables diff --git a/tc/test/test_solve.cpp b/tc/test/test_solve.cpp index 2efcc74..03f162e 100644 --- a/tc/test/test_solve.cpp +++ b/tc/test/test_solve.cpp @@ -11,7 +11,7 @@ testing::AssertionResult AssertSolveOrder( const char *group_expr, const char *sub_gens_expr, const char *expected_order_expr, - const tc::Group<> &group, + const tc::Group &group, const std::vector &sub_gens, size_t expected_order ) { @@ -50,43 +50,43 @@ testing::AssertionResult AssertSolveOrder( using v = std::vector; -tc::Group<> A(unsigned int n) { +tc::Group A(unsigned int n) { return tc::vcoxeter("3 * {}", {n - 1}); } -tc::Group<> B(unsigned int n) { +tc::Group B(unsigned int n) { return tc::vcoxeter("4 3 * {}", {n - 2}); } -tc::Group<> D(unsigned int n) { +tc::Group D(unsigned int n) { return tc::vcoxeter("3 * [1 1 {}]", {n - 3}); } -tc::Group<> E(unsigned int n) { +tc::Group E(unsigned int n) { return tc::vcoxeter("3 * [1 2 {}]", {n - 4}); } -tc::Group<> F4() { +tc::Group F4() { return tc::coxeter("3 4 3"); } -tc::Group<> G2() { +tc::Group G2() { return tc::coxeter("6"); } -tc::Group<> H(unsigned int n) { +tc::Group H(unsigned int n) { return tc::vcoxeter("5 3 * {}", {n - 2}); } -tc::Group<> I2(unsigned int n) { +tc::Group I2(unsigned int n) { return tc::vcoxeter("{}", {n}); } -tc::Group<> T(unsigned int m, unsigned int n) { +tc::Group T(unsigned int m, unsigned int n) { return tc::vcoxeter("{} 2 {}", {m, n}); } -tc::Group<> T(unsigned int n) { +tc::Group T(unsigned int n) { return T(n, n); } diff --git a/vis/include/mirror.hpp b/vis/include/mirror.hpp index 8bd2194..a835d16 100644 --- a/vis/include/mirror.hpp +++ b/vis/include/mirror.hpp @@ -9,7 +9,7 @@ #include template -Eigen::Matrix mirror(const tc::Group<> &group) { +Eigen::Matrix mirror(const tc::Group &group) { Eigen::Matrix res; res.setZero(); diff --git a/vis/include/solver.hpp b/vis/include/solver.hpp index 4034892..1545d6a 100644 --- a/vis/include/solver.hpp +++ b/vis/include/solver.hpp @@ -7,6 +7,9 @@ #include #include "combo_iterator.hpp" +#include "fmt/core.h" +#include "fmt/ranges.h" + /** * An primitive stage N indices. * @tparam N @@ -28,7 +31,7 @@ struct Primitive { ~Primitive() = default; - void apply(const tc::Cosets<> &table, int gen) { + void apply(const tc::Cosets &table, int gen) { for (auto &ind: indices) { ind = table.get(ind, gen); } @@ -38,7 +41,7 @@ struct Primitive { /** * Produce a list of all generators for the group context. The range [0..group.ngens). */ -std::vector generators(const tc::Group<> &context) { +std::vector generators(const tc::Group &context) { std::vector g_gens(context.rank()); std::iota(g_gens.begin(), g_gens.end(), 0); return g_gens; @@ -65,7 +68,7 @@ std::vector recontext_gens( * Apply some context transformation to all primitives of this mesh. */ template -std::vector> apply(std::vector> prims, const tc::Cosets<> &table, int gen) { +std::vector> apply(std::vector> prims, const tc::Cosets &table, int gen) { for (auto &prim: prims) { prim.apply(table, gen); } @@ -79,7 +82,7 @@ template [[nodiscard]] std::vector> recontext( std::vector> prims, - const tc::Group<> &context, + const tc::Group &context, const std::vector &g_gens, const std::vector &sg_gens ) { @@ -110,13 +113,13 @@ std::vector> recontext( template std::vector> merge(const std::vector>> &meshes) { size_t size = 0; - for (const auto &mesh : meshes) { + for (const auto &mesh: meshes) { size += mesh.size(); } std::vector> res; res.reserve(size); - for (const auto &mesh : meshes) { + for (const auto &mesh: meshes) { res.insert(res.end(), mesh.begin(), mesh.end()); } @@ -127,18 +130,17 @@ template [[nodiscard]] std::vector>> each_tile( std::vector> prims, - const tc::Group<> &context, + const tc::Group &context, const std::vector &g_gens, const std::vector &sg_gens ) { std::vector> base = recontext(prims, context, g_gens, sg_gens); const auto proper_sg_gens = recontext_gens(g_gens, sg_gens); - const auto table = context.sub(g_gens).solve({}); + const auto &table = context.sub(g_gens).solve({}); + const auto &cosets = context.sub(g_gens).solve(proper_sg_gens); - const tc::Cosets<> &cosets = context.sub(g_gens).solve(proper_sg_gens); - - tc::Path path(cosets); + tc::Path<> path(cosets); std::vector>> res(path.order()); path.walk(base, [&](auto from, auto to) { @@ -152,7 +154,7 @@ template [[nodiscard]] std::vector> tile( std::vector> prims, - const tc::Group<> &context, + const tc::Group &context, const std::vector &g_gens, const std::vector &sg_gens ) { @@ -183,7 +185,7 @@ std::vector> fan(std::vector> prims, size_t root) */ template std::vector> triangulate( - const tc::Group<> &context, + const tc::Group &context, const std::vector &g_gens ) { if (g_gens.size() + 1 != N) { @@ -207,7 +209,7 @@ std::vector> triangulate( // Single-index primitives should not be further triangulated. template<> std::vector> triangulate( - const tc::Group<> &, + const tc::Group &, const std::vector &g_gens ) { if (not g_gens.empty()) { @@ -220,7 +222,7 @@ std::vector> triangulate( } template -auto hull(const tc::Group<> &group, T all_sg_gens, const std::vector> &exclude) { +auto hull(const tc::Group &group, T all_sg_gens, const std::vector> &exclude) { std::vector>> parts; auto g_gens = generators(group); @@ -237,7 +239,7 @@ auto hull(const tc::Group<> &group, T all_sg_gens, const std::vector(group, sg_gens); const auto &tiles = each_tile(base, group, g_gens, sg_gens); - for (const auto &tile : tiles) { + for (const auto &tile: tiles) { parts.push_back(tile); } } diff --git a/vis/src/comps.hpp b/vis/src/comps.hpp index 9fba90f..4d3816b 100644 --- a/vis/src/comps.hpp +++ b/vis/src/comps.hpp @@ -19,7 +19,7 @@ namespace vis { struct Group { - tc::Group<> group; + tc::Group group; vec5 root; vec3 color;