consteig
Compile-time eigenvalue and eigenvector computation for C++17
Loading...
Searching...
No Matches
matrix.hpp
1#ifndef MATRIX_HPP
2#define MATRIX_HPP
3
4#include "../consteig_types.hpp"
5#include "../math/math_backend.hpp"
6
7namespace consteig
8{
9
13
14// Forward declarations for member wrapper implementations
15template <typename T, Size R, Size C> class Matrix;
16
17template <typename T, Size R, Size C>
19
20template <typename T, Size R, Size C>
21constexpr T trace(const Matrix<T, R, C> &mat);
22
23template <typename T, Size R, Size C>
24constexpr T determinant(const Matrix<T, R, C> &mat);
25
26template <typename T, Size R, Size C>
27constexpr T norm(const Matrix<T, R, C> &mat);
28
29template <typename T, Size R, Size C>
30constexpr T dot(const Matrix<T, R, C> &lhs, const Matrix<T, R, C> &rhs);
31
55template <typename T, Size R, Size C> class Matrix
56{
57 public:
59 constexpr T &operator()(const Size row, const Size col)
60 {
61 return _data[row][col];
62 }
63
65 constexpr const T &operator()(const Size row, const Size col) const
66 {
67 return _data[row][col];
68 }
69
72 template <typename U>
73 constexpr bool operator==(const Matrix<U, R, C> &rhs) const
74 {
75 for (Size row{0}; row < R; row++)
76 {
77 for (Size col{0}; col < C; col++)
78 {
79 if ((*this)(row, col) != rhs(row, col))
80 {
81 return false;
82 }
83 }
84 }
85 return true;
86 }
87
90 template <typename U>
91 constexpr bool operator!=(const Matrix<U, R, C> &rhs) const
92 {
93 return !(*this == rhs);
94 }
95
98 constexpr Matrix<T, 1, C> row(const Size n) const
99 {
101
102 for (Size col{0}; col < C; col++)
103 {
104 result(0, col) = (*this)(n, col);
105 }
106
107 return result;
108 }
109
116 // Get subset of row
117 template <Size startIndex, Size endIndex>
118 constexpr Matrix<T, 1, endIndex - startIndex + 1> row(const Size n) const
119 {
120 static_assert(C > startIndex, "startIndex cannot be larger than array");
121 static_assert(C > endIndex, "endIndex cannot be larger than array");
122 static_assert(endIndex >= startIndex,
123 "startIndex cannot be larger than endIndex");
124
125 Matrix<T, 1, endIndex - startIndex + 1> result{};
126
127 for (Size col{startIndex}; col <= endIndex; col++)
128 {
129 result(0, col - startIndex) = (*this)(n, col);
130 }
131
132 return result;
133 }
134
137 constexpr Matrix<T, R, 1> col(const Size n) const
138 {
140
141 for (Size row{0}; row < R; row++)
142 {
143 result(row, 0) = (*this)(row, n);
144 }
145
146 return result;
147 }
148
155 // Get subset of column
156 template <Size startIndex, Size endIndex>
157 constexpr Matrix<T, endIndex - startIndex + 1, 1> col(const Size n) const
158 {
159 static_assert(R > startIndex, "startIndex cannot be larger than array");
160 static_assert(R > endIndex, "endIndex cannot be larger than array");
161 static_assert(endIndex >= startIndex,
162 "startIndex cannot be larger than endIndex");
163
164 Matrix<T, endIndex - startIndex + 1, 1> result{};
165
166 for (Size row{startIndex}; row <= endIndex; row++)
167 {
168 result(row - startIndex, 0) = (*this)(row, n);
169 }
170
171 return result;
172 }
173
184 template <Size numRows, Size numCols>
186 Size startCol) const
187 {
189
190 for (Size row{startRow}; row < startRow + numRows; row++)
191 {
192 for (Size col{startCol}; col < startCol + numCols; col++)
193 {
194 result(row - startRow, col - startCol) = (*this)(row, col);
195 }
196 }
197
198 return result;
199 }
200
204 constexpr void setRow(const Matrix<T, 1, C> &mat, const Size n)
205 {
206 for (Size col{0}; col < C; col++)
207 {
208 (*this)(n, col) = mat(0, col);
209 }
210 }
211
218 template <Size startIndex, Size endIndex>
220 const Size n)
221 {
222 static_assert(C > startIndex, "startIndex cannot be larger than array");
223 static_assert(C > endIndex, "endIndex cannot be larger than array");
224 static_assert(endIndex >= startIndex,
225 "startIndex cannot be larger than endIndex");
226
227 for (Size col{startIndex}; col <= endIndex; col++)
228 {
229 (*this)(n, col) = mat(0, col - startIndex);
230 }
231 }
232
236 constexpr void setCol(const Matrix<T, R, 1> &mat, const Size n)
237 {
238 for (Size row{0}; row < R; row++)
239 {
240 (*this)(row, n) = mat(row, 0);
241 }
242 }
243
250 template <Size startIndex, Size endIndex>
252 const Size n)
253 {
254 static_assert(R > startIndex, "startIndex cannot be larger than array");
255 static_assert(R > endIndex, "endIndex cannot be larger than array");
256 static_assert(endIndex >= startIndex,
257 "startIndex cannot be larger than endIndex");
258
259 for (Size row{startIndex}; row <= endIndex; row++)
260 {
261 (*this)(row, n) = mat(row - startIndex, 0);
262 }
263 }
264
276 template <Size numRows, Size numCols>
278 Size startRow, Size startCol)
279 {
280 for (Size row{startRow}; row < startRow + numRows; row++)
281 {
282 for (Size col{startCol}; col < startCol + numCols; col++)
283 {
284 (*this)(row, col) = mat(row - startRow, col - startCol);
285 }
286 }
287 }
288
290 constexpr bool isSquare() const
291 {
292 return rows() == cols();
293 }
294
302 constexpr bool isSymmetric() const
303 {
304 static_assert(R == C, "Symmetric matrices should be square.");
305
306 if (rows() > 1)
307 {
308 for (Size row{1}; row <= rows() - 1; row++)
309 {
310 for (Size col{0}; col < row; col++)
311 {
312 bool eq{false};
313 if constexpr (is_float<T>())
314 {
315 eq = consteig::equalWithin(
316 (*this)(row, col), (*this)(col, row), epsilon<T>());
317 }
318 else
319 {
320 eq = ((*this)(row, col) == (*this)(col, row));
321 }
322
323 if (!eq)
324 {
325 return false;
326 }
327 }
328 }
329 }
330
331 return true;
332 }
333
344 template <typename U> constexpr bool isSymmetric(const U thresh) const
345 {
346 static_assert(is_float<T>(),
347 "isSymmetric with threshold requires floating-point "
348 "matrix elements; integer T would truncate thresh");
349 static_assert(is_float<U>(), "isSymmetric with arg expects to compare\
350 floating point values");
351 static_assert(R == C, "Symmetric matrices should be square.");
352
353 if (rows() > 1)
354 {
355 for (Size row{1}; row <= rows() - 1; row++)
356 {
357 for (Size col{0}; col < row; col++)
358 {
359 if (!consteig::equalWithin((*this)(row, col),
360 (*this)(col, row), thresh))
361 {
362 return false;
363 }
364 }
365 }
366 }
367
368 return true;
369 }
370
379 constexpr bool equalWithin(const Matrix<T, R, C> &rhs, const T thresh) const
380 {
381 for (Size row{0}; row < R; row++)
382 {
383 for (Size col{0}; col < C; col++)
384 {
385 if (!consteig::equalWithin((*this)(row, col), rhs(row, col),
386 thresh))
387 {
388 return false;
389 }
390 }
391 }
392 return true;
393 }
394
396 constexpr Size rows() const
397 {
398 return R;
399 }
401 constexpr Size cols() const
402 {
403 return C;
404 }
405
407 constexpr T *data()
408 {
409 return &_data[0][0];
410 }
411
413 constexpr const T *data() const
414 {
415 return &_data[0][0];
416 }
417
420
422 constexpr Matrix<T, C, R> transpose() const
423 {
424 return consteig::transpose(*this);
425 }
426
428 constexpr T trace() const
429 {
430 return consteig::trace(*this);
431 }
432
434 constexpr T determinant() const
435 {
436 return consteig::determinant(*this);
437 }
438
440 constexpr T norm() const
441 {
442 return consteig::norm(*this);
443 }
444
446 constexpr T dot(const Matrix<T, R, C> &other) const
447 {
448 return consteig::dot(*this, other);
449 }
450
452
453 // Public for aggregate initialization only. C++17 aggregates require all
454 // data members to be public; making this private breaks the {{...}} syntax.
455 // Treat as an implementation detail; use operator() for element access.
456 //
457 // Row-major storage: _data[row][col]. This differs from Eigen and LAPACK,
458 // which default to column-major. The tradeoff is intentional: row-major
459 // matches C's native 2D array layout, so aggregate initialization reads
460 // naturally as written-out matrix rows (e.g. {{1,2},{3,4}}). Interop via
461 // data() with Eigen/LAPACK will produce transposed results unless the
462 // consumer specifies row-major explicitly (e.g. Eigen::RowMajor).
463 T _data[R][C]{};
464};
465
486template <typename T, Size R, Size C, typename... Args>
488{
489 static_assert(sizeof...(Args) == R * C,
490 "make_matrix: argument count must equal R * C");
491
493 T flat[] = {static_cast<T>(args)...};
494
495 for (Size row{0}; row < R; row++)
496 {
497 for (Size col{0}; col < C; col++)
498 {
499 result(row, col) = flat[row * C + col];
500 }
501 }
502
503 return result;
504}
505
523template <typename To, typename From, Size R, Size C>
525{
527
528 for (Size row{0}; row < R; row++)
529 {
530 for (Size col{0}; col < C; col++)
531 {
532 result(row, col) = static_cast<To>(src(row, col));
533 }
534 }
535
536 return result;
537}
538
540
541} // namespace consteig
542#endif // MATRIX_HPP
Fixed-size matrix with compile-time dimensions.
Definition matrix.hpp:56
constexpr bool isSymmetric(const U thresh) const
Returns true if the matrix is symmetric within thresh.
Definition matrix.hpp:344
constexpr Matrix< T, 1, endIndex - startIndex+1 > row(const Size n) const
Extract a contiguous subset of row n.
Definition matrix.hpp:118
constexpr T trace() const
Returns the trace. Delegates to consteig::trace.
Definition matrix.hpp:428
constexpr void setCol(const Matrix< T, R, 1 > &mat, const Size n)
Overwrite column n with the contents of mat.
Definition matrix.hpp:236
constexpr void setRow(const Matrix< T, 1, endIndex - startIndex+1 > &mat, const Size n)
Overwrite a contiguous subset of row n.
Definition matrix.hpp:219
constexpr T determinant() const
Returns the determinant. Delegates to consteig::determinant.
Definition matrix.hpp:434
constexpr const T & operator()(const Size row, const Size col) const
Access element at row row, column col (read-only).
Definition matrix.hpp:65
constexpr Matrix< T, numRows, numCols > block(Size startRow, Size startCol) const
Extract a rectangular submatrix.
Definition matrix.hpp:185
constexpr T dot(const Matrix< T, R, C > &other) const
Dot product with other. Delegates to consteig::dot.
Definition matrix.hpp:446
constexpr bool isSquare() const
Returns true if the matrix has equal row and column counts.
Definition matrix.hpp:290
constexpr Matrix< T, endIndex - startIndex+1, 1 > col(const Size n) const
Extract a contiguous subset of column n.
Definition matrix.hpp:157
constexpr T norm() const
Returns the Frobenius norm. Delegates to consteig::norm.
Definition matrix.hpp:440
constexpr Matrix< T, C, R > transpose() const
Member convenience wrappers that delegate to free functions.
Definition matrix.hpp:422
constexpr Matrix< T, 1, C > row(const Size n) const
Extract row n as a 1×C matrix.
Definition matrix.hpp:98
constexpr Matrix< T, R, 1 > col(const Size n) const
Extract column n as an R×1 matrix.
Definition matrix.hpp:137
constexpr void setRow(const Matrix< T, 1, C > &mat, const Size n)
Overwrite row n with the contents of mat.
Definition matrix.hpp:204
constexpr Size rows() const
Number of rows (same as template parameter R).
Definition matrix.hpp:396
constexpr const T * data() const
Raw pointer to first element (read-only).
Definition matrix.hpp:413
constexpr bool operator!=(const Matrix< U, R, C > &rhs) const
Inequality (exact). Prefer negated equalWithin(rhs, thresh) for floats.
Definition matrix.hpp:91
constexpr void setCol(const Matrix< T, endIndex - startIndex+1, 1 > &mat, const Size n)
Overwrite a contiguous subset of column n.
Definition matrix.hpp:251
constexpr T & operator()(const Size row, const Size col)
Access element at row row, column col (mutable).
Definition matrix.hpp:59
constexpr Size cols() const
Number of columns (same as template parameter C).
Definition matrix.hpp:401
constexpr bool operator==(const Matrix< U, R, C > &rhs) const
Exact element-wise equality. Prefer equalWithin(rhs, thresh) for floats.
Definition matrix.hpp:73
constexpr T * data()
Raw pointer to first element (mutable).
Definition matrix.hpp:407
constexpr bool isSymmetric() const
Returns true if the matrix is symmetric within machine epsilon.
Definition matrix.hpp:302
constexpr void setBlock(const Matrix< T, numRows, numCols > &mat, Size startRow, Size startCol)
Overwrite a rectangular subregion of this matrix.
Definition matrix.hpp:277
constexpr bool equalWithin(const Matrix< T, R, C > &rhs, const T thresh) const
Returns true if every element of rhs is within thresh of the corresponding element of *this.
Definition matrix.hpp:379
constexpr T epsilon()
Machine epsilon for type T.
Definition utilities.hpp:82
constexpr T determinant(const Matrix< T, R, C > &mat)
Determinant via Laplace (cofactor) expansion.
Definition operations.hpp:323
constexpr T norm(const Matrix< T, R, C > &mat)
Frobenius (Euclidean) norm: sqrt(sum of squared elements).
Definition operations.hpp:211
constexpr Matrix< To, R, C > matrix_cast(const Matrix< From, R, C > &src)
Convert a matrix from one element type to another.
Definition matrix.hpp:524
constexpr Matrix< T, C, R > transpose(const Matrix< T, R, C > &mat)
Matrix transpose.
Definition operations.hpp:154
constexpr T dot(const Matrix< T, R, C > &lhs, const Matrix< T, R, C > &rhs)
Dot product of two 1×N row vectors.
Definition operations.hpp:137
constexpr T trace(const Matrix< T, R, C > &mat)
Trace: sum of diagonal elements.
Definition operations.hpp:370
constexpr Matrix< T, R, C > make_matrix(Args... args)
Construct a Matrix from a flat list of scalar arguments in row-major order.
Definition matrix.hpp:487