GKD.RoboCtrl
RoboMaster Linux 电控:异步 IO、设备驱动与机器人控制
载入中...
搜索中...
未找到
Matrix.hpp
1
11//TODO:优化矩阵乘法
12#pragma once
13
14#include <cmath>
15#include <cstdint>
16#include <array>
17#include <algorithm>
18#include <type_traits>
19#include <utility>
20
21namespace roboctrl::utils
22{
23template <int _rows, int _cols, typename T = float>
24 requires(std::is_arithmetic_v<T> && _rows > 0 && _cols > 0) //编译期检查是否为算数类型
25class Matrix
26{
27 template <int r, int c, typename U>
28 requires(std::is_arithmetic_v<U> && r > 0 && c > 0)
29 friend class Matrix;
30
31public:
36 constexpr Matrix() : data{} {}
37
38 constexpr explicit Matrix(T val)
39 {
40 for (int i = 0; i < _rows; i++)
41 std::fill(data[i].begin(), data[i].end(), val);
42 }
43
48 constexpr explicit Matrix(const T *data) : Matrix()
49 {
50 for (int i = 0; i < _rows; i++)
51 for (int j = 0; j < _cols; j++)
52 this->data[i][j] = data[i * _cols + j];
53 }
54
59 constexpr Matrix(const Matrix &mat) : Matrix()
60 {
61 this->data = mat.data;
62 }
63
64 constexpr Matrix(Matrix &&mat) noexcept : Matrix()
65 {
66 this->data = std::move(mat.data);
67 }
68
69 template <typename Ty>
70 requires(std::is_arithmetic_v<Ty>)
71 constexpr Matrix(const Matrix<_rows, _cols, Ty> &mat) : Matrix()
72 {
73 for (int i = 0; i < _rows; i++)
74 for (int j = 0; j < _cols; j++)
75 data[i][j] = static_cast<T>(mat.data[i][j]);
76 }
77
81 ~Matrix() = default;
82
87 [[nodiscard]] constexpr uint32_t rows() const
88 {
89 return _rows;
90 }
91
96 [[nodiscard]] constexpr uint32_t cols() const
97 {
98 return _cols;
99 }
100
105 constexpr std::array<T, _cols> &operator[](int row)
106 {
107 return data[row];
108 }
109
110 constexpr const std::array<T, _cols> &operator[](int row) const
111 {
112 return data[row];
113 }
114
120 constexpr Matrix &operator=(const Matrix &mat)
121 {
122 data = mat.data;
123 return *this;
124 }
125
126 constexpr Matrix &operator=(Matrix &&mat) noexcept
127 {
128 data = std::move(mat.data);
129 return *this;
130 }
131
138 constexpr Matrix &operator+=(const Matrix &mat)
139 {
140 for (int i = 0; i < _rows; i++)
141 for (int j = 0; j < _cols; j++)
142 data[i][j] += mat.data[i][j];
143
144 return *this;
145 }
146
153 constexpr Matrix &operator-=(const Matrix &mat)
154 {
155 for (int i = 0; i < _rows; i++)
156 for (int j = 0; j < _cols; j++)
157 data[i][j] -= mat.data[i][j];
158
159 return *this;
160 }
161
168 template <typename Ty>
169 requires(std::is_arithmetic_v<Ty>)
170 constexpr Matrix &operator*=(Ty val)
171 {
172 for (int i = 0; i < _rows; i++)
173 for (int j = 0; j < _cols; j++)
174 data[i][j] *= val;
175
176 return *this;
177 }
178
186 template <typename Ty>
187 requires(std::is_arithmetic_v<Ty>)
188 constexpr Matrix &operator/=(Ty val)
189 {
190 for (int i = 0; i < _rows; i++)
191 for (int j = 0; j < _cols; j++)
192 data[i][j] /= val;
193
194 return *this;
195 }
196
203 constexpr Matrix operator+(const Matrix &mat) const
204 {
205 Matrix res;
206 for (int i = 0; i < _rows; i++)
207 for (int j = 0; j < _cols; j++)
208 res.data[i][j] = data[i][j] + mat.data[i][j];
209
210 return res;
211 }
212
219 constexpr Matrix operator-(const Matrix &mat) const
220 {
221 Matrix res;
222 for (int i = 0; i < _rows; i++)
223 for (int j = 0; j < _cols; j++)
224 res.data[i][j] = data[i][j] - mat.data[i][j];
225
226 return res;
227 }
228
235 template <typename Ty>
236 requires(std::is_arithmetic_v<Ty>)
237 constexpr Matrix operator*(Ty val) const
238 {
239 Matrix res;
240 for (int i = 0; i < _rows; i++)
241 for (int j = 0; j < _cols; j++)
242 res.data[i][j] = data[i][j] * val;
243
244 return res;
245 }
246
254 template <typename Ty>
255 requires(std::is_arithmetic_v<Ty>)
256 constexpr friend Matrix operator*(Ty val, const Matrix &mat)
257 {
258 return mat * val;
259 }
260
268 template <typename Ty>
269 requires(std::is_arithmetic_v<Ty>)
270 Matrix operator/(Ty val) const
271 {
272 Matrix res;
273 for (int i = 0; i < _rows; i++)
274 for (int j = 0; j < _cols; j++)
275 res.data[i][j] = data[i][j] / val;
276
277 return res;
278 }
279
286 template <int cols2>
288 const Matrix<_cols, cols2, T> &mat2)
289 {
291
292 for (int i = 0; i < _rows; i++)
293 for (int k = 0; k < _cols; k++)
294 for (int j = 0; j < cols2; j++)
295 res[i][j] += mat1[i][k] * mat2[k][j];
296
297 return res;
298 }
299
304 constexpr bool operator==(const Matrix &mat) const
305 {
306 return data == mat.data;
307 }
308
309 // Submatrix
310 template <int rows, int cols> constexpr Matrix<rows, cols, T> block(int start_row, int start_col) const
311 {
313 for (int i = 0; i < rows; i++)
314 std::copy(data[i + start_row].begin() + start_col, data[i + start_row].begin() + start_col + cols,
315 res.data[i].begin());
316 return res;
317 }
318
324 constexpr Matrix<1, _cols, T> row(int row) const
325 {
326 return block<1, _cols>(row, 0);
327 }
328
334 constexpr Matrix<_rows, 1, T> col(int col) const
335 {
336 return block<_rows, 1>(0, col);
337 }
338
345 {
347 for (int i = 0; i < _rows; i++)
348 for (int j = 0; j < _cols; j++)
349 res[j][i] = data[i][j];
350
351 return res;
352 }
353
358 constexpr Matrix clone() const
359 {
360 Matrix res;
361 res.data = data;
362 return res;
363 }
364
370 constexpr T trace() const
371 {
372 T res = 0;
373 for (int i = 0; i < std::min(_rows, _cols); i++)
374 res += data[i][i];
375 return res;
376 }
377
383 constexpr Matrix inv() const
384 {
385 static_assert(_cols == _rows, "Matrix must be square");
386 Matrix res = Matrix::eye();
387
388 Matrix temp = this->clone();
389
390 // Gauss-Jordan elimination with partial pivoting.
391 for (int k = 0; k < _cols; k++)
392 {
393 int pivot_row = k;
394 auto magnitude = [](T value) constexpr {
395 const auto converted = static_cast<long double>(value);
396 return converted < 0.0L ? -converted : converted;
397 };
398 auto pivot_magnitude = magnitude(temp[k][k]);
399 for (int i = k + 1; i < _rows; i++)
400 {
401 const auto candidate_magnitude = magnitude(temp[i][k]);
402 if (candidate_magnitude > pivot_magnitude)
403 {
404 pivot_row = i;
405 pivot_magnitude = candidate_magnitude;
406 }
407 }
408
409 // Preserve the historical singular-matrix contract: return zeros
410 // when no non-zero pivot exists for the current column.
411 if (pivot_magnitude == 0.0L)
412 {
413 return zeros();
414 }
415
416 if (pivot_row != k)
417 {
418 std::swap(temp[pivot_row], temp[k]);
419 std::swap(res[pivot_row], res[k]);
420 }
421
422 T pivot = temp[k][k];
423 for (int j = 0; j < _cols; j++)
424 {
425 temp[k][j] /= pivot;
426 res[k][j] /= pivot;
427 }
428
429 for (int i = 0; i < _rows; i++)
430 {
431 if (i != k)
432 {
433 T factor = temp[i][k];
434 for (int j = 0; j < _cols; j++)
435 {
436 temp[i][j] -= factor * temp[k][j];
437 res[i][j] -= factor * res[k][j];
438 }
439 }
440 }
441 }
442
443 return res;
444 }
445
446 /*==============================================================*/
447 // Static function
454 static constexpr Matrix zeros()
455 {
456 return Matrix(static_cast<T>(0));
457 }
458
465 static constexpr Matrix ones()
466 {
467 return Matrix(static_cast<T>(1));
468 }
469
476 static constexpr Matrix eye()
477 {
478 Matrix mat = Matrix::zeros();
479
480 for (int i = 0; i < std::min(_rows, _cols); i++)
481 mat[i][i] = 1;
482
483 return mat;
484 }
485
493 static constexpr Matrix diag(const Matrix<_rows, 1, T> &vec)
494 {
495 Matrix res = Matrix::zeros();
496 for (int i = 0; i < std::min(_rows, _cols); i++)
497 {
498 res[i][i] = vec[i][0];
499 }
500 return res;
501 }
502
503private:
504 std::array<std::array<T, _cols>, _rows> data;
505
506};
507
508template <int r, int c> using Matrixf = Matrix<r, c, float>;
509} // namespace Power
constexpr Matrix(const T *data)
Constructor with input data
Definition Matrix.hpp:48
constexpr uint32_t cols() const
return the column size of the matrix
Definition Matrix.hpp:96
constexpr Matrix operator+(const Matrix &mat) const
Additonal operator
Definition Matrix.hpp:203
constexpr Matrix< _cols, _rows, T > trans() const
Get the transpose of the matrix
Definition Matrix.hpp:344
constexpr std::array< T, _cols > & operator[](int row)
Return the element of the matrix
Definition Matrix.hpp:105
constexpr uint32_t rows() const
returns the row size of the matrix
Definition Matrix.hpp:87
constexpr Matrix inv() const
Get the inverse of the matrix
Definition Matrix.hpp:383
static constexpr Matrix eye()
Returns a _rows * columns matrix
Definition Matrix.hpp:476
static constexpr Matrix diag(const Matrix< _rows, 1, T > &vec)
Returns a _rows x _cols diagonal matrix
Definition Matrix.hpp:493
~Matrix()=default
Destructor
static constexpr Matrix zeros()
Returns a _rows x _cols zero matrix
Definition Matrix.hpp:454
constexpr Matrix< _rows, 1, T > col(int col) const
Return the specific row of the matrix
Definition Matrix.hpp:334
constexpr Matrix & operator=(const Matrix &mat)
Copy assignment of the matrix(row * size) instance
Definition Matrix.hpp:120
constexpr Matrix()
Constructor without input data
Definition Matrix.hpp:36
constexpr Matrix clone() const
Definition Matrix.hpp:358
constexpr Matrix(const Matrix &mat)
Copy Constructor
Definition Matrix.hpp:59
constexpr Matrix & operator-=(const Matrix &mat)
Substraction operator of two matrices(row * size)
Definition Matrix.hpp:153
constexpr T trace() const
Get the trace of the matrix
Definition Matrix.hpp:370
constexpr bool operator==(const Matrix &mat) const
Compare whether two matrices are identical
Definition Matrix.hpp:304
static constexpr Matrix ones()
Returns a _rows x _cols one matrix
Definition Matrix.hpp:465
constexpr Matrix< 1, _cols, T > row(int row) const
Return the specific row of the matrix
Definition Matrix.hpp:324
constexpr Matrix & operator+=(const Matrix &mat)
Additional operator of two matrices(row * size)
Definition Matrix.hpp:138
constexpr friend Matrix< _rows, cols2, T > operator*(const Matrix< _rows, _cols, T > &mat1, const Matrix< _cols, cols2, T > &mat2)
The matrix multiplication
Definition Matrix.hpp:287
constexpr Matrix operator-(const Matrix &mat) const
Substraction matrix
Definition Matrix.hpp:219
用于存放工具函数的命名空间。
Definition ballistics.hpp:6