diff --git a/tc/CMakeLists.txt b/tc/CMakeLists.txt index ee13ab0..294c5ce 100644 --- a/tc/CMakeLists.txt +++ b/tc/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(tc + include/tc/pair_map.hpp include/tc/core.hpp include/tc/cosets.hpp include/tc/group.hpp @@ -9,3 +10,5 @@ add_library(tc src/solve.cpp) target_include_directories(tc PUBLIC include) + +add_subdirectory(test) diff --git a/tc/include/tc/pair_map.hpp b/tc/include/tc/pair_map.hpp new file mode 100644 index 0000000..614f639 --- /dev/null +++ b/tc/include/tc/pair_map.hpp @@ -0,0 +1,453 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace tc { + template + struct pair_map { + struct iterator; + struct const_iterator; + struct view; + struct const_view; + + private: + size_t _size; + std::vector _data{}; + + static size_t idx(size_t i, size_t j); + + public: + explicit pair_map(size_t size); + + explicit pair_map(size_t size, const T &value); + + [[nodiscard]] size_t size() const; + + T &operator()(size_t i, size_t j); + + T operator()(size_t i, size_t j) const; + + view of(size_t f); + + const_view of(size_t f) const; + + const_view cof(size_t f); + + iterator begin(); + + iterator end(); + + const_iterator begin() const; + + const_iterator end() const; + + const_iterator cbegin(); + + const_iterator cend(); + }; + + template + struct pair_map::iterator { + using reference = std::tuple; + + private: + pair_map &_map; + size_t _i, _j; + + public: + iterator(pair_map &map, size_t i, size_t j); + + iterator operator++(); + + iterator operator++(int) &; + + reference operator*(); + + bool operator!=(const iterator &other); + }; + + template + struct pair_map::const_iterator { + using value_type = std::tuple; + + private: + const pair_map &_map; + size_t _i, _j; + + public: + const_iterator(const pair_map &map, size_t i, size_t j); + + const_iterator operator++(); + + const_iterator operator++(int) &; + + value_type operator*(); + + bool operator!=(const const_iterator &other); + }; + + template + struct pair_map::view { + struct iterator; + struct const_iterator; + + private: + pair_map &_map; + size_t _f; + + public: + view(pair_map &map, size_t f); + + iterator begin(); + + iterator end(); + + const_iterator begin() const; + + const_iterator end() const; + + const_iterator cbegin(); + + const_iterator cend(); + }; + + template + struct pair_map::view::iterator { + using reference = std::tuple; + + private: + pair_map &_map; + size_t _f, _v; + + public: + iterator(pair_map &map, size_t f, size_t v); + + iterator operator++(); + + iterator operator++(int); + + reference operator*(); + + bool operator!=(const iterator &other); + }; + + template + struct pair_map::view::const_iterator { + using value_type = std::tuple; + + private: + const pair_map &_map; + size_t _f, _v; + + public: + const_iterator(const pair_map &map, size_t f, size_t v); + + const_iterator operator++(); + + const_iterator operator++(int); + + value_type operator*(); + + bool operator!=(const const_iterator &other); + }; + + template + struct pair_map::const_view { + using const_iterator = typename pair_map::view::const_iterator; + + private: + const pair_map &_map; + size_t _f; + + public: + const_view(const pair_map &map, size_t f); + + const_iterator begin() const; + + const_iterator end() const; + + const_iterator cbegin(); + + const_iterator cend(); + }; + + // region pair_map + + template + size_t pair_map::idx(size_t i, size_t j) { + if (i < j) std::swap(i, j); + return j * (j + 1) / 2 + i; + } + + template + pair_map::pair_map(size_t size) + : _size(size), _data(size * (size + 1) / 2) {} + + template + pair_map::pair_map(size_t size, const T &value) + : _size(size), _data(size * (size + 1) / 2, value) {} + + template + size_t pair_map::size() const { + return _size; + } + + template + T &pair_map::operator()(size_t i, size_t j) { + return _data[idx(i, j)]; + } + + template + T pair_map::operator()(size_t i, size_t j) const { + return _data[idx(i, j)]; + } + + template + typename pair_map::view pair_map::of(size_t f) { + return view(*this, f); + } + + template + typename pair_map::const_view pair_map::of(size_t f) const { + return const_view(*this, f); + } + + template + typename pair_map::const_view pair_map::cof(size_t f) { + return const_view(*this, f); + } + + template + typename pair_map::iterator pair_map::begin() { + return iterator(*this, 0, 0); + } + + template + typename pair_map::iterator pair_map::end() { + return iterator(*this, 0, _size); + } + + template + typename pair_map::const_iterator pair_map::begin() const { + return const_iterator(*this, 0, 0); + } + + template + typename pair_map::const_iterator pair_map::end() const { + return const_iterator(*this, 0, _size); + } + + template + typename pair_map::const_iterator pair_map::cbegin() { + return const_iterator(*this, 0, 0); + } + + template + typename pair_map::const_iterator pair_map::cend() { + return const_iterator(*this, 0, _size); + } + + // endregion + + // region pair_map::iterator + + template + pair_map::iterator::iterator(pair_map &map, size_t i, size_t j) + :_map(map), _i(i), _j(j) {} + + template + typename pair_map::iterator pair_map::iterator::operator++() { + if (++_i > _j) { + _i = 0; + ++_j; + } + return *this; + } + + template + typename pair_map::iterator pair_map::iterator::operator++(int) &{ + iterator it = *this; + ++this; + return it; + } + + template + typename pair_map::iterator::reference pair_map::iterator::operator*() { + return std::tie(_i, _j, _map(_i, _j)); + } + + template + bool pair_map::iterator::operator!=(const pair_map::iterator &other) { + return &_map != &other._map || _i != other._i || _j != other._j; + } + + // endregion + + // region pair_map::const_iterator + + template + pair_map::const_iterator::const_iterator(const pair_map &map, size_t i, size_t j) + :_map(map), _i(i), _j(j) {} + + template + typename pair_map::const_iterator pair_map::const_iterator::operator++() { + if (++_i > _j) { + _i = 0; + ++_j; + } + return *this; + } + + template + typename pair_map::const_iterator pair_map::const_iterator::operator++(int) &{ + const_iterator it = *this; + ++this; + return it; + } + + template + typename pair_map::const_iterator::value_type pair_map::const_iterator::operator*() { + return std::tuple(_i, _j, _map(_i, _j)); + } + + template + bool pair_map::const_iterator::operator!=(const pair_map::const_iterator &other) { + return &_map != &other._map || _i != other._i || _j != other._j; + } + + // endregion + + // region pair_map::view + + template + pair_map::view::view(pair_map &map, size_t f) + : _map(map), _f(f) {} + + template + typename pair_map::view::iterator pair_map::view::begin() { + return iterator(_map, _f, 0); + } + + template + typename pair_map::view::iterator pair_map::view::end() { + return iterator(_map, _f, _map._size); + } + + template + typename pair_map::view::const_iterator pair_map::view::begin() const { + return const_iterator(_map, _f, 0); + } + + template + typename pair_map::view::const_iterator pair_map::view::end() const { + return const_iterator(_map, _f, _map._size); + } + + template + typename pair_map::view::const_iterator pair_map::view::cbegin() { + return const_iterator(_map, _f, 0); + } + + template + typename pair_map::view::const_iterator pair_map::view::cend() { + return const_iterator(_map, _f, _map._size); + } + + // endregion + + // region pair_map::view::iterator + + template + pair_map::view::iterator::iterator(pair_map &map, size_t f, size_t v) + : _map(map), _f(f), _v(v) {} + + template + typename pair_map::view::iterator pair_map::view::iterator::operator++() { + ++_v; + return *this; + } + + template + typename pair_map::view::iterator pair_map::view::iterator::operator++(int) { + iterator it = *this; + ++this; + return it; + } + + template + typename pair_map::view::iterator::reference pair_map::view::iterator::operator*() { + auto [i, j] = std::minmax(_f, _v); + return std::tie(i, j, _map(i, j)); + } + + template + bool pair_map::view::iterator::operator!=(const pair_map::view::iterator &other) { + return &_map != &other._map || _f != other._f || _v != other._v; + } + + // endregion + + // region pair_map::view::const_iterator + + template + pair_map::view::const_iterator::const_iterator(const pair_map &map, size_t f, size_t v) + : _map(map), _f(f), _v(v) {} + + template + typename pair_map::view::const_iterator pair_map::view::const_iterator::operator++() { + ++_v; + return *this; + } + + template + typename pair_map::view::const_iterator pair_map::view::const_iterator::operator++(int) { + const_iterator it = *this; + ++this; + return it; + } + + template + typename pair_map::view::const_iterator::value_type pair_map::view::const_iterator::operator*() { + auto [i, j] = std::minmax(_f, _v); + return std::tuple(i, j, _map(i, j)); + } + + template + bool pair_map::view::const_iterator::operator!=(const pair_map::view::const_iterator &other) { + return &_map != &other._map || _f != other._f || _v != other._v; + } + + // endregion + + // region pair_map::const_view + + template + pair_map::const_view::const_view(const pair_map &map, size_t f) + : _map(map), _f(f) {} + + template + typename pair_map::const_view::const_iterator pair_map::const_view::begin() const { + return const_iterator(_map, _f, 0); + } + + template + typename pair_map::const_view::const_iterator pair_map::const_view::end() const { + return const_iterator(_map, _f, _map._size); + } + + template + typename pair_map::const_view::const_iterator pair_map::const_view::cbegin() { + return const_iterator(_map, _f, 0); + } + + template + typename pair_map::const_view::const_iterator pair_map::const_view::cend() { + return const_iterator(_map, _f, _map._size); + } + + // endregion +} diff --git a/tc/src/keep.cpp b/tc/src/keep.cpp new file mode 100644 index 0000000..4020e10 --- /dev/null +++ b/tc/src/keep.cpp @@ -0,0 +1 @@ +#include diff --git a/tc/test/CMakeLists.txt b/tc/test/CMakeLists.txt new file mode 100644 index 0000000..e9621bd --- /dev/null +++ b/tc/test/CMakeLists.txt @@ -0,0 +1,13 @@ +add_executable(grouptests grouptest.cpp) +target_link_libraries(grouptests PUBLIC tc) + +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_custom_target(alltests DEPENDS grouptests) diff --git a/tc/test/grouptest.cpp b/tc/test/grouptest.cpp new file mode 100644 index 0000000..4c9c562 --- /dev/null +++ b/tc/test/grouptest.cpp @@ -0,0 +1,94 @@ +#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(); +}