14 #ifndef OTUS_MATRIX_HPP
15 #define OTUS_MATRIX_HPP
19 #include <initializer_list>
21 #include <unordered_map>
27 template <
typename T, T DefaultValue,
size_t Dimension = 2>
30 static_assert(Dimension > 0,
"The dimension of the matrix must be greater than 0");
32 template <
typename TupleType,
unsigned N,
typename... Types>
33 struct generate_tuple_type {
34 using type =
typename generate_tuple_type<TupleType, N - 1, TupleType, Types...>::type;
37 template <
typename TupleType,
typename... Types>
38 struct generate_tuple_type<TupleType, 0, Types...> {
39 using type = std::tuple<Types...>;
47 template <
size_t N,
typename... Types>
50 template <
typename... Types>
51 class Layout<0, Types...>;
53 using TupleKey =
typename generate_tuple_type<size_t, Dimension>::type;
54 using Contanter = std::unordered_map<TupleKey, T, TupleHash>;
55 using NextLayout = Layout<Dimension - 1,
size_t>;
58 const T defaultValue_{DefaultValue};
63 Matrix(
const Matrix &other) noexcept : elements_(other.elements_) {}
64 Matrix(
Matrix &&other) noexcept : elements_(std::move(other.elements_)) {}
66 Matrix(std::initializer_list<std::pair<const TupleKey, T>> list) {
67 elements_.reserve(list.size());
68 for (
const auto &element : list) {
69 elements_.emplace(element);
74 elements_ = other.elements_;
78 elements_ = std::move(other.elements_);
85 NextLayout
operator[](
size_t idx) {
return NextLayout(idx, elements_); }
86 const NextLayout
operator[](
size_t idx)
const {
return NextLayout(idx, elements_); }
94 auto end() const noexcept {
return Iterator(elements_.cend()); }
98 size_t size() const noexcept {
return elements_.size(); }
101 void clear() noexcept { elements_.clear(); }
109 template <
typename T, T DefaultValue,
size_t Dimension>
111 inline size_t get_hash(
size_t &seed,
size_t value)
const {
112 return std::hash<size_t>()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
115 template <std::size_t... Indices>
116 void combine_hash(
size_t &seed,
const TupleKey &tuple, std::index_sequence<Indices...>)
const {
117 using swallow =
size_t[];
118 (void)swallow{(seed ^= get_hash(seed, std::get<Indices>(tuple)))...};
124 combine_hash(seed, tuple, std::make_index_sequence<Dimension>{});
133 template <
typename T, T DefaultValue,
size_t Dimension>
135 using MapIteratorType =
typename Contanter::const_iterator;
136 MapIteratorType map_iterator_;
138 inline auto get_value()
const {
139 return std::tuple_cat((*map_iterator_).first, std::tie((*map_iterator_).second));
144 decltype(std::tuple_cat((*map_iterator_).first, std::tie((*map_iterator_).second)));
147 explicit Iterator(MapIteratorType map_iterator) : map_iterator_(map_iterator) {}
167 template <
typename T, T DefaultValue,
size_t Dimension>
168 template <
size_t N,
typename... Types>
169 class Matrix<T, DefaultValue, Dimension>::Layout {
170 using NextLayout = Layout<N - 1, Types...,
size_t>;
172 const Matrix::Contanter &elements_;
173 std::tuple<Types...> tuple_;
176 Layout(std::tuple<Types...> tuple,
const Matrix::Contanter &elements)
177 : elements_{elements}, tuple_{tuple} {}
180 return NextLayout(std::tuple_cat(tuple_, std::tie(idx)), elements_);
182 const NextLayout
operator[](
size_t idx)
const {
183 return NextLayout(std::tuple_cat(tuple_, std::tie(idx)), elements_);
190 template <
typename T, T DefaultValue,
size_t Dimension>
191 template <
typename... Types>
192 class Matrix<T, DefaultValue, Dimension>::Layout<0, Types...> {
193 std::tuple<Types...> tuple_;
194 const Matrix::Contanter &elements_;
195 const T default_{DefaultValue};
198 Layout(std::tuple<Types...> tuple,
const Matrix::Contanter &elements)
199 : tuple_{tuple}, elements_{elements} {}
202 if (value != DefaultValue) {
203 const_cast<Matrix::Contanter &
>(elements_)[tuple_] = value;
205 auto iter = elements_.find(tuple_);
206 if (iter != elements_.cend()) {
207 const_cast<Matrix::Contanter &
>(elements_).erase(iter);
213 operator const T &()
const noexcept {
214 auto iter = elements_.find(tuple_);
215 return (iter != elements_.cend()) ? iter->second : default_;
221 #endif // OTUS_MATRIX_HPP
bool operator!=(Iterator other) const
Definition: matrix.hpp:159
Matrix(Matrix &&other) noexcept
Definition: matrix.hpp:64
Matrix & operator=(Matrix &&other) noexcept
Definition: matrix.hpp:77
decltype(std::tuple_cat((*map_iterator_).first, std::tie((*map_iterator_).second))) value_type
Definition: matrix.hpp:144
Matrix(std::initializer_list< std::pair< const TupleKey, T >> list)
Definition: matrix.hpp:66
auto end() const noexcept
Definition: matrix.hpp:94
auto begin() const noexcept
Definition: matrix.hpp:90
Matrix & operator=(const Matrix &other)
Definition: matrix.hpp:73
std::input_iterator_tag iterator_category
Definition: matrix.hpp:145
Class of The multi-dimensional sparse matrix.
Definition: matrix.hpp:28
Iterator operator++(int)
Definition: matrix.hpp:153
Definition: matrix.hpp:134
value_type operator*() const
Definition: matrix.hpp:161
bool operator!=(const Matrix &other) const
Definition: matrix.hpp:83
size_t operator()(const TupleKey &tuple) const
Definition: matrix.hpp:122
Iterator(MapIteratorType map_iterator)
Definition: matrix.hpp:147
void clear() noexcept
Clears the mapped matrix.
Definition: matrix.hpp:101
Layout(std::tuple< Types...> tuple, const Matrix::Contanter &elements)
Definition: matrix.hpp:198
NextLayout operator[](size_t idx)
Definition: matrix.hpp:85
size_t size() const noexcept
Definition: matrix.hpp:98
const NextLayout operator[](size_t idx) const
Definition: matrix.hpp:86
Definition: matrix.hpp:110
Iterator & operator++()
Definition: matrix.hpp:149
auto & operator=(const T &value)
Definition: matrix.hpp:201
bool operator==(Iterator other) const
Definition: matrix.hpp:158
bool operator==(const Matrix &other) const
Definition: matrix.hpp:82
Matrix(const Matrix &other) noexcept
Definition: matrix.hpp:63