INSTINCT Code Coverage Report


Directory: src/
File: util/Container/KeyedMatrix.hpp
Date: 2025-06-02 15:19:59
Exec Total Coverage
Lines: 887 898 98.8%
Functions: 846 944 89.6%
Branches: 579 1095 52.9%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 /// @file KeyedMatrix.hpp
10 /// @brief Matrix which can be accessed by keys
11 /// @author T. Topp (topp@ins.uni-stuttgart.de)
12 /// @note Based on ideas from Kevin Gutsche (kevin.gutsche@ins.uni-stuttgart.de) and Bayram Stucke (bayram.stucke@ins.uni-stuttgart.de)
13 /// @date 2023-07-06
14
15 #pragma once
16
17 #include <unordered_set>
18 #include <vector>
19 #include <array>
20 #include <span>
21 #include <algorithm>
22 #include <ranges>
23 #include <type_traits>
24 #include "util/Assert.h"
25 #include "util/Eigen.hpp"
26 #include "util/Container/Vector.hpp"
27 #include "util/Container/Unordered_map.hpp"
28
29 #if defined(__GNUC__) && !defined(__clang__)
30 #pragma GCC diagnostic push
31 #pragma GCC diagnostic ignored "-Wvirtual-move-assign" // NOLINT(clang-diagnostic-unknown-warning-option)
32 #endif
33
34 namespace NAV
35 {
36 namespace internal
37 {
38 /// @brief All type to request all rows or columns in KeyedMatrices
39 struct all_t
40 {
41 /// @brief Default Constructor
42 all_t() = default;
43 };
44
45 /// @brief KeyedMatrix storage class
46 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
47 /// @tparam Rows Number of rows, or \b Dynamic
48 /// @tparam Cols Number of columns, or \b Dynamic
49 template<typename Scalar, int Rows, int Cols>
50 class KeyedMatrixStorage
51 {
52 protected:
53 Eigen::Matrix<Scalar, Rows, Cols> matrix; ///< Data storage of the type
54 mutable std::mutex _sliceMutex; ///< Mutex for accessing the slices
55
56 private:
57 template<typename Scalar_, typename RowKeyType_, typename ColKeyType_, int Rows_, int Cols_>
58 friend class KeyedMatrixBase;
59 template<typename Scalar_, typename RowKeyType_, int Rows_>
60 friend class KeyedVectorBase;
61 template<typename Scalar_, typename ColKeyType_, int Cols_>
62 friend class KeyedRowVectorBase;
63 };
64
65 // ###########################################################################################################
66
67 /// @brief Base class for Keyed matrices with multiple rows
68 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
69 /// @tparam RowKeyType Type of the key used for row lookup
70 /// @tparam Rows Number of rows, or \b Dynamic
71 /// @tparam Cols Number of columns, or \b Dynamic
72 template<typename Scalar, typename RowKeyType, int Rows, int Cols>
73 class KeyedMatrixRowsBase : virtual public KeyedMatrixStorage<Scalar, Rows, Cols>
74 {
75 public:
76 /// @brief Return the rows of the underlying Eigen matrix
77 80912 [[nodiscard]] decltype(auto) rows() const { return this->matrix.rows(); }
78
79 /// @brief Returns the row keys
80 2467768 const std::vector<RowKeyType>& rowKeys() const { return rowKeysVector; }
81
82 /// @brief Checks if the matrix has the key
83 /// @param key Row key to check for
84 3437 bool hasRow(const RowKeyType& key) const { return rowIndices.contains(key); }
85
86 /// @brief Checks if the matrix has multiple keys
87 /// @param keys Row keys to check for
88 800 bool hasRows(std::span<const RowKeyType> keys) const
89 {
90 2129 return std::ranges::all_of(keys, [&](const RowKeyType& key) { return hasRow(key); });
91 }
92
93 /// @brief Checks if the matrix has any key
94 /// @param keys Row keys to check for
95 872 bool hasAnyRows(std::span<const RowKeyType> keys) const
96 {
97 1382 return std::ranges::any_of(keys, [&](const RowKeyType& key) { return hasRow(key); });
98 }
99
100 /// @brief Replace the old with the new key
101 /// @param[in] oldKey Old key to replace
102 /// @param[in] newKey New key to use instead
103 17 void replaceRowKey(const RowKeyType& oldKey, const RowKeyType& newKey)
104 {
105
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
17 auto iter = std::ranges::find(rowKeysVector, oldKey);
106
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
17 INS_ASSERT_USER_ERROR(iter != rowKeysVector.end(), "You cannot replace keys, which are not in the vector/matrix.");
107
108 17 *iter = newKey;
109
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
17 rowIndices[newKey] = rowIndices.at(oldKey);
110
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
17 rowIndices.erase(oldKey);
111 17 }
112
113 protected:
114 /// RowKey to Row Index mapping
115 unordered_map<RowKeyType, Eigen::Index> rowIndices;
116 /// Row Keys
117 std::vector<RowKeyType> rowKeysVector;
118
119 /// Row Slice used for accessing
120 mutable std::vector<Eigen::Index> rowSlice;
121
122 private:
123 template<typename Scalar_, typename RowKeyType_, typename ColKeyType_, int Rows_, int Cols_>
124 friend class KeyedMatrixBase;
125 template<typename Scalar_, typename RowKeyType_, int Rows_>
126 friend class KeyedVectorBase;
127 };
128
129 /// @brief Base class for Keyed matrices with multiple rows of static size
130 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
131 /// @tparam RowKeyType Type of the key used for row lookup
132 /// @tparam Rows Number of rows, or \b Dynamic
133 /// @tparam Cols Number of columns, or \b Dynamic
134 template<typename Scalar, typename RowKeyType, int Rows, int Cols>
135 class KeyedMatrixRows : public KeyedMatrixRowsBase<Scalar, RowKeyType, Rows, Cols>
136 {};
137
138 /// @brief Base class for Keyed matrices with multiple rows of dynamic size
139 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
140 /// @tparam RowKeyType Type of the key used for row lookup
141 /// @tparam Cols Number of columns, or \b Dynamic
142 template<typename Scalar, typename RowKeyType, int Cols>
143 class KeyedMatrixRows<Scalar, RowKeyType, Eigen::Dynamic, Cols> : public KeyedMatrixRowsBase<Scalar, RowKeyType, Eigen::Dynamic, Cols>
144 {
145 public:
146 /// @brief Adds a new row to the matrix
147 /// @param rowKey Row key
148
4/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
8 void addRow(const RowKeyType& rowKey) { addRows(std::initializer_list<RowKeyType>{ rowKey }); }
149
150 /// @brief Adds new rows to the matrix
151 /// @param rowKeys Row keys
152 220 void addRows(std::span<const RowKeyType> rowKeys)
153 {
154
2/4
✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 110 times.
✗ Branch 4 not taken.
220 INS_ASSERT_USER_ERROR(!this->hasAnyRows(rowKeys), "You cannot add a row key which is already in the matrix.");
155
4/12
✓ Branch 3 taken 110 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 110 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 110 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 110 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
440 INS_ASSERT_USER_ERROR(std::unordered_set<RowKeyType>(rowKeys.begin(), rowKeys.end()).size() == rowKeys.size(), "Each row key must be unique");
156
157 220 auto initialSize = static_cast<Eigen::Index>(this->rowIndices.size());
158
7/9
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 110 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 110 times.
✓ Branch 11 taken 106 times.
✓ Branch 13 taken 8 times.
✓ Branch 14 taken 4 times.
456 for (const auto& rowKey : rowKeys) { this->rowIndices.insert({ rowKey, static_cast<Eigen::Index>(this->rowIndices.size()) }); }
159
1/2
✓ Branch 3 taken 110 times.
✗ Branch 4 not taken.
220 this->rowKeysVector.reserve(this->rowKeysVector.size() + rowKeys.size());
160
2/4
✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 110 times.
✗ Branch 7 not taken.
220 std::copy(rowKeys.begin(), rowKeys.end(), std::back_inserter(this->rowKeysVector));
161 220 auto finalSize = static_cast<Eigen::Index>(this->rowIndices.size());
162
163
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
220 if (finalSize > initialSize)
164 {
165
1/2
✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
220 this->matrix.conservativeResize(finalSize, Eigen::NoChange);
166
3/6
✓ Branch 2 taken 110 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 110 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 110 times.
✗ Branch 10 not taken.
220 this->matrix.block(initialSize, 0, finalSize - initialSize, this->matrix.cols()) = Eigen::MatrixX<Scalar>::Zero(finalSize - initialSize, this->matrix.cols());
167 }
168
1/2
✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
220 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
169
1/2
✓ Branch 2 taken 110 times.
✗ Branch 3 not taken.
220 this->rowSlice.reserve(this->rowKeysVector.size());
170 220 }
171
172 /// @brief Removes the row from the matrix
173 /// @param rowKey Row Key
174
5/13
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
6 void removeRow(const RowKeyType& rowKey) { removeRows(std::initializer_list<RowKeyType>{ rowKey }); }
175
176 /// @brief Removes the rows from the matrix
177 /// @param rowKeys Row Keys
178 16 void removeRows(std::span<const RowKeyType> rowKeys)
179 {
180 16 std::vector<int> indices;
181
2/2
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 8 times.
44 for (const auto& rowKey : rowKeys)
182 {
183
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 auto iter = this->rowIndices.find(rowKey);
184
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 INS_ASSERT_USER_ERROR(iter != this->rowIndices.end(), "You tried removing a row key, which did not exist.");
185
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 if (iter != this->rowIndices.end())
186 {
187
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 indices.push_back(static_cast<int>(iter->second));
188 }
189 }
190
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 NAV::removeRows(this->matrix, indices);
191
192
2/2
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 8 times.
44 for (const auto& rowKey : rowKeys)
193 {
194
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 auto iter = this->rowIndices.find(rowKey);
195
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 if (iter != this->rowIndices.end())
196 {
197
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
118 std::erase_if(this->rowKeysVector, [&](const auto& item) { return item == rowKey; });
198
199 28 auto idx = iter->second;
200
2/2
✓ Branch 5 taken 90 times.
✓ Branch 6 taken 14 times.
208 for (auto& rowIndex : this->rowIndices)
201 {
202
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 50 times.
180 if (rowIndex.second > idx) { rowIndex.second--; }
203 }
204
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 this->rowIndices.erase(iter);
205 }
206 }
207 16 }
208 };
209
210 // ###########################################################################################################
211
212 /// @brief Base class for Keyed matrices with multiple columns
213 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
214 /// @tparam ColKeyType Type of the key used for col lookup
215 /// @tparam Rows Number of rows, or \b Dynamic
216 /// @tparam Cols Number of columns, or \b Dynamic
217 template<typename Scalar, typename ColKeyType, int Rows, int Cols>
218 class KeyedMatrixColsBase : virtual public KeyedMatrixStorage<Scalar, Rows, Cols>
219 {
220 public:
221 /// @brief Return the cols of the underlying Eigen matrix
222 26888 [[nodiscard]] decltype(auto) cols() const { return this->matrix.cols(); }
223
224 /// @brief Returns the col keys
225 2017169 const std::vector<ColKeyType>& colKeys() const { return colKeysVector; }
226
227 /// @brief Checks if the matrix has the key
228 /// @param key Col key to check for
229 437 bool hasCol(const ColKeyType& key) const { return colIndices.contains(key); }
230
231 /// @brief Checks if the matrix has multiple keys
232 /// @param keys Col keys to check for
233 10 bool hasCols(std::span<const ColKeyType> keys) const
234 {
235 18 return std::ranges::all_of(keys, [&](const ColKeyType& key) { return hasCol(key); });
236 }
237
238 /// @brief Checks if the matrix has any keys
239 /// @param keys Col keys to check for
240 391 bool hasAnyCols(std::span<const ColKeyType> keys) const
241 {
242 791 return std::ranges::any_of(keys, [&](const ColKeyType& key) { return hasCol(key); });
243 }
244
245 /// @brief Replace the old with the new key
246 /// @param[in] oldKey Old key to replace
247 /// @param[in] newKey New key to use instead
248 8 void replaceColKey(const ColKeyType& oldKey, const ColKeyType& newKey)
249 {
250
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 auto iter = std::ranges::find(colKeysVector, oldKey);
251
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 INS_ASSERT_USER_ERROR(iter != colKeysVector.end(), "You cannot replace keys, which are not in the vector/matrix.");
252
253 8 *iter = newKey;
254
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 colIndices[newKey] = colIndices.at(oldKey);
255
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 colIndices.erase(oldKey);
256 8 }
257
258 protected:
259 /// ColKey to Col Index mapping
260 unordered_map<ColKeyType, Eigen::Index> colIndices;
261 /// Col Keys
262 std::vector<ColKeyType> colKeysVector;
263
264 /// Col Slice used for accessing
265 mutable std::vector<Eigen::Index> colSlice;
266
267 private:
268 template<typename Scalar_, typename RowKeyType_, typename ColKeyType_, int Rows_, int Cols_>
269 friend class KeyedMatrixBase;
270 template<typename Scalar_, typename ColKeyType_, int Cols_>
271 friend class KeyedRowVectorBase;
272 };
273
274 /// @brief Base class for Keyed matrices with multiple columns of static size
275 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
276 /// @tparam ColKeyType Type of the key used for col lookup
277 /// @tparam Rows Number of rows, or \b Dynamic
278 /// @tparam Cols Number of columns, or \b Dynamic
279 template<typename Scalar, typename ColKeyType, int Rows, int Cols>
280 class KeyedMatrixCols : public KeyedMatrixColsBase<Scalar, ColKeyType, Rows, Cols>
281 {};
282
283 /// @brief Base class for Keyed matrices with multiple columns of dynamic size
284 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
285 /// @tparam ColKeyType Type of the key used for col lookup
286 /// @tparam Rows Number of rows, or \b Dynamic
287 template<typename Scalar, typename ColKeyType, int Rows>
288 class KeyedMatrixCols<Scalar, ColKeyType, Rows, Eigen::Dynamic> : public KeyedMatrixColsBase<Scalar, ColKeyType, Rows, Eigen::Dynamic>
289 {
290 public:
291 /// @brief Adds a new col to the matrix
292 /// @param colKey Col key
293
5/13
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
8 void addCol(const ColKeyType& colKey) { addCols(std::initializer_list<ColKeyType>{ colKey }); }
294
295 /// @brief Adds new cols to the matrix
296 /// @param colKeys Col keys
297 63 void addCols(std::span<const ColKeyType> colKeys)
298 {
299
2/4
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
63 INS_ASSERT_USER_ERROR(!this->hasAnyCols(colKeys), "You cannot add a col key which is already in the matrix.");
300
4/12
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 58 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 58 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 58 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
126 INS_ASSERT_USER_ERROR(std::unordered_set<ColKeyType>(colKeys.begin(), colKeys.end()).size() == colKeys.size(), "Each col key must be unique");
301
302 63 auto initialSize = static_cast<Eigen::Index>(this->colIndices.size());
303
7/9
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 59 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 59 times.
✓ Branch 11 taken 56 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 2 times.
136 for (const auto& colKey : colKeys) { this->colIndices.insert({ colKey, static_cast<Eigen::Index>(this->colIndices.size()) }); }
304
1/2
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
63 this->colKeysVector.reserve(this->colKeysVector.size() + colKeys.size());
305
2/4
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 58 times.
✗ Branch 7 not taken.
63 std::copy(colKeys.begin(), colKeys.end(), std::back_inserter(this->colKeysVector));
306 63 auto finalSize = static_cast<Eigen::Index>(this->colIndices.size());
307
308
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
63 if (finalSize > initialSize)
309 {
310
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
63 this->matrix.conservativeResize(Eigen::NoChange, finalSize);
311
3/6
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 58 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 58 times.
✗ Branch 10 not taken.
63 this->matrix.block(0, initialSize, this->matrix.rows(), finalSize - initialSize) = Eigen::MatrixX<Scalar>::Zero(this->matrix.rows(), finalSize - initialSize);
312 }
313
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
63 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
314
1/2
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
63 this->colSlice.reserve(this->colKeysVector.size());
315 63 }
316
317 /// @brief Removes the col from the matrix
318 /// @param colKey Col Key
319
5/13
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
6 void removeCol(const ColKeyType& colKey) { removeCols(std::initializer_list<ColKeyType>{ colKey }); }
320
321 /// @brief Removes the cols from the matrix
322 /// @param colKeys Col Keys
323 10 void removeCols(std::span<const ColKeyType> colKeys)
324 {
325 10 std::vector<int> indices;
326
2/2
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 6 times.
26 for (const auto& colKey : colKeys)
327 {
328
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
16 auto iter = this->colIndices.find(colKey);
329
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
16 INS_ASSERT_USER_ERROR(iter != this->colIndices.end(), "You tried removing a col key, which did not exist.");
330
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
16 if (iter != this->colIndices.end())
331 {
332
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
16 indices.push_back(static_cast<int>(iter->second));
333 }
334 }
335
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
10 NAV::removeCols(this->matrix, indices);
336
337
2/2
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 6 times.
26 for (const auto& colKey : colKeys)
338 {
339
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
16 auto iter = this->colIndices.find(colKey);
340
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
16 if (iter != this->colIndices.end())
341 {
342
2/3
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
76 std::erase_if(this->colKeysVector, [&](const auto& item) { return item == colKey; });
343
344 16 auto idx = iter->second;
345
2/2
✓ Branch 5 taken 60 times.
✓ Branch 6 taken 10 times.
106 for (auto& colIndex : this->colIndices)
346 {
347
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
90 if (colIndex.second > idx) { colIndex.second--; }
348 }
349
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
16 this->colIndices.erase(iter);
350 }
351 }
352 10 }
353 };
354
355 // ###########################################################################################################
356
357 template<typename Scalar, typename ColKeyType, int Cols>
358 class KeyedRowVectorBase;
359
360 /// @brief Class to inherit common methods for static and dynamic sized vectors
361 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
362 /// @tparam RowKeyType Type of the key used for row lookup
363 /// @tparam Rows Number of rows, or \b Dynamic
364 template<typename Scalar, typename RowKeyType, int Rows>
365 class KeyedVectorBase : public KeyedMatrixRows<Scalar, RowKeyType, Rows, 1>
366 {
367 public:
368 /// @brief Constructor
369 /// @param vector Eigen vector to initialize from
370 template<typename Derived>
371 2625 explicit KeyedVectorBase(const Eigen::MatrixBase<Derived>& vector)
372 2625 {
373
1/2
✓ Branch 1 taken 1821 times.
✗ Branch 2 not taken.
2625 this->matrix = vector;
374 2625 }
375
376 /// @brief Constructor
377 /// @param vector Eigen vector to initialize from
378 /// @param rowKeys Row keys describing the vector
379 template<typename Derived>
380 111328 KeyedVectorBase(const Eigen::MatrixBase<Derived>& vector, std::span<const RowKeyType> rowKeys)
381 111328 {
382
4/12
✓ Branch 3 taken 55664 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 55664 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 55664 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 55664 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
222656 INS_ASSERT_USER_ERROR(std::unordered_set<RowKeyType>(rowKeys.begin(), rowKeys.end()).size() == rowKeys.size(), "Each row key must be unique");
383
384
1/2
✓ Branch 1 taken 55664 times.
✗ Branch 2 not taken.
111328 INS_ASSERT_USER_ERROR(vector.cols() == 1, "Only vectors with 1 column are allowed.");
385
1/2
✓ Branch 2 taken 26823 times.
✗ Branch 3 not taken.
53646 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || vector.rows() == static_cast<int>(rowKeys.size()), "Number of vector rows doesn't correspond to the amount of row keys");
386
387
7/8
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 382321 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 382321 times.
✓ Branch 7 taken 55661 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 3 times.
875996 for (size_t i = 0; i < rowKeys.size(); i++) { this->rowIndices.insert({ rowKeys[i], static_cast<Eigen::Index>(i) }); }
388
389
1/2
✓ Branch 1 taken 55664 times.
✗ Branch 2 not taken.
111328 this->matrix = vector;
390
2/4
✓ Branch 1 taken 55664 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 55664 times.
✗ Branch 5 not taken.
111328 std::ranges::copy(rowKeys, std::back_inserter(this->rowKeysVector));
391
1/2
✓ Branch 2 taken 55664 times.
✗ Branch 3 not taken.
111328 this->rowSlice.reserve(this->rowKeysVector.size());
392 111328 }
393
394 // #######################################################################################################
395 // Special member functions
396 // #######################################################################################################
397
398 /// @brief Destructor
399 118028 ~KeyedVectorBase() = default;
400 /// @brief Copy constructor
401 /// @param other The other object
402 3046 KeyedVectorBase(const KeyedVectorBase& other)
403 3046 {
404
1/2
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
3046 this->matrix = other.matrix;
405
1/2
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
3046 this->rowIndices = other.rowIndices;
406
1/2
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
3046 this->rowKeysVector = other.rowKeysVector;
407
1/2
✓ Branch 2 taken 1523 times.
✗ Branch 3 not taken.
3046 this->rowSlice.reserve(this->rowKeysVector.size());
408 3046 }
409 /// @brief Copy assignment operator
410 /// @param other The other object
411 4 KeyedVectorBase& operator=(const KeyedVectorBase& other)
412 {
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if (this == &other) { return *this; } // Guard self assignment
414
415 4 this->matrix = other.matrix;
416 4 this->rowIndices = other.rowIndices;
417 4 this->rowKeysVector = other.rowKeysVector;
418 4 this->rowSlice.reserve(this->rowKeysVector.size());
419
420 4 return *this;
421 }
422 /// @brief Move constructor
423 /// @param other The other object
424 4 KeyedVectorBase(KeyedVectorBase&& other) noexcept
425 4 {
426 4 this->matrix = std::move(other.matrix);
427 4 this->rowIndices = std::move(other.rowIndices);
428 4 this->rowKeysVector = std::move(other.rowKeysVector);
429 4 this->rowSlice.reserve(this->rowKeysVector.size());
430 4 }
431 /// @brief Move assignment operator
432 /// @param other The other object
433 55441 KeyedVectorBase& operator=(KeyedVectorBase&& other) noexcept
434 {
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28180 times.
55441 if (this == &other) { return *this; } // Guard self assignment
436
437 55441 this->matrix = std::move(other.matrix);
438 55441 this->rowIndices = std::move(other.rowIndices);
439 55441 this->rowKeysVector = std::move(other.rowKeysVector);
440 55441 this->rowSlice.reserve(this->rowKeysVector.size());
441
442 55441 return *this;
443 }
444
445 // ###########################################################################################################
446 // Special member functions with different Rows/Cols
447 // ###########################################################################################################
448
449 /// @brief Copy constructor
450 /// @param other The other object
451 template<int oRows>
452 4 KeyedVectorBase(const KeyedVectorBase<Scalar, RowKeyType, oRows>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
453 4 {
454
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || other.rows() == Rows, "Can only copy construct dynamic<=>static matrices if the rows match");
455
456
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->matrix = other.matrix;
457
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->rowIndices = other.rowIndices;
458
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->rowKeysVector = other.rowKeysVector;
459
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 this->rowSlice.reserve(this->rowKeysVector.size());
460 4 }
461 /// @brief Copy assignment operator
462 /// @param other The other object
463 template<int oRows>
464 4 KeyedVectorBase& operator=(const KeyedVectorBase<Scalar, RowKeyType, oRows>& other)
465 {
466 // No need to guard self assignment, as the types are different, so it cannot be the same object
467
468
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 INS_ASSERT_USER_ERROR(other.rowKeys() == this->rowKeys(), "Can only copy assign matrices if the row keys match");
469
470 4 this->matrix = other.matrix;
471 4 this->rowIndices = other.rowIndices;
472 4 this->rowKeysVector = other.rowKeysVector;
473 4 this->rowSlice.reserve(this->rowKeysVector.size());
474
475 4 return *this;
476 }
477 /// @brief Move constructor
478 /// @param other The other object
479 template<int oRows>
480 4 KeyedVectorBase(KeyedVectorBase<Scalar, RowKeyType, oRows>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
481 4 {
482
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || other.rows() == Rows, "Can only copy construct dynamic<=>static matrices if the rows match");
483
484 4 this->matrix = std::move(other.matrix);
485 4 this->rowIndices = std::move(other.rowIndices);
486 4 this->rowKeysVector = std::move(other.rowKeysVector);
487 4 this->rowSlice.reserve(this->rowKeysVector.size());
488 4 }
489 /// @brief Move assignment operator
490 /// @param other The other object
491 template<int oRows>
492 53630 KeyedVectorBase& operator=(KeyedVectorBase<Scalar, RowKeyType, oRows>&& other) noexcept
493 {
494 // No need to guard self assignment, as the types are different, so it cannot be the same object
495
496
1/2
✓ Branch 3 taken 26815 times.
✗ Branch 4 not taken.
53630 INS_ASSERT_USER_ERROR(other.rowKeys() == this->rowKeys(), "Can only copy assign matrices if the row keys match");
497
498 53630 this->matrix = std::move(other.matrix);
499 53630 this->rowIndices = std::move(other.rowIndices);
500 53630 this->rowKeysVector = std::move(other.rowKeysVector);
501 53630 this->rowSlice.reserve(this->rowKeysVector.size());
502
503 53630 return *this;
504 }
505
506 // #######################################################################################################
507 // Access
508 // #######################################################################################################
509
510 /// @brief Gets the value for the row key
511 /// @param rowKey Row Key
512 /// @return Scalar value
513 2336 const Scalar& operator()(const RowKeyType& rowKey) const
514 {
515 2336 return this->matrix(this->rowIndices.at(rowKey), 0);
516 }
517 /// @brief Gets the value for the row key
518 /// @param rowKey Row Key
519 /// @return Scalar value
520 99865 Scalar& operator()(const RowKeyType& rowKey)
521 {
522 99865 return this->matrix(this->rowIndices.at(rowKey), 0);
523 }
524
525 /// @brief Gets the values for the row keys
526 /// @param rowKeys Row Keys
527 /// @return View into the matrix for the row keys
528 decltype(auto) operator()(std::span<const RowKeyType> rowKeys) const
529 {
530 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
531 this->rowSlice.clear();
532 for (const auto& rowKey : rowKeys) { this->rowSlice.push_back(this->rowIndices.at(rowKey)); }
533
534 return this->matrix(this->rowSlice, 0);
535 }
536 /// @brief Gets the values for the row keys
537 /// @param rowKeys Row Keys
538 /// @return View into the matrix for the row keys
539 1 decltype(auto) operator()(std::span<const RowKeyType> rowKeys)
540 {
541
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
542 1 this->rowSlice.clear();
543
4/6
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 1 times.
4 for (const auto& rowKey : rowKeys) { this->rowSlice.push_back(this->rowIndices.at(rowKey)); }
544
545
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return this->matrix(this->rowSlice, 0);
546 1 }
547
548 /// @brief Requests the full vector
549 2267 const Eigen::Matrix<Scalar, Rows, 1>& operator()(all_t /* all */) const { return this->matrix; }
550 /// @brief Requests the full vector
551 416336 Eigen::Matrix<Scalar, Rows, 1>& operator()(all_t /* all */) { return this->matrix; }
552 /// @brief Conversion into Eigen::Vector
553 explicit operator Eigen::Vector<Scalar, Rows>() { return this->matrix; }
554
555 // #######################################################################################################
556 // Block operations
557 // #######################################################################################################
558
559 /// @brief Gets the values for the row keys
560 /// @param rowKeys Row Keys
561 /// @return View into the matrix for the row keys
562 template<size_t P>
563 1474 decltype(auto) segment(std::span<const RowKeyType> rowKeys) const // NOLINT(readability-const-return-type)
564 {
565 1474 checkContinuousSegment(rowKeys, P);
566
567 1474 return this->matrix.template middleRows<P>(this->rowIndices.at(rowKeys.front()));
568 }
569 /// @brief Gets the values for the row keys
570 /// @param rowKeys Row Keys
571 /// @return View into the matrix for the row keys
572 template<size_t P>
573 134069 decltype(auto) segment(std::span<const RowKeyType> rowKeys)
574 {
575 134069 checkContinuousSegment(rowKeys, P);
576
577 134069 return this->matrix.template middleRows<P>(this->rowIndices.at(rowKeys.front()));
578 }
579 /// @brief Gets the values for the row keys
580 /// @param rowKeys Row Keys
581 /// @return View into the matrix for the row keys
582 decltype(auto) segment(std::span<const RowKeyType> rowKeys) const // NOLINT(readability-const-return-type)
583 {
584 checkContinuousSegment(rowKeys, rowKeys.size());
585
586 return this->matrix.middleRows(this->rowIndices.at(rowKeys.front()), rowKeys.size());
587 }
588 /// @brief Gets the values for the row keys
589 /// @param rowKeys Row Keys
590 /// @return View into the matrix for the row keys
591 4 decltype(auto) segment(std::span<const RowKeyType> rowKeys)
592 {
593 4 checkContinuousSegment(rowKeys, rowKeys.size());
594
595 4 return this->matrix.middleRows(this->rowIndices.at(rowKeys.front()), rowKeys.size());
596 }
597
598 // #######################################################################################################
599 // Methods
600 // #######################################################################################################
601
602 /// @brief Calculates the transposed vector
603 4 [[nodiscard]] KeyedRowVectorBase<Scalar, RowKeyType, Rows> transposed() const
604 {
605
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 return { this->matrix.transpose(), this->rowKeys() };
606 }
607
608 private:
609 /// @brief Checks if the row keys are describing a continuous block
610 /// @param rowKeys Row keys
611 /// @param P Size of the row keys
612 135547 void checkContinuousSegment([[maybe_unused]] std::span<const RowKeyType> rowKeys, [[maybe_unused]] size_t P) const
613 {
614 #ifndef NDEBUG
615
1/2
✓ Branch 1 taken 135543 times.
✗ Branch 2 not taken.
135547 INS_ASSERT_USER_ERROR(P == rowKeys.size(), "The block size must be equivalent to the amount of row keys.");
616
617
1/2
✓ Branch 2 taken 135543 times.
✗ Branch 3 not taken.
135547 std::vector<Eigen::Index> consecutiveRows(rowKeys.size());
618
1/2
✓ Branch 2 taken 135543 times.
✗ Branch 3 not taken.
271094 std::iota(std::begin(consecutiveRows), std::end(consecutiveRows), this->rowIndices.at(rowKeys.front()));
619 135547 std::vector<Eigen::Index> rowIndices;
620
1/2
✓ Branch 2 taken 135543 times.
✗ Branch 3 not taken.
135547 rowIndices.reserve(rowKeys.size());
621
4/6
✓ Branch 4 taken 406625 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 406625 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 406625 times.
✓ Branch 12 taken 135543 times.
542180 for (const auto& rowKey : rowKeys) { rowIndices.push_back(this->rowIndices.at(rowKey)); }
622
2/4
✓ Branch 1 taken 135543 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 135543 times.
✗ Branch 4 not taken.
135547 INS_ASSERT_USER_ERROR(rowIndices == consecutiveRows, "The given rowKeys must describe a consecutive part in the matrix.");
623 #endif
624 135547 }
625 };
626
627 /// @brief Class to inherit common methods for static and dynamic sized row vectors
628 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
629 /// @tparam ColKeyType Type of the key used for col lookup
630 /// @tparam Cols Number of columns, or \b Dynamic
631 template<typename Scalar, typename ColKeyType, int Cols>
632 class KeyedRowVectorBase : public KeyedMatrixCols<Scalar, ColKeyType, 1, Cols>
633 {
634 public:
635 /// @brief Constructor
636 /// @param vector Eigen vector to initialize from
637 template<typename Derived>
638 explicit KeyedRowVectorBase(const Eigen::MatrixBase<Derived>& vector)
639 {
640 this->matrix = vector;
641 }
642
643 /// @brief Constructor
644 /// @param vector Eigen vector to initialize from
645 /// @param colKeys Col keys describing the vector
646 template<typename Derived>
647 40 KeyedRowVectorBase(const Eigen::MatrixBase<Derived>& vector, std::span<const ColKeyType> colKeys)
648 40 {
649
4/12
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
80 INS_ASSERT_USER_ERROR(std::unordered_set<ColKeyType>(colKeys.begin(), colKeys.end()).size() == colKeys.size(), "Each col key must be unique");
650
651
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 INS_ASSERT_USER_ERROR(vector.rows() == 1, "Only vectors with 1 row are allowed.");
652
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
20 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || vector.cols() == static_cast<Eigen::Index>(colKeys.size()), "Number of vector cols doesn't correspond to the amount of col keys");
653
654
7/8
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 55 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 55 times.
✓ Branch 7 taken 17 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 3 times.
176 for (size_t i = 0; i < colKeys.size(); i++) { this->colIndices.insert({ colKeys[i], static_cast<Eigen::Index>(i) }); }
655
656
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 this->matrix = vector;
657
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 std::ranges::copy(colKeys, std::back_inserter(this->colKeysVector));
658
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
40 this->colSlice.reserve(this->colKeysVector.size());
659 40 }
660
661 // #######################################################################################################
662 // Special member functions
663 // #######################################################################################################
664
665 /// @brief Destructor
666 56 ~KeyedRowVectorBase() = default;
667 /// @brief Copy constructor
668 /// @param other The other object
669 4 KeyedRowVectorBase(const KeyedRowVectorBase& other)
670 4 {
671
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->matrix = other.matrix;
672
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colIndices = other.colIndices;
673
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colKeysVector = other.colKeysVector;
674
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 this->colSlice.reserve(this->colKeysVector.size());
675 4 }
676 /// @brief Copy assignment operator
677 /// @param other The other object
678 4 KeyedRowVectorBase& operator=(const KeyedRowVectorBase& other)
679 {
680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if (this == &other) { return *this; } // Guard self assignment
681
682 4 this->matrix = other.matrix;
683 4 this->colIndices = other.colIndices;
684 4 this->colKeysVector = other.colKeysVector;
685 4 this->colSlice.reserve(this->colKeysVector.size());
686
687 4 return *this;
688 }
689 /// @brief Move constructor
690 /// @param other The other object
691 4 KeyedRowVectorBase(KeyedRowVectorBase&& other) noexcept
692 4 {
693 4 this->matrix = std::move(other.matrix);
694 4 this->colIndices = std::move(other.colIndices);
695 4 this->colKeysVector = std::move(other.colKeysVector);
696 4 this->colSlice.reserve(this->colKeysVector.size());
697 4 }
698 /// @brief Move assignment operator
699 /// @param other The other object
700 4 KeyedRowVectorBase& operator=(KeyedRowVectorBase&& other) noexcept
701 {
702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if (this == &other) { return *this; } // Guard self assignment
703
704 4 this->matrix = std::move(other.matrix);
705 4 this->colIndices = std::move(other.colIndices);
706 4 this->colKeysVector = std::move(other.colKeysVector);
707 4 this->colSlice.reserve(this->colKeysVector.size());
708
709 4 return *this;
710 }
711
712 // ###########################################################################################################
713 // Special member functions with different Rows/Cols
714 // ###########################################################################################################
715
716 /// @brief Copy constructor
717 /// @param other The other object
718 template<int oCols>
719 4 KeyedRowVectorBase(const KeyedRowVectorBase<Scalar, ColKeyType, oCols>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
720 4 {
721
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || other.cols() == Cols, "Can only copy construct dynamic<=>static matrices if the cols match");
722
723
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->matrix = other.matrix;
724
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colIndices = other.colIndices;
725
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colKeysVector = other.colKeysVector;
726
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 this->colSlice.reserve(this->colKeysVector.size());
727 4 }
728 /// @brief Copy assignment operator
729 /// @param other The other object
730 template<int oCols>
731 4 KeyedRowVectorBase& operator=(const KeyedRowVectorBase<Scalar, ColKeyType, oCols>& other)
732 {
733 // No need to guard self assignment, as the types are different, so it cannot be the same object
734
735
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 INS_ASSERT_USER_ERROR(other.colKeys() == this->colKeys(), "Can only copy assign matrices if the col keys match");
736
737 4 this->matrix = other.matrix;
738 4 this->colIndices = other.colIndices;
739 4 this->colKeysVector = other.colKeysVector;
740 4 this->colSlice.reserve(this->colKeysVector.size());
741
742 4 return *this;
743 }
744 /// @brief Move constructor
745 /// @param other The other object
746 template<int oCols>
747 4 KeyedRowVectorBase(KeyedRowVectorBase<Scalar, ColKeyType, oCols>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
748 4 {
749
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || other.cols() == Cols, "Can only copy construct dynamic<=>static matrices if the cols match");
750
751 4 this->matrix = std::move(other.matrix);
752 4 this->colIndices = std::move(other.colIndices);
753 4 this->colKeysVector = std::move(other.colKeysVector);
754 4 this->colSlice.reserve(this->colKeysVector.size());
755 4 }
756 /// @brief Move assignment operator
757 /// @param other The other object
758 template<int oCols>
759 4 KeyedRowVectorBase& operator=(KeyedRowVectorBase<Scalar, ColKeyType, oCols>&& other) noexcept
760 {
761 // No need to guard self assignment, as the types are different, so it cannot be the same object
762
763
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 INS_ASSERT_USER_ERROR(other.colKeys() == this->colKeys(), "Can only copy assign matrices if the col keys match");
764
765 4 this->matrix = std::move(other.matrix);
766 4 this->colIndices = std::move(other.colIndices);
767 4 this->colKeysVector = std::move(other.colKeysVector);
768 4 this->colSlice.reserve(this->colKeysVector.size());
769
770 4 return *this;
771 }
772
773 // #######################################################################################################
774 // Access
775 // #######################################################################################################
776
777 /// @brief Gets the value for the col key
778 /// @param colKey Col Key
779 /// @return Scalar value
780 const Scalar& operator()(const ColKeyType& colKey) const
781 {
782 return this->matrix(0, this->colIndices.at(colKey));
783 }
784 /// @brief Gets the value for the col key
785 /// @param colKey Col Key
786 /// @return Scalar value
787 Scalar& operator()(const ColKeyType& colKey)
788 {
789 return this->matrix(0, this->colIndices.at(colKey));
790 }
791
792 /// @brief Gets the values for the col keys
793 /// @param colKeys Col Keys
794 /// @return View into the matrix for the col keys
795 decltype(auto) operator()(std::span<const ColKeyType> colKeys) const
796 {
797 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
798 this->colSlice.clear();
799 for (const auto& colKey : colKeys) { this->colSlice.push_back(this->colIndices.at(colKey)); }
800
801 return this->matrix(0, this->colSlice);
802 }
803 /// @brief Gets the values for the col keys
804 /// @param colKeys Col Keys
805 /// @return View into the matrix for the col keys
806 decltype(auto) operator()(std::span<const ColKeyType> colKeys)
807 {
808 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
809 this->colSlice.clear();
810 for (const auto& colKey : colKeys) { this->colSlice.push_back(this->colIndices.at(colKey)); }
811
812 return this->matrix(0, this->colSlice);
813 }
814
815 /// @brief Requests the full vector
816 42 const Eigen::Matrix<Scalar, 1, Cols>& operator()(all_t /* all */) const { return this->matrix; }
817 /// @brief Requests the full vector
818 74 Eigen::Matrix<Scalar, 1, Cols>& operator()(all_t /* all */) { return this->matrix; }
819 /// @brief Conversion into Eigen::RowVector
820 explicit operator Eigen::RowVector<Scalar, Cols>() { return this->matrix; }
821
822 // #######################################################################################################
823 // Block operations
824 // #######################################################################################################
825
826 /// @brief Gets the values for the col keys
827 /// @param colKeys Col Keys
828 /// @return View into the matrix for the col keys
829 template<size_t Q>
830 decltype(auto) segment(std::span<const ColKeyType> colKeys) const
831 {
832 checkContinuousSegment(colKeys, Q);
833
834 return this->matrix.template middleCols<Q>(this->colIndices.at(colKeys.front()));
835 }
836 /// @brief Gets the values for the col keys
837 /// @param colKeys Col Keys
838 /// @return View into the matrix for the col keys
839 template<size_t Q>
840 4 decltype(auto) segment(std::span<const ColKeyType> colKeys)
841 {
842 4 checkContinuousSegment(colKeys, Q);
843
844 4 return this->matrix.template middleCols<Q>(this->colIndices.at(colKeys.front()));
845 }
846 /// @brief Gets the values for the col keys
847 /// @param colKeys Col Keys
848 /// @return View into the matrix for the col keys
849 decltype(auto) segment(std::span<const ColKeyType> colKeys) const
850 {
851 checkContinuousSegment(colKeys, colKeys.size());
852
853 return this->matrix.middleCols(this->colIndices.at(colKeys.front()), colKeys.size());
854 }
855 /// @brief Gets the values for the col keys
856 /// @param colKeys Col Keys
857 /// @return View into the matrix for the col keys
858 4 decltype(auto) segment(std::span<const ColKeyType> colKeys)
859 {
860 4 checkContinuousSegment(colKeys, colKeys.size());
861
862 4 return this->matrix.middleCols(this->colIndices.at(colKeys.front()), colKeys.size());
863 }
864
865 // #######################################################################################################
866 // Methods
867 // #######################################################################################################
868
869 /// @brief Calculates the transposed vector
870 4 [[nodiscard]] KeyedVectorBase<Scalar, ColKeyType, Cols> transposed() const
871 {
872
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 return { this->matrix.transpose(), this->colKeys() };
873 }
874
875 private:
876 /// @brief Checks if the col keys are describing a continuous block
877 /// @param colKeys Col keys
878 /// @param Q Size of the col keys
879 8 void checkContinuousSegment([[maybe_unused]] std::span<const ColKeyType> colKeys, [[maybe_unused]] size_t Q) const
880 {
881 #ifndef NDEBUG
882
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 INS_ASSERT_USER_ERROR(Q == colKeys.size(), "The block size must be equivalent to the amount of col keys.");
883
884
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 std::vector<Eigen::Index> consecutiveCols(colKeys.size());
885
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
16 std::iota(std::begin(consecutiveCols), std::end(consecutiveCols), this->colIndices.at(colKeys.front()));
886 8 std::vector<Eigen::Index> colIndices;
887
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 colIndices.reserve(colKeys.size());
888
4/6
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 4 times.
24 for (const auto& colKey : colKeys) { colIndices.push_back(this->colIndices.at(colKey)); }
889
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
8 INS_ASSERT_USER_ERROR(colIndices == consecutiveCols, "The given colKeys must describe a consecutive part in the matrix.");
890 #endif
891 8 }
892 };
893
894 /// @brief Class to inherit common methods for static and dynamic sized matrices
895 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
896 /// @tparam RowKeyType Type of the key used for row lookup
897 /// @tparam ColKeyType Type of the key used for col lookup
898 /// @tparam Rows Number of rows, or \b Dynamic
899 /// @tparam Cols Number of columns, or \b Dynamic
900 template<typename Scalar, typename RowKeyType, typename ColKeyType, int Rows, int Cols>
901 class KeyedMatrixBase : public KeyedMatrixRows<Scalar, RowKeyType, Rows, Cols>, public KeyedMatrixCols<Scalar, ColKeyType, Rows, Cols>
902 {
903 public:
904 /// @brief Constructor
905 /// @param matrix Eigen Matrix to initialize from
906 template<typename Derived>
907 13004 explicit KeyedMatrixBase(const Eigen::MatrixBase<Derived>& matrix)
908 13004 {
909
1/2
✓ Branch 1 taken 6502 times.
✗ Branch 2 not taken.
13004 this->matrix = matrix;
910 13004 }
911 /// @brief Non-symmetric matrix constructor
912 /// @param matrix Eigen Matrix to initialize from
913 /// @param rowKeys Row keys describing the matrix
914 /// @param colKeys Col keys describing the matrix
915 template<typename Derived>
916 1093808 KeyedMatrixBase(const Eigen::MatrixBase<Derived>& matrix, std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
917 1093808 {
918
5/12
✓ Branch 3 taken 546949 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 546912 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 546913 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 546937 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
2187732 INS_ASSERT_USER_ERROR(std::unordered_set<RowKeyType>(rowKeys.begin(), rowKeys.end()).size() == rowKeys.size(), "Each row key must be unique");
919
4/12
✓ Branch 3 taken 546949 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 546946 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 546946 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 546948 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
2187756 INS_ASSERT_USER_ERROR(std::unordered_set<ColKeyType>(colKeys.begin(), colKeys.end()).size() == colKeys.size(), "Each col key must be unique");
920
921
1/2
✓ Branch 2 taken 546935 times.
✗ Branch 3 not taken.
1093896 INS_ASSERT_USER_ERROR(matrix.rows() == static_cast<Eigen::Index>(rowKeys.size()), "Number of matrix rows doesn't correspond to the amount of row keys");
922
1/2
✓ Branch 2 taken 546939 times.
✗ Branch 3 not taken.
1093870 INS_ASSERT_USER_ERROR(matrix.cols() == static_cast<Eigen::Index>(colKeys.size()), "Number of matrix cols doesn't correspond to the amount of col keys");
923
924
1/2
✓ Branch 1 taken 153689 times.
✗ Branch 2 not taken.
307378 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || Rows == static_cast<int>(rowKeys.size()), "Number of matrix rows doesn't correspond to the static amount of row keys");
925
1/2
✓ Branch 1 taken 153689 times.
✗ Branch 2 not taken.
307378 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || Cols == static_cast<int>(colKeys.size()), "Number of matrix cols doesn't correspond to the static amount of col keys");
926
927
7/8
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 6050131 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 6050094 times.
✓ Branch 7 taken 546937 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 7 times.
13193980 for (size_t i = 0; i < rowKeys.size(); i++) { this->rowIndices.insert({ rowKeys[i], static_cast<Eigen::Index>(i) }); }
928
7/8
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6301959 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 6301950 times.
✓ Branch 7 taken 546940 times.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 3 times.
13697740 for (size_t i = 0; i < colKeys.size(); i++) { this->colIndices.insert({ colKeys[i], static_cast<Eigen::Index>(i) }); }
929
930
1/2
✓ Branch 1 taken 546935 times.
✗ Branch 2 not taken.
1093886 this->matrix = matrix;
931
2/4
✓ Branch 1 taken 546928 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 546949 times.
✗ Branch 5 not taken.
1093870 std::ranges::copy(rowKeys, std::back_inserter(this->rowKeysVector));
932
2/4
✓ Branch 1 taken 546944 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 546954 times.
✗ Branch 5 not taken.
1093898 std::ranges::copy(colKeys, std::back_inserter(this->colKeysVector));
933
1/2
✓ Branch 2 taken 546927 times.
✗ Branch 3 not taken.
1093908 this->colSlice.reserve(this->colKeysVector.size());
934
1/2
✓ Branch 2 taken 546943 times.
✗ Branch 3 not taken.
1093854 this->rowSlice.reserve(this->rowKeysVector.size());
935 1093886 }
936
937 // #######################################################################################################
938 // Special member functions
939 // #######################################################################################################
940
941 /// @brief Destructor
942 1121865 ~KeyedMatrixBase() = default;
943 /// @brief Copy constructor
944 /// @param other The other object
945 14954 KeyedMatrixBase(const KeyedMatrixBase& other)
946 14954 {
947
1/2
✓ Branch 1 taken 9952 times.
✗ Branch 2 not taken.
14954 this->matrix = other.matrix;
948
1/2
✓ Branch 1 taken 9952 times.
✗ Branch 2 not taken.
14954 this->rowIndices = other.rowIndices;
949
1/2
✓ Branch 1 taken 9952 times.
✗ Branch 2 not taken.
14954 this->rowKeysVector = other.rowKeysVector;
950
1/2
✓ Branch 1 taken 9952 times.
✗ Branch 2 not taken.
14954 this->colIndices = other.colIndices;
951
1/2
✓ Branch 1 taken 9952 times.
✗ Branch 2 not taken.
14954 this->colKeysVector = other.colKeysVector;
952
1/2
✓ Branch 2 taken 9952 times.
✗ Branch 3 not taken.
14954 this->colSlice.reserve(this->colKeysVector.size());
953
1/2
✓ Branch 2 taken 9952 times.
✗ Branch 3 not taken.
14954 this->rowSlice.reserve(this->rowKeysVector.size());
954 14954 }
955 /// @brief Copy assignment operator
956 /// @param other The other object
957 4 KeyedMatrixBase& operator=(const KeyedMatrixBase& other)
958 {
959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if (this == &other) { return *this; } // Guard self assignment
960
961 4 this->matrix = other.matrix;
962 4 this->rowIndices = other.rowIndices;
963 4 this->rowKeysVector = other.rowKeysVector;
964 4 this->colIndices = other.colIndices;
965 4 this->colKeysVector = other.colKeysVector;
966 4 this->colSlice.reserve(this->colKeysVector.size());
967 4 this->rowSlice.reserve(this->rowKeysVector.size());
968
969 4 return *this;
970 }
971 /// @brief Move constructor
972 /// @param other The other object
973 259913 KeyedMatrixBase(KeyedMatrixBase&& other) noexcept
974 259913 {
975 259950 this->matrix = std::move(other.matrix);
976 259926 this->rowIndices = std::move(other.rowIndices);
977 259926 this->rowKeysVector = std::move(other.rowKeysVector);
978 259920 this->colIndices = std::move(other.colIndices);
979 259949 this->colKeysVector = std::move(other.colKeysVector);
980 259950 this->colSlice.reserve(this->colKeysVector.size());
981 259941 this->rowSlice.reserve(this->rowKeysVector.size());
982 259952 }
983 /// @brief Move assignment operator
984 /// @param other The other object
985 262398 KeyedMatrixBase& operator=(KeyedMatrixBase&& other) noexcept
986 {
987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131199 times.
262398 if (this == &other) { return *this; } // Guard self assignment
988
989 262398 this->matrix = std::move(other.matrix);
990 262398 this->rowIndices = std::move(other.rowIndices);
991 262398 this->rowKeysVector = std::move(other.rowKeysVector);
992 262398 this->colIndices = std::move(other.colIndices);
993 262398 this->colKeysVector = std::move(other.colKeysVector);
994 262398 this->colSlice.reserve(this->colKeysVector.size());
995 262398 this->rowSlice.reserve(this->rowKeysVector.size());
996
997 262398 return *this;
998 }
999
1000 // ###########################################################################################################
1001 // Special member functions with different Rows/Cols
1002 // ###########################################################################################################
1003
1004 /// @brief Copy constructor
1005 /// @param other The other object
1006 template<int oRows, int oCols>
1007 4 KeyedMatrixBase(const KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1008 4 {
1009
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || other.rows() == Rows, "Can only copy construct dynamic<=>static matrices if the rows match");
1010
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || other.cols() == Cols, "Can only copy construct dynamic<=>static matrices if the cols match");
1011
1012
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->matrix = other.matrix;
1013
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->rowIndices = other.rowIndices;
1014
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->rowKeysVector = other.rowKeysVector;
1015
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colIndices = other.colIndices;
1016
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 this->colKeysVector = other.colKeysVector;
1017
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 this->colSlice.reserve(this->colKeysVector.size());
1018
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 this->rowSlice.reserve(this->rowKeysVector.size());
1019 4 }
1020 /// @brief Copy assignment operator
1021 /// @param other The other object
1022 template<int oRows, int oCols>
1023 4 KeyedMatrixBase& operator=(const KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>& other)
1024 {
1025 // No need to guard self assignment, as the types are different, so it cannot be the same object
1026
1027
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 INS_ASSERT_USER_ERROR(other.rowKeys() == this->rowKeys(), "Can only copy assign matrices if the row keys match");
1028
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 INS_ASSERT_USER_ERROR(other.colKeys() == this->colKeys(), "Can only copy assign matrices if the col keys match");
1029
1030 4 this->matrix = other.matrix;
1031 4 this->rowIndices = other.rowIndices;
1032 4 this->rowKeysVector = other.rowKeysVector;
1033 4 this->colIndices = other.colIndices;
1034 4 this->colKeysVector = other.colKeysVector;
1035 4 this->colSlice.reserve(this->colKeysVector.size());
1036 4 this->rowSlice.reserve(this->rowKeysVector.size());
1037
1038 4 return *this;
1039 }
1040 /// @brief Move constructor
1041 /// @param other The other object
1042 template<int oRows, int oCols>
1043 4 KeyedMatrixBase(KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1044 4 {
1045
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Rows == Eigen::Dynamic || other.rows() == Rows, "Can only copy construct dynamic<=>static matrices if the rows match");
1046
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 INS_ASSERT_USER_ERROR(Cols == Eigen::Dynamic || other.cols() == Cols, "Can only copy construct dynamic<=>static matrices if the cols match");
1047
1048 4 this->matrix = std::move(other.matrix);
1049 4 this->rowIndices = std::move(other.rowIndices);
1050 4 this->rowKeysVector = std::move(other.rowKeysVector);
1051 4 this->colIndices = std::move(other.colIndices);
1052 4 this->colKeysVector = std::move(other.colKeysVector);
1053 4 this->colSlice.reserve(this->colKeysVector.size());
1054 4 this->rowSlice.reserve(this->rowKeysVector.size());
1055 4 }
1056 /// @brief Move assignment operator
1057 /// @param other The other object
1058 template<int oRows, int oCols>
1059 307346 KeyedMatrixBase& operator=(KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>&& other) noexcept
1060 {
1061 // No need to guard self assignment, as the types are different, so it cannot be the same object
1062
1063
1/2
✓ Branch 3 taken 153673 times.
✗ Branch 4 not taken.
307346 INS_ASSERT_USER_ERROR(other.rowKeys() == this->rowKeys(), "Can only copy assign matrices if the row keys match");
1064
1/2
✓ Branch 3 taken 153673 times.
✗ Branch 4 not taken.
307346 INS_ASSERT_USER_ERROR(other.colKeys() == this->colKeys(), "Can only copy assign matrices if the col keys match");
1065
1066 307346 this->matrix = std::move(other.matrix);
1067 307346 this->rowIndices = std::move(other.rowIndices);
1068 307346 this->rowKeysVector = std::move(other.rowKeysVector);
1069 307346 this->colIndices = std::move(other.colIndices);
1070 307346 this->colKeysVector = std::move(other.colKeysVector);
1071 307346 this->colSlice.reserve(this->colKeysVector.size());
1072 307346 this->rowSlice.reserve(this->rowKeysVector.size());
1073
1074 307346 return *this;
1075 }
1076
1077 // #######################################################################################################
1078 // Access
1079 // #######################################################################################################
1080
1081 /// @brief Gets the value for the row and col key
1082 /// @param rowKey Row Key
1083 /// @param colKey Col Key
1084 /// @return Scalar value
1085 9361 const Scalar& operator()(const RowKeyType& rowKey, const ColKeyType& colKey) const
1086 {
1087 9361 return this->matrix(this->rowIndices.at(rowKey), this->colIndices.at(colKey));
1088 }
1089 /// @brief Gets the value for the row and col key
1090 /// @param rowKey Row Key
1091 /// @param colKey Col Key
1092 /// @return Scalar value
1093 1264332 Scalar& operator()(const RowKeyType& rowKey, const ColKeyType& colKey)
1094 {
1095 1264332 return this->matrix(this->rowIndices.at(rowKey), this->colIndices.at(colKey));
1096 }
1097
1098 /// @brief Gets the values for the row and col keys
1099 /// @param rowKeys Row Keys
1100 /// @param colKeys Col Keys
1101 /// @return View into the matrix for the row and col keys
1102 207 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys) const
1103 {
1104
1/2
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
207 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
1105 207 this->rowSlice.clear();
1106
4/6
✓ Branch 4 taken 614 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 614 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 614 times.
✓ Branch 12 taken 205 times.
825 for (const auto& rowKey : rowKeys) { this->rowSlice.push_back(this->rowIndices.at(rowKey)); }
1107
1108 207 this->colSlice.clear();
1109
4/6
✓ Branch 4 taken 614 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 614 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 614 times.
✓ Branch 12 taken 205 times.
825 for (const auto& colKey : colKeys) { this->colSlice.push_back(this->colIndices.at(colKey)); }
1110
1111
1/2
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
414 return this->matrix(this->rowSlice, this->colSlice);
1112 207 }
1113 /// @brief Gets the values for the row and col keys
1114 /// @param rowKeys Row Keys
1115 /// @param colKeys Col Keys
1116 /// @return View into the matrix for the row and col keys
1117 154357 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
1118 {
1119
1/2
✓ Branch 1 taken 77523 times.
✗ Branch 2 not taken.
154357 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
1120 154357 this->rowSlice.clear();
1121
4/6
✓ Branch 4 taken 694435 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 694435 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 694435 times.
✓ Branch 12 taken 77523 times.
1540130 for (const auto& rowKey : rowKeys) { this->rowSlice.push_back(this->rowIndices.at(rowKey)); }
1122
1123 154357 this->colSlice.clear();
1124
4/6
✓ Branch 4 taken 694441 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 694441 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 694441 times.
✓ Branch 12 taken 77523 times.
1540142 for (const auto& colKey : colKeys) { this->colSlice.push_back(this->colIndices.at(colKey)); }
1125
1126
1/2
✓ Branch 1 taken 77523 times.
✗ Branch 2 not taken.
308714 return this->matrix(this->rowSlice, this->colSlice);
1127 154357 }
1128 /// @brief Gets the values for the row and col keys
1129 /// @param rowKeys Row Keys
1130 /// @param colKey Col Key
1131 /// @return View into the matrix for the row and col keys
1132 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey) const { return (*this)(rowKeys, std::initializer_list<ColKeyType>{ colKey }); }
1133 /// @brief Gets the values for the row and col keys
1134 /// @param rowKeys Row Keys
1135 /// @param colKey Col Key
1136 /// @return View into the matrix for the row and col keys
1137
5/13
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
16 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey) { return (*this)(rowKeys, std::initializer_list<ColKeyType>{ colKey }); }
1138 /// @brief Gets the values for the row and col keys
1139 /// @param rowKey Row Key
1140 /// @param colKeys Col Keys
1141 /// @return View into the matrix for the row and col keys
1142 decltype(auto) operator()(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys) const { return (*this)(std::initializer_list<RowKeyType>{ rowKey }, colKeys); }
1143 /// @brief Gets the values for the row and col keys
1144 /// @param rowKey Row Key
1145 /// @param colKeys Col Keys
1146 /// @return View into the matrix for the row and col keys
1147
5/13
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
12 decltype(auto) operator()(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys) { return (*this)(std::initializer_list<RowKeyType>{ rowKey }, colKeys); }
1148
1149 /// @brief Gets the values for the row key
1150 /// @param rowKey Row Key
1151 /// @return View into the matrix for the row key
1152 decltype(auto) operator()(const RowKeyType& rowKey, all_t /* all */) const { return (*this)(std::initializer_list<RowKeyType>{ rowKey }, this->colKeys()); }
1153 /// @brief Gets the values for the row key
1154 /// @param rowKey Row Key
1155 /// @return View into the matrix for the row key
1156
5/13
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
10 decltype(auto) operator()(const RowKeyType& rowKey, all_t /* all */) { return (*this)(std::initializer_list<RowKeyType>{ rowKey }, this->colKeys()); }
1157 /// @brief Gets the values for the col key
1158 /// @param colKey Col Key
1159 /// @return View into the matrix for the col key
1160 decltype(auto) operator()(all_t /* all */, const ColKeyType& colKey) const { return *this(this->rowKeys(), std::initializer_list<ColKeyType>{ colKey }); }
1161 /// @brief Gets the values for the col keys
1162 /// @param colKey Col Key
1163 /// @return View into the matrix for the col key
1164
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 decltype(auto) operator()(all_t /* all */, const ColKeyType& colKey) { return (*this)(this->rowKeys(), std::initializer_list<ColKeyType>{ colKey }); }
1165 /// @brief Gets the values for the row keys
1166 /// @param rowKeys Row Keys
1167 /// @return View into the matrix for the row keys
1168 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, all_t /* all */) const { return (*this)(rowKeys, this->colKeys()); }
1169 /// @brief Gets the values for the row keys
1170 /// @param rowKeys Row Keys
1171 /// @return View into the matrix for the row keys
1172
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
6 decltype(auto) operator()(std::span<const RowKeyType> rowKeys, all_t /* all */) { return (*this)(rowKeys, this->colKeys()); }
1173 /// @brief Gets the values for the col keys
1174 /// @param colKeys Col Keys
1175 /// @return View into the matrix for the col keys
1176 decltype(auto) operator()(all_t /* all */, std::span<const ColKeyType> colKeys) const { return (*this)(this->rowKeys(), colKeys); }
1177 /// @brief Gets the values for the col keys
1178 /// @param colKeys Col Keys
1179 /// @return View into the matrix for the col keys
1180
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 decltype(auto) operator()(all_t /* all */, std::span<const ColKeyType> colKeys) { return (*this)(this->rowKeys(), colKeys); }
1181
1182 /// @brief Requests the full matrix
1183 152056 const Eigen::Matrix<Scalar, Rows, Cols>& operator()(all_t /* all */, all_t /* all */) const { return this->matrix; }
1184 /// @brief Requests the full matrix
1185 3018270 Eigen::Matrix<Scalar, Rows, Cols>& operator()(all_t /* all */, all_t /* all */) { return this->matrix; }
1186 /// @brief Conversion into Eigen::Matrix
1187 explicit operator Eigen::Matrix<Scalar, Rows, Cols>() { return this->matrix; }
1188
1189 // ###########################################################################################################
1190 // Static Block operations
1191 // ###########################################################################################################
1192
1193 /// @brief Gets the values for the row and col keys
1194 /// @param rowKeys Row Keys
1195 /// @param colKeys Col Keys
1196 /// @return View into the matrix for the row and col keys
1197 template<size_t P, size_t Q = P>
1198 decltype(auto) block(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys) const // NOLINT(readability-const-return-type)
1199 {
1200 checkContinuousBlock(rowKeys, colKeys, P, Q);
1201
1202 return this->matrix.template block<P, Q>(this->rowIndices.at(rowKeys.front()), this->colIndices.at(colKeys.front()));
1203 }
1204 /// @brief Gets the values for the row and col keys
1205 /// @param rowKeys Row Keys
1206 /// @param colKeys Col Keys
1207 /// @return View into the matrix for the row and col keys
1208 template<size_t P, size_t Q = P>
1209 2665602 decltype(auto) block(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
1210 {
1211 2665602 checkContinuousBlock(rowKeys, colKeys, P, Q);
1212
1213 2665602 return this->matrix.template block<P, Q>(this->rowIndices.at(rowKeys.front()), this->colIndices.at(colKeys.front()));
1214 }
1215 /// @brief Gets the values for the row and col keys
1216 /// @param rowKeys Row Keys
1217 /// @param colKey Col Key
1218 /// @return View into the matrix for the row and col keys
1219 template<size_t P>
1220 decltype(auto) block(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey) const // NOLINT(readability-const-return-type)
1221 {
1222 return this->block<P, 1>(rowKeys, std::initializer_list<ColKeyType>{ colKey });
1223 }
1224 /// @brief Gets the values for the row and col keys
1225 /// @param rowKeys Row Keys
1226 /// @param colKey Col Key
1227 /// @return View into the matrix for the row and col keys
1228 template<size_t P>
1229 4 decltype(auto) block(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey)
1230 {
1231
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return this->block<P, 1>(rowKeys, std::initializer_list<ColKeyType>{ colKey });
1232 }
1233 /// @brief Gets the values for the row and col keys
1234 /// @param rowKey Row Key
1235 /// @param colKeys Col Keys
1236 /// @return View into the matrix for the row and col keys
1237 template<size_t Q>
1238 decltype(auto) block(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys) const // NOLINT(readability-const-return-type)
1239 {
1240 return this->block<1, Q>(std::initializer_list<RowKeyType>{ rowKey }, colKeys);
1241 }
1242 /// @brief Gets the values for the row and col keys
1243 /// @param rowKey Row Key
1244 /// @param colKeys Col Keys
1245 /// @return View into the matrix for the row and col keys
1246 template<size_t Q>
1247 74464 decltype(auto) block(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys)
1248 {
1249
1/2
✓ Branch 2 taken 74462 times.
✗ Branch 3 not taken.
74464 return this->block<1, Q>(std::initializer_list<RowKeyType>{ rowKey }, colKeys);
1250 }
1251
1252 /// @brief Gets the values for the row keys
1253 /// @param rowKeys Row Keys
1254 /// @return View into the matrix for the row keys
1255 template<size_t P>
1256 decltype(auto) middleRows(std::span<const RowKeyType> rowKeys) const // NOLINT(readability-const-return-type)
1257 {
1258 checkContinuousBlock(rowKeys, this->colKeys(), P, this->colKeys().size());
1259
1260 return this->matrix.template middleRows<P>(this->rowIndices.at(rowKeys.front()));
1261 }
1262 /// @brief Gets the values for the row keys
1263 /// @param rowKeys Row Keys
1264 /// @return View into the matrix for the row keys
1265 template<size_t P>
1266 566488 decltype(auto) middleRows(std::span<const RowKeyType> rowKeys)
1267 {
1268
1/2
✓ Branch 5 taken 283244 times.
✗ Branch 6 not taken.
566488 checkContinuousBlock(rowKeys, this->colKeys(), P, this->colKeys().size());
1269
1270 566488 return this->matrix.template middleRows<P>(this->rowIndices.at(rowKeys.front()));
1271 }
1272 /// @brief Gets the values for the col keys
1273 /// @param colKeys Col Keys
1274 /// @return View into the matrix for the col keys
1275 template<size_t Q>
1276 decltype(auto) middleCols(std::span<const ColKeyType> colKeys) const // NOLINT(readability-const-return-type)
1277 {
1278 checkContinuousBlock(this->rowKeys(), colKeys, this->rowKeys().size(), Q);
1279
1280 return this->matrix.template middleCols<Q>(this->colIndices.at(colKeys.front()));
1281 }
1282 /// @brief Gets the values for the col keys
1283 /// @param colKeys Col Keys
1284 /// @return View into the matrix for the col keys
1285 template<size_t Q>
1286 673740 decltype(auto) middleCols(std::span<const ColKeyType> colKeys)
1287 {
1288
1/2
✓ Branch 5 taken 336870 times.
✗ Branch 6 not taken.
673740 checkContinuousBlock(this->rowKeys(), colKeys, this->rowKeys().size(), Q);
1289
1290 673740 return this->matrix.template middleCols<Q>(this->colIndices.at(colKeys.front()));
1291 }
1292 /// @brief Gets the values for the row key
1293 /// @param rowKey Row Key
1294 /// @return View into the matrix for the row key
1295 decltype(auto) row(const RowKeyType& rowKey) const { return this->matrix.row(this->rowIndices.at(rowKey)); }
1296 /// @brief Gets the values for the row key
1297 /// @param rowKey Row Key
1298 /// @return View into the matrix for the row key
1299 4 decltype(auto) row(const RowKeyType& rowKey) { return this->matrix.row(this->rowIndices.at(rowKey)); }
1300 /// @brief Gets the values for the col key
1301 /// @param colKey Col Key
1302 /// @return View into the matrix for the col key
1303 decltype(auto) col(const ColKeyType& colKey) const { return this->matrix.col(this->colIndices.at(colKey)); }
1304 /// @brief Gets the values for the col key
1305 /// @param colKey Col Key
1306 /// @return View into the matrix for the col key
1307 4 decltype(auto) col(const ColKeyType& colKey) { return this->matrix.col(this->colIndices.at(colKey)); }
1308
1309 /// @brief Requests the full matrix
1310 const Eigen::Matrix<Scalar, Rows, Cols>& block(all_t /* all */, all_t /* all */) const { return this->matrix; }
1311 /// @brief Requests the full matrix
1312 4 Eigen::Matrix<Scalar, Rows, Cols>& block(all_t /* all */, all_t /* all */) { return this->matrix; }
1313
1314 // ###########################################################################################################
1315 // Dynamic block operations
1316 // ###########################################################################################################
1317
1318 /// @brief Gets the values for the row and col keys
1319 /// @param rowKeys Row Keys
1320 /// @param colKeys Col Keys
1321 /// @return View into the matrix for the row and col keys
1322 decltype(auto) block(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys) const
1323 {
1324 checkContinuousBlock(rowKeys, colKeys, rowKeys.size(), colKeys.size());
1325
1326 return this->matrix.block(this->rowIndices.at(rowKeys.front()), this->colIndices.at(colKeys.front()), rowKeys.size(), colKeys.size());
1327 }
1328 /// @brief Gets the values for the row and col keys
1329 /// @param rowKeys Row Keys
1330 /// @param colKeys Col Keys
1331 /// @return View into the matrix for the row and col keys
1332 16 decltype(auto) block(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
1333 {
1334 16 checkContinuousBlock(rowKeys, colKeys, rowKeys.size(), colKeys.size());
1335
1336 16 return this->matrix.block(this->rowIndices.at(rowKeys.front()), this->colIndices.at(colKeys.front()), rowKeys.size(), colKeys.size());
1337 }
1338 /// @brief Gets the values for the row and col keys
1339 /// @param rowKeys Row Keys
1340 /// @param colKey Col Key
1341 /// @return View into the matrix for the row and col keys
1342 decltype(auto) block(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey) const
1343 {
1344 return this->block(rowKeys, std::initializer_list<ColKeyType>{ colKey });
1345 }
1346 /// @brief Gets the values for the row and col keys
1347 /// @param rowKeys Row Keys
1348 /// @param colKey Col Key
1349 /// @return View into the matrix for the row and col keys
1350 4 decltype(auto) block(std::span<const RowKeyType> rowKeys, const ColKeyType& colKey)
1351 {
1352
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return this->block(rowKeys, std::initializer_list<ColKeyType>{ colKey });
1353 }
1354 /// @brief Gets the values for the row and col keys
1355 /// @param rowKey Row Key
1356 /// @param colKeys Col Keys
1357 /// @return View into the matrix for the row and col keys
1358 decltype(auto) block(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys) const
1359 {
1360 return this->block(std::initializer_list<RowKeyType>{ rowKey }, colKeys);
1361 }
1362 /// @brief Gets the values for the row and col keys
1363 /// @param rowKey Row Key
1364 /// @param colKeys Col Keys
1365 /// @return View into the matrix for the row and col keys
1366 4 decltype(auto) block(const RowKeyType& rowKey, std::span<const ColKeyType> colKeys)
1367 {
1368
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return this->block(std::initializer_list<RowKeyType>{ rowKey }, colKeys);
1369 }
1370
1371 /// @brief Gets the values for the row keys
1372 /// @param rowKeys Row Keys
1373 /// @return View into the matrix for the row keys
1374 decltype(auto) middleRows(std::span<const RowKeyType> rowKeys) const
1375 {
1376 checkContinuousBlock(rowKeys, this->colKeys(), rowKeys.size(), this->colKeys().size());
1377
1378 return this->matrix.middleRows(this->rowIndices.at(rowKeys.front()), rowKeys.size());
1379 }
1380 /// @brief Gets the values for the row keys
1381 /// @param rowKeys Row Keys
1382 /// @return View into the matrix for the row keys
1383 4 decltype(auto) middleRows(std::span<const RowKeyType> rowKeys)
1384 {
1385
1/2
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 checkContinuousBlock(rowKeys, this->colKeys(), rowKeys.size(), this->colKeys().size());
1386
1387 4 return this->matrix.middleRows(this->rowIndices.at(rowKeys.front()), rowKeys.size());
1388 }
1389 /// @brief Gets the values for the col keys
1390 /// @param colKeys Col Keys
1391 /// @return View into the matrix for the col keys
1392 decltype(auto) middleCols(std::span<const ColKeyType> colKeys) const
1393 {
1394 checkContinuousBlock(this->rowKeys(), colKeys, this->rowKeys().size(), colKeys.size());
1395
1396 return this->matrix.middleCols(this->colIndices.at(colKeys.front()), colKeys.size());
1397 }
1398 /// @brief Gets the values for the col keys
1399 /// @param colKeys Col Keys
1400 /// @return View into the matrix for the col keys
1401 4 decltype(auto) middleCols(std::span<const ColKeyType> colKeys)
1402 {
1403
1/2
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 checkContinuousBlock(this->rowKeys(), colKeys, this->rowKeys().size(), colKeys.size());
1404
1405 4 return this->matrix.middleCols(this->colIndices.at(colKeys.front()), colKeys.size());
1406 }
1407
1408 // #######################################################################################################
1409 // Methods
1410 // #######################################################################################################
1411
1412 /// @brief Calculates the transposed matrix
1413 4 [[nodiscard]] KeyedMatrixBase<Scalar, ColKeyType, RowKeyType, Cols, Rows> transposed() const
1414 {
1415
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
4 return { this->matrix.transpose(), this->colKeys(), this->rowKeys() };
1416 }
1417
1418 /// @brief Calculates the inverse matrix
1419 347 [[nodiscard]] KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols> inverse() const
1420 {
1421
2/4
✓ Branch 1 taken 345 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 345 times.
✗ Branch 9 not taken.
347 return { this->matrix.inverse(), this->rowKeys(), this->colKeys() };
1422 }
1423
1424 private:
1425 /// @brief Checks if the row and col keys are describing a continuous block
1426 /// @param rowKeys Row keys
1427 /// @param colKeys Col keys
1428 /// @param P Size of the row keys
1429 /// @param Q Size of the col keys
1430 3905854 void checkContinuousBlock([[maybe_unused]] std::span<const RowKeyType> rowKeys, [[maybe_unused]] std::span<const ColKeyType> colKeys,
1431 [[maybe_unused]] size_t P, [[maybe_unused]] size_t Q) const
1432 {
1433 #ifndef NDEBUG
1434
1/2
✓ Branch 1 taken 1952927 times.
✗ Branch 2 not taken.
3905854 INS_ASSERT_USER_ERROR(P == rowKeys.size(), "The block size must be equivalent to the amount of row keys.");
1435
1/2
✓ Branch 1 taken 1952927 times.
✗ Branch 2 not taken.
3905854 INS_ASSERT_USER_ERROR(Q == colKeys.size(), "The block size must be equivalent to the amount of col keys.");
1436
1437
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
3905854 std::vector<Eigen::Index> consecutiveRows(rowKeys.size());
1438
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
7811708 std::iota(std::begin(consecutiveRows), std::end(consecutiveRows), this->rowIndices.at(rowKeys.front()));
1439 3905854 std::vector<Eigen::Index> rowIndices;
1440
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
3905854 rowIndices.reserve(rowKeys.size());
1441
4/6
✓ Branch 4 taken 9180146 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9180146 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 9180146 times.
✓ Branch 12 taken 1952927 times.
22266146 for (const auto& rowKey : rowKeys) { rowIndices.push_back(this->rowIndices.at(rowKey)); }
1442
2/4
✓ Branch 1 taken 1952927 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1952927 times.
✗ Branch 4 not taken.
3905854 INS_ASSERT_USER_ERROR(rowIndices == consecutiveRows, "The given rowKeys must describe a consecutive part in the matrix.");
1443
1444
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
3905854 std::vector<Eigen::Index> consecutiveCols(colKeys.size());
1445
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
7811708 std::iota(std::begin(consecutiveCols), std::end(consecutiveCols), this->colIndices.at(colKeys.front()));
1446 3905854 std::vector<Eigen::Index> colIndices;
1447
1/2
✓ Branch 2 taken 1952927 times.
✗ Branch 3 not taken.
3905854 colIndices.reserve(colKeys.size());
1448
4/6
✓ Branch 4 taken 9448871 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9448871 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 9448871 times.
✓ Branch 12 taken 1952927 times.
22803596 for (const auto& colKey : colKeys) { colIndices.push_back(this->colIndices.at(colKey)); }
1449
2/4
✓ Branch 1 taken 1952927 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1952927 times.
✗ Branch 4 not taken.
3905854 INS_ASSERT_USER_ERROR(colIndices == consecutiveCols, "The given colKeys must describe a consecutive part in the matrix.");
1450 #endif
1451 3905854 }
1452 };
1453
1454 } // namespace internal
1455
1456 /// @brief Used to request all rows or columns in KeyedMatrices
1457 static const internal::all_t all;
1458
1459 template<typename Scalar, typename ColKeyType, int Cols>
1460 class KeyedRowVector;
1461
1462 /// @brief Static sized KeyedVector
1463 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
1464 /// @tparam RowKeyType Type of the key used for row lookup
1465 /// @tparam Rows Number of rows, or \b Dynamic
1466 template<typename Scalar, typename RowKeyType, int Rows>
1467 class KeyedVector : public internal::KeyedVectorBase<Scalar, RowKeyType, Rows>
1468 {
1469 public:
1470 /// @brief Vector constructor
1471 /// @tparam Derived Derived Eigen Type
1472 /// @param vector Eigen vector to initialize from
1473 /// @param rowKeys Row keys describing the vector
1474 template<typename Derived>
1475 53644 KeyedVector(const Eigen::MatrixBase<Derived>& vector, std::span<const RowKeyType> rowKeys)
1476 53644 : internal::KeyedVectorBase<Scalar, RowKeyType, Rows>(vector, rowKeys)
1477 53644 {}
1478
1479 // #######################################################################################################
1480 // Special member functions
1481 // #######################################################################################################
1482
1483 /// @brief Destructor
1484 53652 ~KeyedVector() = default;
1485 /// @brief Copy constructor
1486 /// @param other The other object
1487 1 KeyedVector(const KeyedVector& other)
1488 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Rows>(other)
1489 1 {}
1490 /// @brief Copy assignment operator
1491 /// @param other The other object
1492 1 KeyedVector& operator=(const KeyedVector& other)
1493 {
1494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1495
1496 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(*this) =
1497 static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(other);
1498
1499 1 return *this;
1500 }
1501 /// @brief Move constructor
1502 /// @param other The other object
1503 1 KeyedVector(KeyedVector&& other) noexcept
1504 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Rows>(std::move(other))
1505 1 {}
1506 /// @brief Move assignment operator
1507 /// @param other The other object
1508 1 KeyedVector& operator=(KeyedVector&& other) noexcept
1509 {
1510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1511
1512 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(*this) =
1513 1 std::move(static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(other));
1514
1515 1 return *this;
1516 }
1517
1518 // ###########################################################################################################
1519 // Special member functions with different Rows/Cols
1520 // ###########################################################################################################
1521
1522 /// @brief Copy constructor
1523 /// @param other The other object
1524 1 KeyedVector(const KeyedVector<Scalar, RowKeyType, Eigen::Dynamic>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1525 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Rows>(other)
1526 {
1527
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows, "Can only copy assign dynamic matrices from static ones if the size matches");
1528 1 }
1529 /// @brief Copy assignment operator
1530 /// @param other The other object
1531 1 KeyedVector& operator=(const KeyedVector<Scalar, RowKeyType, Eigen::Dynamic>& other)
1532 {
1533 // No need to guard self assignment, as the types are different, so it cannot be the same object
1534
1535
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows, "Can only copy assign dynamic matrices from static ones if the size matches");
1536
1537 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(*this) =
1538 static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(other);
1539
1540 1 return *this;
1541 }
1542 /// @brief Move constructor
1543 /// @param other The other object
1544 1 KeyedVector(KeyedVector<Scalar, RowKeyType, Eigen::Dynamic>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1545 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Rows>(std::move(other))
1546 {
1547
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(this->rows() == Rows, "Can only move construct dynamic matrices from static ones if the size matches");
1548 1 }
1549 /// @brief Move assignment operator
1550 /// @param other The other object
1551 1 KeyedVector& operator=(KeyedVector<Scalar, RowKeyType, Eigen::Dynamic>&& other) noexcept
1552 {
1553 // No need to guard self assignment, as the types are different, so it cannot be the same object
1554
1555
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows, "Can only move assign dynamic matrices from static ones if the size matches");
1556
1557 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(*this) =
1558 1 std::move(static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(other));
1559
1560 1 return *this;
1561 }
1562
1563 // #######################################################################################################
1564 // Methods
1565 // #######################################################################################################
1566
1567 /// @brief Calculates the transposed vector
1568 1 [[nodiscard]] KeyedRowVector<Scalar, RowKeyType, Rows> transposed() const
1569 {
1570
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, Rows>&>(*this).transposed();
1571
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 return { transpose(all), transpose.colKeys() };
1572 1 }
1573 };
1574
1575 /// @brief Dynamic sized KeyedVector
1576 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
1577 /// @tparam RowKeyType Type of the key used for row lookup
1578 template<typename Scalar, typename RowKeyType>
1579 class KeyedVector<Scalar, RowKeyType, Eigen::Dynamic> : public internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>
1580 {
1581 public:
1582 /// @brief Default Constructor
1583 2625 KeyedVector()
1584
2/4
✓ Branch 2 taken 1821 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1821 times.
✗ Branch 6 not taken.
2625 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(Eigen::VectorX<Scalar>()) {}
1585
1586 /// @brief Vector constructor
1587 /// @tparam Derived Derived Eigen Type
1588 /// @param vector Eigen vector to initialize from
1589 /// @param rowKeys Row keys describing the vector
1590 template<typename Derived>
1591 57680 KeyedVector(const Eigen::MatrixBase<Derived>& vector, std::span<const RowKeyType> rowKeys)
1592
1/2
✓ Branch 2 taken 28840 times.
✗ Branch 3 not taken.
57680 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(vector, rowKeys)
1593 57680 {}
1594
1595 // #######################################################################################################
1596 // Special member functions
1597 // #######################################################################################################
1598
1599 /// @brief Destructor
1600 64372 ~KeyedVector() = default;
1601 /// @brief Copy constructor
1602 /// @param other The other object
1603 3043 KeyedVector(const KeyedVector& other)
1604
1/2
✓ Branch 2 taken 1522 times.
✗ Branch 3 not taken.
3043 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(other)
1605 3043 {}
1606 /// @brief Copy assignment operator
1607 /// @param other The other object
1608 1 KeyedVector& operator=(const KeyedVector& other)
1609 {
1610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1611
1612 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(*this) =
1613 static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(other);
1614
1615 1 return *this;
1616 }
1617 /// @brief Move constructor
1618 /// @param other The other object
1619 1 KeyedVector(KeyedVector&& other) noexcept
1620 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(std::move(other))
1621 1 {}
1622 /// @brief Move assignment operator
1623 /// @param other The other object
1624 55438 KeyedVector& operator=(KeyedVector&& other) noexcept
1625 {
1626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28179 times.
55438 if (this == &other) { return *this; } // Guard self assignment
1627
1628 55438 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(*this) =
1629 55438 std::move(static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(other));
1630
1631 55438 return *this;
1632 }
1633
1634 // ###########################################################################################################
1635 // Special member functions with different Rows/Cols
1636 // ###########################################################################################################
1637
1638 /// @brief Copy constructor
1639 /// @param other The other object
1640 template<int oRows>
1641 1 KeyedVector(const KeyedVector<Scalar, RowKeyType, oRows>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1642
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(other)
1643 1 {}
1644 /// @brief Copy assignment operator
1645 /// @param other The other object
1646 template<int oRows>
1647 1 KeyedVector& operator=(const KeyedVector<Scalar, RowKeyType, oRows>& other)
1648 {
1649 // No need to guard self assignment, as the types are different, so it cannot be the same object
1650
1651 1 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(*this) =
1652 static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, oRows>&>(other);
1653
1654 1 return *this;
1655 }
1656 /// @brief Move constructor
1657 /// @param other The other object
1658 template<int oRows>
1659 1 KeyedVector(KeyedVector<Scalar, RowKeyType, oRows>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1660 1 : internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>(std::move(other))
1661 1 {}
1662 /// @brief Move assignment operator
1663 /// @param other The other object
1664 template<int oRows>
1665 53627 KeyedVector& operator=(KeyedVector<Scalar, RowKeyType, oRows>&& other) noexcept
1666 {
1667 // No need to guard self assignment, as the types are different, so it cannot be the same object
1668
1669 53627 static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(*this) =
1670 53627 std::move(static_cast<internal::KeyedVectorBase<Scalar, RowKeyType, oRows>&>(other));
1671
1672 53627 return *this;
1673 }
1674
1675 // #######################################################################################################
1676 // Methods
1677 // #######################################################################################################
1678
1679 /// @brief Calculates the transposed vector
1680 1 [[nodiscard]] KeyedRowVector<Scalar, RowKeyType, Eigen::Dynamic> transposed() const
1681 {
1682
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedVectorBase<Scalar, RowKeyType, Eigen::Dynamic>&>(*this).transposed();
1683
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 return { transpose(all), transpose.colKeys() };
1684 1 }
1685 };
1686
1687 /// @brief Static sized KeyedRowVector
1688 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
1689 /// @tparam ColKeyType Type of the key used for col lookup
1690 /// @tparam Cols Number of columns, or \b Dynamic
1691 template<typename Scalar, typename ColKeyType, int Cols>
1692 class KeyedRowVector : public internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>
1693 {
1694 public:
1695 /// @brief RowVector constructor
1696 /// @tparam Derived Derived Eigen Type
1697 /// @param vector Eigen vector to initialize from
1698 /// @param colKeys Col keys describing the vector
1699 template<typename Derived>
1700 18 KeyedRowVector(const Eigen::MatrixBase<Derived>& vector, std::span<const ColKeyType> colKeys)
1701 18 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>(vector, colKeys)
1702 18 {}
1703
1704 // #######################################################################################################
1705 // Special member functions
1706 // #######################################################################################################
1707
1708 /// @brief Destructor
1709 26 ~KeyedRowVector() = default;
1710 /// @brief Copy constructor
1711 /// @param other The other object
1712 1 KeyedRowVector(const KeyedRowVector& other)
1713 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>(other)
1714 1 {}
1715 /// @brief Copy assignment operator
1716 /// @param other The other object
1717 1 KeyedRowVector& operator=(const KeyedRowVector& other)
1718 {
1719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1720
1721 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(*this) =
1722 static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(other);
1723
1724 1 return *this;
1725 }
1726 /// @brief Move constructor
1727 /// @param other The other object
1728 1 KeyedRowVector(KeyedRowVector&& other) noexcept
1729 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>(std::move(other))
1730 1 {}
1731 /// @brief Move assignment operator
1732 /// @param other The other object
1733 1 KeyedRowVector& operator=(KeyedRowVector&& other) noexcept
1734 {
1735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1736
1737 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(*this) =
1738 1 std::move(static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(other));
1739
1740 1 return *this;
1741 }
1742
1743 // ###########################################################################################################
1744 // Special member functions with different Cols
1745 // ###########################################################################################################
1746
1747 /// @brief Copy constructor
1748 /// @param other The other object
1749 1 KeyedRowVector(const KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1750 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>(other)
1751 {
1752
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.cols() == Cols, "Can only copy assign dynamic matrices from static ones if the size matches");
1753 1 }
1754 /// @brief Copy assignment operator
1755 /// @param other The other object
1756 1 KeyedRowVector& operator=(const KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>& other)
1757 {
1758 // No need to guard self assignment, as the types are different, so it cannot be the same object
1759
1760
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.cols() == Cols, "Can only copy assign dynamic matrices from static ones if the size matches");
1761
1762 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(*this) =
1763 static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(other);
1764
1765 1 return *this;
1766 }
1767 /// @brief Move constructor
1768 /// @param other The other object
1769 1 KeyedRowVector(KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1770 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>(std::move(other))
1771 {
1772
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(this->cols() == Cols, "Can only move construct dynamic matrices from static ones if the size matches");
1773 1 }
1774 /// @brief Move assignment operator
1775 /// @param other The other object
1776 1 KeyedRowVector& operator=(KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>&& other) noexcept
1777 {
1778 // No need to guard self assignment, as the types are different, so it cannot be the same object
1779
1780
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 INS_ASSERT_USER_ERROR(other.cols() == Cols, "Can only move assign dynamic matrices from static ones if the size matches");
1781
1782 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(*this) =
1783 1 std::move(static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(other));
1784
1785 1 return *this;
1786 }
1787
1788 // #######################################################################################################
1789 // Methods
1790 // #######################################################################################################
1791
1792 /// @brief Calculates the transposed vector
1793 1 [[nodiscard]] KeyedVector<Scalar, ColKeyType, Cols> transposed() const
1794 {
1795
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, Cols>&>(*this).transposed();
1796
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 return { transpose(all), transpose.rowKeys() };
1797 1 }
1798 };
1799
1800 /// @brief Dynamic sized KeyedRowVector
1801 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
1802 /// @tparam ColKeyType Type of the key used for col lookup
1803 template<typename Scalar, typename ColKeyType>
1804 class KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>
1805 : public internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>
1806 {
1807 public:
1808 /// @brief Default Constructor
1809 KeyedRowVector()
1810 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(Eigen::RowVectorX<Scalar>()) {}
1811
1812 /// @brief RowVector constructor
1813 /// @tparam Derived Derived Eigen Type
1814 /// @param vector Eigen vector to initialize from
1815 /// @param colKeys Col keys describing the vector
1816 template<typename Derived>
1817 18 KeyedRowVector(const Eigen::MatrixBase<Derived>& vector, std::span<const ColKeyType> colKeys)
1818
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
18 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(vector, colKeys)
1819 18 {}
1820
1821 // #######################################################################################################
1822 // Special member functions
1823 // #######################################################################################################
1824
1825 /// @brief Destructor
1826 26 ~KeyedRowVector() = default;
1827 /// @brief Copy constructor
1828 /// @param other The other object
1829 1 KeyedRowVector(const KeyedRowVector& other)
1830
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(other)
1831 1 {}
1832 /// @brief Copy assignment operator
1833 /// @param other The other object
1834 1 KeyedRowVector& operator=(const KeyedRowVector& other)
1835 {
1836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1837
1838 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(*this) =
1839 static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(other);
1840
1841 1 return *this;
1842 }
1843 /// @brief Move constructor
1844 /// @param other The other object
1845 1 KeyedRowVector(KeyedRowVector&& other) noexcept
1846 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(std::move(other))
1847 1 {}
1848 /// @brief Move assignment operator
1849 /// @param other The other object
1850 1 KeyedRowVector& operator=(KeyedRowVector&& other) noexcept
1851 {
1852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1853
1854 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(*this) =
1855 1 std::move(static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(other));
1856
1857 1 return *this;
1858 }
1859
1860 // ###########################################################################################################
1861 // Special member functions with different Cols
1862 // ###########################################################################################################
1863
1864 /// @brief Copy constructor
1865 /// @param other The other object
1866 template<int oCols>
1867 1 KeyedRowVector(const KeyedRowVector<Scalar, ColKeyType, oCols>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1868
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(other)
1869 1 {}
1870 /// @brief Copy assignment operator
1871 /// @param other The other object
1872 template<int oCols>
1873 1 KeyedRowVector& operator=(const KeyedRowVector<Scalar, ColKeyType, oCols>& other)
1874 {
1875 // No need to guard self assignment, as the types are different, so it cannot be the same object
1876
1877 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(*this) =
1878 static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, oCols>&>(other);
1879
1880 1 return *this;
1881 }
1882 /// @brief Move constructor
1883 /// @param other The other object
1884 template<int oCols>
1885 1 KeyedRowVector(KeyedRowVector<Scalar, ColKeyType, oCols>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1886 1 : internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>(std::move(other))
1887 1 {}
1888 /// @brief Move assignment operator
1889 /// @param other The other object
1890 template<int oCols>
1891 1 KeyedRowVector& operator=(KeyedRowVector<Scalar, ColKeyType, oCols>&& other) noexcept
1892 {
1893 // No need to guard self assignment, as the types are different, so it cannot be the same object
1894
1895 1 static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(*this) =
1896 1 std::move(static_cast<internal::KeyedRowVectorBase<Scalar, ColKeyType, oCols>&>(other));
1897
1898 1 return *this;
1899 }
1900
1901 // #######################################################################################################
1902 // Methods
1903 // #######################################################################################################
1904
1905 /// @brief Calculates the transposed vector
1906 1 [[nodiscard]] KeyedVector<Scalar, ColKeyType, Eigen::Dynamic> transposed() const
1907 {
1908
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedRowVectorBase<Scalar, ColKeyType, Eigen::Dynamic>&>(*this).transposed();
1909
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 return { transpose(all), transpose.rowKeys() };
1910 1 }
1911 };
1912
1913 /// @brief Static sized KeyedMatrix
1914 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
1915 /// @tparam RowKeyType Type of the key used for row lookup
1916 /// @tparam ColKeyType Type of the key used for col lookup
1917 /// @tparam Rows Number of rows, or \b Dynamic
1918 /// @tparam Cols Number of columns, or \b Dynamic
1919 template<typename Scalar, typename RowKeyType, typename ColKeyType, int Rows, int Cols>
1920 class KeyedMatrix : public internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>
1921 {
1922 public:
1923 /// @brief Non-symmetric matrix constructor
1924 /// @tparam Derived Derived Eigen Type
1925 /// @param matrix Eigen matrix to initialize from
1926 /// @param rowKeys Row keys describing the matrix
1927 /// @param colKeys Col keys describing the matrix
1928 template<typename Derived>
1929 307374 KeyedMatrix(const Eigen::MatrixBase<Derived>& matrix, std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
1930 307374 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>(matrix, rowKeys, colKeys)
1931 307374 {}
1932
1933 /// @brief Symmetric matrix constructor
1934 /// @tparam Derived Derived Eigen Type
1935 /// @param matrix Eigen matrix to initialize from
1936 /// @param keys Row and col keys describing the matrix
1937 template<typename Derived>
1938 153723 KeyedMatrix(const Eigen::MatrixBase<Derived>& matrix, std::span<const RowKeyType> keys)
1939 153723 : KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols>(matrix, keys, keys)
1940 153723 {}
1941
1942 // #######################################################################################################
1943 // Special member functions
1944 // #######################################################################################################
1945
1946 /// @brief Destructor
1947 307382 ~KeyedMatrix() = default;
1948 /// @brief Copy constructor
1949 /// @param other The other object
1950 1 KeyedMatrix(const KeyedMatrix& other)
1951 1 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>(other)
1952 1 {}
1953 /// @brief Copy assignment operator
1954 /// @param other The other object
1955 1 KeyedMatrix& operator=(const KeyedMatrix& other)
1956 {
1957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1958
1959 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this) =
1960 static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(other);
1961
1962 1 return *this;
1963 }
1964 /// @brief Move constructor
1965 /// @param other The other object
1966 1 KeyedMatrix(KeyedMatrix&& other) noexcept
1967 1 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>(std::move(other))
1968 1 {}
1969 /// @brief Move assignment operator
1970 /// @param other The other object
1971 1 KeyedMatrix& operator=(KeyedMatrix&& other) noexcept
1972 {
1973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
1974
1975 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this) =
1976 1 std::move(static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(other));
1977
1978 1 return *this;
1979 }
1980
1981 // ###########################################################################################################
1982 // Special member functions with different Rows/Cols
1983 // ###########################################################################################################
1984
1985 /// @brief Copy constructor
1986 /// @param other The other object
1987 1 KeyedMatrix(const KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
1988 1 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>(other)
1989 {
1990
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows && other.cols() == Cols, "Can only copy assign dynamic matrices from static ones if the size matches");
1991 1 }
1992 /// @brief Copy assignment operator
1993 /// @param other The other object
1994 1 KeyedMatrix& operator=(const KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>& other)
1995 {
1996 // No need to guard self assignment, as the types are different, so it cannot be the same object
1997
1998
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows && other.cols() == Cols, "Can only copy assign dynamic matrices from static ones if the size matches");
1999
2000 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this) =
2001 static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(other);
2002
2003 1 return *this;
2004 }
2005 /// @brief Move constructor
2006 /// @param other The other object
2007 1 KeyedMatrix(KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
2008 1 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>(std::move(other))
2009 {
2010
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 INS_ASSERT_USER_ERROR(this->rows() == Rows && this->cols() == Cols, "Can only move construct dynamic matrices from static ones if the size matches");
2011 1 }
2012 /// @brief Move assignment operator
2013 /// @param other The other object
2014 1 KeyedMatrix& operator=(KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&& other) noexcept
2015 {
2016 // No need to guard self assignment, as the types are different, so it cannot be the same object
2017
2018
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 INS_ASSERT_USER_ERROR(other.rows() == Rows && other.cols() == Cols, "Can only move assign dynamic matrices from static ones if the size matches");
2019
2020 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this) =
2021 1 std::move(static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(other));
2022
2023 1 return *this;
2024 }
2025
2026 // #######################################################################################################
2027 // Methods
2028 // #######################################################################################################
2029
2030 /// @brief Returns a submatrix specified by the row and col keys
2031 /// @param rowKeys Row keys
2032 /// @param colKeys Col keys
2033 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>
2034 1 getSubMatrix(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys) const
2035 {
2036
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if (rowKeys == this->rowKeysVector && colKeys == this->colKeysVector)
2037 {
2038 return *this;
2039 }
2040
2041
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 return { (*this)(rowKeys, colKeys), rowKeys, colKeys };
2042 }
2043
2044 /// @brief Calculates the transposed matrix
2045 1 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols> transposed() const
2046 {
2047
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this).transposed();
2048
1/2
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 return { transpose(all, all), transpose.rowKeys(), transpose.colKeys() };
2049 1 }
2050
2051 /// @brief Calculates the inverse matrix
2052 1 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols> inverse() const
2053 {
2054
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto inv = static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Rows, Cols>&>(*this).inverse();
2055
1/2
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 return { inv(all, all), inv.rowKeys(), inv.colKeys() };
2056 1 }
2057 };
2058
2059 /// @brief Dynamic sized KeyedMatrix
2060 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
2061 /// @tparam RowKeyType Type of the key used for row lookup
2062 /// @tparam ColKeyType Type of the key used for col lookup
2063 template<typename Scalar, typename RowKeyType, typename ColKeyType>
2064 class KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>
2065 : public internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>
2066 {
2067 public:
2068 /// @brief Default Constructor
2069 13004 KeyedMatrix()
2070
2/4
✓ Branch 2 taken 6502 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6502 times.
✗ Branch 6 not taken.
13004 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(Eigen::MatrixX<Scalar>()) {}
2071
2072 /// @brief Non-symmetric matrix constructor
2073 /// @tparam Derived Derived Eigen Type
2074 /// @param matrix Eigen matrix to initialize from
2075 /// @param rowKeys Row keys describing the matrix
2076 /// @param colKeys Col keys describing the matrix
2077 template<typename Derived>
2078 785742 KeyedMatrix(const Eigen::MatrixBase<Derived>& matrix, std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
2079
1/2
✓ Branch 2 taken 392918 times.
✗ Branch 3 not taken.
785742 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(matrix, rowKeys, colKeys)
2080 785836 {}
2081
2082 /// @brief Symmetric matrix constructor
2083 /// @tparam Derived Derived Eigen Type
2084 /// @param matrix Eigen matrix to initialize from
2085 /// @param keys Row and col keys describing the matrix
2086 template<typename Derived>
2087 524370 KeyedMatrix(const Eigen::MatrixBase<Derived>& matrix, std::span<const RowKeyType> keys)
2088 524370 : KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(matrix, keys, keys)
2089 524478 {}
2090
2091 // #######################################################################################################
2092 // Special member functions
2093 // #######################################################################################################
2094
2095 /// @brief Destructor
2096 813802 ~KeyedMatrix() = default;
2097 /// @brief Copy constructor
2098 /// @param other The other object
2099 14951 KeyedMatrix(const KeyedMatrix& other)
2100
1/2
✓ Branch 2 taken 9951 times.
✗ Branch 3 not taken.
14951 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(other)
2101 14951 {}
2102 /// @brief Copy assignment operator
2103 /// @param other The other object
2104 1 KeyedMatrix& operator=(const KeyedMatrix& other)
2105 {
2106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (this == &other) { return *this; } // Guard self assignment
2107
2108 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this) =
2109 static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(other);
2110
2111 1 return *this;
2112 }
2113 /// @brief Move constructor
2114 /// @param other The other object
2115 259922 KeyedMatrix(KeyedMatrix&& other) noexcept
2116 259922 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(std::move(other))
2117 259952 {}
2118 /// @brief Move assignment operator
2119 /// @param other The other object
2120 262396 KeyedMatrix& operator=(KeyedMatrix&& other) noexcept
2121 {
2122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131198 times.
262396 if (this == &other) { return *this; } // Guard self assignment
2123
2124 262396 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this) =
2125 262396 std::move(static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(other));
2126
2127 262396 return *this;
2128 }
2129
2130 // ###########################################################################################################
2131 // Special member functions with different Rows/Cols
2132 // ###########################################################################################################
2133
2134 /// @brief Copy constructor
2135 /// @param other The other object
2136 template<int oRows, int oCols>
2137 2 KeyedMatrix(const KeyedMatrix<Scalar, RowKeyType, ColKeyType, oRows, oCols>& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
2138
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(other)
2139 2 {}
2140 /// @brief Copy assignment operator
2141 /// @param other The other object
2142 template<int oRows, int oCols>
2143 1 KeyedMatrix& operator=(const KeyedMatrix<Scalar, RowKeyType, ColKeyType, oRows, oCols>& other)
2144 {
2145 // No need to guard self assignment, as the types are different, so it cannot be the same object
2146
2147 1 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this) =
2148 static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>&>(other);
2149
2150 1 return *this;
2151 }
2152 /// @brief Move constructor
2153 /// @param other The other object
2154 template<int oRows, int oCols>
2155 1 KeyedMatrix(KeyedMatrix<Scalar, RowKeyType, ColKeyType, oRows, oCols>&& other) noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
2156 1 : internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>(std::move(other))
2157 1 {}
2158 /// @brief Move assignment operator
2159 /// @param other The other object
2160 template<int oRows, int oCols>
2161 153672 KeyedMatrix& operator=(KeyedMatrix<Scalar, RowKeyType, ColKeyType, oRows, oCols>&& other) noexcept
2162 {
2163 // No need to guard self assignment, as the types are different, so it cannot be the same object
2164
2165 153672 static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this) =
2166 153672 std::move(static_cast<internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, oRows, oCols>&>(other));
2167
2168 153672 return *this;
2169 }
2170
2171 // #######################################################################################################
2172 // Modifying methods
2173 // #######################################################################################################
2174
2175 /// @brief Adds new rows and cols to the matrix
2176 /// @param rowKeys Row keys
2177 /// @param colKeys Col keys
2178 319 void addRowsCols(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
2179 {
2180
2/4
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
319 INS_ASSERT_USER_ERROR(!this->hasAnyRows(rowKeys), "You cannot add a row key which is already in the matrix.");
2181
2/4
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
319 INS_ASSERT_USER_ERROR(!this->hasAnyCols(colKeys), "You cannot add a col key which is already in the matrix.");
2182
4/12
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 319 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 319 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 319 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
638 INS_ASSERT_USER_ERROR(std::unordered_set<RowKeyType>(rowKeys.begin(), rowKeys.end()).size() == rowKeys.size(), "Each row key must be unique");
2183
4/12
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 319 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 319 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 319 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
638 INS_ASSERT_USER_ERROR(std::unordered_set<ColKeyType>(colKeys.begin(), colKeys.end()).size() == colKeys.size(), "Each col key must be unique");
2184
2185 319 auto initialRowSize = static_cast<Eigen::Index>(this->rowIndices.size());
2186
7/9
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 330 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 330 times.
✓ Branch 11 taken 318 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 1 times.
651 for (const auto& rowKey : rowKeys) { this->rowIndices.insert({ rowKey, static_cast<Eigen::Index>(this->rowIndices.size()) }); }
2187
1/2
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
319 this->rowKeysVector.reserve(this->rowKeysVector.size() + rowKeys.size());
2188
2/4
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 319 times.
✗ Branch 7 not taken.
319 std::copy(rowKeys.begin(), rowKeys.end(), std::back_inserter(this->rowKeysVector));
2189 319 auto finalRowSize = static_cast<Eigen::Index>(this->rowIndices.size());
2190
2191 319 auto initialColSize = static_cast<Eigen::Index>(this->colIndices.size());
2192
3/4
✓ Branch 6 taken 332 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 332 times.
✓ Branch 11 taken 319 times.
651 for (const auto& colKey : colKeys) { this->colIndices.insert({ colKey, static_cast<Eigen::Index>(this->colIndices.size()) }); }
2193
1/2
✓ Branch 3 taken 319 times.
✗ Branch 4 not taken.
319 this->colKeysVector.reserve(this->colKeysVector.size() + colKeys.size());
2194
2/4
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 319 times.
✗ Branch 7 not taken.
319 std::copy(colKeys.begin(), colKeys.end(), std::back_inserter(this->colKeysVector));
2195 319 auto finalColSize = static_cast<Eigen::Index>(this->colIndices.size());
2196
2197 319 auto rows = finalRowSize - initialRowSize;
2198 319 auto cols = finalColSize - initialColSize;
2199
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
319 if (rows > 0 || cols > 0)
2200 {
2201
1/2
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
319 this->matrix.conservativeResize(finalRowSize, finalColSize);
2202
3/6
✓ Branch 2 taken 319 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 319 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 319 times.
✗ Branch 10 not taken.
319 this->matrix.block(initialRowSize, 0, rows, this->matrix.cols()) = Eigen::MatrixX<Scalar>::Zero(rows, this->matrix.cols());
2203
3/6
✓ Branch 2 taken 319 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 319 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 319 times.
✗ Branch 10 not taken.
319 this->matrix.block(0, initialColSize, this->matrix.rows(), cols) = Eigen::MatrixX<Scalar>::Zero(this->matrix.rows(), cols);
2204 }
2205
1/2
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
319 std::lock_guard<std::mutex> lg{ this->_sliceMutex };
2206
1/2
✓ Branch 2 taken 319 times.
✗ Branch 3 not taken.
319 this->colSlice.reserve(this->colKeysVector.size());
2207
1/2
✓ Branch 2 taken 319 times.
✗ Branch 3 not taken.
319 this->rowSlice.reserve(this->rowKeysVector.size());
2208 319 }
2209
2210 /// @brief Removes the rows and cols from the matrix
2211 /// @param rowKeys Row Keys
2212 /// @param colKeys Col Keys
2213 13 void removeRowsCols(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys)
2214 {
2215 13 std::vector<int> rowIndices;
2216
2/2
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 13 times.
40 for (const auto& rowKey : rowKeys)
2217 {
2218
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 auto iter = this->rowIndices.find(rowKey);
2219
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 INS_ASSERT_USER_ERROR(iter != this->rowIndices.end(), "You tried removing a row key, which did not exist.");
2220
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 if (iter != this->rowIndices.end())
2221 {
2222
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 rowIndices.push_back(static_cast<int>(iter->second));
2223 }
2224 }
2225 13 std::vector<int> colIndices;
2226
2/2
✓ Branch 5 taken 26 times.
✓ Branch 6 taken 13 times.
39 for (const auto& colKey : colKeys)
2227 {
2228
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 auto iter = this->colIndices.find(colKey);
2229
1/2
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 INS_ASSERT_USER_ERROR(iter != this->colIndices.end(), "You tried removing a col key, which did not exist.");
2230
1/2
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 if (iter != this->colIndices.end())
2231 {
2232
1/2
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 colIndices.push_back(static_cast<int>(iter->second));
2233 }
2234 }
2235
2236
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 NAV::removeRowsAndCols(this->matrix, rowIndices, colIndices);
2237
2238
2/2
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 13 times.
40 for (const auto& rowKey : rowKeys)
2239 {
2240
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 auto iter = this->rowIndices.find(rowKey);
2241
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 if (iter != this->rowIndices.end())
2242 {
2243
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
219 std::erase_if(this->rowKeysVector, [&](const auto& item) { return item == rowKey; });
2244
2245 27 auto idx = iter->second;
2246
2/2
✓ Branch 5 taken 192 times.
✓ Branch 6 taken 27 times.
219 for (auto& rowIndex : this->rowIndices)
2247 {
2248
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 125 times.
192 if (rowIndex.second > idx) { rowIndex.second--; }
2249 }
2250
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 this->rowIndices.erase(iter);
2251 }
2252 }
2253
2/2
✓ Branch 5 taken 26 times.
✓ Branch 6 taken 13 times.
39 for (const auto& colKey : colKeys)
2254 {
2255
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 auto iter = this->colIndices.find(colKey);
2256
1/2
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 if (iter != this->colIndices.end())
2257 {
2258
2/3
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
215 std::erase_if(this->colKeysVector, [&](const auto& item) { return item == colKey; });
2259
2260 26 auto idx = iter->second;
2261
2/2
✓ Branch 5 taken 189 times.
✓ Branch 6 taken 26 times.
215 for (auto& colIndex : this->colIndices)
2262 {
2263
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 125 times.
189 if (colIndex.second > idx) { colIndex.second--; }
2264 }
2265
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 this->colIndices.erase(iter);
2266 }
2267 }
2268 13 }
2269
2270 // #######################################################################################################
2271 // Methods
2272 // #######################################################################################################
2273
2274 /// @brief Returns a submatrix specified by the row and col keys
2275 /// @param rowKeys Row keys
2276 /// @param colKeys Col keys
2277 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>
2278 1 getSubMatrix(std::span<const RowKeyType> rowKeys, std::span<const ColKeyType> colKeys) const
2279 {
2280
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if (rowKeys == this->rowKeysVector && colKeys == this->colKeysVector)
2281 {
2282 return *this;
2283 }
2284
2285
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 return { (*this)(rowKeys, colKeys), rowKeys, colKeys };
2286 }
2287
2288 /// @brief Calculates the transposed matrix
2289 1 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic> transposed() const
2290 {
2291
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto transpose = static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this).transposed();
2292
1/2
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 return { transpose(all, all), transpose.rowKeys(), transpose.colKeys() };
2293 1 }
2294
2295 /// @brief Calculates the inverse matrix
2296 344 [[nodiscard]] KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic> inverse() const
2297 {
2298
1/2
✓ Branch 1 taken 344 times.
✗ Branch 2 not taken.
344 auto inv = static_cast<const internal::KeyedMatrixBase<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>&>(*this).inverse();
2299
1/2
✓ Branch 6 taken 344 times.
✗ Branch 7 not taken.
688 return { inv(all, all), inv.rowKeys(), inv.colKeys() };
2300 344 }
2301 };
2302
2303 /// @brief Dynamic size KeyedMatrix
2304 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
2305 /// @tparam RowKeyType Type of the key used for row lookup
2306 /// @tparam ColKeyType Type of the key used for col lookup
2307 template<typename Scalar, typename RowKeyType, typename ColKeyType = RowKeyType>
2308 using KeyedMatrixX = KeyedMatrix<Scalar, RowKeyType, ColKeyType, Eigen::Dynamic, Eigen::Dynamic>;
2309 /// @brief Dynamic size KeyedMatrix with double types
2310 /// @tparam RowKeyType Type of the key used for row lookup
2311 /// @tparam ColKeyType Type of the key used for col lookup
2312 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2313 using KeyedMatrixXd = KeyedMatrixX<double, RowKeyType, ColKeyType>;
2314 /// @brief Static 2x2 squared size KeyedMatrix with double types
2315 /// @tparam RowKeyType Type of the key used for row lookup
2316 /// @tparam ColKeyType Type of the key used for col lookup
2317 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2318 using KeyedMatrix2d = KeyedMatrix<double, RowKeyType, ColKeyType, 2, 2>;
2319 /// @brief Static 3x3 squared size KeyedMatrix with double types
2320 /// @tparam RowKeyType Type of the key used for row lookup
2321 /// @tparam ColKeyType Type of the key used for col lookup
2322 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2323 using KeyedMatrix3d = KeyedMatrix<double, RowKeyType, ColKeyType, 3, 3>;
2324 /// @brief Static 4x4 squared size KeyedMatrix with double types
2325 /// @tparam RowKeyType Type of the key used for row lookup
2326 /// @tparam ColKeyType Type of the key used for col lookup
2327 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2328 using KeyedMatrix4d = KeyedMatrix<double, RowKeyType, ColKeyType, 4, 4>;
2329 /// @brief Static 5x5 squared size KeyedMatrix with double types
2330 /// @tparam RowKeyType Type of the key used for row lookup
2331 /// @tparam ColKeyType Type of the key used for col lookup
2332 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2333 using KeyedMatrix5d = KeyedMatrix<double, RowKeyType, ColKeyType, 5, 5>;
2334 /// @brief Static 6x6 squared size KeyedMatrix with double types
2335 /// @tparam RowKeyType Type of the key used for row lookup
2336 /// @tparam ColKeyType Type of the key used for col lookup
2337 template<typename RowKeyType, typename ColKeyType = RowKeyType>
2338 using KeyedMatrix6d = KeyedMatrix<double, RowKeyType, ColKeyType, 6, 6>;
2339
2340 /// @brief Dynamic size KeyedVector
2341 /// @tparam Scalar Numeric type, e.g. float, double, int or std::complex<float>.
2342 /// @tparam RowKeyType Type of the key used for row lookup
2343 template<typename Scalar, typename RowKeyType>
2344 using KeyedVectorX = KeyedVector<Scalar, RowKeyType, Eigen::Dynamic>;
2345 /// @brief Dynamic size KeyedVector with double types
2346 /// @tparam RowKeyType Type of the key used for row lookup
2347 template<typename RowKeyType>
2348 using KeyedVectorXd = KeyedVectorX<double, RowKeyType>;
2349 /// @brief Static 2 row KeyedVector with double types
2350 /// @tparam RowKeyType Type of the key used for row lookup
2351 template<typename RowKeyType>
2352 using KeyedVector2d = KeyedVector<double, RowKeyType, 2>;
2353 /// @brief Static 3 row KeyedVector with double types
2354 /// @tparam RowKeyType Type of the key used for row lookup
2355 template<typename RowKeyType>
2356 using KeyedVector3d = KeyedVector<double, RowKeyType, 3>;
2357 /// @brief Static 4 row KeyedVector with double types
2358 /// @tparam RowKeyType Type of the key used for row lookup
2359 template<typename RowKeyType>
2360 using KeyedVector4d = KeyedVector<double, RowKeyType, 4>;
2361 /// @brief Static 5 row KeyedVector with double types
2362 /// @tparam RowKeyType Type of the key used for row lookup
2363 template<typename RowKeyType>
2364 using KeyedVector5d = KeyedVector<double, RowKeyType, 5>;
2365 /// @brief Static 6 row KeyedVector with double types
2366 /// @tparam RowKeyType Type of the key used for row lookup
2367 template<typename RowKeyType>
2368 using KeyedVector6d = KeyedVector<double, RowKeyType, 6>;
2369
2370 /// @brief Dynamic size KeyedRowVector
2371 /// @tparam ColKeyType Type of the key used for col lookup
2372 template<typename Scalar, typename ColKeyType>
2373 using KeyedRowVectorX = KeyedRowVector<Scalar, ColKeyType, Eigen::Dynamic>;
2374 /// @brief Dynamic size KeyedRowVector with double types
2375 /// @tparam ColKeyType Type of the key used for col lookup
2376 template<typename ColKeyType>
2377 using KeyedRowVectorXd = KeyedRowVectorX<double, ColKeyType>;
2378 /// @brief Static 2 col KeyedRowVector with double types
2379 /// @tparam ColKeyType Type of the key used for col lookup
2380 template<typename ColKeyType>
2381 using KeyedRowVector2d = KeyedRowVector<double, ColKeyType, 2>;
2382 /// @brief Static 3 col KeyedRowVector with double types
2383 /// @tparam ColKeyType Type of the key used for col lookup
2384 template<typename ColKeyType>
2385 using KeyedRowVector3d = KeyedRowVector<double, ColKeyType, 3>;
2386 /// @brief Static 4 col KeyedRowVector with double types
2387 /// @tparam ColKeyType Type of the key used for col lookup
2388 template<typename ColKeyType>
2389 using KeyedRowVector4d = KeyedRowVector<double, ColKeyType, 4>;
2390 /// @brief Static 5 col KeyedRowVector with double types
2391 /// @tparam ColKeyType Type of the key used for col lookup
2392 template<typename ColKeyType>
2393 using KeyedRowVector5d = KeyedRowVector<double, ColKeyType, 5>;
2394 /// @brief Static 6 col KeyedRowVector with double types
2395 /// @tparam ColKeyType Type of the key used for col lookup
2396 template<typename ColKeyType>
2397 using KeyedRowVector6d = KeyedRowVector<double, ColKeyType, 6>;
2398
2399 } // namespace NAV
2400
2401 #if defined(__GNUC__) && !defined(__clang__)
2402 #pragma GCC diagnostic pop
2403 #endif
2404
2405 #ifndef DOXYGEN_IGNORE
2406
2407 /// @brief Formatter for KeyedMatrix
2408 template<typename Scalar, typename RowKeyType, typename ColKeyType, int Rows, int Cols>
2409 struct fmt::formatter<NAV::KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols>> : fmt::formatter<std::string>
2410 {
2411 /// @brief Defines how to format KeyedMatrix structs
2412 /// @param[in] mat Struct to format
2413 /// @param[in, out] ctx Format context
2414 /// @return Output iterator
2415 4 auto format(const NAV::KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols>& mat, format_context& ctx) const
2416 {
2417 4 std::string result;
2418 4 auto rows = static_cast<size_t>(mat.rows());
2419 4 auto cols = static_cast<size_t>(mat.cols());
2420
2421
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 if (rows > 0 && cols > 0)
2422 {
2423 4 std::vector<std::string> rowKeysStr;
2424 4 std::vector<size_t> rowKeysLength;
2425
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 rowKeysStr.reserve(rows);
2426
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 rowKeysLength.reserve(rows);
2427 4 size_t rowKeysColSpace = 0;
2428
2/2
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 2 times.
16 for (const auto& rowKey : mat.rowKeys())
2429 {
2430
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
24 rowKeysStr.push_back(fmt::format("{}", rowKey));
2431 12 auto rowKeyLength = rowKeysStr.back().length();
2432 12 rowKeysColSpace = std::max(rowKeysColSpace, rowKeyLength);
2433
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 rowKeysLength.push_back(rowKeyLength);
2434 }
2435
2436 4 constexpr size_t colMinLength = 9UL;
2437
2438 4 std::vector<std::string> colKeysStr;
2439 4 std::vector<size_t> colKeysLength;
2440 4 size_t rowLineLength = rowKeysColSpace + 1; // '\n' at the end of line
2441
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 colKeysStr.reserve(cols);
2442
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 colKeysLength.reserve(cols);
2443
2/2
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
16 for (const auto& colKey : mat.colKeys())
2444 {
2445
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
24 colKeysStr.push_back(fmt::format("{}", colKey));
2446 12 auto colKeyLength = colKeysStr.back().length();
2447
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 colKeysLength.push_back(colKeyLength);
2448 12 rowLineLength += 2 + std::max(colKeysStr.back().length(), colMinLength); // 2 spaces before each column
2449 }
2450
2451
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result.reserve((rows + 1) * rowLineLength);
2452 // ---------------------------------------- Column keys ------------------------------------------
2453
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
4 result += " " + std::string(rowKeysColSpace, ' ');
2454
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
16 for (size_t c = 0; c < cols; c++)
2455 {
2456
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 result += " ";
2457
3/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 1 times.
12 if (colMinLength > colKeysLength.at(c))
2458 {
2459
3/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
20 result += std::string(colMinLength - colKeysLength.at(c), ' '); // Spaces in front of column name (if too short)
2460 }
2461
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
12 result += colKeysStr.at(c);
2462 }
2463
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result += '\n';
2464 // ------------------------------------------- Rows ----------------------------------------------
2465
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
16 for (size_t r = 0; r < rows; r++)
2466 {
2467
3/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
12 if (rowKeysColSpace > rowKeysLength.at(r))
2468 {
2469
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
8 result += std::string(rowKeysColSpace - rowKeysLength.at(r), ' '); // Spaces in front of row name (if too short)
2470 }
2471
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
12 result += rowKeysStr.at(r) + " ";
2472
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 6 times.
48 for (size_t c = 0; c < cols; c++)
2473 {
2474
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 auto colLength = std::max(colKeysStr.at(c).length(), colMinLength);
2475
2476
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 std::string tmp = fmt::format(" {:> {}.{}g}", mat(NAV::all, NAV::all)(static_cast<int>(r), static_cast<int>(c)), colLength, colLength - 2);
2477
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 if (tmp.length() > colLength)
2478 {
2479
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
72 tmp = fmt::format(" {:> {}.{}g}", mat(NAV::all, NAV::all)(static_cast<int>(r), static_cast<int>(c)), colLength, colLength - 6);
2480 }
2481
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 result += tmp;
2482 }
2483
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
12 if (r != rows - 1) { result += '\n'; }
2484 }
2485 4 }
2486
2487 12 return fmt::formatter<std::string>::format(result, ctx);
2488 4 }
2489 };
2490
2491 /// @brief Formatter for KeyedVector
2492 template<typename Scalar, typename RowKeyType, int Rows>
2493 struct fmt::formatter<NAV::KeyedVector<Scalar, RowKeyType, Rows>> : fmt::formatter<std::string>
2494 {
2495 /// @brief Defines how to format KeyedVector structs
2496 /// @param[in] vec Struct to format
2497 /// @param[in, out] ctx Format context
2498 /// @return Output iterator
2499 4 auto format(const NAV::KeyedVector<Scalar, RowKeyType, Rows>& vec, format_context& ctx) const
2500 {
2501 4 std::string result;
2502 4 auto rows = static_cast<size_t>(vec.rows());
2503
2504
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if (rows > 0)
2505 {
2506 4 std::vector<std::string> rowKeysStr;
2507 4 std::vector<size_t> rowKeysLength;
2508
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 rowKeysStr.reserve(rows);
2509
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 rowKeysLength.reserve(rows);
2510 4 size_t rowKeysColSpace = 0;
2511
2/2
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 2 times.
32 for (const auto& rowKey : vec.rowKeys())
2512 {
2513
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
56 rowKeysStr.push_back(fmt::format("{}", rowKey));
2514 28 auto rowKeyLength = rowKeysStr.back().length();
2515 28 rowKeysColSpace = std::max(rowKeysColSpace, rowKeyLength);
2516
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 rowKeysLength.push_back(rowKeyLength);
2517 }
2518
2519 4 size_t colLength = 9UL;
2520
2521
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result.reserve(rows * (rowKeysColSpace + 2 + colLength));
2522 // ------------------------------------------- Rows ----------------------------------------------
2523
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2 times.
32 for (size_t r = 0; r < rows; r++)
2524 {
2525
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 8 times.
28 if (rowKeysColSpace > rowKeysLength.at(r))
2526 {
2527
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
24 result += std::string(rowKeysColSpace - rowKeysLength.at(r), ' '); // Spaces in front of row name (if too short)
2528 }
2529
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
28 result += rowKeysStr.at(r);
2530
2531
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 std::string tmp = fmt::format(" {:> {}.{}g}", vec(NAV::all)(static_cast<int>(r)), colLength, colLength - 2);
2532
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 if (tmp.length() > colLength)
2533 {
2534
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
56 tmp = fmt::format(" {:> {}.{}g}", vec(NAV::all)(static_cast<int>(r)), colLength, colLength - 6);
2535 }
2536
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 result += tmp;
2537
2538
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
28 if (r != rows - 1) { result += '\n'; }
2539 }
2540 4 }
2541
2542 12 return fmt::formatter<std::string>::format(result, ctx);
2543 4 }
2544 };
2545
2546 /// @brief Formatter for KeyedRowVector
2547 template<typename Scalar, typename ColKeyType, int Cols>
2548 struct fmt::formatter<NAV::KeyedRowVector<Scalar, ColKeyType, Cols>> : fmt::formatter<std::string>
2549 {
2550 /// @brief Defines how to format KeyedRowVector structs
2551 /// @param[in] vec Struct to format
2552 /// @param[in, out] ctx Format context
2553 /// @return Output iterator
2554 4 auto format(const NAV::KeyedRowVector<Scalar, ColKeyType, Cols>& vec, format_context& ctx) const
2555 {
2556 4 std::string result;
2557 4 auto cols = static_cast<size_t>(vec.cols());
2558
2559
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if (cols > 0)
2560 {
2561 4 size_t colMinLength = 9UL;
2562
2563 4 std::vector<std::string> colKeysStr;
2564 4 std::vector<size_t> colKeysLength;
2565 4 size_t rowLineLength = 1; // '\n' at the end of line
2566
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 colKeysStr.reserve(cols);
2567
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 colKeysLength.reserve(cols);
2568
2/2
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 2 times.
32 for (const auto& colKey : vec.colKeys())
2569 {
2570
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
56 colKeysStr.push_back(fmt::format("{}", colKey));
2571 28 auto colKeyLength = colKeysStr.back().length();
2572
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 colKeysLength.push_back(colKeyLength);
2573 28 rowLineLength += 2 + std::max(colKeysStr.back().length(), colMinLength); // 2 spaces before each column
2574 }
2575
2576
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result.reserve(2 * rowLineLength);
2577 // ---------------------------------------- Column keys ------------------------------------------
2578
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
32 for (size_t c = 0; c < cols; c++)
2579 {
2580
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
28 if (c != 0) { result += " "; }
2581
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 1 times.
28 if (colMinLength > colKeysLength.at(c))
2582 {
2583
3/6
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
52 result += std::string(colMinLength - colKeysLength.at(c), ' '); // Spaces in front of column name (if too short)
2584 }
2585
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
28 result += colKeysStr.at(c);
2586 }
2587
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result += '\n';
2588 // ------------------------------------------ Values ---------------------------------------------
2589
2590
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2 times.
32 for (size_t c = 0; c < cols; c++)
2591 {
2592
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 auto colLength = std::max(colKeysStr.at(c).length(), colMinLength);
2593
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
28 if (c != 0) { result += " "; }
2594
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 std::string tmp = fmt::format("{:> {}.{}g}", vec(NAV::all)(static_cast<int>(c)), colLength, colLength - 2);
2595
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
28 if (tmp.length() > colLength)
2596 {
2597
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
28 tmp = fmt::format("{:> {}.{}g}", vec(NAV::all)(static_cast<int>(c)), colLength, colLength - 6);
2598 }
2599
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 result += tmp;
2600 }
2601 4 }
2602
2603 12 return fmt::formatter<std::string>::format(result, ctx);
2604 4 }
2605 };
2606
2607 #endif
2608
2609 /// @brief Stream insertion operator overload
2610 /// @param[in, out] os Output stream object to stream the time into
2611 /// @param[in] obj Object to print
2612 /// @return Returns the output stream object in order to chain stream insertions
2613 template<typename Scalar, typename RowKeyType, typename ColKeyType, int Rows, int Cols>
2614 std::ostream& operator<<(std::ostream& os, const NAV::KeyedMatrix<Scalar, RowKeyType, ColKeyType, Rows, Cols>& obj)
2615 {
2616 return os << fmt::format("{}", obj);
2617 }
2618 /// @brief Stream insertion operator overload
2619 /// @param[in, out] os Output stream object to stream the time into
2620 /// @param[in] obj Object to print
2621 /// @return Returns the output stream object in order to chain stream insertions
2622 template<typename Scalar, typename RowKeyType, int Rows>
2623 std::ostream& operator<<(std::ostream& os, const NAV::KeyedVector<Scalar, RowKeyType, Rows>& obj)
2624 {
2625 return os << fmt::format("{}", obj);
2626 }
2627 /// @brief Stream insertion operator overload
2628 /// @param[in, out] os Output stream object to stream the time into
2629 /// @param[in] obj Object to print
2630 /// @return Returns the output stream object in order to chain stream insertions
2631 template<typename Scalar, typename ColKeyType, int Cols>
2632 std::ostream& operator<<(std::ostream& os, const NAV::KeyedRowVector<Scalar, ColKeyType, Cols>& obj)
2633 {
2634 return os << fmt::format("{}", obj);
2635 }
2636