block.cpp
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2006-2010 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 #define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths
00026 #include "main.h"
00027 
00028 template<typename MatrixType> void block(const MatrixType& m)
00029 {
00030   typedef typename MatrixType::Index Index;
00031   typedef typename MatrixType::Scalar Scalar;
00032   typedef typename MatrixType::RealScalar RealScalar;
00033   typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
00034   typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
00035   typedef Matrix<Scalar, Dynamic, Dynamic> DynamicMatrixType;
00036   typedef Matrix<Scalar, Dynamic, 1> DynamicVectorType;
00037   
00038   Index rows = m.rows();
00039   Index cols = m.cols();
00040 
00041   MatrixType m1 = MatrixType::Random(rows, cols),
00042              m1_copy = m1,
00043              m2 = MatrixType::Random(rows, cols),
00044              m3(rows, cols),
00045              mzero = MatrixType::Zero(rows, cols),
00046              ones = MatrixType::Ones(rows, cols);
00047   VectorType v1 = VectorType::Random(rows),
00048              v2 = VectorType::Random(rows),
00049              v3 = VectorType::Random(rows),
00050              vzero = VectorType::Zero(rows);
00051 
00052   Scalar s1 = internal::random<Scalar>();
00053 
00054   Index r1 = internal::random<Index>(0,rows-1);
00055   Index r2 = internal::random<Index>(r1,rows-1);
00056   Index c1 = internal::random<Index>(0,cols-1);
00057   Index c2 = internal::random<Index>(c1,cols-1);
00058 
00059   //check row() and col()
00060   VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1));
00061   //check operator(), both constant and non-constant, on row() and col()
00062   m1 = m1_copy;
00063   m1.row(r1) += s1 * m1_copy.row(r2);
00064   VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + s1 * m1_copy.row(r2));
00065   // check nested block xpr on lhs
00066   m1.row(r1).row(0) += s1 * m1_copy.row(r2);
00067   VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + Scalar(2) * s1 * m1_copy.row(r2));
00068   m1 = m1_copy;
00069   m1.col(c1) += s1 * m1_copy.col(c2);
00070   VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2));
00071   m1.col(c1).col(0) += s1 * m1_copy.col(c2);
00072   VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2));
00073 
00074   //check block()
00075   Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);
00076 
00077   RowVectorType br1(m1.block(r1,0,1,cols));
00078   VectorType bc1(m1.block(0,c1,rows,1));
00079   VERIFY_IS_EQUAL(b1, m1.block(r1,c1,1,1));
00080   VERIFY_IS_EQUAL(m1.row(r1), br1);
00081   VERIFY_IS_EQUAL(m1.col(c1), bc1);
00082   //check operator(), both constant and non-constant, on block()
00083   m1.block(r1,c1,r2-r1+1,c2-c1+1) = s1 * m2.block(0, 0, r2-r1+1,c2-c1+1);
00084   m1.block(r1,c1,r2-r1+1,c2-c1+1)(r2-r1,c2-c1) = m2.block(0, 0, r2-r1+1,c2-c1+1)(0,0);
00085 
00086   enum {
00087     BlockRows = 2,
00088     BlockCols = 5
00089   };
00090   if (rows>=5 && cols>=8)
00091   {
00092     // test fixed block() as lvalue
00093     m1.template block<BlockRows,BlockCols>(1,1) *= s1;
00094     // test operator() on fixed block() both as constant and non-constant
00095     m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2);
00096     // check that fixed block() and block() agree
00097     Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
00098     VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols));
00099   }
00100 
00101   if (rows>2)
00102   {
00103     // test sub vectors
00104     VERIFY_IS_EQUAL(v1.template head<2>(), v1.block(0,0,2,1));
00105     VERIFY_IS_EQUAL(v1.template head<2>(), v1.head(2));
00106     VERIFY_IS_EQUAL(v1.template head<2>(), v1.segment(0,2));
00107     VERIFY_IS_EQUAL(v1.template head<2>(), v1.template segment<2>(0));
00108     Index i = rows-2;
00109     VERIFY_IS_EQUAL(v1.template tail<2>(), v1.block(i,0,2,1));
00110     VERIFY_IS_EQUAL(v1.template tail<2>(), v1.tail(2));
00111     VERIFY_IS_EQUAL(v1.template tail<2>(), v1.segment(i,2));
00112     VERIFY_IS_EQUAL(v1.template tail<2>(), v1.template segment<2>(i));
00113     i = internal::random<Index>(0,rows-2);
00114     VERIFY_IS_EQUAL(v1.segment(i,2), v1.template segment<2>(i));
00115   }
00116 
00117   // stress some basic stuffs with block matrices
00118   VERIFY(internal::real(ones.col(c1).sum()) == RealScalar(rows));
00119   VERIFY(internal::real(ones.row(r1).sum()) == RealScalar(cols));
00120 
00121   VERIFY(internal::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
00122   VERIFY(internal::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols));
00123 
00124   // now test some block-inside-of-block.
00125   
00126   // expressions with direct access
00127   VERIFY_IS_EQUAL( (m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , (m1.block(r2,c2,rows-r2,cols-c2)) );
00128   VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , (m1.row(r1).segment(c1,c2-c1+1)) );
00129   VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , (m1.col(c1).segment(r1,r2-r1+1)) );
00130   VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() );
00131   VERIFY_IS_EQUAL( (m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() );
00132 
00133   // expressions without direct access
00134   VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , ((m1+m2).block(r2,c2,rows-r2,cols-c2)) );
00135   VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) );
00136   VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , ((m1+m2).col(c1).segment(r1,r2-r1+1)) );
00137   VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
00138   VERIFY_IS_EQUAL( ((m1+m2).transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
00139 
00140   // evaluation into plain matrices from expressions with direct access (stress MapBase)
00141   DynamicMatrixType dm;
00142   DynamicVectorType dv;
00143   dm.setZero();
00144   dm = m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2);
00145   VERIFY_IS_EQUAL(dm, (m1.block(r2,c2,rows-r2,cols-c2)));
00146   dm.setZero();
00147   dv.setZero();
00148   dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0).transpose();
00149   dv = m1.row(r1).segment(c1,c2-c1+1);
00150   VERIFY_IS_EQUAL(dv, dm);
00151   dm.setZero();
00152   dv.setZero();
00153   dm = m1.col(c1).segment(r1,r2-r1+1);
00154   dv = m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0);
00155   VERIFY_IS_EQUAL(dv, dm);
00156   dm.setZero();
00157   dv.setZero();
00158   dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0);
00159   dv = m1.row(r1).segment(c1,c2-c1+1);
00160   VERIFY_IS_EQUAL(dv, dm);
00161   dm.setZero();
00162   dv.setZero();
00163   dm = m1.row(r1).segment(c1,c2-c1+1).transpose();
00164   dv = m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0);
00165   VERIFY_IS_EQUAL(dv, dm);
00166 }
00167 
00168 
00169 template<typename MatrixType>
00170 void compare_using_data_and_stride(const MatrixType& m)
00171 {
00172   typedef typename MatrixType::Index Index;
00173   Index rows = m.rows();
00174   Index cols = m.cols();
00175   Index size = m.size();
00176   Index innerStride = m.innerStride();
00177   Index outerStride = m.outerStride();
00178   Index rowStride = m.rowStride();
00179   Index colStride = m.colStride();
00180   const typename MatrixType::Scalar* data = m.data();
00181 
00182   for(int j=0;j<cols;++j)
00183     for(int i=0;i<rows;++i)
00184       VERIFY(m.coeff(i,j) == data[i*rowStride + j*colStride]);
00185 
00186   if(!MatrixType::IsVectorAtCompileTime)
00187   {
00188     for(int j=0;j<cols;++j)
00189       for(int i=0;i<rows;++i)
00190         VERIFY(m.coeff(i,j) == data[(MatrixType::Flags&RowMajorBit)
00191                                      ? i*outerStride + j*innerStride
00192                                      : j*outerStride + i*innerStride]);
00193   }
00194 
00195   if(MatrixType::IsVectorAtCompileTime)
00196   {
00197     VERIFY(innerStride == int((&m.coeff(1))-(&m.coeff(0))));
00198     for (int i=0;i<size;++i)
00199       VERIFY(m.coeff(i) == data[i*innerStride]);
00200   }
00201 }
00202 
00203 template<typename MatrixType>
00204 void data_and_stride(const MatrixType& m)
00205 {
00206   typedef typename MatrixType::Index Index;
00207   Index rows = m.rows();
00208   Index cols = m.cols();
00209 
00210   Index r1 = internal::random<Index>(0,rows-1);
00211   Index r2 = internal::random<Index>(r1,rows-1);
00212   Index c1 = internal::random<Index>(0,cols-1);
00213   Index c2 = internal::random<Index>(c1,cols-1);
00214 
00215   MatrixType m1 = MatrixType::Random(rows, cols);
00216   compare_using_data_and_stride(m1.block(r1, c1, r2-r1+1, c2-c1+1));
00217   compare_using_data_and_stride(m1.transpose().block(c1, r1, c2-c1+1, r2-r1+1));
00218   compare_using_data_and_stride(m1.row(r1));
00219   compare_using_data_and_stride(m1.col(c1));
00220   compare_using_data_and_stride(m1.row(r1).transpose());
00221   compare_using_data_and_stride(m1.col(c1).transpose());
00222 }
00223 
00224 void test_block()
00225 {
00226   for(int i = 0; i < g_repeat; i++) {
00227     CALL_SUBTEST_1( block(Matrix<float, 1, 1>()) );
00228     CALL_SUBTEST_2( block(Matrix4d()) );
00229     CALL_SUBTEST_3( block(MatrixXcf(3, 3)) );
00230     CALL_SUBTEST_4( block(MatrixXi(8, 12)) );
00231     CALL_SUBTEST_5( block(MatrixXcd(20, 20)) );
00232     CALL_SUBTEST_6( block(MatrixXf(20, 20)) );
00233 
00234     CALL_SUBTEST_8( block(Matrix<float,Dynamic,4>(3, 4)) );
00235 
00236 #ifndef EIGEN_DEFAULT_TO_ROW_MAJOR
00237     CALL_SUBTEST_6( data_and_stride(MatrixXf(internal::random(5,50), internal::random(5,50))) );
00238     CALL_SUBTEST_7( data_and_stride(Matrix<int,Dynamic,Dynamic,RowMajor>(internal::random(5,50), internal::random(5,50))) );
00239 #endif
00240   }
00241 }


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