Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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);
00036 int j;
00037 do {
00038 j = Eigen::ei_random<int>(0,m.rows()-1);
00039 } while (i==j);
00040 m.row(i) += d * m.row(j);
00041
00042 i = Eigen::ei_random<int>(0,m.cols()-1);
00043 do {
00044 j = Eigen::ei_random<int>(0,m.cols()-1);
00045 } while (i==j);
00046 m.col(i) += d * m.col(j);
00047 }
00048 }
00049
00050 template<typename MatrixType> void lu_non_invertible()
00051 {
00052
00053
00054
00055
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
00087
00088
00089
00090 }
00091
00092 template<typename MatrixType> void lu_invertible()
00093 {
00094
00095
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
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 }