Loading...
Searching...
No Matches
base_swap.h
Go to the documentation of this file.
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Hannah Schreiber
4 *
5 * Copyright (C) 2022 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
17
18#ifndef PM_BASE_SWAP_H
19#define PM_BASE_SWAP_H
20
21#include <utility> //std::swap, std::move & std::exchange
22#include <algorithm> //std::max
23
24namespace Gudhi {
25namespace persistence_matrix {
26
33struct Dummy_base_swap {
34 friend void swap([[maybe_unused]] Dummy_base_swap& d1, [[maybe_unused]] Dummy_base_swap& d2) noexcept {}
35
36 Dummy_base_swap([[maybe_unused]] unsigned int numberOfColumns = 0) {}
37};
38
48template <class Master_matrix, class Base_matrix>
50{
51 public:
52 using Column_container = typename Master_matrix::Column_container;
53 using Index = typename Master_matrix::Index;
54 using ID_index = typename Master_matrix::ID_index;
55
59 Base_swap();
65 Base_swap(unsigned int numberOfColumns);
71 Base_swap(const Base_swap& matrixToCopy) = default;
77 Base_swap(Base_swap&& other) noexcept;
78
79 ~Base_swap() = default;
80
88 void swap_columns(Index columnIndex1, Index columnIndex2);
96 void swap_rows(ID_index rowIndex1, ID_index rowIndex2);
97
101 Base_swap& operator=(const Base_swap& other) = default;
105 Base_swap& operator=(Base_swap&& other) noexcept;
106
110 friend void swap(Base_swap& base1, Base_swap& base2) noexcept
111 {
112 base1.indexToRow_.swap(base2.indexToRow_);
113 base1.rowToIndex_.swap(base2.rowToIndex_);
114 std::swap(base1.rowSwapped_, base2.rowSwapped_);
115 }
116
117 protected:
118 void _orderRows();
119 void _initialize_row_index(Index index);
120 Index _erase_row(Index index);
121 Index _get_row_index(Index index) const;
122 bool _row_were_swapped() const;
123 void _reset();
124
125 private:
126 using Index_dictionary = typename Master_matrix::template Dictionary<Index>;
127 using Row_dictionary = typename Master_matrix::template Dictionary<ID_index>;
128
129 Index_dictionary indexToRow_;
130 Row_dictionary rowToIndex_;
131 bool rowSwapped_;
132
133 // access to inheriting matrix class
134 constexpr Base_matrix* _matrix() { return static_cast<Base_matrix*>(this); }
135
136 constexpr const Base_matrix* _matrix() const { return static_cast<const Base_matrix*>(this); }
137};
138
139template <class Master_matrix, class Base_matrix>
141{
142}
143
144template <class Master_matrix, class Base_matrix>
145inline Base_swap<Master_matrix, Base_matrix>::Base_swap(unsigned int numberOfColumns)
146 : indexToRow_(numberOfColumns), rowToIndex_(numberOfColumns), rowSwapped_(false)
147{
148 for (Index i = 0; i < numberOfColumns; i++) {
149 indexToRow_[i] = i;
150 rowToIndex_[i] = i;
151 }
152}
153
154template <class Master_matrix, class Base_matrix>
156 : indexToRow_(std::move(other.indexToRow_)),
157 rowToIndex_(std::move(other.rowToIndex_)),
158 rowSwapped_(std::exchange(other.rowSwapped_, false))
159{
160}
161
162template <class Master_matrix, class Base_matrix>
164{
165 swap(_matrix()->matrix_.at(columnIndex1), _matrix()->matrix_.at(columnIndex2));
166 if constexpr (Master_matrix::Option_list::has_row_access) rowSwapped_ = true; // to update column index in entries.
167}
168
169template <class Master_matrix, class Base_matrix>
171{
172 rowSwapped_ = true;
173
174 if constexpr (Master_matrix::Option_list::has_map_column_container) {
175 auto it1 = indexToRow_.find(rowIndex1);
176 auto it2 = indexToRow_.find(rowIndex2);
177
178 if (it1 == indexToRow_.end() && it2 == indexToRow_.end()) return;
179
180 if (it1 == indexToRow_.end()) {
181 indexToRow_.emplace(rowIndex1, it2->second);
182 rowToIndex_.at(it2->second) = rowIndex1;
183 indexToRow_.erase(it2->second);
184 return;
185 }
186
187 if (it2 == indexToRow_.end()) {
188 indexToRow_.emplace(rowIndex2, it1->second);
189 rowToIndex_.at(it1->second) = rowIndex2;
190 indexToRow_.erase(it1);
191 return;
192 }
193
194 std::swap(rowToIndex_.at(it1->second), rowToIndex_.at(it2->second));
195 std::swap(it1->second, it2->second);
196 } else {
197 for (auto i = indexToRow_.size(); i <= std::max(rowIndex1, rowIndex2); ++i) indexToRow_.push_back(i);
198
199 std::swap(rowToIndex_[indexToRow_[rowIndex1]], rowToIndex_[indexToRow_[rowIndex2]]);
200 std::swap(indexToRow_[rowIndex1], indexToRow_[rowIndex2]);
201 }
202}
203
204template <class Master_matrix, class Base_matrix>
206 Base_swap&& other) noexcept
207{
208 if (this == &other) return *this;
209
210 indexToRow_ = std::move(other.indexToRow_);
211 rowToIndex_ = std::move(other.rowToIndex_);
212 rowSwapped_ = std::exchange(other.rowSwapped_, false);
213 return *this;
214}
215
216template <class Master_matrix, class Base_matrix>
217inline void Base_swap<Master_matrix, Base_matrix>::_orderRows()
218{
219 for (unsigned int i = 0; i < _matrix()->get_number_of_columns(); i++) {
220 _matrix()->matrix_.at(i).reorder(rowToIndex_, i);
221 }
222 for (Index i = 0; i < _matrix()->get_number_of_columns(); i++) {
223 indexToRow_[i] = i;
224 rowToIndex_[i] = i;
225 }
226 rowSwapped_ = false;
227}
228
229template <class Master_matrix, class Base_matrix>
230inline void Base_swap<Master_matrix, Base_matrix>::_initialize_row_index(Index index)
231{
232 if constexpr (Master_matrix::Option_list::has_map_column_container) {
233 indexToRow_.emplace(index, index);
234 rowToIndex_.emplace(index, index);
235 } else {
236 indexToRow_.reserve(index + 1);
237 rowToIndex_.reserve(index + 1);
238 for (Index i = indexToRow_.size(); i <= index; ++i) {
239 indexToRow_.push_back(i);
240 rowToIndex_.push_back(i);
241 }
242 }
243}
244
245template <class Master_matrix, class Base_matrix>
246inline typename Base_swap<Master_matrix, Base_matrix>::Index Base_swap<Master_matrix, Base_matrix>::_erase_row(
247 Index index)
248{
249 if constexpr (Master_matrix::Option_list::has_map_column_container) {
250 auto it = indexToRow_.find(index);
251 auto rowID = it->second;
252 rowToIndex_.erase(rowID);
253 indexToRow_.erase(it);
254 return rowID;
255 } else {
256 return indexToRow_[index];
257 }
258}
259
260template <class Master_matrix, class Base_matrix>
261inline typename Base_swap<Master_matrix, Base_matrix>::Index Base_swap<Master_matrix, Base_matrix>::_get_row_index(
262 Index index) const
263{
264 if constexpr (Master_matrix::Option_list::has_map_column_container) {
265 return indexToRow_.at(index);
266 } else {
267 return indexToRow_[index];
268 }
269}
270
271template <class Master_matrix, class Base_matrix>
272inline bool Base_swap<Master_matrix, Base_matrix>::_row_were_swapped() const
273{
274 return rowSwapped_;
275}
276
277template <class Master_matrix, class Base_matrix>
278inline void Base_swap<Master_matrix, Base_matrix>::_reset()
279{
280 indexToRow_.clear();
281 rowToIndex_.clear();
282 rowSwapped_ = false;
283}
284
285} // namespace persistence_matrix
286} // namespace Gudhi
287
288#endif // PM_BASE_SWAP_H
A basic matrix structure allowing to easily manipulate and access entire columns and rows,...
Definition Base_matrix.h:39
friend void swap(Base_swap &base1, Base_swap &base2) noexcept
Swap operator.
Definition base_swap.h:110
Base_swap(const Base_swap &matrixToCopy)=default
Copy constructor.
void swap_rows(ID_index rowIndex1, ID_index rowIndex2)
Swaps the two rows at the given indices, but in a lazy manner. That is, the swap is registered but no...
Definition base_swap.h:170
Base_swap()
Default constructor.
Definition base_swap.h:140
void swap_columns(Index columnIndex1, Index columnIndex2)
Swaps the two columns at given indices in the column container. Does not updates the column index val...
Definition base_swap.h:163
Base_swap & operator=(const Base_swap &other)=default
Assign operator.
typename Master_matrix::Index Index
Definition base_swap.h:53
typename Master_matrix::Column_container Column_container
Definition base_swap.h:52
typename Master_matrix::ID_index ID_index
Definition base_swap.h:54
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14