10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This file is part of Eigen, a lightweight C++ template library
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// for linear algebra.
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This Source Code Form is subject to the terms of the Mozilla
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Public License v. 2.0. If a copy of the MPL was not distributed
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifndef EIGEN_SPARSEPRODUCT_H
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define EIGEN_SPARSEPRODUCT_H
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace Eigen {
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename Lhs, typename Rhs>
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct SparseSparseProductReturnType
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org{
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef typename internal::traits<Lhs>::Scalar Scalar;
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef typename internal::traits<Lhs>::Index Index;
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  enum {
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LhsRowMajor = internal::traits<Lhs>::Flags & RowMajorBit,
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RhsRowMajor = internal::traits<Rhs>::Flags & RowMajorBit,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransposeRhs = (!LhsRowMajor) && RhsRowMajor,
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransposeLhs = LhsRowMajor && (!RhsRowMajor)
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  };
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef typename internal::conditional<TransposeLhs,
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SparseMatrix<Scalar,0,Index>,
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    typename internal::nested<Lhs,Rhs::RowsAtCompileTime>::type>::type LhsNested;
30a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef typename internal::conditional<TransposeRhs,
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SparseMatrix<Scalar,0,Index>,
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type>::type RhsNested;
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef SparseSparseProduct<LhsNested, RhsNested> Type;
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace internal {
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename LhsNested, typename RhsNested>
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct traits<SparseSparseProduct<LhsNested, RhsNested> >
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org{
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef MatrixXpr XprKind;
432007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  // clean the nested types:
442007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  typedef typename remove_all<LhsNested>::type _LhsNested;
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef typename remove_all<RhsNested>::type _RhsNested;
462007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  typedef typename _LhsNested::Scalar Scalar;
472007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  typedef typename promote_index_type<typename traits<_LhsNested>::Index,
482007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org                                         typename traits<_RhsNested>::Index>::type Index;
492007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org
502007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  enum {
512007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    LhsCoeffReadCost = _LhsNested::CoeffReadCost,
522007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    RhsCoeffReadCost = _RhsNested::CoeffReadCost,
532007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    LhsFlags = _LhsNested::Flags,
542007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    RhsFlags = _RhsNested::Flags,
552007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RowsAtCompileTime    = _LhsNested::RowsAtCompileTime,
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ColsAtCompileTime    = _RhsNested::ColsAtCompileTime,
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          | EvalBeforeAssigningBit
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          | EvalBeforeNestingBit,
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CoeffReadCost = Dynamic
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  };
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef Sparse StorageKind;
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // end namespace internal
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename LhsNested, typename RhsNested>
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass SparseSparseProduct : internal::no_assignment_operator,
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  public SparseMatrixBase<SparseSparseProduct<LhsNested, RhsNested> >
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org{
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  public:
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    typedef SparseMatrixBase<SparseSparseProduct> Base;
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EIGEN_DENSE_PUBLIC_INTERFACE(SparseSparseProduct)
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  private:
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    typedef typename internal::traits<SparseSparseProduct>::_LhsNested _LhsNested;
91e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    typedef typename internal::traits<SparseSparseProduct>::_RhsNested _RhsNested;
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  public:
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    template<typename Lhs, typename Rhs>
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs)
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : m_lhs(lhs), m_rhs(rhs), m_tolerance(0), m_conservative(true)
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    {
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      init();
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
102e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    template<typename Lhs, typename Rhs>
1032007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs, const RealScalar& tolerance)
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : m_lhs(lhs), m_rhs(rhs), m_tolerance(tolerance), m_conservative(false)
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    {
1065aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org      init();
1072007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    }
1085aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org
1095aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org    SparseSparseProduct pruned(const Scalar& reference = 0, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) const
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    {
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      using std::abs;
1122007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      return SparseSparseProduct(m_lhs,m_rhs,abs(reference)*epsilon);
1132007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    }
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    template<typename Dest>
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    void evalTo(Dest& result) const
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    {
1182007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      if(m_conservative)
1192007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org        internal::conservative_sparse_sparse_product_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result);
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      else
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        internal::sparse_sparse_product_with_pruning_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result,m_tolerance);
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1232007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org
1242007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org    EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  protected:
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    void init()
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    {
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      eigen_assert(m_lhs.cols() == m_rhs.rows());
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      enum {
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      || _RhsNested::RowsAtCompileTime==Dynamic
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      || int(_LhsNested::ColsAtCompileTime)==int(_RhsNested::RowsAtCompileTime),
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime,
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested,_RhsNested)
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      };
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // note to the lost user:
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      //    * for a dot product use: v1.dot(v2)
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      //    * for a coeff-wise product use: v1.cwise()*v2
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LhsNested m_lhs;
153e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    RhsNested m_rhs;
154e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    RealScalar m_tolerance;
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    bool m_conservative;
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// sparse = sparse * sparse
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename Derived>
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename Lhs, typename Rhs>
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline Derived& SparseMatrixBase<Derived>::operator=(const SparseSparseProduct<Lhs,Rhs>& product)
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org{
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  product.evalTo(derived());
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return derived();
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/** \returns an expression of the product of two sparse matrices.
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * By default a conservative product preserving the symbolic non zeros is performed.
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * The automatic pruning of the small values can be achieved by calling the pruned() function
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * in which case a totally different product algorithm is employed:
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * \code
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * C = (A*B).pruned();             // supress numerical zeros (exact)
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * C = (A*B).pruned(ref);
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * C = (A*B).pruned(ref,epsilon);
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * \endcode
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * where \c ref is a meaningful non zero reference value.
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  * */
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename Derived>
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<typename OtherDerived>
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline const typename SparseSparseProductReturnType<Derived,OtherDerived>::Type
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org{
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return typename SparseSparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // end namespace Eigen
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // EIGEN_SPARSEPRODUCT_H
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org