eigen2_lu.cpp
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra. Eigen itself is part of the KDE project.
00003 //
00004 // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #include "main.h"
00026 #include <Eigen/LU>
00027 
00028 template<typename Derived>
00029 void doSomeRankPreservingOperations(Eigen::MatrixBase<Derived>& m)
00030 {
00031   typedef typename Derived::RealScalar RealScalar;
00032   for(int a = 0; a < 3*(m.rows()+m.cols()); a++)
00033   {
00034     RealScalar d = Eigen::ei_random<RealScalar>(-1,1);
00035     int i = Eigen::ei_random<int>(0,m.rows()-1); // i is a random row number
00036     int j;
00037     do {
00038       j = Eigen::ei_random<int>(0,m.rows()-1);
00039     } while (i==j); // j is another one (must be different)
00040     m.row(i) += d * m.row(j);
00041 
00042     i = Eigen::ei_random<int>(0,m.cols()-1); // i is a random column number
00043     do {
00044       j = Eigen::ei_random<int>(0,m.cols()-1);
00045     } while (i==j); // j is another one (must be different)
00046     m.col(i) += d * m.col(j);
00047   }
00048 }
00049 
00050 template<typename MatrixType> void lu_non_invertible()
00051 {
00052   /* this test covers the following files:
00053      LU.h
00054   */
00055   // NOTE there seems to be a problem with too small sizes -- could easily lie in the doSomeRankPreservingOperations function
00056   int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200);
00057   int rank = ei_random<int>(1, std::min(rows, cols)-1);
00058 
00059   MatrixType m1(rows, cols), m2(cols, cols2), m3(rows, cols2), k(1,1);
00060   m1 = MatrixType::Random(rows,cols);
00061   if(rows <= cols)
00062     for(int i = rank; i < rows; i++) m1.row(i).setZero();
00063   else
00064     for(int i = rank; i < cols; i++) m1.col(i).setZero();
00065   doSomeRankPreservingOperations(m1);
00066 
00067   LU<MatrixType> lu(m1);
00068   typename LU<MatrixType>::KernelResultType m1kernel = lu.kernel();
00069   typename LU<MatrixType>::ImageResultType m1image = lu.image();
00070 
00071   VERIFY(rank == lu.rank());
00072   VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
00073   VERIFY(!lu.isInjective());
00074   VERIFY(!lu.isInvertible());
00075   VERIFY(lu.isSurjective() == (lu.rank() == rows));
00076   VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
00077   VERIFY(m1image.lu().rank() == rank);
00078   MatrixType sidebyside(m1.rows(), m1.cols() + m1image.cols());
00079   sidebyside << m1, m1image;
00080   VERIFY(sidebyside.lu().rank() == rank);
00081   m2 = MatrixType::Random(cols,cols2);
00082   m3 = m1*m2;
00083   m2 = MatrixType::Random(cols,cols2);
00084   lu.solve(m3, &m2);
00085   VERIFY_IS_APPROX(m3, m1*m2);
00086   /* solve now always returns true
00087   m3 = MatrixType::Random(rows,cols2);
00088   VERIFY(!lu.solve(m3, &m2));
00089   */
00090 }
00091 
00092 template<typename MatrixType> void lu_invertible()
00093 {
00094   /* this test covers the following files:
00095      LU.h
00096   */
00097   typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
00098   int size = ei_random<int>(10,200);
00099 
00100   MatrixType m1(size, size), m2(size, size), m3(size, size);
00101   m1 = MatrixType::Random(size,size);
00102 
00103   if (ei_is_same_type<RealScalar,float>::ret)
00104   {
00105     // let's build a matrix more stable to inverse
00106     MatrixType a = MatrixType::Random(size,size*2);
00107     m1 += a * a.adjoint();
00108   }
00109 
00110   LU<MatrixType> lu(m1);
00111   VERIFY(0 == lu.dimensionOfKernel());
00112   VERIFY(size == lu.rank());
00113   VERIFY(lu.isInjective());
00114   VERIFY(lu.isSurjective());
00115   VERIFY(lu.isInvertible());
00116   VERIFY(lu.image().lu().isInvertible());
00117   m3 = MatrixType::Random(size,size);
00118   lu.solve(m3, &m2);
00119   VERIFY_IS_APPROX(m3, m1*m2);
00120   VERIFY_IS_APPROX(m2, lu.inverse()*m3);
00121   m3 = MatrixType::Random(size,size);
00122   VERIFY(lu.solve(m3, &m2));
00123 }
00124 
00125 void test_eigen2_lu()
00126 {
00127   for(int i = 0; i < g_repeat; i++) {
00128     CALL_SUBTEST_1( lu_non_invertible<MatrixXf>() );
00129     CALL_SUBTEST_2( lu_non_invertible<MatrixXd>() );
00130     CALL_SUBTEST_3( lu_non_invertible<MatrixXcf>() );
00131     CALL_SUBTEST_4( lu_non_invertible<MatrixXcd>() );
00132     CALL_SUBTEST_1( lu_invertible<MatrixXf>() );
00133     CALL_SUBTEST_2( lu_invertible<MatrixXd>() );
00134     CALL_SUBTEST_3( lu_invertible<MatrixXcf>() );
00135     CALL_SUBTEST_4( lu_invertible<MatrixXcd>() );
00136   }
00137 }


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:03