29template <
typename T,
size_t N,
size_t M>
32 for (
int i = 0; i < N; ++i) {
33 accum +=
Dot(a[i], a[i]);
38template <
typename T,
size_t N,
size_t M>
43template <
typename T,
size_t D0,
int D1, MOCHI_CONCEPT_DEF(D0 >= 3 && D1 >= 3)>
45 return HSum<3>(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
48template <
typename T,
size_t D0,
int D1, MOCHI_CONCEPT_DEF(D0 >= 3 && D1 >= 3)>
57template <
typename T,
size_t N,
size_t M>
62 for (
size_t i = 0; i < result.
size(); ++i) {
63 result[i] =
Dot(a[i], b);
68template <
typename T,
size_t N,
size_t M>
71 for (
size_t i = 0; i < out.
size(); ++i) {
72 out[i] =
Dot(b, a[i]);
76template <
typename T,
size_t N,
size_t M>
88 a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2],
89 a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2],
90 a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2]};
93template <
size_t N,
typename T,
size_t D0>
95 static_assert(D0 >= 3,
"Requires a matrix with at least 3 rows");
96 auto const a =
VDot<N>(m[0], v);
97 auto const b =
VDot<N>(m[1], v);
98 auto const c =
VDot<N>(m[2], v);
102template <
typename T,
size_t D0>
109 auto a =
VDot(m[0], v);
110 auto b =
VDot(m[1], v);
111 auto c =
VDot(m[2], v);
112 auto d =
VDot(m[3], v);
122template <
typename T,
size_t N,
size_t M>
126 if constexpr (N == 3 && M == 3) {
128 a[0] * b[0][0] + a[1] * b[1][0] + a[2] * b[2][0],
129 a[0] * b[0][1] + a[1] * b[1][1] + a[2] * b[2][1],
130 a[0] * b[0][2] + a[1] * b[1][2] + a[2] * b[2][2]};
143 return temp0 + temp1;
146template <
typename T,
size_t D0>
148 static_assert(D0 == 3 || D0 == 4,
"Requires a matrix with 3 or 4 rows");
162template <
typename T,
size_t N,
size_t M,
size_t L>
168 for (
int n = 0; n < N; ++n) {
188 a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0],
189 a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1],
190 a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]},
192 a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0],
193 a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1],
194 a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]},
196 a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0],
197 a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1],
198 a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]}};
201template <
typename T,
size_t D0A,
size_t D0B>
214 return a0 * b0 + a1 * b1;
275 for (
int i = 0; i < 3; ++i) {
276 result[i] =
Outer3(mat[i], vec);
286 for (
int i = 0; i < 3; ++i) {
299 for (
int i = 0; i < 3; ++i) {
312 for (
int i = 0; i < 3; ++i) {
329 for (
int i = 0; i < 2; i++) {
330 for (
int j = 0; j < 2; j++) {
331 result[i][j] = a[2 * i + j] * b;
344 for (
int i = 0; i < 3; ++i) {
345 result +=
Dot<3>(A[i], B[i]);
350template <
typename T,
size_t N,
size_t M>
353 for (
size_t i = 0; i < N; ++i) {
354 result +=
Dot(A[i], B[i]);
361 return A[0] * B[0] + T{2_r} * A[1] * B[1] + A[2] * B[2];
376 T
const invDet = T(1) / det;
392 A[1][1] * A[2][2] - A[1][2] * A[2][1],
393 A[0][2] * A[2][1] - A[0][1] * A[2][2],
394 A[0][1] * A[1][2] - A[0][2] * A[1][1]},
396 A[1][2] * A[2][0] - A[1][0] * A[2][2],
397 A[0][0] * A[2][2] - A[0][2] * A[2][0],
398 A[0][2] * A[1][0] - A[0][0] * A[1][2]},
400 A[1][0] * A[2][1] - A[1][1] * A[2][0],
401 A[0][1] * A[2][0] - A[0][0] * A[2][1],
402 A[0][0] * A[1][1] - A[0][1] * A[1][0]}};
403 return cofactorTranspose / det;
411 (*outInv)[0] =
DotMatVec(coef_1, at[1]) / coef_2;
412 (*outInv)[1] = -
DotMatVec(coef_1, at[0]) / coef_2;
418Minor4x4(T
const m[16],
int r0,
int r1,
int r2,
int c0,
int c1,
int c2) {
419 return m[4 * r0 + c0] * (m[4 * r1 + c1] * m[4 * r2 + c2] - m[4 * r2 + c1] * m[4 * r1 + c2]) -
420 m[4 * r0 + c1] * (m[4 * r1 + c0] * m[4 * r2 + c2] - m[4 * r2 + c0] * m[4 * r1 + c2]) +
421 m[4 * r0 + c2] * (m[4 * r1 + c0] * m[4 * r2 + c1] - m[4 * r2 + c0] * m[4 * r1 + c1]);
426 adjOut[0] =
Minor4x4(m, 1, 2, 3, 1, 2, 3);
427 adjOut[1] = -
Minor4x4(m, 0, 2, 3, 1, 2, 3);
428 adjOut[2] =
Minor4x4(m, 0, 1, 3, 1, 2, 3);
429 adjOut[3] = -
Minor4x4(m, 0, 1, 2, 1, 2, 3);
430 adjOut[4] = -
Minor4x4(m, 1, 2, 3, 0, 2, 3);
431 adjOut[5] =
Minor4x4(m, 0, 2, 3, 0, 2, 3);
432 adjOut[6] = -
Minor4x4(m, 0, 1, 3, 0, 2, 3);
433 adjOut[7] =
Minor4x4(m, 0, 1, 2, 0, 2, 3);
434 adjOut[8] =
Minor4x4(m, 1, 2, 3, 0, 1, 3);
435 adjOut[9] = -
Minor4x4(m, 0, 2, 3, 0, 1, 3);
436 adjOut[10] =
Minor4x4(m, 0, 1, 3, 0, 1, 3);
437 adjOut[11] = -
Minor4x4(m, 0, 1, 2, 0, 1, 3);
438 adjOut[12] = -
Minor4x4(m, 1, 2, 3, 0, 1, 2);
439 adjOut[13] =
Minor4x4(m, 0, 2, 3, 0, 1, 2);
440 adjOut[14] = -
Minor4x4(m, 0, 1, 3, 0, 1, 2);
441 adjOut[15] =
Minor4x4(m, 0, 1, 2, 0, 1, 2);
445inline constexpr T
Det4x4(T
const m[16]) {
446 return m[0] *
Minor4x4(m, 1, 2, 3, 1, 2, 3) - m[1] *
Minor4x4(m, 1, 2, 3, 0, 2, 3) +
447 m[2] *
Minor4x4(m, 1, 2, 3, 0, 1, 3) - m[3] *
Minor4x4(m, 1, 2, 3, 0, 1, 2);
458 T inv_det = T(1) / det;
459 for (
int i = 0; i < 16; ++i) {
460 invOut[i] = invOut[i] * inv_det;
477 InvertRowMajor4x4(
reinterpret_cast<T const*
>(&A[0]),
reinterpret_cast<T*
>(&out[0]));
510#if MOCHI_ASSERT_VERBOSE_ENABLED
514 (mat[0][3] == 0) && (mat[1][3] == 0) && (mat[2][3] == 0) && (mat[3][3] == 1),
515 "Expected a transformation matrix where the last column is {0, 0, 0, 1}");
524 "Expected a transformation matrix with orthogonal basis vectors");
538 auto sizeSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
541 "Transformation matrix has degenerate scale on at least one axis");
566template <
size_t N,
typename T>
569 for (
size_t i = 0; i < result.
size(); ++i) {
570 result[i][i] = valueOnDiagonal;
575template <
size_t N,
typename T>
578 for (
size_t i = 0; i < result.
size(); ++i) {
579 result[i][i] = diagonalVector[i];
586 return {a00, a01, a11};
591 return {m[0][0], T{0.5_r} * (m[0][1] + m[1][0]), m[1][1]};
599template <
size_t N,
typename T>
605template <
size_t N,
typename T>
607 static_assert(N >= 1 && N <= 4,
"Requires 1-4 rows");
611 if constexpr (N >= 1) {
614 if constexpr (N >= 2) {
617 if constexpr (N >= 3) {
620 if constexpr (N == 4) {
626template <
size_t N,
typename T>
631template <
size_t N,
typename T>
642 return A[0][0] * A[1][1] - A[0][1] * A[1][0];
648 A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
649 A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
650 A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
658template <
typename T,
size_t N>
660 static_assert(N == 3 || N == 4,
"Expected a 3x3 or 4x4 Simd matrix");
673 auto const result = A[0] * (a * b - c * d);
678template <
typename T,
size_t N>
685 return A[0] * A[3] - A[1] * A[2];
691template <
typename T,
size_t N,
size_t M>
694 for (
size_t i = 0; i < M; ++i) {
695 for (
size_t j = 0; j < N; ++j) {
696 result[i][j] = mat[j][i];
724template <
typename T,
size_t D0>
726 static_assert(D0 == 3 || D0 == 4,
"Expected 3x3 or 4x3 matrix");
752 mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1],
753 mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2],
754 mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]},
756 mat[0][2] * mat[2][1] - mat[0][1] * mat[2][2],
757 mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0],
758 mat[0][1] * mat[2][0] - mat[0][0] * mat[2][1]},
760 mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1],
761 mat[0][2] * mat[1][0] - mat[0][0] * mat[1][2],
762 mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]}};
787 auto const a2 = mat[1];
794 auto const d2 = mat[2];
799 auto const e2 = mat[0];
803 auto const a1b1 = a1 * b1;
804 auto const a2b2 = a2 * b2;
805 auto const c1d1 = c1 * d1;
806 auto const c2d2 = c2 * d2;
807 auto const e1f1 = e1 * f1;
808 auto const e2f2 = e2 * f2;
848template <
typename T,
size_t DimTotal,
size_t DimTrace>
850 static_assert(DimTrace <= DimTotal,
"Invalid dimensions");
851 static_assert(DimTotal >= 1,
"Invalid dimensions");
852 static_assert(DimTrace >= 1,
"Invalid dimensions");
854 if constexpr (DimTrace >= 1) {
857 if constexpr (DimTrace >= 2) {
860 if constexpr (DimTrace >= 3) {
863 if constexpr (DimTrace >= 4) {
866 if constexpr (DimTrace >= 5) {
867 for (
int i = 4; i < DimTrace; ++i) {
876 return mat[0] + mat[3];
914 matrix[2][1] - matrix[1][2], matrix[0][2] - matrix[2][0], matrix[1][0] - matrix[0][1]};
935 T
const vNorm =
Norm<3>(v) + std::numeric_limits<T>::min();
940template <
typename T,
size_t N>
945template <
typename T,
size_t N>
947 constexpr auto kMin = std::numeric_limits<ScalarType<T>>::min();
948 static_assert(kMin > 0);
949 T
const invNorm = T(1) / (
Sqrt(sqrNorm) + T(kMin));
952 for (
size_t i = 0; i < N; ++i) {
953 for (
size_t j = 0; j < N; ++j) {
954 result[i][j] = -n[i] * n[j] * invNorm;
956 result[i][i] += invNorm;
967template <
typename T,
size_t D0,
size_t D1>
971 for (
size_t i = 0; i < D0; ++i) {
976 auto index =
ArgMax(sqrNorms);
979 if (sqrNorm !=
nullptr) {
980 *sqrNorm = sqrNorms[index];
993 Vec4r entriesSqr = A * A;
995 Vec4r normSqr = entriesSqr + temp0;
1000 if (r1NormSqr > r2NormSqr) {
1001 outNormSqr = r1NormSqr;
1004 outNormSqr = r2NormSqr;
1016 Vec4r diagSqr = A[0] * A[0];
1017 Vec4r offdSqr = A[1] * A[1];
1020 Vec4r normSqr = diagSqr + temp0 + temp1;
1024 if (max ==
Get<0>(normSqr)) {
1027 }
else if (max ==
Get<1>(normSqr)) {
static constexpr int size()
constexpr SizeT size() const
#define MOCHI_ASSERT_VERBOSE(condition_without_side_effects,...)
constexpr NdArray< T, M > DotVecMat(NdArray< T, N > const &a, NdArray< T, N, M > const &b)
T Dot(Simd< T, N > a, Simd< T, N > b)
Simd< T, 2 > Shuffle(Simd< T, 2 > a)
constexpr T Trace(NdArray< T, DimTotal, DimTotal > const &mat)
constexpr NdArray< T, N, N > DNormalize(NdArray< T, N > const &v)
constexpr NdArray< T, 2, 2 > SymMatrix2x2(T a00, T a01, T a11)
NdArray< Simd< T, 4 >, 3 > DNormalize3(Simd< T, 4 > const &v)
Simd< T, 4 > Transpose2x2(Simd< T, 4 > const &m)
constexpr NdArray< T, 3 > Sym2x2Components(T a00, T a01, T a11)
T NormSqr(Simd< T, N > a)
NdArray< Simd< T, 4 >, 3 > Cofactor3x3(NdArray< Simd< T, 4 >, 3 > const &mat)
Simd< T, 4 > DotVecMat4x4(Simd< T, 4 > a, NdArray< Simd< T, 4 >, 4 > const &b)
Simd< T, 4 > Invert2x2(Simd< T, 4 > const &mat, T det)
NdArray< Simd< T, 4 >, 4 > InvertTransformation(NdArray< Simd< T, 4 >, 4 > const &mat)
constexpr Simd< T, 4 > InvSkew3(NdArray< Simd< T, 4 >, 3 > const &matrix)
constexpr T kDefaultNearEqualEpsilon
T Det2x2(Simd< T, 4 > const &A)
Simd< T, 4 > DotMatVec3xN(NdArray< Simd< T, 4 >, D0 > const &m, Simd< T, 4 > v)
constexpr auto LargestRow(NdArray< T, D0, D1 > const &A, T *sqrNorm=nullptr)
NdArray< Simd< T, 4 >, 3, 3 > VDSkew3()
constexpr NdArray< T, N > DotMatVec(NdArray< T, N, M > const &a, NdArray< T, M > const &b)
Simd< T, 4 > DotMatVec4x4(NdArray< Simd< T, 4 >, 4 > const &m, Simd< T, 4 > v)
Simd< T, N > Set(Simd< T, N > a, T value)
NdArray< Simd< T, 4 >, 3 > Transpose3x3(NdArray< Simd< T, 4 >, D0 > const &m)
NdArray< Simd< T, 4 >, 2 > CofactorSym3x3(NdArray< Simd< T, 4 >, 2 > const &mat)
NdArray< Simd< T, 4 >, 4 > InvertTransformationTransposed(NdArray< Simd< T, 4 >, 4 > const &mat)
Simd< real, 4 > VSymMatrix2x2r
Special case for the SIMD representation of a 2x2 symmetric matrix.
V Broadcast(typename V::Scalar a)
constexpr NdArray< T, M, N > Transpose(NdArray< T, N, M > const &mat)
auto LargestRowColSym2x2(VSymMatrix2x2r A, Vec4r &outNormSqr)
Simd< T, N > Blend(Simd< T, N > a, Simd< T, N > b)
constexpr NdArray< T, N, N > Eye()
TransformRT Invert(TransformRT const &a)
Simd< T, 4 > DotVecMat3x3(Simd< T, 4 > v, NdArray< Simd< T, 4 >, D0 > const &m)
constexpr T Colon(NdArray< T, N, M > const &A, NdArray< T, N, M > const &B)
constexpr T Minor4x4(T const m[16], int r0, int r1, int r2, int c0, int c1, int c2)
Simd< T, 4 > DotVecMat2x3(Simd< T, 4 > v, NdArray< Simd< T, 4 >, 2 > const &m)
NdArray< Simd< T, 4 >, 4 > Transpose4x4(NdArray< Simd< T, 4 >, 4 > const &m)
NdArray< Simd< T, 4 >, 2, 2 > Outer2(Simd< T, 4 > const &a, Simd< T, 4 > const &b)
void PseudoInvert(NdArray< T, 3, 2 > const &a, NdArray< T, 2, 3 > *outInv, T *outDet)
NdArray< Simd< T, 4 >, 4 > Dot4x4(NdArray< Simd< T, 4 >, 4 > const &a, NdArray< Simd< T, 4 >, 4 > const &b)
T Colon3x3(NdArray< Simd< T, 4 >, 3 > const &A, NdArray< Simd< T, 4 >, 3 > const &B)
constexpr T Det4x4(T const m[16])
NdArray< Simd< T, 4 >, 2 > OuterSym3(Simd< T, 4 > a, Simd< T, 4 > b)
auto LargestRowColSym3x3(VSymMatrix3x3r A, Vec4r &outNormSqr)
Simd< T, 4 > DotMatVec3x3(NdArray< Simd< T, 4 >, D0 > const &m, Simd< T, 4 > v)
Simd< T, 4 > Dot2x2(Simd< T, 4 > const &a, Simd< T, 4 > const &b)
constexpr NdArray< T, 3, 3 > Skew(NdArray< T, 3 > const &v)
constexpr NdArray< Simd< T, 4 >, 3 > Skew3(Simd< T, 4 > const &vector)
NdArray< Simd< T, 4 >, 3 > Invert3x3(NdArray< Simd< T, 4 >, 3 > const &mat)
constexpr size_t ArgMax(NdArray< T, N > const &a)
constexpr NdArray< T, 2, 2 > Cofactor(NdArray< T, 2, 2 > const &mat)
T Norm3x3(NdArray< Simd< T, D1 >, D0 > const &a)
T NormSqr3x3(NdArray< Simd< T, D1 >, D0 > const &a)
constexpr void Cofactor4x4(T const m[16], T adjOut[16])
Simd< T, 4 > CofactorSym2x2(Simd< T, 4 > const &mat)
constexpr NdArray< T, 2, 2 > Outer(NdArray< T, 2 > const &a, NdArray< T, 2 > const &b)
constexpr T Trace3x3(NdArray< Simd< T, 4 >, 3 > const &mat)
NdArray< Simd< T, 4 >, 3 > Outer3(Simd< T, 4 > a, Simd< T, 4 > b)
constexpr T ColonSym2x2(NdArray< T, 3 > const &A, NdArray< T, 3 > const &B)
constexpr void InvertRowMajor4x4(T const m[16], T invOut[16])
NdArray< Simd< real, 4 >, 2 > VSymMatrix3x3r
Special case for the SIMD representation of a 3x3 symmetric matrix.
NdArray< Simd< T, 4 >, N > VEye()
constexpr T Det(NdArray< T, 2, 2 > const &A)
bool NearEqual(TransformRT const &a, TransformRT const &b, real epsilon=kDefaultNearEqualEpsilon< real >)
constexpr NdArray< T, N, N > DiagonalMatrix(T valueOnDiagonal)
NdArray< Simd< T, 4 >, N > VDiagonalMatrix(T valueOnDiagonal)
constexpr T Trace2x2(Simd< T, 4 > const &mat)
Simd< T, N > Neg(Simd< T, N > a)
T Det3x3(NdArray< Simd< T, 4 >, N > const &A)
constexpr auto NearZero(T const &a, T epsilon=kDefaultNearEqualEpsilon< T >)
constexpr NdArray< Simd< T, 4 >, 4 > Invert4x4(NdArray< Simd< T, 4 >, 4 > const &A)
constexpr NdArray< T, 3 > Cross(NdArray< T, 3 > const &a, NdArray< T, 3 > const &b)
Simd< T, 4 > VDet3x3(NdArray< Simd< T, 4 >, N > const &A)
NdArray< Simd< T, 4 >, 3 > Dot3x3(NdArray< Simd< T, 4 >, D0A > const &a, NdArray< Simd< T, 4 >, D0B > const &b)