// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr> // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef SVD_DEFAULT #error a macro SVD_DEFAULT(MatrixType) must be defined prior to including svd_common.h #endif
#ifndef SVD_FOR_MIN_NORM #error a macro SVD_FOR_MIN_NORM(MatrixType) must be defined prior to including svd_common.h #endif
#include"svd_fill.h" #include"solverbase.h"
// Check that the matrix m is properly reconstructed and that the U and V factors are unitary // The SVD must have already been computed. template<typename SvdType, typename MatrixType> void svd_check_full(const MatrixType& m, const SvdType& svd)
{
Index rows = m.rows();
Index cols = m.cols();
// The following checks are not critical. // For instance, with Dived&Conquer SVD, if only the factor 'V' is computedt then different matrix-matrix product implementation will be used // and the resulting 'V' factor might be significantly different when the SVD decomposition is not unique, especially with single precision float.
++g_test_level; if(computationOptions & ComputeFullU) VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU()); if(computationOptions & ComputeThinU) VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize)); if(computationOptions & ComputeFullV) VERIFY_IS_APPROX(svd.matrixV().cwiseAbs(), referenceSvd.matrixV().cwiseAbs()); if(computationOptions & ComputeThinV) VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize));
--g_test_level;
}
// template<typename SvdType, typename MatrixType> void svd_least_square(const MatrixType& m, unsignedint computationOptions)
{ typedeftypename MatrixType::Scalar Scalar; typedeftypename MatrixType::RealScalar RealScalar;
Index rows = m.rows();
Index cols = m.cols();
RealScalar residual = (m*x-rhs).norm();
RealScalar rhs_norm = rhs.norm(); if(!test_isMuchSmallerThan(residual,rhs.norm()))
{ // ^^^ If the residual is very small, then we have an exact solution, so we are already good.
// evaluate normal equation which works also for least-squares solutions if(internal::is_same<RealScalar,double>::value || svd.rank()==m.diagonal().size())
{ using std::sqrt; // This test is not stable with single precision. // This is probably because squaring m signicantly affects the precision. if(internal::is_same<RealScalar,float>::value) ++g_test_level;
// check minimal norm solutions, the inoput matrix m is only used to recover problem size template<typename MatrixType> void svd_min_norm(const MatrixType& m, unsignedint computationOptions)
{ typedeftypename MatrixType::Scalar Scalar;
Index cols = m.cols();
// work around stupid msvc error when constructing at compile time an expression that involves // a division by zero, even if the numeric type has floating point template<typename Scalar>
EIGEN_DONT_INLINE Scalar zero() { return Scalar(0); }
// workaround aggressive optimization in ICC template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
// This function verifies we don't iterate infinitely on nan/inf values, // and that info() returns InvalidInput. template<typename SvdType, typename MatrixType> void svd_inf_nan()
{
SvdType svd; typedeftypename MatrixType::Scalar Scalar;
Scalar some_inf = Scalar(1) / zero<Scalar>();
VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf));
svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV);
VERIFY(svd.info() == InvalidInput);
// Regression test for bug 286: JacobiSVD loops indefinitely with some // matrices containing denormal numbers. template<typename> void svd_underoverflow()
{ #ifdefined __INTEL_COMPILER // shut up warning #239: floating point underflow #pragma warning push #pragma warning disable 239 #endif
Matrix2d M;
M << -7.90884e-313, -4.94e-324,
0, 5.60844e-313;
SVD_DEFAULT(Matrix2d) svd;
svd.compute(M,ComputeFullU|ComputeFullV);
CALL_SUBTEST( svd_check_full(M,svd) );
// Check all 2x2 matrices made with the following coefficients:
VectorXd value_set(9);
value_set << 0, 1, -1, 5.60844e-313, -5.60844e-313, 4.94e-324, -4.94e-324, -4.94e-223, 4.94e-223;
Array4i id(0,0,0,0); int k = 0; do
{
M << value_set(id(0)), value_set(id(1)), value_set(id(2)), value_set(id(3));
svd.compute(M,ComputeFullU|ComputeFullV);
CALL_SUBTEST( svd_check_full(M,svd) );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.