diff --git a/tc/include/tc/group.hpp b/tc/include/tc/group.hpp index bf6992b..85d5e7b 100644 --- a/tc/include/tc/group.hpp +++ b/tc/include/tc/group.hpp @@ -2,23 +2,20 @@ #include +#include + namespace tc { struct Group; struct SubGroup; struct Group { int ngens; - std::vector> _mults; + tc::pair_map _mults; Group(const Group &) = default; explicit Group(int ngens, const std::vector &rels = {}) - : ngens(ngens) { - _mults.resize(ngens); - - for (auto &mult: _mults) { - mult.resize(ngens, 2); - } + : ngens(ngens), _mults(ngens, 2) { for (const auto &rel: rels) { set(rel); @@ -26,12 +23,11 @@ namespace tc { } void set(const Rel &r) { - _mults[r.gens[0]][r.gens[1]] = r.mult; - _mults[r.gens[1]][r.gens[0]] = r.mult; + _mults(r.gens[0], r.gens[1]) = r.mult; } [[nodiscard]] int get(int a, int b) const { - return _mults[a][b]; + return _mults(a, b); } [[nodiscard]] std::vector rels() const { diff --git a/tc/test/CMakeLists.txt b/tc/test/CMakeLists.txt index 53a56e4..8190659 100644 --- a/tc/test/CMakeLists.txt +++ b/tc/test/CMakeLists.txt @@ -1,35 +1,28 @@ -#add_executable(grouptests grouptest.cpp) -#target_link_libraries(grouptests PUBLIC tc) +function(add_simple_test exec arg) + add_test(NAME "${exec}_${arg}" COMMAND ${exec} ${arg}) + set_tests_properties("${exec}_${arg}" PROPERTIES TIMEOUT 5) +endfunction() -add_executable(tctests tctest.cpp) -target_link_libraries(tctests PUBLIC tc) +add_executable(test_pair_map test_pair_map.cpp) +target_link_libraries(test_pair_map PUBLIC tc) +add_simple_test(test_pair_map populate) +add_simple_test(test_pair_map symmetry) +add_simple_test(test_pair_map fill) +add_simple_test(test_pair_map copy) +add_simple_test(test_pair_map move) +add_simple_test(test_pair_map iterate) +add_simple_test(test_pair_map iterate_ref) +add_simple_test(test_pair_map view) -#add_test(NAME GroupIterateRef COMMAND grouptests iterate_ref) -#set_tests_properties(GroupIterateRef PROPERTIES TIMEOUT 30) -#add_test(NAME GroupIterateConst COMMAND grouptests iterate_const) -#set_tests_properties(GroupIterateConst PROPERTIES TIMEOUT 30) -#add_test(NAME GroupIterate COMMAND grouptests iterate) -#set_tests_properties(GroupIterate PROPERTIES TIMEOUT 30) -#add_test(NAME GroupView COMMAND grouptests view) -#set_tests_properties(GroupView PROPERTIES TIMEOUT 30) - -add_test(NAME SolveA COMMAND tctests A) -set_tests_properties(SolveA PROPERTIES TIMEOUT 5) -add_test(NAME SolveB COMMAND tctests B) -set_tests_properties(SolveB PROPERTIES TIMEOUT 5) -add_test(NAME SolveD COMMAND tctests D) -set_tests_properties(SolveD PROPERTIES TIMEOUT 5) -add_test(NAME SolveE COMMAND tctests E) -set_tests_properties(SolveE PROPERTIES TIMEOUT 5) -add_test(NAME SolveF COMMAND tctests F) -set_tests_properties(SolveF PROPERTIES TIMEOUT 5) -add_test(NAME SolveG COMMAND tctests G) -set_tests_properties(SolveG PROPERTIES TIMEOUT 5) -add_test(NAME SolveH COMMAND tctests H) -set_tests_properties(SolveH PROPERTIES TIMEOUT 5) -add_test(NAME SolveI COMMAND tctests I) -set_tests_properties(SolveI PROPERTIES TIMEOUT 5) -add_test(NAME SolveT COMMAND tctests T) -set_tests_properties(SolveT PROPERTIES TIMEOUT 5) - -add_custom_target(alltests DEPENDS grouptests tctests) +add_executable(test_solve test_solve.cpp) +target_link_libraries(test_solve PUBLIC tc) +add_simple_test(test_solve A) +add_simple_test(test_solve B) +add_simple_test(test_solve D) +add_simple_test(test_solve E) +add_simple_test(test_solve F) +add_simple_test(test_solve G) +add_simple_test(test_solve H) +add_simple_test(test_solve I) +add_simple_test(test_solve T) +add_simple_test(test_solve X) diff --git a/tc/test/grouptest.cpp b/tc/test/grouptest.cpp deleted file mode 100644 index 4c9c562..0000000 --- a/tc/test/grouptest.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -#include - -int iterate_ref() { - tc::pair_map pm(4, 2); - - for (auto [i, j, m]: pm) { - m = i + j; - } - - for (auto [i, j, m]: pm) { - std::cout << "(" << i << "," << j << ") = " << m << std::endl; - } - - return EXIT_SUCCESS; -} - -int iterate_const() { - tc::pair_map pm(4, 2); - for (const auto &[i, j, m]: pm) { - m = i + j; - } - - const tc::pair_map pmc = pm; - for (auto [i, j, m]: pmc) { - std::cout << "(" << i << "," << j << ") = " << m << std::endl; - } - - return EXIT_SUCCESS; -} - -int iterate() { - tc::pair_map pm(4, 2); - - std::cout << pm(0, 0) << std::endl; - pm(0, 0) = 3; - std::cout << pm(0, 0) << std::endl; - - for (auto [i, j, m]: pm) { - std::cout << i << " " << j << " = " << m << std::endl; - } - - std::cout << pm(1, 0) << " " << pm(0, 1) << std::endl; - pm(1, 0) = 7; - std::cout << pm(1, 0) << " " << pm(0, 1) << std::endl; - pm(0, 1) = 9; - std::cout << pm(1, 0) << " " << pm(0, 1) << std::endl; - - return EXIT_SUCCESS; -} - -int view() { - tc::pair_map pm(4, 2); - - for (int i = 0; i < 4; ++i) { - for (int j = i; j < 4; ++j) { - pm(i, j) = i + j; - } - } - - std::cout << "ALL:" << std::endl; - for (auto [i, j, m]: pm) { - std::cout << " (" << i << "," << j << ") = " << m << std::endl; - } - - std::cout << "VIEW:" << std::endl; - for (auto [i, j, m]: pm.of(2)) { - std::cout << " (" << i << "," << j << ") = " << m << std::endl; - } - - return EXIT_SUCCESS; -} - -static std::unordered_map> tests = { - {"iterate_ref", iterate_ref}, - {"iterate_const", iterate_const}, - {"iterate", iterate}, - {"view", view}, -}; - -int main(int argc, char *argv[]) { - std::vector args(argv + 1, argv + argc); - - auto it = tests.find(args[0]); - if (it == tests.end()) { - std::cout << "Test not found" << std::endl; - return EXIT_FAILURE; - } - auto test = it->second; - return test(); -} diff --git a/tc/test/tctest.cpp b/tc/test/tctest.cpp deleted file mode 100644 index 171e3db..0000000 --- a/tc/test/tctest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include - -#include -#include - -int main(int argc, char *argv[]) { - std::string key = argv[1]; - - std::vector> groups; - - // See the group orders here https://en.wikipedia.org/wiki/Coxeter_group#Properties - if (key == "A") { - groups = { - {"A(1)", tc::group::A(1), 2}, - {"A(2)", tc::group::A(2), 6}, - {"A(3)", tc::group::A(3), 24}, - {"A(4)", tc::group::A(4), 120}, - }; - } - if (key == "B") { - groups = { - {"B(2)", tc::group::B(2), 8}, - {"B(3)", tc::group::B(3), 48}, - {"B(4)", tc::group::B(4), 384}, - {"B(5)", tc::group::B(5), 3840}, - {"B(6)", tc::group::B(6), 46080}, - }; - } - if (key == "D") { - groups = { - {"D(2)", tc::group::D(2), 4}, - {"D(3)", tc::group::D(3), 24}, - {"D(4)", tc::group::D(4), 192}, - {"D(5)", tc::group::D(5), 1920}, - {"D(6)", tc::group::D(6), 23040}, - }; - } - if (key == "E") { - groups = { - {"E(3)", tc::group::E(3), 12}, - {"E(4)", tc::group::E(4), 120}, - {"E(5)", tc::group::E(5), 1920}, - {"E(6)", tc::group::E(6), 51840}, - }; - } - if (key == "F") { - groups = { - {"F4()", tc::group::F4(), 1152}, - }; - } - if (key == "G") { - groups = { - {"G2()", tc::group::G2(), 12}, - }; - } - if (key == "H") { - groups = { - {"H(2)", tc::group::H(2), 10}, - {"H(3)", tc::group::H(3), 120}, - {"H(4)", tc::group::H(4), 14400}, - }; - } - if (key == "I") { - groups = { - {"I2(2)", tc::group::I2(2), 4}, - {"I2(3)", tc::group::I2(3), 6}, - {"I2(4)", tc::group::I2(4), 8}, - {"I2(5)", tc::group::I2(5), 10}, - }; - } - if (key == "T") { - groups = { - {"T(3)", tc::group::T(3), 36}, - {"T(4)", tc::group::T(4), 64}, - {"T(400)", tc::group::T(400), 640000}, - {"T(400, 300)", tc::group::T(400, 300), 480000}, - }; - } - - int status = EXIT_SUCCESS; - - for (const auto &[name, group, expected]: groups) { - auto cos = group.solve({}); - auto actual = cos.size(); - std::cout << name << " : " << actual; - if (expected != actual) { - std::cout << " (Expected " << expected << ")"; - status = EXIT_FAILURE; - } - std::cout << std::endl; - } - - return status; -} diff --git a/tc/test/test_pair_map.cpp b/tc/test/test_pair_map.cpp new file mode 100644 index 0000000..e3302c4 --- /dev/null +++ b/tc/test/test_pair_map.cpp @@ -0,0 +1,222 @@ +#include +#include +#include + +#include + +int test_populate() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = f(i, j); + } + } + + for (int i = 0; i < pm.size(); ++i) { + for (int j = 0; j < pm.size(); ++j) { + if (pm(i, j) != (f(i, j))) { + std::cerr << "pm(" << i << ", " << j << ") != " << (f(i, j)) << "" << std::endl; + return EXIT_FAILURE; + } + if (pm(j, i) != (f(i, j))) { + std::cerr << "pm(" << j << ", " << i << ") != " << (f(i, j)) << "" << std::endl; + return EXIT_FAILURE; + } + } + } + + return EXIT_SUCCESS; +} + +int test_symmetry() { + size_t key = 1; + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = key++; + } + } + + for (int i = 0; i < pm.size(); ++i) { + for (int j = 0; j < pm.size(); ++j) { + if (pm(i, j) != pm(j, i)) { + std::cerr << "pm(" << i << ", " << j << ") != pm(" << j << ", " << i << ")" << std::endl; + return EXIT_FAILURE; + } + } + } + + return EXIT_SUCCESS; +} + +int test_fill() { + tc::pair_map pm(6, 42); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + if (pm(i, j) != 42) { + std::cerr << "pm(" << i << ", " << j << ") != 42" << std::endl; + return EXIT_FAILURE; + } + } + } + + return EXIT_SUCCESS; +} + +int test_copy() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = f(i, j); + } + } + + tc::pair_map cp = pm; + + for (int i = 0; i < pm.size(); ++i) { + for (int j = 0; j < pm.size(); ++j) { + if (cp(i, j) != pm(i, j)) { + std::cerr << "cp(" << i << ", " << j << ") (" << cp(i, j) << ") != pm(" << i << ", " << j << ") (" + << pm(i, j) << ")" << std::endl; + return EXIT_FAILURE; + } + } + } + + return EXIT_SUCCESS; +} + +int test_move() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = f(i, j); + } + } + + tc::pair_map cp = std::move(pm); + + for (int i = 0; i < cp.size(); ++i) { + for (int j = 0; j < cp.size(); ++j) { + if (cp(i, j) != (f(i, j))) { + std::cerr << "cp(" << i << ", " << j << ") != " << (f(i, j)) << "" << std::endl; + return EXIT_FAILURE; + } + if (cp(j, i) != (f(i, j))) { + std::cerr << "cp(" << j << ", " << i << ") != " << (f(i, j)) << "" << std::endl; + return EXIT_FAILURE; + } + } + } + + return EXIT_SUCCESS; +} + +int test_iterate() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = f(i, j); + } + } + + size_t count = 0; + for (const auto &[i, j, m]: pm) { + if (m != f(i, j)) { + std::cerr << "m (" << m << ") != " << (f(i, j)) << "" << std::endl; + return EXIT_FAILURE; + } + count++; + } + + if (count != 21) { + std::cerr << "count (" << count << ") != " << 21 << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int test_iterate_ref() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (const auto &[i, j, m]: pm) { + m = f(i, j); + } + + for (const auto &[i, j, m]: pm) { + if (m != f(i, j)) { + std::cerr << "m (" << m << ") != " << f(i, j) << std::endl; + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + +int test_view() { + auto f = [](size_t i, size_t j) { return ((i + j) << 12) ^ i ^ j; }; + + tc::pair_map pm(6); + + for (int i = 0; i < pm.size(); ++i) { + for (int j = i; j < pm.size(); ++j) { + pm(i, j) = f(i, j); + } + } + + size_t count = 0; + for (const auto &[i, j, m]: pm.of(4)) { + if (i != 4 && j != 4) { + std::cerr << i << ", " << j << " != " << 4 << std::endl; + return EXIT_FAILURE; + } + count++; + } + + if (count != 6) { + std::cerr << "count (" << count << ") != " << 6 << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static std::unordered_map> tests = { + {"populate", test_populate}, + {"symmetry", test_symmetry}, + {"fill", test_fill}, + {"copy", test_copy}, + {"move", test_move}, + {"iterate", test_iterate}, + {"iterate_ref", test_iterate_ref}, + {"view", test_view}, +}; + +int main(int argc, char *argv[]) { + std::vector args(argv + 1, argv + argc); + + auto it = tests.find(args[0]); + if (it == tests.end()) { + std::cerr << "Test not found" << std::endl; + return EXIT_FAILURE; + } + auto test = it->second; + return test(); +} diff --git a/tc/test/test_solve.cpp b/tc/test/test_solve.cpp new file mode 100644 index 0000000..f9eb8e8 --- /dev/null +++ b/tc/test/test_solve.cpp @@ -0,0 +1,105 @@ +#include +#include +#include + +#include +#include + +int main(int argc, char *argv[]) { + std::string key = argv[1]; + + std::vector, size_t>> groups; + + // See the group orders here https://en.wikipedia.org/wiki/Coxeter_group#Properties + if (key == "A") { + groups = { + {"A(1)", tc::group::A(1), {}, 2}, + {"A(2)", tc::group::A(2), {}, 6}, + {"A(3)", tc::group::A(3), {}, 24}, + {"A(4)", tc::group::A(4), {}, 120}, + }; + } + if (key == "B") { + groups = { + {"B(2)", tc::group::B(2), {}, 8}, + {"B(3)", tc::group::B(3), {}, 48}, + {"B(4)", tc::group::B(4), {}, 384}, + {"B(5)", tc::group::B(5), {}, 3840}, + {"B(6)", tc::group::B(6), {}, 46080}, + }; + } + if (key == "D") { + groups = { + {"D(2)", tc::group::D(2), {}, 4}, + {"D(3)", tc::group::D(3), {}, 24}, + {"D(4)", tc::group::D(4), {}, 192}, + {"D(5)", tc::group::D(5), {}, 1920}, + {"D(6)", tc::group::D(6), {}, 23040}, + }; + } + if (key == "E") { + groups = { + {"E(3)", tc::group::E(3), {}, 12}, + {"E(4)", tc::group::E(4), {}, 120}, + {"E(5)", tc::group::E(5), {}, 1920}, + {"E(6)", tc::group::E(6), {}, 51840}, + }; + } + if (key == "F") { + groups = { + {"F4()", tc::group::F4(), {}, 1152}, + }; + } + if (key == "G") { + groups = { + {"G2()", tc::group::G2(), {}, 12}, + }; + } + if (key == "H") { + groups = { + {"H(2)", tc::group::H(2), {}, 10}, + {"H(3)", tc::group::H(3), {}, 120}, + {"H(4)", tc::group::H(4), {}, 14400}, + }; + } + if (key == "I") { + groups = { + {"I2(2)", tc::group::I2(2), {}, 4}, + {"I2(3)", tc::group::I2(3), {}, 6}, + {"I2(4)", tc::group::I2(4), {}, 8}, + {"I2(5)", tc::group::I2(5), {}, 10}, + }; + } + if (key == "T") { + groups = { + {"T(3)", tc::group::T(3), {}, 36}, + {"T(4)", tc::group::T(4), {}, 64}, + {"T(400)", tc::group::T(400), {}, 640000}, + {"T(400, 300)", tc::group::T(400, 300), {}, 480000}, + }; + } + if (key == "X") { + groups = { + {"H3 x I2", tc::schlafli({5, 3, 3, 2}), {}, 28800}, + {"H3 x I2", tc::schlafli({5, 3, 3, 2}), {0}, 14400}, + {"H2 / {0, 1}", tc::schlafli({5, 3}), {0, 1}, 12}, + {"H2 / {0, 2}", tc::schlafli({5, 3}), {0, 2}, 30}, + {"H2 / {1, 2}", tc::schlafli({5, 3}), {1, 2}, 20}, + }; + } + + int status = EXIT_SUCCESS; + + for (const auto &[name, group, sub_gens, expected]: groups) { + auto cos = group.solve(sub_gens); + auto actual = cos.size(); + std::cout << name << " : " << actual; + if (expected != actual) { + std::cout << " (Expected " << expected << ")"; + status = EXIT_FAILURE; + } + std::cout << std::endl; + } + + return status; +}