void EigenSolver(const Matrix3x3& mtx, float* eigenValues, Vector3* eigenVecs) { double roots[3] = {0.0}; ComputeRoots(mtx, roots); eigenValues[0] = static_cast<float>(roots[0]); eigenValues[1] = static_cast<float>(roots[1]); eigenValues[2] = static_cast<float>(roots[2]); Matrix3x3 m0 = mtx - (Matrix3x3::IDENTITY * eigenValues[0]); int m0rank = ::ComputeRank(m0); if (m0rank == 0) { eigenVecs[0] = Vector3(1.0f, 0.0f, 0.0f); eigenVecs[1] = Vector3(0.0f, 1.0f, 0.0f); eigenVecs[2] = Vector3(0.0f, 0.0f, 1.0f); return; } else if (m0rank == 1) { GetComplement2(m0.GetRow(0), eigenVecs[0], eigenVecs[1]); eigenVecs[2] = eigenVecs[0].Cross(eigenVecs[1]); return; } // m0rank == 2 eigenVecs[0] = GetComplement1(m0.GetRow(0), m0.GetRow(1)); Matrix3x3 diag( eigenValues[1], 0.0f, 0.0f, 0.0f, eigenValues[1], 0.0f, 0.0f, 0.0f, eigenValues[1]); Matrix3x3 m1 = mtx - diag;//(Matrix3x3::IDENTITY * eigenValues[1]); int m1rank = ComputeRank(m1); if (m1rank == 1) { GetComplement2(eigenVecs[0], eigenVecs[1], eigenVecs[2]); return; } // m1rank == 2 GetComplement2(eigenVecs[0], eigenVecs[1], eigenVecs[2]); //eigenVecs[1] = GetComplement1(m1.GetRow(0), m1.GetRow(1)); //eigenVecs[2] = eigenVecs[0].Cross(eigenVecs[1]); }
NoniterativeEigen3x3<Real>::NoniterativeEigen3x3 (const Matrix3<Real>& A) { // Scale the matrix so its entries are in [-1,1]. The scaling is applied // only when at least one matrix entry has magnitude larger than 1. Matrix3<Real> AScaled = A; Real* scaledEntry = (Real*)AScaled; Real maxValue = Math<Real>::FAbs(scaledEntry[0]); Real absValue = Math<Real>::FAbs(scaledEntry[1]); if (absValue > maxValue) { maxValue = absValue; } absValue = Math<Real>::FAbs(scaledEntry[2]); if (absValue > maxValue) { maxValue = absValue; } absValue = Math<Real>::FAbs(scaledEntry[4]); if (absValue > maxValue) { maxValue = absValue; } absValue = Math<Real>::FAbs(scaledEntry[5]); if (absValue > maxValue) { maxValue = absValue; } absValue = Math<Real>::FAbs(scaledEntry[8]); if (absValue > maxValue) { maxValue = absValue; } int i; if (maxValue > (Real)1) { Real invMaxValue = ((Real)1)/maxValue; for (i = 0; i < 9; ++i) { scaledEntry[i] *= invMaxValue; } } // Compute the eigenvalues using double-precision arithmetic. double root[3]; ComputeRoots(AScaled,root); mEigenvalue[0] = (Real)root[0]; mEigenvalue[1] = (Real)root[1]; mEigenvalue[2] = (Real)root[2]; Real maxEntry[3]; Vector3<Real> maxRow[3]; for (i = 0; i < 3; ++i) { Matrix3<Real> M = AScaled; M[0][0] -= mEigenvalue[i]; M[1][1] -= mEigenvalue[i]; M[2][2] -= mEigenvalue[i]; if (!PositiveRank(M, maxEntry[i], maxRow[i])) { // Rescale back to the original size. if (maxValue > (Real)1) { for (int j = 0; j < 3; ++j) { mEigenvalue[j] *= maxValue; } } mEigenvector[0] = Vector3<Real>::UNIT_X; mEigenvector[1] = Vector3<Real>::UNIT_Y; mEigenvector[2] = Vector3<Real>::UNIT_Z; return; } } Real totalMax = maxEntry[0]; i = 0; if (maxEntry[1] > totalMax) { totalMax = maxEntry[1]; i = 1; } if (maxEntry[2] > totalMax) { i = 2; } if (i == 0) { maxRow[0].Normalize(); ComputeVectors(AScaled, maxRow[0], 1, 2, 0); } else if (i == 1) { maxRow[1].Normalize(); ComputeVectors(AScaled, maxRow[1], 2, 0, 1); } else { maxRow[2].Normalize(); ComputeVectors(AScaled, maxRow[2], 0, 1, 2); } // Rescale back to the original size. if (maxValue > (Real)1) { for (i = 0; i < 3; ++i) { mEigenvalue[i] *= maxValue; } } }