1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "sparse.h"
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename SparseMatrixType, typename DenseMatrix, bool IsRowMajor=SparseMatrixType::IsRowMajor> struct test_outer;
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,false> {
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename SparseMatrixType::Index Index;
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index c  = internal::random<Index>(0,m2.cols()-1);
187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index c1 = internal::random<Index>(0,m2.cols()-1);
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2.col(c)*refMat2.col(c1).transpose(), refMat4=refMat2.col(c)*refMat2.col(c1).transpose());
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.col(c).transpose(), refMat4=refMat2.col(c1)*refMat2.col(c).transpose());
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,true> {
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename SparseMatrixType::Index Index;
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index r  = internal::random<Index>(0,m2.rows()-1);
287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index c1 = internal::random<Index>(0,m2.cols()-1);
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2.row(r).transpose()*refMat2.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*refMat2.col(c1).transpose());
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.row(r), refMat4=refMat2.col(c1)*refMat2.row(r));
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// (m2,m4,refMat2,refMat4,dv1);
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     VERIFY_IS_APPROX(m4=m2.innerVector(c)*dv1.transpose(), refMat4=refMat2.colVector(c)*dv1.transpose());
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     VERIFY_IS_APPROX(m4=dv1*mcm.col(c).transpose(), refMat4=dv1*refMat2.col(c).transpose());
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename SparseMatrixType> void sparse_product()
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename SparseMatrixType::Index Index;
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index n = 100;
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index rows  = internal::random<Index>(1,n);
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index cols  = internal::random<Index>(1,n);
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index depth = internal::random<Index>(1,n);
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename SparseMatrixType::Scalar Scalar;
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum { Flags = SparseMatrixType::Flags };
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  double density = (std::max)(8./(rows*cols), 0.1);
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<Scalar,Dynamic,1> DenseVector;
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef SparseVector<Scalar,0,Index> ColSpVector;
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef SparseVector<Scalar,RowMajor,Index> RowSpVector;
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar s1 = internal::random<Scalar>();
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar s2 = internal::random<Scalar>();
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // test matrix-matrix product
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat2  = DenseMatrix::Zero(rows, depth);
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat2t = DenseMatrix::Zero(depth, rows);
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat3  = DenseMatrix::Zero(depth, cols);
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat3t = DenseMatrix::Zero(cols, depth);
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat4  = DenseMatrix::Zero(rows, cols);
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat4t = DenseMatrix::Zero(cols, rows);
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat5  = DenseMatrix::Random(depth, cols);
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refMat6  = DenseMatrix::Random(rows, rows);
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     DenseVector dv1 = DenseVector::Random(rows);
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m2 (rows, depth);
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m2t(depth, rows);
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m3 (depth, cols);
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m3t(cols, depth);
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m4 (rows, cols);
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m4t(cols, rows);
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m6(rows, rows);
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat2,  m2);
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat2t, m2t);
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat3,  m3);
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat3t, m3t);
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat4,  m4);
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat4t, m4t);
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse(density, refMat6, m6);
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     int c = internal::random<int>(0,depth-1);
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // sparse * sparse
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3);
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose());
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4 = m2*m3/s1, refMat4 = refMat2*refMat3/s1);
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1);
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4 = s2*m2*m3*s1, refMat4 = s2*refMat2*refMat3*s1);
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=(m2*m3).pruned(0), refMat4=refMat2*refMat3);
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=(m2t.transpose()*m3).pruned(0), refMat4=refMat2t.transpose()*refMat3);
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=(m2t.transpose()*m3t.transpose()).pruned(0), refMat4=refMat2t.transpose()*refMat3t.transpose());
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=(m2*m3t.transpose()).pruned(0), refMat4=refMat2*refMat3t.transpose());
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // test aliasing
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m4 = m2; refMat4 = refMat2;
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m4=m4*m3, refMat4=refMat4*refMat3);
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // sparse * dense
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2*refMat3t.transpose(), refMat4=refMat2*refMat3t.transpose());
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3, refMat4=refMat2t.transpose()*refMat3);
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2*(refMat3+refMat3), refMat4=refMat2*(refMat3+refMat3));
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=m2t.transpose()*(refMat3+refMat5)*0.5, refMat4=refMat2t.transpose()*(refMat3+refMat5)*0.5);
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // dense * sparse
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=refMat2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose());
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3);
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // sparse * dense and dense * sparse outer product
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    test_outer<SparseMatrixType,DenseMatrix>::run(m2,m4,refMat2,refMat4);
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m6=m6*m6, refMat6=refMat6*refMat6);
1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // sparse matrix * sparse vector
1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ColSpVector cv0(cols), cv1;
1287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseVector dcv0(cols), dcv1;
1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    initSparse(2*density,dcv0, cv0);
1307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RowSpVector rv0(depth), rv1;
1327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RowDenseVector drv0(depth), drv1(rv1);
1337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    initSparse(2*density,drv0, rv0);
1347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(cv1=rv0*m3, dcv1=drv0*refMat3);
1367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(rv1=rv0*m3, drv1=drv0*refMat3);
1377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(cv1=m3*cv0, dcv1=refMat3*dcv0);
1387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(cv1=m3t.adjoint()*cv0, dcv1=refMat3t.adjoint()*dcv0);
1397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(rv1=m3*cv0, drv1=refMat3*dcv0);
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
1417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // test matrix - diagonal product
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
1447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseMatrix refM2 = DenseMatrix::Zero(rows, cols);
1457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseMatrix refM3 = DenseMatrix::Zero(rows, cols);
1467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseMatrix d3 = DenseMatrix::Zero(rows, cols);
1477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(cols));
1487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DiagonalMatrix<Scalar,Dynamic> d2(DenseVector::Random(rows));
1497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrixType m2(rows, cols);
1507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrixType m3(rows, cols);
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse<Scalar>(density, refM2, m2);
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    initSparse<Scalar>(density, refM3, m3);
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
1547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
1557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=d2*m2, refM3=d2*refM2);
1567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1*refM2.transpose());
1577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // also check with a SparseWrapper:
1597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseVector v1 = DenseVector::Random(cols);
1607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    DenseVector v2 = DenseVector::Random(rows);
1617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=m2*v1.asDiagonal(), refM3=refM2*v1.asDiagonal());
1627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=m2.transpose()*v2.asDiagonal(), refM3=refM2.transpose()*v2.asDiagonal());
1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2, refM3=v2.asDiagonal()*refM2);
1647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=v1.asDiagonal()*m2.transpose(), refM3=v1.asDiagonal()*refM2.transpose());
1657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2*v1.asDiagonal(), refM3=v2.asDiagonal()*refM2*v1.asDiagonal());
1677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // evaluate to a dense matrix to check the .row() and .col() iterator functions
1697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(d3=m2*d1, refM3=refM2*d1);
1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(d3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
1717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(d3=d2*m2, refM3=d2*refM2);
1727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(d3=d1*m2.transpose(), refM3=d1*refM2.transpose());
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // test self adjoint products
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix b = DenseMatrix::Random(rows, rows);
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix x = DenseMatrix::Random(rows, rows);
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refX = DenseMatrix::Random(rows, rows);
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    DenseMatrix refS = DenseMatrix::Zero(rows, rows);
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType mUp(rows, rows);
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType mLo(rows, rows);
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType mS(rows, rows);
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    do {
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    } while (refUp.isZero());
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refLo = refUp.adjoint();
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mLo = mUp.adjoint();
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refS = refUp + refLo;
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refS.diagonal() *= 0.5;
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mS = mUp + mLo;
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // TODO be able to address the diagonal....
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int k=0; k<mS.outerSize(); ++k)
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if (it.index() == k)
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          it.valueRef() *= 0.5;
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(refS.adjoint(), refS);
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(mS.adjoint(), mS);
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(mS, refS);
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b);
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b);
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b);
2087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // sparse selfadjointView * sparse
2107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrixType mSres(rows,rows);
2117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(mSres = mLo.template selfadjointView<Lower>()*mS,
2127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                     refX = refLo.template selfadjointView<Lower>()*refS);
2137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // sparse * sparse selfadjointview
2147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    VERIFY_IS_APPROX(mSres = mS * mLo.template selfadjointView<Lower>(),
2157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                     refX = refS * refLo.template selfadjointView<Lower>());
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
2177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// New test for Bug in SparseTimeDenseProduct
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename SparseMatrixType, typename DenseMatrixType> void sparse_product_regression_test()
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // This code does not compile with afflicted versions of the bug
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  SparseMatrixType sm1(3,2);
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  DenseMatrixType m2(2,2);
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  sm1.setZero();
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2.setZero();
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  DenseMatrixType m3 = sm1*m2;
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // This code produces a segfault with afflicted versions of another SparseTimeDenseProduct
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // bug
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  SparseMatrixType sm2(20000,2);
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  sm2.setZero();
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  DenseMatrixType m4(sm2*m2);
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX( m4(0,0), 0.0 );
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_sparse_product()
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < g_repeat; i++) {
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,ColMajor> >()) );
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,RowMajor> >()) );
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, ColMajor > >()) );
248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, RowMajor > >()) );
2497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    CALL_SUBTEST_3( (sparse_product<SparseMatrix<float,ColMajor,long int> >()) );
250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_4( (sparse_product_regression_test<SparseMatrix<double,RowMajor>, Matrix<double, Dynamic, Dynamic, RowMajor> >()) );
251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
253