SparseSparseProductWithPruning.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H
11 #define EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 namespace Eigen {
16 
17 namespace internal {
18 
19 
20 // perform a pseudo in-place sparse * sparse product assuming all matrices are col major
21 template<typename Lhs, typename Rhs, typename ResultType>
22 static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, const typename ResultType::RealScalar& tolerance)
23 {
24  // return sparse_sparse_product_with_pruning_impl2(lhs,rhs,res);
25 
26  typedef typename remove_all_t<Rhs>::Scalar RhsScalar;
27  typedef typename remove_all_t<ResultType>::Scalar ResScalar;
28  typedef typename remove_all_t<Lhs>::StorageIndex StorageIndex;
29 
30  // make sure to call innerSize/outerSize since we fake the storage order.
31  Index rows = lhs.innerSize();
32  Index cols = rhs.outerSize();
33  //Index size = lhs.outerSize();
34  eigen_assert(lhs.outerSize() == rhs.innerSize());
35 
36  // allocate a temporary buffer
37  AmbiVector<ResScalar,StorageIndex> tempVector(rows);
38 
39  // mimics a resizeByInnerOuter:
40  if(ResultType::IsRowMajor)
41  res.resize(cols, rows);
42  else
43  res.resize(rows, cols);
44 
45  evaluator<Lhs> lhsEval(lhs);
46  evaluator<Rhs> rhsEval(rhs);
47 
48  // estimate the number of non zero entries
49  // given a rhs column containing Y non zeros, we assume that the respective Y columns
50  // of the lhs differs in average of one non zeros, thus the number of non zeros for
51  // the product of a rhs column with the lhs is X+Y where X is the average number of non zero
52  // per column of the lhs.
53  // Therefore, we have nnz(lhs*rhs) = nnz(lhs) + nnz(rhs)
54  Index estimated_nnz_prod = lhsEval.nonZerosEstimate() + rhsEval.nonZerosEstimate();
55 
56  res.reserve(estimated_nnz_prod);
57  double ratioColRes = double(estimated_nnz_prod)/(double(lhs.rows())*double(rhs.cols()));
58  for (Index j=0; j<cols; ++j)
59  {
60  // FIXME:
61  //double ratioColRes = (double(rhs.innerVector(j).nonZeros()) + double(lhs.nonZeros())/double(lhs.cols()))/double(lhs.rows());
62  // let's do a more accurate determination of the nnz ratio for the current column j of res
63  tempVector.init(ratioColRes);
64  tempVector.setZero();
65  for (typename evaluator<Rhs>::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt)
66  {
67  // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index())
68  tempVector.restart();
69  RhsScalar x = rhsIt.value();
70  for (typename evaluator<Lhs>::InnerIterator lhsIt(lhsEval, rhsIt.index()); lhsIt; ++lhsIt)
71  {
72  tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x;
73  }
74  }
75  res.startVec(j);
76  for (typename AmbiVector<ResScalar,StorageIndex>::Iterator it(tempVector,tolerance); it; ++it)
77  res.insertBackByOuterInner(j,it.index()) = it.value();
78  }
79  res.finalize();
80 }
81 
82 template<typename Lhs, typename Rhs, typename ResultType,
83  int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit,
84  int RhsStorageOrder = traits<Rhs>::Flags&RowMajorBit,
85  int ResStorageOrder = traits<ResultType>::Flags&RowMajorBit>
86 struct sparse_sparse_product_with_pruning_selector;
87 
88 template<typename Lhs, typename Rhs, typename ResultType>
89 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,ColMajor>
90 {
91  typedef typename ResultType::RealScalar RealScalar;
92 
93  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
94  {
95  remove_all_t<ResultType> _res(res.rows(), res.cols());
96  internal::sparse_sparse_product_with_pruning_impl<Lhs,Rhs,ResultType>(lhs, rhs, _res, tolerance);
97  res.swap(_res);
98  }
99 };
100 
101 template<typename Lhs, typename Rhs, typename ResultType>
102 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,RowMajor>
103 {
104  typedef typename ResultType::RealScalar RealScalar;
105  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
106  {
107  // we need a col-major matrix to hold the result
108  typedef SparseMatrix<typename ResultType::Scalar,ColMajor,typename ResultType::StorageIndex> SparseTemporaryType;
109  SparseTemporaryType _res(res.rows(), res.cols());
110  internal::sparse_sparse_product_with_pruning_impl<Lhs,Rhs,SparseTemporaryType>(lhs, rhs, _res, tolerance);
111  res = _res;
112  }
113 };
114 
115 template<typename Lhs, typename Rhs, typename ResultType>
116 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,RowMajor>
117 {
118  typedef typename ResultType::RealScalar RealScalar;
119  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
120  {
121  // let's transpose the product to get a column x column product
122  remove_all_t<ResultType> _res(res.rows(), res.cols());
123  internal::sparse_sparse_product_with_pruning_impl<Rhs,Lhs,ResultType>(rhs, lhs, _res, tolerance);
124  res.swap(_res);
125  }
126 };
127 
128 template<typename Lhs, typename Rhs, typename ResultType>
129 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
130 {
131  typedef typename ResultType::RealScalar RealScalar;
132  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
133  {
134  typedef SparseMatrix<typename Lhs::Scalar,ColMajor,typename Lhs::StorageIndex> ColMajorMatrixLhs;
135  typedef SparseMatrix<typename Rhs::Scalar,ColMajor,typename Lhs::StorageIndex> ColMajorMatrixRhs;
136  ColMajorMatrixLhs colLhs(lhs);
137  ColMajorMatrixRhs colRhs(rhs);
138  internal::sparse_sparse_product_with_pruning_impl<ColMajorMatrixLhs,ColMajorMatrixRhs,ResultType>(colLhs, colRhs, res, tolerance);
139 
140  // let's transpose the product to get a column x column product
141 // typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
142 // SparseTemporaryType _res(res.cols(), res.rows());
143 // sparse_sparse_product_with_pruning_impl<Rhs,Lhs,SparseTemporaryType>(rhs, lhs, _res);
144 // res = _res.transpose();
145  }
146 };
147 
148 template<typename Lhs, typename Rhs, typename ResultType>
149 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,RowMajor,RowMajor>
150 {
151  typedef typename ResultType::RealScalar RealScalar;
152  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
153  {
154  typedef SparseMatrix<typename Lhs::Scalar,RowMajor,typename Lhs::StorageIndex> RowMajorMatrixLhs;
155  RowMajorMatrixLhs rowLhs(lhs);
156  sparse_sparse_product_with_pruning_selector<RowMajorMatrixLhs,Rhs,ResultType,RowMajor,RowMajor>(rowLhs,rhs,res,tolerance);
157  }
158 };
159 
160 template<typename Lhs, typename Rhs, typename ResultType>
161 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,ColMajor,RowMajor>
162 {
163  typedef typename ResultType::RealScalar RealScalar;
164  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
165  {
166  typedef SparseMatrix<typename Rhs::Scalar,RowMajor,typename Lhs::StorageIndex> RowMajorMatrixRhs;
167  RowMajorMatrixRhs rowRhs(rhs);
168  sparse_sparse_product_with_pruning_selector<Lhs,RowMajorMatrixRhs,ResultType,RowMajor,RowMajor,RowMajor>(lhs,rowRhs,res,tolerance);
169  }
170 };
171 
172 template<typename Lhs, typename Rhs, typename ResultType>
173 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,ColMajor,RowMajor,ColMajor>
174 {
175  typedef typename ResultType::RealScalar RealScalar;
176  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
177  {
178  typedef SparseMatrix<typename Rhs::Scalar,ColMajor,typename Lhs::StorageIndex> ColMajorMatrixRhs;
179  ColMajorMatrixRhs colRhs(rhs);
180  internal::sparse_sparse_product_with_pruning_impl<Lhs,ColMajorMatrixRhs,ResultType>(lhs, colRhs, res, tolerance);
181  }
182 };
183 
184 template<typename Lhs, typename Rhs, typename ResultType>
185 struct sparse_sparse_product_with_pruning_selector<Lhs,Rhs,ResultType,RowMajor,ColMajor,ColMajor>
186 {
187  typedef typename ResultType::RealScalar RealScalar;
188  static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance)
189  {
190  typedef SparseMatrix<typename Lhs::Scalar,ColMajor,typename Lhs::StorageIndex> ColMajorMatrixLhs;
191  ColMajorMatrixLhs colLhs(lhs);
192  internal::sparse_sparse_product_with_pruning_impl<ColMajorMatrixLhs,Rhs,ResultType>(colLhs, rhs, res, tolerance);
193  }
194 };
195 
196 } // end namespace internal
197 
198 } // end namespace Eigen
199 
200 #endif // EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H
#define eigen_assert(x)
Definition: Macros.h:902
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
@ ColMajor
Definition: Constants.h:321
@ RowMajor
Definition: Constants.h:323
const unsigned int RowMajorBit
Definition: Constants.h:68
static void sparse_sparse_product_with_pruning_impl(const Lhs &lhs, const Rhs &rhs, ResultType &res, const typename ResultType::RealScalar &tolerance)
typename remove_all< T >::type remove_all_t
Definition: Meta.h:119
: InteropHeaders
Definition: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
std::ptrdiff_t j