43 #pragma region COLUMN_CLASS
138 #pragma region PRIVATE_METHODS
140 template<arithmetic... Ts, size_t... Idxs>
142 template<
class... Ts, size_t... Idxs, std::enable_if_t<are_arithmetic_v<Ts...>,
bool> =
true>
145 ((_values[Idxs / R][Idxs % R] =
static_cast<T>(values)), ...);
149 template<size_t VN, arithmetic VT>
151 template<size_t VN,
class VT, std::enable_if_t<std::is_arithmetic_v<VT>,
bool> =
true>
154 size_t maxSize = std::min(VN, R);
156 std::copy_n(
static_cast<
const T*>(column), maxSize, &_values[idx]);
159 for (size_t y = 0; y != maxSize; ++y) { _values[idx][y] = (T)column[y]; }
161 _fill_column_from(maxSize, idx, T(0));
165 template<size_t VN, arithmetic... Ts, size_t... Idxs>
167 template<size_t VN,
class... Ts, size_t... Idxs, std::enable_if_t<are_arithmetic_v<Ts...>,
bool> =
true>
170 (_set_column(Idxs, columns), ...);
174 if (colIdx >= C) {
return; }
175 std::fill_n(&_values[colIdx], C, value);
179 if (colIdx >= C) {
return; }
180 if (firstIdx >= R) {
return; }
181 std::fill_n(&_values[colIdx][firstIdx], R - firstIdx, value);
187 if (firstIdx >= size) {
return; }
188 std::fill_n(&_values[0][0] + firstIdx, size - firstIdx, value);
192 std::fill_n(&_values[0][0], size, T(0));
193 size_t minSize = std::min(C, R);
194 for (size_t i = 0; i != minSize; ++i) { _values[i][i] = value; }
198 template<arithmetic OT>
200 template<
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
204 std::copy_n(values, std::min(mat<C, R, T>::size, size), &_values[0][0]);
207 size_t sizeLeft = size;
208 for (size_t x = 0; x != C; ++x) {
209 for (size_t y = 0; y != std::min(sizeLeft, R); ++y) {
210 _values[x][y] =
static_cast<T>(values[x][y]);
212 if (sizeLeft <= R) {
break; }
219 template<arithmetic OT>
221 template<
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
224 size_t colSize = std::min(columns, C);
225 size_t rowSize = std::min(rows, R);
227 for (size_t x = 0; x != colSize; ++x) {
228 std::copy_n(&values[x * rowSize], rowSize, &_values[x]);
229 _fill_column_from(rowSize, x,
static_cast<T>(0));
233 for (size_t x = 0; x != colSize; ++x) {
234 for (size_t y = 0; y != rowSize; ++y) { _values[x][y] =
static_cast<T>(values[x][y]); }
235 _fill_column_from(rowSize, x,
static_cast<T>(0));
241 template<size_t ON, arithmetic OT>
243 template<size_t ON,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
246 _copy_values_from(&values, ON);
250 template<size_t OC, size_t OR, arithmetic OT>
252 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
255 _copy_values_from(&values, OC, OR);
259 template<size_t VN, arithmetic OT>
261 template<size_t VN,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
264 size_t colSize = std::min(C, size);
265 size_t rowSize = std::min(VN, R);
267 for (size_t x = 0; x != colSize; ++x) {
268 std::copy_n(
static_cast<
const T*>(columns[x]), rowSize, &_values[x][0]);
269 _fill_column_from(rowSize, x,
static_cast<T>(0));
273 for (size_t x = 0; x != colSize; ++x) {
274 for (size_t y = 0; y != rowSize; ++y) { _values[x][y] =
static_cast<T>(columns[x][y]); }
275 _fill_column_from(rowSize, x,
static_cast<T>(0));
281 template<size_t VN, size_t N, arithmetic OT>
283 template<size_t VN, size_t N,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
286 _copy_values_from(&columns, N);
290 template<size_t OC, size_t OR, arithmetic OT>
292 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
295 size_t colSize = std::min(OC, C);
296 size_t rowSize = std::min(OR, R);
298 for (size_t x = 0; x != colSize; ++x) {
299 std::copy_n(
static_cast<
const T*>(other[x]), rowSize, &_values[x][0]);
300 _fill_column_from(rowSize, x,
static_cast<T>(0));
304 for (size_t x = 0; x != colSize; ++x) {
305 for (size_t y = 0; y != rowSize; ++y) { _values[x][y] =
static_cast<T>(other[x][y]); }
306 _fill_column_from(rowSize, x,
static_cast<T>(0));
314 #pragma region CONSTRUCTORS
319 template<arithmetic OT>
321 template<
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
324 _copy_values_from(values, size);
325 _fill_values_from(size,
static_cast<T>(0));
329 template<arithmetic OT>
331 template<
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
334 _copy_values_from(values, columns, rows);
335 _fill_values_from(columns * R,
static_cast<T>(0));
338 template<size_t ON, arithmetic OT>
340 template<size_t ON,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
345 template<size_t OC, size_t OR, arithmetic OT>
347 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
352 template<arithmetic... Ts>
353 requires (
sizeof...(Ts) > 0 &&
sizeof...(Ts) <= size)
355 template<
class... Ts,
356 std::enable_if_t<((
sizeof...(Ts) > 0) && (
sizeof...(Ts) <=
size) &&
mstd::are_arithmetic_v<Ts...>),
bool> =
true>
359 _set_values(std::index_sequence_for<Ts...>(), values...);
360 _fill_values_from(
sizeof...(Ts),
static_cast<T>(0));
363 template<size_t VN, arithmetic OT>
365 template<size_t VN,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
368 _copy_values_from(columns, size);
369 _fill_values_from(size * R,
static_cast<T>(0));
372 template<size_t N, size_t VN, arithmetic OT>
374 template<size_t N, size_t VN,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
379 template<size_t VN, arithmetic... Ts>
380 requires (
sizeof...(Ts) > 0 &&
sizeof...(Ts) <= C)
382 template<size_t VN,
class... Ts, std::enable_if_t<(
sizeof...(Ts) > 0 &&
sizeof...(Ts) <= C),
bool> =
true>
385 _set_values(std::index_sequence_for<Ts...>(), columns...);
386 _fill_values_from(
sizeof...(Ts) * R,
static_cast<T>(0));
389 template<size_t OC, size_t OR, arithmetic OT>
391 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
394 _copy_values_from(other);
395 _fill_values_from(OC * R,
static_cast<T>(0));
400 #pragma region DESTRUCTOR
404 #pragma region ASSIGN
406 template<size_t ON, arithmetic OT>
408 template<size_t ON,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
411 _copy_values_from(values);
412 _fill_values_from(ON,
static_cast<T>(0));
416 template<size_t OC, size_t OR, arithmetic OT>
418 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
421 _copy_values_from(values);
422 _fill_values_from(OC * R,
static_cast<T>(0));
426 template<size_t VN, arithmetic OT, size_t N>
428 template<size_t VN,
class OT, size_t N, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
431 _copy_values_from(columns);
432 _fill_values_from(N * R,
static_cast<T>(0));
436 template<size_t OC, size_t OR, arithmetic OT>
438 template<size_t OC, size_t OR,
class OT, std::enable_if_t<std::is_arithmetic_v<OT>,
bool> =
true>
441 _copy_values_from(other);
442 _fill_values_from(OC * R,
static_cast<T>(0));
448 #pragma region PREDEFINED
456 res._fill_values(value);
460 #pragma region PREDEFINED_SQUARE_MATRIX
468 res._set_identity_values(value);
475 mat<C, R, T> res = mat<C, R, T>::identity();
476 for (size_t y = 0; y != R - 1; ++y) { res[C - 1][y] = transVec[y]; }
484 for (size_t i = 0; i != R - 1; ++i) { res[i][i] = scaleVec[i]; }
485 res[C - 1][R - 1] = T(1);
492 return mat<C, R, T>::fill_identity(scaleFactor);
495 #pragma region PREDEFINED_MATRIX_3x3
498 static _MSTD_CONSTEXPR20 mat<C, R, T> screen(
const T& left,
const T& right,
const T& bottom,
const T& top,
const T& width,
500 const T& invBt = 1.0 / (bottom - top);
501 const T& invRl = 1.0 / (right - left);
503 mat<C, R, T> res = mat<C, R, T>::zero();
504 res[0][0] = width * invRl;
505 res[2][0] = -width * left * invRl;
506 res[1][1] = height * invBt;
507 res[2][1] = -height * top * invBt;
513 static _MSTD_CONSTEXPR20 mat<C, R, T> symetric_screen(
const T& right,
const T& top,
const T& width,
515 return screen(-right, right, -top, top, width, height);
520 #pragma region PREDEFINED_MATRIX_4x4
524 T cosA =
static_cast<T>(std::cos(radians));
525 T sinA =
static_cast<T>(std::sin(radians));
528 mat<C, R, T> res = mat<C, R, T>::identity();
539 T cosA =
static_cast<T>(std::cos(radians));
540 T sinA =
static_cast<T>(std::sin(radians));
543 mat<C, R, T> res = mat<C, R, T>::identity();
554 T cosA =
static_cast<T>(std::cos(radians));
555 T sinA =
static_cast<T>(std::sin(radians));
558 mat<C, R, T> res = mat<C, R, T>::identity();
569 const T& sinA =
static_cast<T>(std::sin(radians));
570 const T& cosA =
static_cast<T>(std::cos(radians));
571 const T& oneMinCosA =
static_cast<T>(1) - cosA;
573 vec<R - 1, T> normAxis = axis;
574 if (!normAxis.is_zero()) { normAxis.normalize(); }
576 mat<C, R, T> res = mat<C, R, T>::identity();
577 res[0][0] = (normAxis[0] * normAxis[0]) + (cosA * (1 - (normAxis[0] * normAxis[0])));
578 res[0][1] = ((normAxis[0] * normAxis[1]) * oneMinCosA) - (sinA * normAxis[2]);
579 res[0][2] = ((normAxis[0] * normAxis[2]) * oneMinCosA) - (sinA * normAxis[1]);
581 res[1][0] = ((normAxis[0] * normAxis[1]) * oneMinCosA) + (sinA * normAxis[2]);
582 res[1][1] = (normAxis[1] * normAxis[1]) + (cosA * (1 - (normAxis[1] * normAxis[1])));
583 res[1][2] = ((normAxis[1] * normAxis[2]) * oneMinCosA) - (sinA * normAxis[0]);
585 res[2][0] = ((normAxis[0] * normAxis[2]) * oneMinCosA) - (sinA * normAxis[1]);
586 res[2][1] = ((normAxis[1] * normAxis[2]) * oneMinCosA) + (sinA * normAxis[0]);
587 res[2][2] = (normAxis[2] * normAxis[2]) + (cosA * (1 - (normAxis[2] * normAxis[2])));
597 const T& x2 = quaternion.v[0] * quaternion.v[0];
598 const T& y2 = quaternion.v[1] * quaternion.v[1];
599 const T& z2 = quaternion.v[2] * quaternion.v[2];
601 const T& sx = quaternion.s * quaternion.v[0];
602 const T& sy = quaternion.s * quaternion.v[1];
603 const T& sz = quaternion.s * quaternion.v[2];
604 const T& xy = quaternion.v[0] * quaternion.v[1];
605 const T& xz = quaternion.v[0] * quaternion.v[2];
606 const T& yz = quaternion.v[1] * quaternion.v[2];
608 mat<C, R, T> res = mat<C, R, T>::identity();
609 res[0][0] = 1.f - (two * (y2 + z2));
610 res[1][0] = two * (xy - sz);
611 res[2][0] = two * (xz + sy);
613 res[0][1] = two * (xy + sz);
614 res[1][1] = 1.f - (two * (x2 + z2));
615 res[2][1] = two * (yz - sx);
617 res[0][2] = two * (xz - sy);
618 res[1][2] = two * (yz + sx);
619 res[2][2] = 1.f - (two * (x2 + y2));
625 static _MSTD_CONSTEXPR20 mat<C, R, T> frustrum(
const T& left,
const T& right,
const T& bottom,
const T& top,
626 const T& near,
const T& far,
const T& resLeft =
static_cast<T>(-1),
const T& resRight =
static_cast<T>(1),
627 const T& resBottom =
static_cast<T>(-1),
const T& resTop =
static_cast<T>(1),
const T& resNear =
static_cast<T>(-1),
628 const T& resFar =
static_cast<T>(1))
_MSTD_REQUIRES(C == R && C == 4) {
629 const T& absNear = std::abs(near);
630 const T& absFar = std::abs(far);
632 const T& xDir = right > left ?
static_cast<T>(1) :
static_cast<T>(-1);
633 const T& yDir = top > bottom ?
static_cast<T>(1) :
static_cast<T>(-1);
634 const T& zDir = -(xDir * yDir);
636 const T& invRl = right == left ? 0.f : (1.f / (right - left));
637 const T& invTb = top == bottom ? 0.f : (1.f / (top - bottom));
638 const T& invFn = absFar == absNear ? 0.f : (1.f / (absFar - absNear));
641 res[0][0] = (resRight - resLeft) * absNear * invRl;
642 res[2][0] = ((resLeft * right) - (resRight * left)) * zDir * invRl;
643 res[1][1] = (resTop - resBottom) * absNear * invTb;
644 res[2][1] = ((resBottom * top) - (resTop * bottom)) * zDir * invTb;
645 res[2][2] = ((resFar * absFar) - (resNear * absNear)) * zDir * invFn;
646 res[3][2] = (resNear - resFar) * absNear * absFar * invFn;
654 static _MSTD_CONSTEXPR20 mat<C, R, T> symetric_frustrum(
const T& right,
const T& top,
const T& near,
const T& far,
655 const T& resRight =
static_cast<T>(1),
const T& resTop =
static_cast<T>(1),
const T& resNear =
static_cast<T>(-1),
656 const T& resFar =
static_cast<T>(1))
_MSTD_REQUIRES(C == R && C == 4) {
657 return frustrum(-right, right, -top, top, near, far, -resRight, resRight, -resTop, resTop, resNear, resFar);
662 static _MSTD_CONSTEXPR20 mat<C, R, T> perspective(
const T& fov,
const T& aspect,
const T& near,
const T& far,
663 bool rightPosX =
true,
bool topPosY =
true,
bool horizontalFov =
true,
const T& resRight =
static_cast<T>(1),
664 const T& resTop =
static_cast<T>(1),
const T& resNear =
static_cast<T>(-1),
665 const T& resFar =
static_cast<T>(1))
_MSTD_REQUIRES(C == R && C == 4) {
668 const T& absNear = std::abs(near);
669 const T& absFar = std::abs(far);
674 right =
static_cast<T>(std::tan(fov * half) * absNear);
675 top = aspect ==
static_cast<T>(0) ?
static_cast<T>(0) : (right / aspect);
678 top =
static_cast<T>(std::tan(fov * half) * absNear);
679 right = top * aspect;
682 return symetric_frustrum(rightPosX ? right : -right, topPosY ? top : -top, absNear, absFar, resRight, resTop, resNear,
688 static _MSTD_CONSTEXPR20 mat<C, R, T> ortographic(
const T& left,
const T& right,
const T& bottom,
const T& top,
689 const T& near,
const T& far,
const T& resLeft =
static_cast<T>(-1),
const T& resRight =
static_cast<T>(1),
690 const T& resBottom =
static_cast<T>(-1),
const T& resTop =
static_cast<T>(1),
const T& resNear =
static_cast<T>(-1),
691 const T& resFar =
static_cast<T>(1))
_MSTD_REQUIRES(C == R && C == 4) {
692 const T& absNear = std::abs(near);
693 const T& absFar = std::abs(far);
695 const T& xDir = right > left ?
static_cast<T>(1) :
static_cast<T>(-1);
696 const T& yDir = top > bottom ?
static_cast<T>(1) :
static_cast<T>(-1);
697 const T& zDir = -(xDir * yDir);
699 const T& invRl = right == left ? 0.0 : (1.0 / (right - left));
700 const T& invTb = top == bottom ? 0.0 : (1.0 / (top - bottom));
701 const T& invFn = absFar == absNear ? 0.0 : (1.0 / (absFar - absNear));
704 res[0][0] = (resRight - resLeft) * invRl;
705 res[3][0] = ((resLeft * right) - (resRight * left)) * invRl;
706 res[1][1] = (resTop - resBottom) * invTb;
707 res[3][1] = ((resBottom * top) - (resTop * bottom)) * invTb;
708 res[2][2] = (resFar - resNear) * zDir * invFn;
709 res[3][2] = ((resNear * absFar) - (resFar * absNear)) * invFn;
716 static _MSTD_CONSTEXPR20 mat<C, R, T> symetric_ortographic(
const T& right,
const T& top,
const T& near,
const T& far,
717 const T& resRight =
static_cast<T>(1),
const T& resTop =
static_cast<T>(1),
const T& resNear =
static_cast<T>(-1),
718 const T& resFar =
static_cast<T>(1))
_MSTD_REQUIRES(C == R && C == 4) {
719 return ortographic(-right, right, -top, top, near, far, -resRight, resRight, -resTop, resTop, resNear, resFar);
724 static _MSTD_CONSTEXPR20 mat<C, R, T> view(
const vec<3ull, T>& pos,
const vec<3ull, T>& right,
725 const vec<3ull, T>& forward,
const vec<3ull, T>& up)
_MSTD_REQUIRES(C == R && C == 4) {
727 res[0] = vec4(right[0], up[0], -forward[0], T(0));
728 res[1] = vec4(right[1], up[1], -forward[1], T(0));
729 res[2] = vec4(right[2], up[2], -forward[2], T(0));
730 res[3] = vec4(-pos[0], -pos[1], -pos[2], T(1));
736 static _MSTD_CONSTEXPR20 mat<C, R, T> look_at(
const vec<3ull, T>& eyePos,
const vec<3ull, T>& lookAtPos,
738 using vec3_type = vec<3ull, T>;
740 vec3_type forward = (lookAtPos - eyePos).normalize();
741 vec3_type normWorldUp = worldUp.normalized();
742 vec3_type right = forward.cross(worldUp);
743 vec3_type up = right.cross(forward);
745 return view(eyePos, right, forward, up);
752 #pragma region PREDEFINED_CHECKS
754 _MSTD_CONSTEXPR20 bool is_zero()
const {
return is_filled_with(
static_cast<T>(0)); }
759 for (size_t x = 0; x != C; ++x) {
760 for (size_t y = 0; y != R; ++y) {
761 if (_values[x][y] != value) {
return false; }
767 #pragma region PREDEFINED_SQUARE_MATRIX_CHECKS
775 for (size_t x = 0; x != C; ++x) {
776 for (size_t y = 0; y != R; ++y) {
777 if ((x == y && mstd::is_not_equal(_values[x][y], value)) ||
778 (x != y && mstd::is_not_equal(_values[x][y],
static_cast<T>(0)))) {
789 #pragma region MATRIX_OPERATIONS
793 for (size_t x = 0; x != C; ++x) {
794 for (size_t y = 0; y != R; ++y) { res[y][x] = _values[x][y]; }
801 mat<C - 1, R - 1, T> res;
802 for (size_t x = 0, subX = 0; x != C; ++x) {
803 if (x == colIdx) {
continue; }
808 std::copy_n(_values[x], std::min(rowIdx, R - 1),
static_cast<T*>(res[subX]));
812 if (rowIdx != R - 1) {
813 std::copy_n(_values[x] + rowIdx + 1, R - rowIdx - 1,
static_cast<T*>(res[subX]) + subY);
821 mat<C, R - 1, T>) get_sub_row_matrix(size_t rowIdx)
const _MSTD_REQUIRES(R > 1) {
822 mat<C, R - 1, T> res;
823 for (size_t x = 0; x != C; ++x) {
828 std::copy_n(_values[x], std::min(rowIdx, R - 1),
static_cast<T*>(res[x]));
832 if (rowIdx != R - 1) {
833 std::copy_n(_values[x] + rowIdx + 1, R - 1 - rowIdx,
static_cast<T*>(res[x]) + subY);
840 mat<C - 1, R, T>) get_sub_col_matrix(size_t colIdx)
const _MSTD_REQUIRES(C > 1) {
841 mat<C - 1, R, T> res;
842 for (size_t x = 0, subX = 0; x != C; ++x) {
843 if (x == colIdx) {
continue; }
846 std::copy_n(_values[x], R,
static_cast<T*>(res[subX]));
853 for (size_t x = 0; x != C; ++x) {
854 for (size_t y = 0; y != R; ++y) { _values[x][y] = std::clamp(_values[x][y], minVal, maxVal); }
859 _MSTD_CONSTEXPR20 mat<C, R, T> clampped(
const T& minVal,
const T& maxVal)
const {
860 mat<C, R, T> res = *
this;
861 return res.clamp(minVal, maxVal);
864 _MSTD_CONSTEXPR20 mat<C, R, T>& clamp(
const mat<C, R, T>& minVal,
const mat<C, R, T>& maxVal) {
865 for (size_t x = 0; x != C; ++x) {
866 for (size_t y = 0; y != R; ++y) { _values[x][y] = std::clamp(_values[x][y], minVal[x][y], maxVal[x][y]); }
871 _MSTD_CONSTEXPR20 mat<C, R, T> clampped(
const mat<C, R, T>& minVal,
const mat<C, R, T>& maxVal)
const {
872 mat<C, R, T> res = *
this;
873 return res.clamp(minVal, maxVal);
876 #pragma region SQUARE_MATRIX_OPERATIONS
880 for (size_t y = 0; y != R; ++y) {
881 for (size_t x = 0; x != C; ++x) {
882 if (x == y) {
break; }
884 T temp = _values[x][y];
885 _values[x][y] = _values[y][x];
886 _values[y][x] = temp;
896 else if _MSTD_CONSTEXPR17 (R == 2) {
return (_values[0][0] * _values[1][1]) - (_values[0][1] * _values[1][0]); }
899 if (_values[0][0] !=
static_cast<T>(0)) {
900 det += _values[0][0] * ((_values[1][1] * _values[2][2]) - (_values[2][1] * _values[1][2]));
902 if (_values[1][0] !=
static_cast<T>(0)) {
903 det += _values[1][0] * ((_values[2][1] * _values[0][2]) - (_values[0][1] * _values[2][2]));
905 if (_values[2][0] !=
static_cast<T>(0)) {
906 det += _values[2][0] * ((_values[0][1] * _values[1][2]) - (_values[1][1] * _values[0][2]));
912 if (_values[0][0] !=
static_cast<T>(0)) {
913 det += _values[0][0] *
914 ((_values[1][1] * ((_values[2][2] * _values[3][3]) - (_values[3][2] * _values[2][3]))) +
915 (_values[2][1] * ((_values[3][2] * _values[1][3]) - (_values[1][2] * _values[3][3]))) +
916 (_values[3][1] * ((_values[1][2] * _values[2][3]) - (_values[2][2] * _values[1][3]))));
918 if (_values[0][1] !=
static_cast<T>(0)) {
919 det -= _values[1][0] *
920 ((_values[0][1] * ((_values[2][2] * _values[3][3]) - (_values[3][2] * _values[2][3]))) +
921 (_values[2][1] * ((_values[3][2] * _values[0][3]) - (_values[0][2] * _values[3][3]))) +
922 (_values[3][1] * ((_values[0][2] * _values[2][3]) - (_values[2][2] * _values[0][3]))));
924 if (_values[2][0] !=
static_cast<T>(0)) {
925 det += _values[2][0] *
926 ((_values[0][1] * ((_values[1][2] * _values[3][3]) - (_values[3][2] * _values[1][3]))) +
927 (_values[1][1] * ((_values[3][2] * _values[0][3]) - (_values[0][2] * _values[3][3]))) +
928 (_values[3][1] * ((_values[0][2] * _values[1][3]) - (_values[1][2] * _values[0][3]))));
930 if (_values[3][0] !=
static_cast<T>(0)) {
931 det -= _values[3][0] *
932 ((_values[0][1] * ((_values[1][2] * _values[2][3]) - (_values[2][2] * _values[1][3]))) +
933 (_values[1][1] * ((_values[2][2] * _values[0][3]) - (_values[0][2] * _values[2][3]))) +
934 (_values[2][1] * ((_values[0][2] * _values[1][3]) - (_values[1][2] * _values[0][3]))));
941 for (size_t x = 0; x != C; ++x) {
942 if (_values[x][0] !=
static_cast<T>(0)) {
944 mat<C - 1, R - 1, T> subMat = get_sub_matrix(0, x);
947 T subDet = subMat.determinant();
950 det += sign * _values[x][0] * subDet;
971 T det = determinant();
973 T invD =
static_cast<T>(det ==
static_cast<T>(0) ? 0.0 : (1.0 / det));
979 res[0][0] = _values[1][1] * invD;
980 res[1][0] = -_values[1][0] * invD;
981 res[0][1] = -_values[0][1] * invD;
982 res[1][1] = _values[0][0] * invD;
985 res[0][0] = ((_values[1][1] * _values[2][2]) - (_values[2][1] * _values[1][2])) * invD;
986 res[1][0] = ((_values[2][0] * _values[1][2]) - (_values[1][0] * _values[2][2])) * invD;
987 res[2][0] = ((_values[1][0] * _values[2][1]) - (_values[2][0] * _values[1][1])) * invD;
988 res[0][1] = ((_values[0][2] * _values[2][1]) - (_values[0][1] * _values[2][2])) * invD;
989 res[1][1] = ((_values[0][0] * _values[2][2]) - (_values[2][0] * _values[0][2])) * invD;
990 res[2][1] = ((_values[2][0] * _values[0][1]) - (_values[0][0] * _values[2][1])) * invD;
991 res[0][2] = ((_values[0][1] * _values[1][2]) - (_values[1][1] * _values[0][2])) * invD;
992 res[1][2] = ((_values[1][0] * _values[0][2]) - (_values[0][0] * _values[1][2])) * invD;
993 res[2][2] = ((_values[0][0] * _values[1][1]) - (_values[0][1] * _values[1][0])) * invD;
999 const mat<R, C, T>& trans = transposed();
1000 for (size_t x = 0; x != C; ++x) {
1001 for (size_t y = 0; y != R; ++y) {
1003 mat<R - 1, C - 1, T> subMat = get_sub_matrix(y, x);
1009 T subDet = subMat.determinant();
1012 if (subDet !=
static_cast<T>(0)) {
1014 res[x][y] = ((x + y) % 2 == 0 ? 1 : -1) * subDet * invD;
1027 #pragma region OPERATORS
1030 for (size_t x = 0; x != C; ++x) {
1031 for (size_t y = 0; y != R; ++y) { _values[x][y] += other[x][y]; }
1037 for (size_t x = 0; x != C; ++x) {
1038 for (size_t y = 0; y != R; ++y) { _values[x][y] -= other[x][y]; }
1044 for (size_t x = 0; x != C; ++x) {
1045 for (size_t y = 0; y != R; ++y) { _values[x][y] += other; }
1051 for (size_t x = 0; x != C; ++x) {
1052 for (size_t y = 0; y != R; ++y) { _values[x][y] -= other; }
1058 for (size_t x = 0; x != C; ++x) {
1059 for (size_t y = 0; y != R; ++y) { _values[x][y] *= other; }
1065 if (other ==
static_cast<T>(0)) {
return *
this; }
1066 for (size_t x = 0; x != C; ++x) {
1067 for (size_t y = 0; y != R; ++y) { _values[x][y] /= other; }
1073 mat<C, R, T> res = *
this;
1079 mat<C, R, T> res = *
this;
1087 for (size_t x = 0; x != OC; ++x) {
1088 for (size_t y = 0; y != R; ++y) {
1089 for (size_t i = 0; i != C; ++i) { res[x][y] += _values[i][y] * other[x][i]; }
1096 mat<C, R, T> res = *
this;
1102 mat<C, R, T> res = *
this;
1108 mat<C, R, T> res = *
this;
1113 friend _MSTD_CONSTEXPR20 mat<C, R, T> operator*(
const T& other,
const mat<C, R, T>& matrix) {
return matrix * other; }
1116 mat<C, R, T> res = *
this;
1123 for (size_t y = 0; y != R; ++y) {
1124 for (size_t x = 0; x != C; ++x) { res[y] += _values[x][y] * other[x]; }
1129 _MSTD_CONSTEXPR20 mat<C, R, T> operator+()
const {
return mat<C, R, T>(*
this); }
1137 template<size_t OC, size_t OR>
1141 for (size_t x = 0; x != C; ++x) {
1142 if (std::memcmp(_values[x], other[x], R *
sizeof(T)) != 0) {
return false; }
1148 template<size_t OC, size_t OR>
1150 return !(*
this == other);
1159 friend std::ostream& operator<<(std::ostream& str,
const mat<C, R, T>& matrix) {
1161 static _MSTD_CONSTEXPR17 const char left_bottom_corner =
static_cast<
char>(0xC0);
1164 static _MSTD_CONSTEXPR17 const char right_bottom_corner =
static_cast<
char>(0xD9);
1166 size_t cellWidth = 0;
1168 for (size_t y = 0; y != R; ++y) {
1169 for (size_t x = 0; x != C; ++x) {
1170 std::ostringstream oss;
1171 oss << matrix[y][x];
1172 cellWidth = std::max(cellWidth, oss.str().size());
1176 for (size_t y = 0; y != R; ++y) {
1178 if (y == 0) { str << left_top_corner; }
1179 else if (y == R - 1) { str << left_bottom_corner; }
1180 else { str << side; }
1182 else { str << side; }
1185 for (size_t x = 0; x != C; ++x) {
1186 str << std::setw(cellWidth) << matrix[x][y];
1191 if (y == 0) { str << right_top_corner; }
1192 else if (y == R - 1) { str << right_bottom_corner; }
1193 else { str << side; }
1195 else { str << side; }
1197 if (y != R - 1) { str << std::endl; }
1202 #pragma region SQUARE_MATRIX_OPERATORS
1206 *
this = *
this * other;
1213 *
this *= other.inverted();
1220 mat<C, R, T> res = *
this;