24 template <
typename Scalar>
41 if (init(mat.
size())) {
42 for (
unsigned r = 0; r < m_matrixSize; r++)
43 for (
unsigned c = 0; c < m_matrixSize; c++)
52 if (init(mat.
size())) {
53 for (
unsigned r = 0; r < m_matrixSize; r++)
54 for (
unsigned c = 0; c < m_matrixSize; c++)
67 unsigned size = (rotationOnly ? 3 : 4);
70 for (
unsigned r = 0; r <
size; r++)
71 for (
unsigned c = 0; c <
size; c++)
72 m_values[r][c] =
static_cast<Scalar
>(M16f[c * 4 + r]);
84 unsigned size = (rotationOnly ? 3 : 4);
87 for (
unsigned r = 0; r <
size; r++)
88 for (
unsigned c = 0; c <
size; c++)
89 m_values[r][c] =
static_cast<Scalar
>(M16d[c * 4 + r]);
106 assert(m_matrixSize <= 3);
107 for (
unsigned r = 0; r < m_matrixSize; r++)
108 for (
unsigned c = 0; c < m_matrixSize; c++)
110 static_cast<Scalar
>(mat.data[c * m_matrixSize + r]);
115 assert(m_matrixSize <= 4);
116 for (
unsigned r = 0; r < m_matrixSize; r++)
117 for (
unsigned c = 0; c < m_matrixSize; c++)
119 static_cast<Scalar
>(mat.data[c * m_matrixSize + r]);
124 memset(data, 0,
sizeof(Scalar) * m_matrixSize * m_matrixSize);
126 for (
unsigned r = 0; r < m_matrixSize; r++)
127 for (
unsigned c = 0; c < m_matrixSize; c++)
128 data[r + c * m_matrixSize] =
129 static_cast<double>(
m_values[r][c]);
133 inline unsigned size()
const {
return m_matrixSize; }
138 inline bool isValid()
const {
return (m_matrixSize != 0); }
144 delete[] m_underlyingData;
145 m_underlyingData =
nullptr;
151 matrixSquareSize = 0;
163 void inline setValue(
unsigned row,
unsigned column, Scalar value) {
174 if (m_matrixSize != B.
size()) {
179 for (
unsigned r = 0; r < m_matrixSize; r++)
180 for (
unsigned c = 0; c < m_matrixSize; c++)
196 assert(B.
size() == m_matrixSize);
198 for (
unsigned r = 0; r < m_matrixSize; r++)
199 for (
unsigned c = 0; c < m_matrixSize; c++)
215 assert(B.
size() == m_matrixSize);
217 for (
unsigned r = 0; r < m_matrixSize; r++)
218 for (
unsigned c = 0; c < m_matrixSize; c++)
226 assert(B.
size() == m_matrixSize);
230 for (
unsigned r = 0; r < m_matrixSize; r++) {
231 for (
unsigned c = 0; c < m_matrixSize; c++) {
233 for (
unsigned k = 0; k < m_matrixSize; k++)
244 if (m_matrixSize == 3) {
267 for (
unsigned r = 0; r < m_matrixSize; r++) {
269 for (
unsigned k = 0; k < m_matrixSize; k++)
270 sum +=
m_values[r][k] *
static_cast<double>(vec[k]);
271 result[r] =
static_cast<float>(sum);
281 for (
unsigned r = 0; r < m_matrixSize; r++) {
283 for (
unsigned k = 0; k < m_matrixSize; k++)
284 sum +=
m_values[r][k] *
static_cast<double>(vec[k]);
295 for (
unsigned r = 0; r < m_matrixSize; r++) {
297 for (
unsigned k = 0; k < m_matrixSize; k++)
298 sum +=
m_values[r][k] *
static_cast<double>(vec[k]);
305 for (
unsigned r = 0; r < m_matrixSize - 1; r++)
306 for (
unsigned c = r + 1; c < m_matrixSize; c++)
320 for (
unsigned r = 0; r < m_matrixSize; ++r) {
321 memset(
m_values[r], 0,
sizeof(Scalar) * m_matrixSize);
329 Scalar** tempM =
nullptr;
331 tempM =
new Scalar*[m_matrixSize];
336 for (
unsigned i = 0; i < m_matrixSize; i++) {
337 tempM[i] =
new Scalar[2 * m_matrixSize];
340 for (
unsigned j = 0; j < i; j++)
delete[] tempM[j];
349 for (
unsigned i = 0; i < m_matrixSize; i++) {
350 for (
unsigned j = 0; j < m_matrixSize; j++) {
353 tempM[i][j + m_matrixSize] = 1;
355 tempM[i][j + m_matrixSize] = 0;
362 for (
unsigned i = 0; i < m_matrixSize; i++) {
366 while (tempM[j][i] == 0) {
367 if (++j >= m_matrixSize) {
369 for (
unsigned k = 0; k < m_matrixSize; ++k)
380 for (
unsigned k = i; k < 2 * m_matrixSize; k++)
384 if (tempM[i][i] != 1.0) {
385 const Scalar& tmpVal = tempM[i][i];
386 for (
unsigned k = i; k < 2 * m_matrixSize; ++k)
387 tempM[i][k] /= tmpVal;
391 for (
unsigned j = i + 1; j < m_matrixSize; j++) {
392 if (tempM[j][i] != 0) {
393 const Scalar& tmpVal = tempM[j][i];
394 for (
unsigned k = i; k < 2 * m_matrixSize; k++)
395 tempM[j][k] -= tempM[i][k] * tmpVal;
403 for (
unsigned i = m_matrixSize - 1; i > 0; i--) {
404 for (
unsigned j = 0; j < i; j++) {
405 if (tempM[j][i] != 0) {
406 const Scalar& tmpVal = tempM[j][i];
407 for (
unsigned k = i; k < 2 * m_matrixSize; k++)
408 tempM[j][k] -= tempM[i][k] * tmpVal;
417 for (
unsigned i = 0; i < m_matrixSize; i++)
418 for (
unsigned j = 0; j < m_matrixSize; j++)
419 result.m_values[i][j] = tempM[i][j + m_matrixSize];
424 for (
unsigned i = 0; i < m_matrixSize; i++)
delete[] tempM[i];
435 void print(FILE* fp =
nullptr)
const {
436 for (
unsigned r = 0; r < m_matrixSize; r++) {
437 for (
unsigned c = 0; c < m_matrixSize; c++) {
439 fprintf(fp,
"%6.6f ",
m_values[r][c]);
455 for (
unsigned r = 0; r < m_matrixSize; r++)
m_values[r][r] = 1;
460 for (
unsigned r = 0; r < m_matrixSize; r++)
461 for (
unsigned c = 0; c < m_matrixSize; c++)
m_values[r][c] *= coef;
468 for (
unsigned r = 0; r < m_matrixSize; r++)
trace +=
m_values[r][r];
481 double qd[4] = {
static_cast<double>(q[0]),
static_cast<double>(q[1]),
482 static_cast<double>(q[2]),
static_cast<double>(q[3])};
493 if (m_matrixSize == 0)
494 if (!init(3))
return;
495 assert(m_matrixSize == 3);
497 double q00 = q[0] * q[0];
498 double q11 = q[1] * q[1];
499 double q22 = q[2] * q[2];
500 double q33 = q[3] * q[3];
501 double q03 = q[0] * q[3];
502 double q13 = q[1] * q[3];
503 double q23 = q[2] * q[3];
504 double q02 = q[0] * q[2];
505 double q12 = q[1] * q[2];
506 double q01 = q[0] * q[1];
508 m_values[0][0] =
static_cast<Scalar
>(q00 + q11 - q22 - q33);
509 m_values[1][1] =
static_cast<Scalar
>(q00 - q11 + q22 - q33);
510 m_values[2][2] =
static_cast<Scalar
>(q00 - q11 - q22 + q33);
511 m_values[0][1] =
static_cast<Scalar
>(2.0 * (q12 - q03));
512 m_values[1][0] =
static_cast<Scalar
>(2.0 * (q12 + q03));
513 m_values[0][2] =
static_cast<Scalar
>(2.0 * (q13 + q02));
514 m_values[2][0] =
static_cast<Scalar
>(2.0 * (q13 - q02));
515 m_values[1][2] =
static_cast<Scalar
>(2.0 * (q23 - q01));
516 m_values[2][1] =
static_cast<Scalar
>(2.0 * (q23 + q01));
526 if (m_matrixSize != 3)
return false;
528 double dTrace =
static_cast<double>(
m_values[0][0]) +
529 static_cast<double>(
m_values[1][1]) +
530 static_cast<double>(
m_values[2][2]) + 1.0;
533 if (dTrace > 1.0e-6) {
534 double S = 2.0 * sqrt(dTrace);
568 double len = sqrt(w * w + x * x + y * y + z * z);
585 for (
unsigned i = 0; i < m_matrixSize; i++) {
587 for (
unsigned j = 0; j < m_matrixSize; j++) {
588 mat.
m_values[j][i] =
static_cast<Scalar
>(*Vec);
592 for (
unsigned j = 0; j < m_matrixSize; j++)
602 assert(m_matrixSize == 3 || m_matrixSize == 4);
603 memset(M16f, 0,
sizeof(
float) * 16);
605 for (
unsigned r = 0; r < 3; r++)
606 for (
unsigned c = 0; c < 3; c++)
607 M16f[r + c * 4] =
static_cast<float>(
m_values[r][c]);
609 if (m_matrixSize == 4)
610 for (
unsigned r = 0; r < 3; r++) {
611 M16f[12 + r] =
static_cast<float>(
m_values[3][r]);
612 M16f[3 + r * 4] =
static_cast<float>(
m_values[r][3]);
621 assert(m_matrixSize == 3 || m_matrixSize == 4);
622 memset(M16d, 0,
sizeof(
double) * 16);
624 for (
unsigned r = 0; r < 3; r++)
625 for (
unsigned c = 0; c < 3; c++)
626 M16d[r + c * 4] =
static_cast<double>(
m_values[r][c]);
628 if (m_matrixSize == 4) {
629 for (
unsigned r = 0; r < 3; r++) {
630 M16d[12 + r] =
static_cast<double>(
m_values[3][r]);
631 M16d[3 + r * 4] =
static_cast<double>(
m_values[r][3]);
641 if (m_matrixSize < 0)
return false;
654 ComputeSVD(m_matrixSize, U_, S_, V_);
657 std::vector<unsigned> eigOrder(m_matrixSize);
659 for (
unsigned i = 0; i < m_matrixSize; i++) {
662 for (
unsigned i = 0; i < m_matrixSize - 1; i++) {
663 unsigned largest = i;
665 S_.
getValue(eigOrder[largest], eigOrder[largest]));
667 for (
unsigned j = i + 1; j < m_matrixSize; j++) {
670 if (eigValue > largestEigValue) {
672 largestEigValue = eigValue;
676 std::swap(eigOrder[i], eigOrder[largest]);
682 S.init(m_matrixSize);
684 U.init(m_matrixSize);
685 V.init(m_matrixSize);
688 for (
unsigned j = 0; j < m_matrixSize; j++) {
689 unsigned index = eigOrder[j];
691 Scalar eigValue = S_.
getValue(index, index);
696 Scalar sign =
static_cast<Scalar
>(eigValue < 0 ? -1 : 1);
699 for (
unsigned i = 0; i < m_matrixSize; i++) {
713 bool init(
unsigned size) {
715 matrixSquareSize = m_matrixSize * m_matrixSize;
721 m_values =
new Scalar* [m_matrixSize] {};
722 m_underlyingData =
new Scalar[matrixSquareSize]{};
724 if ((
m_values ==
nullptr) || (m_underlyingData ==
nullptr)) {
728 for (
unsigned i = 0; i < m_matrixSize; i++) {
729 m_values[i] = m_underlyingData + (i * m_matrixSize);
736 double computeSubDet(Scalar** mat,
unsigned matSize)
const {
738 return static_cast<double>(mat[0][0] * mat[1][1] -
739 mat[0][1] * mat[1][0]);
742 Scalar** subMat =
new Scalar*[matSize - 1];
747 for (
unsigned row = 0;
row < matSize;
row++) {
749 for (
unsigned i = 0; i < matSize; i++)
750 if (i !=
row) subMat[k++] = mat[i] + 1;
752 subDet +=
static_cast<double>(mat[
row][0]) *
753 computeSubDet(subMat, matSize - 1) * sign;
768 static void GivensL(
SquareMatrixTpl& S,
unsigned m, Scalar a, Scalar b) {
769 Scalar r = sqrt(a * a + b * b);
774 for (
int i = 0; i < static_cast<int>(S.size()); i++) {
775 Scalar S0 = S.getValue(m + 0, i);
776 Scalar S1 = S.getValue(m + 1, i);
777 S.setValue(m, i, S.getValue(m, i) + S0 * (c - 1) - S1 * s);
778 S.setValue(m + 1, i, S.getValue(m + 1, i) + S0 * s + S1 * (c - 1));
782 static void GivensR(
SquareMatrixTpl& S,
unsigned m, Scalar a, Scalar b) {
783 Scalar r = sqrt(a * a + b * b);
788 for (
int i = 0; i < static_cast<int>(S.size()); i++) {
789 Scalar S0 = S.getValue(i, m + 0);
790 Scalar S1 = S.getValue(i, m + 1);
791 S.setValue(i, m, S.getValue(i, m) + S0 * (c - 1) - S1 * s);
792 S.setValue(i, m + 1, S.getValue(i, m + 1) + S0 * s + S1 * (c - 1));
796 static void ComputeSVD(
unsigned matrixSize,
800 assert(matrixSize >= 2);
804 std::vector<Scalar> house_vec(matrixSize);
805 for (
unsigned i = 0; i < matrixSize; i++) {
808 Scalar x1 = S.getValue(i, i);
809 if (x1 < 0) x1 = -x1;
811 Scalar x_inv_norm = 0;
812 for (
unsigned j = i; j < matrixSize; j++) {
813 x_inv_norm += S.getValue(j, i) * S.getValue(j, i);
815 if (x_inv_norm > 0) x_inv_norm = 1 / sqrt(x_inv_norm);
817 Scalar alpha = sqrt(1 + x1 * x_inv_norm);
818 Scalar beta = x_inv_norm / alpha;
819 if (x_inv_norm == 0) alpha = 0;
821 house_vec[i] = -alpha;
822 for (
unsigned j = i + 1; j < matrixSize; j++) {
823 house_vec[j] = -beta * S.getValue(j, i);
825 if (S.getValue(i, i) < 0) {
826 for (
unsigned j = i + 1; j < matrixSize; j++) {
827 house_vec[j] = -house_vec[j];
832 for (
int k = i; k < static_cast<int>(matrixSize); k++) {
834 for (
unsigned j = i; j < matrixSize; j++) {
835 dot_prod += S.getValue(j, k) * house_vec[j];
837 for (
unsigned j = i; j < matrixSize; j++) {
839 S.getValue(j, k) - dot_prod * house_vec[j]);
843 for (
int k = 0; k < static_cast<int>(matrixSize); k++) {
845 for (
unsigned j = i; j < matrixSize; j++) {
846 dot_prod += U.getValue(k, j) * house_vec[j];
848 for (
unsigned j = i; j < matrixSize; j++) {
850 U.getValue(k, j) - dot_prod * house_vec[j]);
855 if (i >= matrixSize - 1)
continue;
857 Scalar x1 = S.getValue(i, i + 1);
858 if (x1 < 0) x1 = -x1;
860 Scalar x_inv_norm = 0;
861 for (
unsigned j = i + 1; j < matrixSize; j++) {
862 x_inv_norm += S.getValue(i, j) * S.getValue(i, j);
864 if (x_inv_norm > 0) x_inv_norm = 1 / sqrt(x_inv_norm);
866 Scalar alpha = sqrt(1 + x1 * x_inv_norm);
867 Scalar beta = x_inv_norm / alpha;
868 if (x_inv_norm == 0) alpha = 0;
870 house_vec[i + 1] = -alpha;
871 for (
unsigned j = i + 2; j < matrixSize; j++) {
872 house_vec[j] = -beta * S.getValue(i, j);
874 if (S.getValue(i, i + 1) < 0) {
875 for (
unsigned j = i + 2; j < matrixSize; j++) {
876 house_vec[j] = -house_vec[j];
881 for (
int k = i; k < static_cast<int>(matrixSize); k++) {
883 for (
unsigned j = i + 1; j < matrixSize; j++) {
884 dot_prod += S.getValue(k, j) * house_vec[j];
886 for (
unsigned j = i + 1; j < matrixSize; j++) {
888 S.getValue(k, j) - dot_prod * house_vec[j]);
892 for (
int k = 0; k < static_cast<int>(matrixSize); k++) {
894 for (
unsigned j = i + 1; j < matrixSize; j++) {
895 dot_prod += V.getValue(j, k) * house_vec[j];
897 for (
unsigned j = i + 1; j < matrixSize; j++) {
899 V.getValue(j, k) - dot_prod * house_vec[j]);
905 const Scalar eps = std::numeric_limits<Scalar>::epsilon() * 64;
908 for (
unsigned k0 = 0; k0 < matrixSize - 1;) {
910 for (
unsigned i = 0; i < matrixSize; i++)
911 S_max = (S_max >
std::abs(S.getValue(i, i))
915 for (
unsigned i = 0; i < matrixSize - 1; i++)
916 S_max = (S_max >
std::abs(S.getValue(i, i + 1))
920 while (k0 < matrixSize - 1 &&
921 std::abs(S.getValue(k0, k0 + 1)) <= eps * S_max)
924 if (k0 == matrixSize - 1)
continue;
928 while (n < matrixSize &&
929 std::abs(S.getValue(n - 1, n)) > eps * S_max)
935 if (n - k0 == 2 &&
std::abs(S.getValue(k0, k0)) < eps * S_max &&
936 std::abs(S.getValue(k0 + 1, k0 + 1)) < eps * S_max) {
941 C[0][0] = S.getValue(n - 2, n - 2) * S.getValue(n - 2, n - 2);
944 S.getValue(n - 3, n - 2) * S.getValue(n - 3, n - 2);
945 C[0][1] = S.getValue(n - 2, n - 2) * S.getValue(n - 2, n - 1);
946 C[1][0] = S.getValue(n - 2, n - 2) * S.getValue(n - 2, n - 1);
947 C[1][1] = S.getValue(n - 1, n - 1) * S.getValue(n - 1, n - 1) +
948 S.getValue(n - 2, n - 1) * S.getValue(n - 2, n - 1);
950 Scalar b = -(C[0][0] + C[1][1]) / 2;
951 Scalar c = C[0][0] * C[1][1] - C[0][1] * C[1][0];
956 b = (C[0][0] - C[1][1]) / 2;
957 c = -C[0][1] * C[1][0];
958 if (b * b - c > 0) d = sqrt(b * b - c);
961 Scalar lambda1 = -b + d;
962 Scalar lambda2 = -b - d;
964 Scalar d1 = lambda1 - C[1][1];
965 d1 = (d1 < 0 ? -d1 : d1);
966 Scalar d2 = lambda2 - C[1][1];
967 d2 = (d2 < 0 ? -d2 : d2);
968 Scalar mu = (d1 < d2 ? lambda1 : lambda2);
970 alpha = S.getValue(k0, k0) * S.getValue(k0, k0) - mu;
971 beta = S.getValue(k0, k0) * S.getValue(k0, k0 + 1);
974 for (
unsigned k = k0; k < n - 1; k++) {
975 GivensR(S, k, alpha, beta);
976 GivensL(V, k, alpha, beta);
978 alpha = S.getValue(k, k);
979 beta = S.getValue(k + 1, k);
980 GivensL(S, k, alpha, beta);
981 GivensR(U, k, alpha, beta);
983 alpha = S.getValue(k, k + 1);
984 beta = S.getValue(k, k + 2);
989 for (
unsigned i0 = k0; i0 < n - 1; i0++) {
990 for (
unsigned i1 = 0; i1 < matrixSize; i1++) {
991 if (i0 > i1 || i0 + 1 < i1) S.setValue(i0, i1, 0);
994 for (
unsigned i0 = 0; i0 < matrixSize; i0++) {
995 for (
unsigned i1 = k0; i1 < n - 1; i1++) {
996 if (i0 > i1 || i0 + 1 < i1) S.setValue(i0, i1, 0);
999 for (
unsigned i = 0; i < matrixSize - 1; i++) {
1000 if (
std::abs(S.getValue(i, i + 1)) <= eps * S_max) {
1001 S.setValue(i, i + 1, 0);
1010 unsigned m_matrixSize;
1013 unsigned matrixSquareSize;
1016 Scalar* m_underlyingData =
nullptr;
3D Vector (templated version)
const SquareMatrixTpl & operator+=(const SquareMatrixTpl &B)
In-place addition.
SquareMatrixTpl inv() const
Returns inverse (Gauss)
void toIdentity()
Sets matrix to identity.
void apply(const float vec[], double result[]) const
Multiplication by a float vector, outputs a double vector.
bool svd(SquareMatrixTpl &S, SquareMatrixTpl &U, SquareMatrixTpl &V) const
SquareMatrixTpl operator*(const SquareMatrixTpl &B) const
Multiplication (M = A*B)
SquareMatrixTpl(const SquareMatrixTpl< float > &mat)
Constructor from another float matrix.
Scalar ** m_values
The matrix rows.
Scalar trace() const
Returns trace.
SquareMatrixTpl(unsigned size)
Constructor with a given size.
void clear()
Sets all elements to 0.
SquareMatrixTpl(const float M16f[], bool rotationOnly=false)
"From OpenGl" constructor (float version)
SquareMatrixTpl & operator=(const Eigen::Matrix< Scalar, 3, 3 > &mat)
Assignment Function.
bool isValid() const
Returns matrix validity.
const SquareMatrixTpl & operator*=(const SquareMatrixTpl &B)
In-place multiplication.
SquareMatrixTpl(const double M16d[], bool rotationOnly=false)
"From OpenGl" constructor (double version)
SquareMatrixTpl & operator=(const SquareMatrixTpl &B)
Matrix copy operator.
void invalidate()
Invalidates matrix.
double computeDet() const
Returns determinant.
SquareMatrixTpl(const SquareMatrixTpl< double > &mat)
Constructor from another double matrix.
Vector3Tpl< Scalar > operator*(const Vector3Tpl< Scalar > &V) const
Multiplication by a vector.
SquareMatrixTpl transposed() const
Returns the transposed version of this matrix.
void initFromQuaternion(const float q[])
Creates a rotation matrix from a quaternion (float version)
SquareMatrixTpl(const Eigen::Matrix< Scalar, 4, 4 > &mat)
void apply(const double vec[], double result[]) const
Multiplication by a double vector.
unsigned size() const
Returns matrix size.
void print(FILE *fp=nullptr) const
Prints out matrix to console or file.
SquareMatrixTpl & operator=(const Eigen::Matrix< Scalar, 4, 4 > &mat)
SquareMatrixTpl operator-(const SquareMatrixTpl &B) const
Subtraction.
SquareMatrixTpl()
Default constructor.
void transpose()
In-place transpose.
void setValue(unsigned row, unsigned column, Scalar value)
Sets a particular matrix value.
SquareMatrixTpl operator+(const SquareMatrixTpl &B) const
Addition.
bool toQuaternion(double q[])
Converts rotation matrix to quaternion.
virtual ~SquareMatrixTpl()
Default destructor.
void scale(Scalar coef)
Scales matrix (all elements are multiplied by the same coef.)
void toGlMatrix(float M16f[]) const
Converts a 3*3 or 4*4 matrix to an OpenGL-style float matrix (float[16])
void apply(const float vec[], float result[]) const
Multiplication by a float vector, outputs a float vector.
SquareMatrixTpl(const Eigen::Matrix< Scalar, 3, 3 > &mat)
Copy Function.
const SquareMatrixTpl & operator-=(const SquareMatrixTpl &B)
In-place subtraction.
Scalar deltaDeterminant(unsigned column, Scalar *Vec) const
Returns Delta-determinant (see Kramer formula)
Scalar * row(unsigned index)
Returns pointer to matrix row.
void toGlMatrix(double M16d[]) const
void initFromQuaternion(const double q[])
Creates a rotation matrix from a quaternion (double version)
void toArray(Scalar data[])
Scalar getValue(unsigned row, unsigned column) const
Returns a particular matrix value.
__host__ __device__ int2 abs(int2 v)
Generic file read and write utility for python interface.
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.