mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 12:02:47 -05:00
ENH: Remove template Group<> and Cosets<>
This commit is contained in:
@@ -11,18 +11,9 @@ namespace tc {
|
|||||||
using Mult = std::uint16_t;
|
using Mult = std::uint16_t;
|
||||||
constexpr Mult FREE = 0;
|
constexpr Mult FREE = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Mapping from "global" generator names or objects to indexes used for value lookup.
|
|
||||||
* @tparam Gen_
|
|
||||||
*/
|
|
||||||
template<typename Gen_=void>
|
|
||||||
struct Index;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Complete representation of a quotient group. Describes the action of each generator on each coset.
|
* @brief Complete representation of a quotient group. Describes the action of each generator on each coset.
|
||||||
* @tparam Gen_
|
|
||||||
*/
|
*/
|
||||||
template<typename Gen_=void>
|
|
||||||
struct Cosets;
|
struct Cosets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +33,6 @@ namespace tc {
|
|||||||
* @see
|
* @see
|
||||||
* <a href="https://en.wikipedia.org/wiki/Coxeter_group#Definition">Coxeter Group (Wikipedia)</a>
|
* <a href="https://en.wikipedia.org/wiki/Coxeter_group#Definition">Coxeter Group (Wikipedia)</a>
|
||||||
*/
|
*/
|
||||||
template<typename Gen_=void>
|
|
||||||
struct Group;
|
struct Group;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,33 +42,7 @@ namespace tc {
|
|||||||
template<typename Gen_=void>
|
template<typename Gen_=void>
|
||||||
struct Path;
|
struct Path;
|
||||||
|
|
||||||
template<>
|
struct Cosets {
|
||||||
struct Index<> {
|
|
||||||
size_t operator()(size_t const &idx) const {
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Gen_>
|
|
||||||
struct Index {
|
|
||||||
using Gen = Gen_;
|
|
||||||
|
|
||||||
std::vector<Gen> _gens{};
|
|
||||||
|
|
||||||
explicit Index(std::vector<Gen> gens) : _gens(gens) {}
|
|
||||||
|
|
||||||
template<typename It>
|
|
||||||
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<> {
|
|
||||||
static constexpr size_t UNSET = std::numeric_limits<size_t>::max();
|
static constexpr size_t UNSET = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -108,7 +72,7 @@ namespace tc {
|
|||||||
|
|
||||||
[[nodiscard]] size_t size() const;
|
[[nodiscard]] size_t size() const;
|
||||||
|
|
||||||
friend Group<>; // only constructible via Group<>::solve
|
friend Group; // only constructible via Group<>::solve
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Cosets(size_t rank);
|
explicit Cosets(size_t rank);
|
||||||
@@ -122,8 +86,7 @@ namespace tc {
|
|||||||
[[nodiscard]] bool isset(size_t idx) const;
|
[[nodiscard]] bool isset(size_t idx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
struct Group {
|
||||||
struct Group<> {
|
|
||||||
using Rel = std::tuple<size_t, size_t, Mult>;
|
using Rel = std::tuple<size_t, size_t, Mult>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -147,7 +110,7 @@ namespace tc {
|
|||||||
|
|
||||||
[[nodiscard]] Group sub(std::vector<size_t> const &idxs) const;
|
[[nodiscard]] Group sub(std::vector<size_t> const &idxs) const;
|
||||||
|
|
||||||
[[nodiscard]] Cosets<> solve(std::vector<size_t> const &idxs = {}, size_t bound = SIZE_MAX) const;
|
[[nodiscard]] Cosets solve(std::vector<size_t> const &idxs = {}, size_t bound = SIZE_MAX) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@@ -160,7 +123,7 @@ namespace tc {
|
|||||||
public:
|
public:
|
||||||
// todo be smarter about move semantics
|
// todo be smarter about move semantics
|
||||||
|
|
||||||
explicit Path(Cosets<> const &cosets) : _data() {
|
explicit Path(Cosets const &cosets) : _data() {
|
||||||
_data.resize(cosets.order());
|
_data.resize(cosets.order());
|
||||||
|
|
||||||
std::vector<bool> complete(cosets.order(), false);
|
std::vector<bool> complete(cosets.order(), false);
|
||||||
@@ -206,101 +169,21 @@ namespace tc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Gen_>
|
|
||||||
struct Cosets : public Cosets<> {
|
|
||||||
using Gen = Gen_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Index<Gen> _index;
|
|
||||||
|
|
||||||
friend Path<Gen>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Cosets(Cosets<> g, std::vector<Gen> 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<Gen> gens() const {
|
|
||||||
return _index._gens;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Cosets(size_t rank, std::vector<Gen> gens) : Cosets<>(rank), _index(gens) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Gen_>
|
|
||||||
struct Group : public Group<> {
|
|
||||||
using Gen = Gen_;
|
|
||||||
using Rel = std::tuple<Gen, Gen, Mult>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Index<Gen> _index;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Group(Group const &) = default;
|
|
||||||
|
|
||||||
Group(Group &&) noexcept = default;
|
|
||||||
|
|
||||||
Group(Group<> g, std::vector<Gen> gens) : Group<>(g), _index(gens) {}
|
|
||||||
|
|
||||||
Group(size_t rank, std::vector<Gen> 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<Gen> gens() const {
|
|
||||||
return _index._gens;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] Group sub(std::vector<Gen> const &gens) const {
|
|
||||||
std::vector<size_t> idxs(gens.size());
|
|
||||||
std::transform(gens.begin(), gens.end(), idxs.begin(), _index);
|
|
||||||
return Group(Group<>::sub(idxs), gens);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] Cosets<Gen> solve(std::vector<Gen> const &gens = {}, size_t bound = SIZE_MAX) const {
|
|
||||||
std::vector<size_t> idxs(gens.size());
|
|
||||||
std::transform(gens.begin(), gens.end(), idxs.begin(), _index);
|
|
||||||
|
|
||||||
return Cosets<Gen>(Group<>::solve(idxs, bound), _index._gens);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Gen_>
|
template<typename Gen_>
|
||||||
struct Path : public Path<> {
|
struct Path : public Path<> {
|
||||||
using Gen = Gen_;
|
using Gen = Gen_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Index<Gen> _index;
|
std::vector<Gen> _index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// todo be smarter about move semantics
|
|
||||||
explicit Path(Cosets<Gen> const &cosets) : Path<>(cosets), _index(cosets._index) {}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Path(Cosets<> const &cosets, T const &gens)
|
Path(Cosets const &cosets, T &&gens)
|
||||||
: Path<>(cosets), _index(gens.begin(), gens.end()) {}
|
: Path<>(cosets), _index(std::forward<T>(gens).begin(), std::forward<T>(gens).end()) {}
|
||||||
|
|
||||||
template<typename Elem, typename BinaryOp, std::random_access_iterator It>
|
template<typename Elem, typename BinaryOp, std::random_access_iterator It>
|
||||||
void walk(Elem const &start, BinaryOp op, It out) {
|
void walk(Elem const &start, BinaryOp op, It out) {
|
||||||
Path<>::walk(start, op, out, _index._gens.begin());
|
Path<>::walk(start, op, out, _index.begin());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ namespace tc {
|
|||||||
* Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c]
|
* Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c]
|
||||||
* @param mults: The sequence of multiplicites between adjacent generators.
|
* @param mults: The sequence of multiplicites between adjacent generators.
|
||||||
*/
|
*/
|
||||||
Group<> schlafli(const std::vector<unsigned int> &mults);
|
Group schlafli(const std::vector<unsigned int> &mults);
|
||||||
|
|
||||||
Group<> coxeter(const std::string &symbol);
|
Group coxeter(const std::string &symbol);
|
||||||
|
|
||||||
Group<> vcoxeter(const std::string &symbol, const std::vector<unsigned int> &values);
|
Group vcoxeter(const std::string &symbol, const std::vector<unsigned int> &values);
|
||||||
|
|
||||||
template<typename ...Args>
|
template<typename ...Args>
|
||||||
Group<> coxeter(const std::string &symbol, const Args &... args) {
|
Group coxeter(const std::string &symbol, const Args &... args) {
|
||||||
std::vector<unsigned int> values = {{args...}};
|
std::vector<unsigned int> values = {{args...}};
|
||||||
return vcoxeter(symbol, values);
|
return vcoxeter(symbol, values);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
#include <tc/core.hpp>
|
#include <tc/core.hpp>
|
||||||
|
|
||||||
namespace tc {
|
namespace tc {
|
||||||
Cosets<>::Cosets(size_t rank)
|
Cosets::Cosets(size_t rank)
|
||||||
: _rank(rank), _order(0), _complete(false), _data() {}
|
: _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);
|
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);
|
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);
|
return isset(coset * rank() + gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t Cosets<>::rank() const {
|
[[nodiscard]] size_t Cosets::rank() const {
|
||||||
return _rank;
|
return _rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t Cosets<>::order() const {
|
[[nodiscard]] size_t Cosets::order() const {
|
||||||
return _order;
|
return _order;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool Cosets<>::complete() const {
|
[[nodiscard]] bool Cosets::complete() const {
|
||||||
return _complete;
|
return _complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t Cosets<>::size() const {
|
[[nodiscard]] size_t Cosets::size() const {
|
||||||
return _data.size();
|
return _data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cosets<>::add_row() {
|
void Cosets::add_row() {
|
||||||
_data.resize(_data.size() + rank(), UNSET);
|
_data.resize(_data.size() + rank(), UNSET);
|
||||||
_order++;
|
_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 coset = idx / rank();
|
||||||
size_t gen = idx % rank();
|
size_t gen = idx % rank();
|
||||||
_data[idx] = target;
|
_data[idx] = target;
|
||||||
_data[target * rank() + gen] = coset;
|
_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];
|
return _data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool Cosets<>::isset(size_t idx) const {
|
[[nodiscard]] bool Cosets::isset(size_t idx) const {
|
||||||
return get(idx) != UNSET;
|
return get(idx) != UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace tc {
|
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) {
|
for (int idx = 0; idx < rank; ++idx) {
|
||||||
set(idx, idx, 1);
|
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(u < rank());
|
||||||
assert(v < rank());
|
assert(v < rank());
|
||||||
|
|
||||||
@@ -17,19 +17,19 @@ namespace tc {
|
|||||||
_mults[v * rank() + u] = m;
|
_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(u < rank());
|
||||||
assert(v < rank());
|
assert(v < rank());
|
||||||
|
|
||||||
return _mults[u * rank() + v];
|
return _mults[u * rank() + v];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t Group<>::rank() const {
|
[[nodiscard]] size_t Group::rank() const {
|
||||||
return _rank;
|
return _rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Group<> Group<>::sub(std::vector<size_t> const &idxs) const {
|
[[nodiscard]] Group Group::sub(std::vector<size_t> const &idxs) const {
|
||||||
Group<> res(idxs.size());
|
Group res(idxs.size());
|
||||||
|
|
||||||
for (int i = 0; i < idxs.size(); ++i) {
|
for (int i = 0; i < idxs.size(); ++i) {
|
||||||
for (int j = i; j < idxs.size(); ++j) {
|
for (int j = i; j < idxs.size(); ++j) {
|
||||||
|
|||||||
@@ -5,15 +5,15 @@
|
|||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
namespace tc {
|
namespace tc {
|
||||||
Group<> schlafli(const std::vector<unsigned int> &mults) {
|
Group schlafli(const std::vector<unsigned int> &mults) {
|
||||||
Group<> res(mults.size() + 1);
|
Group res(mults.size() + 1);
|
||||||
for (size_t i = 0; i < mults.size(); ++i) {
|
for (size_t i = 0; i < mults.size(); ++i) {
|
||||||
res.set(i, i + 1, mults[i]);
|
res.set(i, i + 1, mults[i]);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group<> vcoxeter(const std::string &symbol, const std::vector<unsigned int> &values) {
|
Group vcoxeter(const std::string &symbol, const std::vector<unsigned int> &values) {
|
||||||
fmt::dynamic_format_arg_store<fmt::format_context> ds;
|
fmt::dynamic_format_arg_store<fmt::format_context> ds;
|
||||||
|
|
||||||
for (const auto &value: values) {
|
for (const auto &value: values) {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
struct Graph {
|
struct Graph {
|
||||||
size_t rank{};
|
size_t rank{};
|
||||||
std::vector<tc::Group<>::Rel> edges{};
|
std::vector<tc::Group::Rel> edges{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Op {
|
struct Op {
|
||||||
@@ -287,10 +287,10 @@ Graph eval(const std::vector<Op> &ops) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace tc {
|
namespace tc {
|
||||||
Group<> coxeter(const std::string &symbol) {
|
Group coxeter(const std::string &symbol) {
|
||||||
auto ops = compile(symbol);
|
auto ops = compile(symbol);
|
||||||
auto diagram = eval(ops);
|
auto diagram = eval(ops);
|
||||||
Group<> res(diagram.rank);
|
Group res(diagram.rank);
|
||||||
for (const auto &[i, j, m]: diagram.edges) {
|
for (const auto &[i, j, m]: diagram.edges) {
|
||||||
res.set(i, j, m);
|
res.set(i, j, m);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ namespace tc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Tables {
|
struct Tables {
|
||||||
std::vector<Group<>::Rel> rels;
|
std::vector<Group::Rel> rels;
|
||||||
std::vector<std::vector<Row>> rows;
|
std::vector<std::vector<Row>> rows;
|
||||||
|
|
||||||
explicit Tables(std::vector<Group<>::Rel> rels)
|
explicit Tables(std::vector<Group::Rel> rels)
|
||||||
: rels(std::move(rels)), rows() {
|
: rels(std::move(rels)), rows() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +36,9 @@ namespace tc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] Cosets<> Group<>::solve(std::vector<size_t> const &idxs, size_t bound) const {
|
[[nodiscard]] Cosets Group::solve(std::vector<size_t> const &idxs, size_t bound) const {
|
||||||
// region Initialize Cosets Table
|
// region Initialize Cosets Table
|
||||||
Cosets<> cosets(rank());
|
Cosets cosets(rank());
|
||||||
cosets.add_row();
|
cosets.add_row();
|
||||||
|
|
||||||
if (rank() == 0) {
|
if (rank() == 0) {
|
||||||
@@ -53,7 +53,7 @@ namespace tc {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Initialize Relation Tables
|
// region Initialize Relation Tables
|
||||||
std::vector<Group<>::Rel> rels;
|
std::vector<Group::Rel> rels;
|
||||||
for (int i = 0; i < rank(); ++i) {
|
for (int i = 0; i < rank(); ++i) {
|
||||||
for (int j = i + 1; j < rank(); ++j) {
|
for (int j = i + 1; j < rank(); ++j) {
|
||||||
// The algorithm only works for Coxeter groups; multiplicities m_ii=1 are assumed. Relation tables
|
// The algorithm only works for Coxeter groups; multiplicities m_ii=1 are assumed. Relation tables
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ testing::AssertionResult AssertSolveOrder(
|
|||||||
const char *group_expr,
|
const char *group_expr,
|
||||||
const char *sub_gens_expr,
|
const char *sub_gens_expr,
|
||||||
const char *expected_order_expr,
|
const char *expected_order_expr,
|
||||||
const tc::Group<> &group,
|
const tc::Group &group,
|
||||||
const std::vector<size_t> &sub_gens,
|
const std::vector<size_t> &sub_gens,
|
||||||
size_t expected_order
|
size_t expected_order
|
||||||
) {
|
) {
|
||||||
@@ -50,43 +50,43 @@ testing::AssertionResult AssertSolveOrder(
|
|||||||
|
|
||||||
using v = std::vector<size_t>;
|
using v = std::vector<size_t>;
|
||||||
|
|
||||||
tc::Group<> A(unsigned int n) {
|
tc::Group A(unsigned int n) {
|
||||||
return tc::vcoxeter("3 * {}", {n - 1});
|
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});
|
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});
|
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});
|
return tc::vcoxeter("3 * [1 2 {}]", {n - 4});
|
||||||
}
|
}
|
||||||
|
|
||||||
tc::Group<> F4() {
|
tc::Group F4() {
|
||||||
return tc::coxeter("3 4 3");
|
return tc::coxeter("3 4 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
tc::Group<> G2() {
|
tc::Group G2() {
|
||||||
return tc::coxeter("6");
|
return tc::coxeter("6");
|
||||||
}
|
}
|
||||||
|
|
||||||
tc::Group<> H(unsigned int n) {
|
tc::Group H(unsigned int n) {
|
||||||
return tc::vcoxeter("5 3 * {}", {n - 2});
|
return tc::vcoxeter("5 3 * {}", {n - 2});
|
||||||
}
|
}
|
||||||
|
|
||||||
tc::Group<> I2(unsigned int n) {
|
tc::Group I2(unsigned int n) {
|
||||||
return tc::vcoxeter("{}", {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});
|
return tc::vcoxeter("{} 2 {}", {m, n});
|
||||||
}
|
}
|
||||||
|
|
||||||
tc::Group<> T(unsigned int n) {
|
tc::Group T(unsigned int n) {
|
||||||
return T(n, n);
|
return T(n, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <geometry.hpp>
|
#include <geometry.hpp>
|
||||||
|
|
||||||
template<unsigned int N>
|
template<unsigned int N>
|
||||||
Eigen::Matrix<float, N, N> mirror(const tc::Group<> &group) {
|
Eigen::Matrix<float, N, N> mirror(const tc::Group &group) {
|
||||||
Eigen::Matrix<float, N, N> res;
|
Eigen::Matrix<float, N, N> res;
|
||||||
res.setZero();
|
res.setZero();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "combo_iterator.hpp"
|
#include "combo_iterator.hpp"
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
|
#include "fmt/ranges.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An primitive stage N indices.
|
* An primitive stage N indices.
|
||||||
* @tparam N
|
* @tparam N
|
||||||
@@ -28,7 +31,7 @@ struct Primitive {
|
|||||||
|
|
||||||
~Primitive() = default;
|
~Primitive() = default;
|
||||||
|
|
||||||
void apply(const tc::Cosets<> &table, int gen) {
|
void apply(const tc::Cosets &table, int gen) {
|
||||||
for (auto &ind: indices) {
|
for (auto &ind: indices) {
|
||||||
ind = table.get(ind, gen);
|
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).
|
* Produce a list of all generators for the group context. The range [0..group.ngens).
|
||||||
*/
|
*/
|
||||||
std::vector<size_t> generators(const tc::Group<> &context) {
|
std::vector<size_t> generators(const tc::Group &context) {
|
||||||
std::vector<size_t> g_gens(context.rank());
|
std::vector<size_t> g_gens(context.rank());
|
||||||
std::iota(g_gens.begin(), g_gens.end(), 0);
|
std::iota(g_gens.begin(), g_gens.end(), 0);
|
||||||
return g_gens;
|
return g_gens;
|
||||||
@@ -65,7 +68,7 @@ std::vector<size_t> recontext_gens(
|
|||||||
* Apply some context transformation to all primitives of this mesh.
|
* Apply some context transformation to all primitives of this mesh.
|
||||||
*/
|
*/
|
||||||
template<unsigned N>
|
template<unsigned N>
|
||||||
std::vector<Primitive<N>> apply(std::vector<Primitive<N>> prims, const tc::Cosets<> &table, int gen) {
|
std::vector<Primitive<N>> apply(std::vector<Primitive<N>> prims, const tc::Cosets &table, int gen) {
|
||||||
for (auto &prim: prims) {
|
for (auto &prim: prims) {
|
||||||
prim.apply(table, gen);
|
prim.apply(table, gen);
|
||||||
}
|
}
|
||||||
@@ -79,7 +82,7 @@ template<unsigned N>
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::vector<Primitive<N>> recontext(
|
std::vector<Primitive<N>> recontext(
|
||||||
std::vector<Primitive<N>> prims,
|
std::vector<Primitive<N>> prims,
|
||||||
const tc::Group<> &context,
|
const tc::Group &context,
|
||||||
const std::vector<size_t> &g_gens,
|
const std::vector<size_t> &g_gens,
|
||||||
const std::vector<size_t> &sg_gens
|
const std::vector<size_t> &sg_gens
|
||||||
) {
|
) {
|
||||||
@@ -127,18 +130,17 @@ template<unsigned N>
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::vector<std::vector<Primitive<N>>> each_tile(
|
std::vector<std::vector<Primitive<N>>> each_tile(
|
||||||
std::vector<Primitive<N>> prims,
|
std::vector<Primitive<N>> prims,
|
||||||
const tc::Group<> &context,
|
const tc::Group &context,
|
||||||
const std::vector<size_t> &g_gens,
|
const std::vector<size_t> &g_gens,
|
||||||
const std::vector<size_t> &sg_gens
|
const std::vector<size_t> &sg_gens
|
||||||
) {
|
) {
|
||||||
std::vector<Primitive<N>> base = recontext(prims, context, g_gens, sg_gens);
|
std::vector<Primitive<N>> base = recontext(prims, context, g_gens, sg_gens);
|
||||||
const auto proper_sg_gens = recontext_gens(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<std::vector<Primitive<N>>> res(path.order());
|
std::vector<std::vector<Primitive<N>>> res(path.order());
|
||||||
path.walk(base, [&](auto from, auto to) {
|
path.walk(base, [&](auto from, auto to) {
|
||||||
@@ -152,7 +154,7 @@ template<unsigned N>
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::vector<Primitive<N>> tile(
|
std::vector<Primitive<N>> tile(
|
||||||
std::vector<Primitive<N>> prims,
|
std::vector<Primitive<N>> prims,
|
||||||
const tc::Group<> &context,
|
const tc::Group &context,
|
||||||
const std::vector<size_t> &g_gens,
|
const std::vector<size_t> &g_gens,
|
||||||
const std::vector<size_t> &sg_gens
|
const std::vector<size_t> &sg_gens
|
||||||
) {
|
) {
|
||||||
@@ -183,7 +185,7 @@ std::vector<Primitive<N + 1>> fan(std::vector<Primitive<N>> prims, size_t root)
|
|||||||
*/
|
*/
|
||||||
template<unsigned N>
|
template<unsigned N>
|
||||||
std::vector<Primitive<N>> triangulate(
|
std::vector<Primitive<N>> triangulate(
|
||||||
const tc::Group<> &context,
|
const tc::Group &context,
|
||||||
const std::vector<size_t> &g_gens
|
const std::vector<size_t> &g_gens
|
||||||
) {
|
) {
|
||||||
if (g_gens.size() + 1 != N) {
|
if (g_gens.size() + 1 != N) {
|
||||||
@@ -207,7 +209,7 @@ std::vector<Primitive<N>> triangulate(
|
|||||||
// Single-index primitives should not be further triangulated.
|
// Single-index primitives should not be further triangulated.
|
||||||
template<>
|
template<>
|
||||||
std::vector<Primitive<1>> triangulate(
|
std::vector<Primitive<1>> triangulate(
|
||||||
const tc::Group<> &,
|
const tc::Group &,
|
||||||
const std::vector<size_t> &g_gens
|
const std::vector<size_t> &g_gens
|
||||||
) {
|
) {
|
||||||
if (not g_gens.empty()) {
|
if (not g_gens.empty()) {
|
||||||
@@ -220,7 +222,7 @@ std::vector<Primitive<1>> triangulate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned N, class T>
|
template<unsigned N, class T>
|
||||||
auto hull(const tc::Group<> &group, T all_sg_gens, const std::vector<std::vector<size_t>> &exclude) {
|
auto hull(const tc::Group &group, T all_sg_gens, const std::vector<std::vector<size_t>> &exclude) {
|
||||||
std::vector<std::vector<Primitive<N>>> parts;
|
std::vector<std::vector<Primitive<N>>> parts;
|
||||||
|
|
||||||
auto g_gens = generators(group);
|
auto g_gens = generators(group);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace vis {
|
namespace vis {
|
||||||
struct Group {
|
struct Group {
|
||||||
tc::Group<> group;
|
tc::Group group;
|
||||||
vec5 root;
|
vec5 root;
|
||||||
vec3 color;
|
vec3 color;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user