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]);
371 T
const invDet = T(1) / det;
387 A[1][1] * A[2][2] - A[1][2] * A[2][1],
388 A[0][2] * A[2][1] - A[0][1] * A[2][2],
389 A[0][1] * A[1][2] - A[0][2] * A[1][1]},
391 A[1][2] * A[2][0] - A[1][0] * A[2][2],
392 A[0][0] * A[2][2] - A[0][2] * A[2][0],
393 A[0][2] * A[1][0] - A[0][0] * A[1][2]},
395 A[1][0] * A[2][1] - A[1][1] * A[2][0],
396 A[0][1] * A[2][0] - A[0][0] * A[2][1],
397 A[0][0] * A[1][1] - A[0][1] * A[1][0]}};
398 return cofactorTranspose / det;
406 (*outInv)[0] =
DotMatVec(coef_1, at[1]) / coef_2;
407 (*outInv)[1] = -
DotMatVec(coef_1, at[0]) / coef_2;
413Minor4x4(T
const m[16],
int r0,
int r1,
int r2,
int c0,
int c1,
int c2) {
414 return m[4 * r0 + c0] * (m[4 * r1 + c1] * m[4 * r2 + c2] - m[4 * r2 + c1] * m[4 * r1 + c2]) -
415 m[4 * r0 + c1] * (m[4 * r1 + c0] * m[4 * r2 + c2] - m[4 * r2 + c0] * m[4 * r1 + c2]) +
416 m[4 * r0 + c2] * (m[4 * r1 + c0] * m[4 * r2 + c1] - m[4 * r2 + c0] * m[4 * r1 + c1]);
421 adjOut[0] =
Minor4x4(m, 1, 2, 3, 1, 2, 3);
422 adjOut[1] = -
Minor4x4(m, 0, 2, 3, 1, 2, 3);
423 adjOut[2] =
Minor4x4(m, 0, 1, 3, 1, 2, 3);
424 adjOut[3] = -
Minor4x4(m, 0, 1, 2, 1, 2, 3);
425 adjOut[4] = -
Minor4x4(m, 1, 2, 3, 0, 2, 3);
426 adjOut[5] =
Minor4x4(m, 0, 2, 3, 0, 2, 3);
427 adjOut[6] = -
Minor4x4(m, 0, 1, 3, 0, 2, 3);
428 adjOut[7] =
Minor4x4(m, 0, 1, 2, 0, 2, 3);
429 adjOut[8] =
Minor4x4(m, 1, 2, 3, 0, 1, 3);
430 adjOut[9] = -
Minor4x4(m, 0, 2, 3, 0, 1, 3);
431 adjOut[10] =
Minor4x4(m, 0, 1, 3, 0, 1, 3);
432 adjOut[11] = -
Minor4x4(m, 0, 1, 2, 0, 1, 3);
433 adjOut[12] = -
Minor4x4(m, 1, 2, 3, 0, 1, 2);
434 adjOut[13] =
Minor4x4(m, 0, 2, 3, 0, 1, 2);
435 adjOut[14] = -
Minor4x4(m, 0, 1, 3, 0, 1, 2);
436 adjOut[15] =
Minor4x4(m, 0, 1, 2, 0, 1, 2);
440inline constexpr T
Det4x4(T
const m[16]) {
441 return m[0] *
Minor4x4(m, 1, 2, 3, 1, 2, 3) - m[1] *
Minor4x4(m, 1, 2, 3, 0, 2, 3) +
442 m[2] *
Minor4x4(m, 1, 2, 3, 0, 1, 3) - m[3] *
Minor4x4(m, 1, 2, 3, 0, 1, 2);
453 T inv_det = T(1) / det;
454 for (
int i = 0; i < 16; ++i) {
455 invOut[i] = invOut[i] * inv_det;
472 InvertRowMajor4x4(
reinterpret_cast<T const*
>(&A[0]),
reinterpret_cast<T*
>(&out[0]));
505#if MOCHI_ASSERT_VERBOSE_ENABLED
509 (mat[0][3] == 0) && (mat[1][3] == 0) && (mat[2][3] == 0) && (mat[3][3] == 1),
510 "Expected a transformation matrix where the last column is {0, 0, 0, 1}");
519 "Expected a transformation matrix with orthogonal basis vectors");
533 auto sizeSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
536 "Transformation matrix has degenerate scale on at least one axis");
561template <
size_t N,
typename T>
564 for (
size_t i = 0; i < result.
size(); ++i) {
565 result[i][i] = valueOnDiagonal;
570template <
size_t N,
typename T>
573 for (
size_t i = 0; i < result.
size(); ++i) {
574 result[i][i] = diagonalVector[i];
584template <
size_t N,
typename T>
590template <
size_t N,
typename T>
592 static_assert(N >= 1 && N <= 4,
"Requires 1-4 rows");
596 if constexpr (N >= 1) {
599 if constexpr (N >= 2) {
602 if constexpr (N >= 3) {
605 if constexpr (N == 4) {
611template <
size_t N,
typename T>
616template <
size_t N,
typename T>
627 return A[0][0] * A[1][1] - A[0][1] * A[1][0];
633 A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
634 A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
635 A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
643template <
typename T,
size_t N>
645 static_assert(N == 3 || N == 4,
"Expected a 3x3 or 4x4 Simd matrix");
658 auto const result = A[0] * (a * b - c * d);
663template <
typename T,
size_t N>
670 return A[0] * A[3] - A[1] * A[2];
676template <
typename T,
size_t N,
size_t M>
679 for (
size_t i = 0; i < M; ++i) {
680 for (
size_t j = 0; j < N; ++j) {
681 result[i][j] = mat[j][i];
709template <
typename T,
size_t D0>
711 static_assert(D0 == 3 || D0 == 4,
"Expected 3x3 or 4x3 matrix");
737 mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1],
738 mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2],
739 mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]},
741 mat[0][2] * mat[2][1] - mat[0][1] * mat[2][2],
742 mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0],
743 mat[0][1] * mat[2][0] - mat[0][0] * mat[2][1]},
745 mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1],
746 mat[0][2] * mat[1][0] - mat[0][0] * mat[1][2],
747 mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]}};
772 auto const a2 = mat[1];
779 auto const d2 = mat[2];
784 auto const e2 = mat[0];
788 auto const a1b1 = a1 * b1;
789 auto const a2b2 = a2 * b2;
790 auto const c1d1 = c1 * d1;
791 auto const c2d2 = c2 * d2;
792 auto const e1f1 = e1 * f1;
793 auto const e2f2 = e2 * f2;
833template <
typename T,
size_t DimTotal,
size_t DimTrace>
835 static_assert(DimTrace <= DimTotal,
"Invalid dimensions");
836 static_assert(DimTotal >= 1,
"Invalid dimensions");
837 static_assert(DimTrace >= 1,
"Invalid dimensions");
839 if constexpr (DimTrace >= 1) {
842 if constexpr (DimTrace >= 2) {
845 if constexpr (DimTrace >= 3) {
848 if constexpr (DimTrace >= 4) {
851 if constexpr (DimTrace >= 5) {
852 for (
int i = 4; i < DimTrace; ++i) {
861 return mat[0] + mat[3];
899 matrix[2][1] - matrix[1][2], matrix[0][2] - matrix[2][0], matrix[1][0] - matrix[0][1]};
920 T
const vNorm =
Norm<3>(v) + std::numeric_limits<T>::min();
925template <
typename T,
size_t N>
930template <
typename T,
size_t N>
932 constexpr auto kMin = std::numeric_limits<ScalarType<T>>::min();
933 static_assert(kMin > 0);
934 T
const invNorm = T(1) / (
Sqrt(sqrNorm) + T(kMin));
937 for (
size_t i = 0; i < N; ++i) {
938 for (
size_t j = 0; j < N; ++j) {
939 result[i][j] = -n[i] * n[j] * invNorm;
941 result[i][i] += invNorm;
952template <
typename T,
size_t D0,
size_t D1>
956 for (
size_t i = 0; i < D0; ++i) {
961 auto index =
ArgMax(sqrNorms);
964 if (sqrNorm !=
nullptr) {
965 *sqrNorm = sqrNorms[index];
978 Vec4r entriesSqr = A * A;
980 Vec4r normSqr = entriesSqr + temp0;
985 if (r1NormSqr > r2NormSqr) {
986 outNormSqr = r1NormSqr;
989 outNormSqr = r2NormSqr;
1001 Vec4r diagSqr = A[0] * A[0];
1002 Vec4r offdSqr = A[1] * A[1];
1005 Vec4r normSqr = diagSqr + temp0 + temp1;
1009 if (max ==
Get<0>(normSqr)) {
1012 }
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)
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 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)