sparse_product.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) 2008 Daniel Gomez Ferro <dgomezferro@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 "sparse.h"
00026 
00027 template<typename SparseMatrixType> void sparse_product(const SparseMatrixType& ref)
00028 {
00029   typedef typename SparseMatrixType::Index Index;
00030   const Index rows = ref.rows();
00031   const Index cols = ref.cols();
00032   typedef typename SparseMatrixType::Scalar Scalar;
00033   enum { Flags = SparseMatrixType::Flags };
00034 
00035   double density = std::max(8./(rows*cols), 0.01);
00036   typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
00037   typedef Matrix<Scalar,Dynamic,1> DenseVector;
00038 
00039   Scalar s1 = internal::random<Scalar>();
00040   Scalar s2 = internal::random<Scalar>();
00041 
00042   // test matrix-matrix product
00043   {
00044     DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
00045     DenseMatrix refMat3 = DenseMatrix::Zero(rows, rows);
00046     DenseMatrix refMat4 = DenseMatrix::Zero(rows, rows);
00047     DenseMatrix refMat5 = DenseMatrix::Random(rows, rows);
00048     DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
00049     DenseVector dv1 = DenseVector::Random(rows);
00050     SparseMatrixType m2(rows, rows);
00051     SparseMatrixType m3(rows, rows);
00052     SparseMatrixType m4(rows, rows);
00053     initSparse<Scalar>(density, refMat2, m2);
00054     initSparse<Scalar>(density, refMat3, m3);
00055     initSparse<Scalar>(density, refMat4, m4);
00056 
00057     int c = internal::random<int>(0,rows-1);
00058 
00059     VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
00060     VERIFY_IS_APPROX(m4=m2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
00061     VERIFY_IS_APPROX(m4=m2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
00062     VERIFY_IS_APPROX(m4=m2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
00063 
00064     VERIFY_IS_APPROX(m4 = m2*m3/s1, refMat4 = refMat2*refMat3/s1);
00065     VERIFY_IS_APPROX(m4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1);
00066     VERIFY_IS_APPROX(m4 = s2*m2*m3*s1, refMat4 = s2*refMat2*refMat3*s1);
00067 
00068     // sparse * dense
00069     VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
00070     VERIFY_IS_APPROX(dm4=m2*refMat3.transpose(), refMat4=refMat2*refMat3.transpose());
00071     VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3, refMat4=refMat2.transpose()*refMat3);
00072     VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
00073 
00074     VERIFY_IS_APPROX(dm4=m2*(refMat3+refMat3), refMat4=refMat2*(refMat3+refMat3));
00075     VERIFY_IS_APPROX(dm4=m2.transpose()*(refMat3+refMat5)*0.5, refMat4=refMat2.transpose()*(refMat3+refMat5)*0.5);
00076 
00077     // dense * sparse
00078     VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
00079     VERIFY_IS_APPROX(dm4=refMat2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
00080     VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
00081     VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
00082 
00083     // sparse * dense and dense * sparse outer product
00084     VERIFY_IS_APPROX(m4=m2.col(c)*dv1.transpose(), refMat4=refMat2.col(c)*dv1.transpose());
00085     VERIFY_IS_APPROX(m4=dv1*m2.col(c).transpose(), refMat4=dv1*refMat2.col(c).transpose());
00086 
00087     VERIFY_IS_APPROX(m3=m3*m3, refMat3=refMat3*refMat3);
00088   }
00089 
00090   // test matrix - diagonal product
00091   {
00092     DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
00093     DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
00094     DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(rows));
00095     SparseMatrixType m2(rows, rows);
00096     SparseMatrixType m3(rows, rows);
00097     initSparse<Scalar>(density, refM2, m2);
00098     initSparse<Scalar>(density, refM3, m3);
00099     VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
00100     VERIFY_IS_APPROX(m3=m2.transpose()*d1, refM3=refM2.transpose()*d1);
00101     VERIFY_IS_APPROX(m3=d1*m2, refM3=d1*refM2);
00102     VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1 * refM2.transpose());
00103   }
00104 
00105   // test self adjoint products
00106   {
00107     DenseMatrix b = DenseMatrix::Random(rows, rows);
00108     DenseMatrix x = DenseMatrix::Random(rows, rows);
00109     DenseMatrix refX = DenseMatrix::Random(rows, rows);
00110     DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
00111     DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
00112     DenseMatrix refS = DenseMatrix::Zero(rows, rows);
00113     SparseMatrixType mUp(rows, rows);
00114     SparseMatrixType mLo(rows, rows);
00115     SparseMatrixType mS(rows, rows);
00116     do {
00117       initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
00118     } while (refUp.isZero());
00119     refLo = refUp.transpose().conjugate();
00120     mLo = mUp.transpose().conjugate();
00121     refS = refUp + refLo;
00122     refS.diagonal() *= 0.5;
00123     mS = mUp + mLo;
00124     for (int k=0; k<mS.outerSize(); ++k)
00125       for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
00126         if (it.index() == k)
00127           it.valueRef() *= 0.5;
00128 
00129     VERIFY_IS_APPROX(refS.adjoint(), refS);
00130     VERIFY_IS_APPROX(mS.transpose().conjugate(), mS);
00131     VERIFY_IS_APPROX(mS, refS);
00132     VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
00133 
00134     VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b);
00135     VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b);
00136     VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b);
00137   }
00138 }
00139 
00140 // New test for Bug in SparseTimeDenseProduct
00141 template<typename SparseMatrixType, typename DenseMatrixType> void sparse_product_regression_test()
00142 {
00143   // This code does not compile with afflicted versions of the bug
00144   SparseMatrixType sm1(3,2);
00145   DenseMatrixType m2(2,2);
00146   sm1.setZero();
00147   m2.setZero();
00148 
00149   DenseMatrixType m3 = sm1*m2;
00150 
00151 
00152   // This code produces a segfault with afflicted versions of another SparseTimeDenseProduct
00153   // bug
00154 
00155   SparseMatrixType sm2(20000,2);
00156   sm2.setZero();
00157   DenseMatrixType m4(sm2*m2);
00158 
00159   VERIFY_IS_APPROX( m4(0,0), 0.0 );
00160 }
00161 
00162 void test_sparse_product()
00163 {
00164   for(int i = 0; i < g_repeat; i++) {
00165     CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(8, 8)) );
00166     CALL_SUBTEST_2( sparse_product(SparseMatrix<std::complex<double> >(16, 16)) );
00167     CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(33, 33)) );
00168 
00169     CALL_SUBTEST_3( sparse_product(DynamicSparseMatrix<double>(8, 8)) );
00170 
00171     CALL_SUBTEST_4( (sparse_product_regression_test<SparseMatrix<double,RowMajor>, Matrix<double, Dynamic, Dynamic, RowMajor> >()) );
00172   }
00173 }


libicr
Author(s): Robert Krug
autogenerated on Mon Jan 6 2014 11:33:32