8#include "soo/impl/vector3.h"
18 template <std::
floating_po
int T,
size_t Row,
size_t Col>
19 requires (Row > 0 && Col > 0)
23 using ColArray = std::array<T, Col>;
24 std::array<ColArray, Row> entries;
29 Matrix() : entries{0} {}
30 Matrix(
const std::initializer_list<std::initializer_list<T>>& list)
32 if (list.size() != Row)
34 throw std::invalid_argument(
"Number of rows must be " + std::to_string(Row));
38 for (
auto rowIt = std::cbegin(list); rowIt != std::cend(list); ++rowIt, ++row)
40 if (rowIt->size() != Col)
42 throw std::invalid_argument(
"Number of columns must be " + std::to_string(Col));
46 for (
auto colIt = std::cbegin(*rowIt); colIt != std::cend(*rowIt); ++colIt, ++col)
48 entries[row][col] = *colIt;
53 Matrix(
const Matrix& rhs) noexcept : entries(rhs.entries) {}
54 Matrix(Matrix&& rhs) noexcept : entries(std::move(rhs.entries)) {}
56 ~Matrix()
noexcept =
default;
60 Matrix& operator=(
const Matrix& rhs)
noexcept
64 entries = rhs.entries;
70 Matrix& operator=(Matrix&& rhs)
noexcept
74 entries = std::move(rhs.entries);
80 ColArray& operator[](
const size_t row)
noexcept(
false)
84 throw std::out_of_range(
"Max row is " + std::to_string(Row));
90 const ColArray& operator[](
const size_t row)
const noexcept(
false)
94 throw std::out_of_range(
"Max row is " + std::to_string(Row));
100 bool operator==(
const Matrix& rhs)
const noexcept
102 for (
int row = 0; row < Row; ++row)
113 Matrix operator+(
const Matrix& rhs)
const noexcept
117 newMatrix.
forEachEntry([
this, &rhs](T& entry,
const size_t row,
const size_t col)
119 entry = entries[row][col] + rhs.entries[row][col];
125 Matrix operator-(
const Matrix& rhs)
const noexcept
129 newMatrix.
forEachEntry([
this, &rhs](T& entry,
const size_t row,
const size_t col)
131 entry = entries[row][col] - rhs.entries[row][col];
142 template <
size_t R,
size_t C>
143 Matrix<T, Row, C>
operator*(
const Matrix<T, R, C>& rhs)
const noexcept(
false)
147 throw std::invalid_argument(
"The number of rows must be " + std::to_string(Col));
150 Matrix<T, Row, C> newMatrix{};
152 newMatrix.
forEachEntry([
this, &rhs](T& entry,
const size_t row,
const size_t col)
154 for (
size_t c = 0; c < Col; ++c)
156 entry += entries[row][c] * rhs[c][col];
170 newMatrix.
forEachEntry([
this, val](T& entry,
const size_t row,
const size_t col)
172 entry = entries[row][col] * val;
183 const T a = entries[0][0], b = entries[0][1], c = entries[0][2], d = entries[0][3];
184 const T e = entries[1][0], f = entries[1][1], g = entries[1][2], h = entries[1][3];
185 const T i = entries[2][0], j = entries[2][1], k = entries[2][2], l = entries[2][3];
186 const T m = entries[3][0], n = entries[3][1], o = entries[3][2], p = entries[3][3];
188 const T divisor = m*rhs.x + n*rhs.y + o*rhs.z + p;
191 (a*rhs.x + b*rhs.y + c*rhs.z + d) / divisor,
192 (e*rhs.x + f*rhs.y + g*rhs.z + h) / divisor,
193 (i*rhs.x + j*rhs.y + k*rhs.z + l) / divisor,
199 forEachEntry([&rhs](T& entry,
const size_t row,
const size_t col)
201 entry += rhs.entries[row][col];
209 forEachEntry([&rhs](T& entry,
const size_t row,
const size_t col)
211 entry -= rhs.entries[row][col];
217 Matrix& operator*=(
const T val)
noexcept
219 forEachEntry([val](T& entry,
const size_t,
const size_t)
229 constexpr static size_t getRowSize() noexcept {
return Row; }
230 constexpr static size_t getColSize() noexcept {
return Col; }
232 constexpr static Matrix createIdentity() noexcept requires (Row == Col)
236 for (
size_t i = 0; i < Row; ++i)
238 identity[i][i] = T(1);
249 template <
typename Func>
250 requires std::invocable<Func, T&, const size_t, const size_t>
253 for (
size_t row = 0; row < Row; ++row)
255 for (
size_t col = 0; col < Col; ++col)
257 action(entries[row][col], row, col);
267 Matrix<T, Col, Row> transposed{};
269 transposed.
forEachEntry([
this](T& entry,
const size_t row,
const size_t col)
271 entry = entries[col][row];
281 Matrix
inverse2x2() const noexcept(false) requires (Row == Col && Row == 2)
283 const T a = entries[0][0], b = entries[0][1];
284 const T c = entries[1][0], d = entries[1][1];
286 const T det = a * d - b * c;
290 throw std::domain_error(
"Matrix is not invertible");
293 const T invDet = T(1) / det;
296 {d * invDet, -b * invDet},
297 {-c * invDet, a * invDet}
305 Matrix
inverse3x3() const noexcept(false) requires (Row == Col && Row == 3)
307 const T a = entries[0][0], b = entries[0][1], c = entries[0][2];
308 const T d = entries[1][0], e = entries[1][1], f = entries[1][2];
309 const T g = entries[2][0], h = entries[2][1], i = entries[2][2];
311 const T det = a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g);
315 throw std::domain_error(
"Matrix is not invertible");
318 const T invDet = T(1) / det;
321 {(e*i - f*h) * invDet, (c*h - b*i) * invDet, (b*f - c*e) * invDet},
322 {(f*g - d*i) * invDet, (a*i - c*g) * invDet, (c*d - a*f) * invDet},
323 {(d*h - e*g) * invDet, (b*g - a*h) * invDet, (a*e - b*d) * invDet},
332 Matrix
inverseNxN() const noexcept(false) requires (Row == Col)
334 const Matrix identity = Matrix::createIdentity();
335 std::array<std::array<T, Row*2>, Row> augmented{};
337 for (
int r = 0; r < Row; ++r)
339 for (
int c = 0; c < Row; ++c)
341 augmented[r][c] = entries[r][c];
342 augmented[r][c + Row] = identity[r][c];
346 for (
int i = 0; i < Row; ++i)
350 bool swapped =
false;
352 for (
int k = i + 1; k < Row; ++k)
356 std::swap(augmented[i], augmented[k]);
364 throw std::domain_error(
"Matrix is not invertible");
368 const T invPivot = T(1) / augmented[i][i];
370 for (
int j = i; j < Row * 2; ++j)
372 augmented[i][j] *= invPivot;
375 for (
int k = 0; k < Row; ++k)
379 const T factor = augmented[k][i];
381 for (
int j = i; j < Row * 2; ++j)
383 augmented[k][j] -= factor * augmented[i][j];
391 for (
int r = 0; r < Row; ++r)
393 for (
int c = Row; c < 2 * Row; ++c)
395 inversed[r][c-Row] = augmented[r][c];
405 using Matrix2f = Matrix<float, 2, 2>;
406 using Matrix2d = Matrix<double, 2, 2>;
407 using Matrix2L = Matrix<long double, 2, 2>;
408 using Matrix3f = Matrix<float, 3, 3>;
409 using Matrix3d = Matrix<double, 3, 3>;
410 using Matrix3L = Matrix<long double, 3, 3>;
411 using Matrix4f = Matrix<float, 4, 4>;
412 using Matrix4d = Matrix<double, 4, 4>;
413 using Matrix4L = Matrix<long double, 4, 4>;
Matrix class.
Definition matrix.h:21
Matrix inverseNxN() const noexcept(false)
Definition matrix.h:332
Matrix< T, Col, Row > transpose() const noexcept
Definition matrix.h:265
Matrix inverse2x2() const noexcept(false)
Definition matrix.h:281
Matrix< T, Row, C > operator*(const Matrix< T, R, C > &rhs) const noexcept(false)
Definition matrix.h:143
Vector3< T > operator*(const Vector3< T > &rhs) const
Definition matrix.h:181
Matrix operator*(const T val) const noexcept
Definition matrix.h:166
Matrix inverse3x3() const noexcept(false)
Definition matrix.h:305
void forEachEntry(const Func &action)
Definition matrix.h:251
3D vector class.
Definition vector3.h:22
bool isZero(const T num, const T tolerance=DEFAULT_TOLERANCE)
Definition util.h:66
bool isEqual(const T a, const T b, const T tolerance=DEFAULT_TOLERANCE)
Definition util.h:23
Namespace for math-on-demand.
Definition exception.h:13