![]() |
Eigen
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2009-2015 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H 00011 #define EIGEN_SPARSE_DIAGONAL_PRODUCT_H 00012 00013 namespace Eigen { 00014 00015 // The product of a diagonal matrix with a sparse matrix can be easily 00016 // implemented using expression template. 00017 // We have two consider very different cases: 00018 // 1 - diag * row-major sparse 00019 // => each inner vector <=> scalar * sparse vector product 00020 // => so we can reuse CwiseUnaryOp::InnerIterator 00021 // 2 - diag * col-major sparse 00022 // => each inner vector <=> densevector * sparse vector cwise product 00023 // => again, we can reuse specialization of CwiseBinaryOp::InnerIterator 00024 // for that particular case 00025 // The two other cases are symmetric. 00026 00027 namespace internal { 00028 00029 enum { 00030 SDP_AsScalarProduct, 00031 SDP_AsCwiseProduct 00032 }; 00033 00034 template<typename SparseXprType, typename DiagonalCoeffType, int SDP_Tag> 00035 struct sparse_diagonal_product_evaluator; 00036 00037 template<typename Lhs, typename Rhs, int ProductTag> 00038 struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseShape> 00039 : public sparse_diagonal_product_evaluator<Rhs, typename Lhs::DiagonalVectorType, Rhs::Flags&RowMajorBit?SDP_AsScalarProduct:SDP_AsCwiseProduct> 00040 { 00041 typedef Product<Lhs, Rhs, DefaultProduct> XprType; 00042 enum { CoeffReadCost = HugeCost, Flags = Rhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags 00043 00044 typedef sparse_diagonal_product_evaluator<Rhs, typename Lhs::DiagonalVectorType, Rhs::Flags&RowMajorBit?SDP_AsScalarProduct:SDP_AsCwiseProduct> Base; 00045 explicit product_evaluator(const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {} 00046 }; 00047 00048 template<typename Lhs, typename Rhs, int ProductTag> 00049 struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseShape, DiagonalShape> 00050 : public sparse_diagonal_product_evaluator<Lhs, Transpose<const typename Rhs::DiagonalVectorType>, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct> 00051 { 00052 typedef Product<Lhs, Rhs, DefaultProduct> XprType; 00053 enum { CoeffReadCost = HugeCost, Flags = Lhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags 00054 00055 typedef sparse_diagonal_product_evaluator<Lhs, Transpose<const typename Rhs::DiagonalVectorType>, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct> Base; 00056 explicit product_evaluator(const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal().transpose()) {} 00057 }; 00058 00059 template<typename SparseXprType, typename DiagonalCoeffType> 00060 struct sparse_diagonal_product_evaluator<SparseXprType, DiagonalCoeffType, SDP_AsScalarProduct> 00061 { 00062 protected: 00063 typedef typename evaluator<SparseXprType>::InnerIterator SparseXprInnerIterator; 00064 typedef typename SparseXprType::Scalar Scalar; 00065 00066 public: 00067 class InnerIterator : public SparseXprInnerIterator 00068 { 00069 public: 00070 InnerIterator(const sparse_diagonal_product_evaluator &xprEval, Index outer) 00071 : SparseXprInnerIterator(xprEval.m_sparseXprImpl, outer), 00072 m_coeff(xprEval.m_diagCoeffImpl.coeff(outer)) 00073 {} 00074 00075 EIGEN_STRONG_INLINE Scalar value() const { return m_coeff * SparseXprInnerIterator::value(); } 00076 protected: 00077 typename DiagonalCoeffType::Scalar m_coeff; 00078 }; 00079 00080 sparse_diagonal_product_evaluator(const SparseXprType &sparseXpr, const DiagonalCoeffType &diagCoeff) 00081 : m_sparseXprImpl(sparseXpr), m_diagCoeffImpl(diagCoeff) 00082 {} 00083 00084 Index nonZerosEstimate() const { return m_sparseXprImpl.nonZerosEstimate(); } 00085 00086 protected: 00087 evaluator<SparseXprType> m_sparseXprImpl; 00088 evaluator<DiagonalCoeffType> m_diagCoeffImpl; 00089 }; 00090 00091 00092 template<typename SparseXprType, typename DiagCoeffType> 00093 struct sparse_diagonal_product_evaluator<SparseXprType, DiagCoeffType, SDP_AsCwiseProduct> 00094 { 00095 typedef typename SparseXprType::Scalar Scalar; 00096 typedef typename SparseXprType::StorageIndex StorageIndex; 00097 00098 typedef typename nested_eval<DiagCoeffType,SparseXprType::IsRowMajor ? SparseXprType::RowsAtCompileTime 00099 : SparseXprType::ColsAtCompileTime>::type DiagCoeffNested; 00100 00101 class InnerIterator 00102 { 00103 typedef typename evaluator<SparseXprType>::InnerIterator SparseXprIter; 00104 public: 00105 InnerIterator(const sparse_diagonal_product_evaluator &xprEval, Index outer) 00106 : m_sparseIter(xprEval.m_sparseXprEval, outer), m_diagCoeffNested(xprEval.m_diagCoeffNested) 00107 {} 00108 00109 inline Scalar value() const { return m_sparseIter.value() * m_diagCoeffNested.coeff(index()); } 00110 inline StorageIndex index() const { return m_sparseIter.index(); } 00111 inline Index outer() const { return m_sparseIter.outer(); } 00112 inline Index col() const { return SparseXprType::IsRowMajor ? m_sparseIter.index() : m_sparseIter.outer(); } 00113 inline Index row() const { return SparseXprType::IsRowMajor ? m_sparseIter.outer() : m_sparseIter.index(); } 00114 00115 EIGEN_STRONG_INLINE InnerIterator& operator++() { ++m_sparseIter; return *this; } 00116 inline operator bool() const { return m_sparseIter; } 00117 00118 protected: 00119 SparseXprIter m_sparseIter; 00120 DiagCoeffNested m_diagCoeffNested; 00121 }; 00122 00123 sparse_diagonal_product_evaluator(const SparseXprType &sparseXpr, const DiagCoeffType &diagCoeff) 00124 : m_sparseXprEval(sparseXpr), m_diagCoeffNested(diagCoeff) 00125 {} 00126 00127 Index nonZerosEstimate() const { return m_sparseXprEval.nonZerosEstimate(); } 00128 00129 protected: 00130 evaluator<SparseXprType> m_sparseXprEval; 00131 DiagCoeffNested m_diagCoeffNested; 00132 }; 00133 00134 } // end namespace internal 00135 00136 } // end namespace Eigen 00137 00138 #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H