INSTINCT Code Coverage Report


Directory: src/
File: util/Container/KeyedMatrix.hpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 878 887 99.0%
Functions: 816 887 92.0%
Branches: 551 1045 52.7%

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