00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef EIGEN_SPARSEPRODUCT_H
00011 #define EIGEN_SPARSEPRODUCT_H
00012
00013 namespace Eigen {
00014
00015 template<typename Lhs, typename Rhs>
00016 struct SparseSparseProductReturnType
00017 {
00018 typedef typename internal::traits<Lhs>::Scalar Scalar;
00019 typedef typename internal::traits<Lhs>::Index Index;
00020 enum {
00021 LhsRowMajor = internal::traits<Lhs>::Flags & RowMajorBit,
00022 RhsRowMajor = internal::traits<Rhs>::Flags & RowMajorBit,
00023 TransposeRhs = (!LhsRowMajor) && RhsRowMajor,
00024 TransposeLhs = LhsRowMajor && (!RhsRowMajor)
00025 };
00026
00027 typedef typename internal::conditional<TransposeLhs,
00028 SparseMatrix<Scalar,0,Index>,
00029 typename internal::nested<Lhs,Rhs::RowsAtCompileTime>::type>::type LhsNested;
00030
00031 typedef typename internal::conditional<TransposeRhs,
00032 SparseMatrix<Scalar,0,Index>,
00033 typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type>::type RhsNested;
00034
00035 typedef SparseSparseProduct<LhsNested, RhsNested> Type;
00036 };
00037
00038 namespace internal {
00039 template<typename LhsNested, typename RhsNested>
00040 struct traits<SparseSparseProduct<LhsNested, RhsNested> >
00041 {
00042 typedef MatrixXpr XprKind;
00043
00044 typedef typename remove_all<LhsNested>::type _LhsNested;
00045 typedef typename remove_all<RhsNested>::type _RhsNested;
00046 typedef typename _LhsNested::Scalar Scalar;
00047 typedef typename promote_index_type<typename traits<_LhsNested>::Index,
00048 typename traits<_RhsNested>::Index>::type Index;
00049
00050 enum {
00051 LhsCoeffReadCost = _LhsNested::CoeffReadCost,
00052 RhsCoeffReadCost = _RhsNested::CoeffReadCost,
00053 LhsFlags = _LhsNested::Flags,
00054 RhsFlags = _RhsNested::Flags,
00055
00056 RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
00057 ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
00058 MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
00059 MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
00060
00061 InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
00062
00063 EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
00064
00065 RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
00066
00067 Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
00068 | EvalBeforeAssigningBit
00069 | EvalBeforeNestingBit,
00070
00071 CoeffReadCost = Dynamic
00072 };
00073
00074 typedef Sparse StorageKind;
00075 };
00076
00077 }
00078
00079 template<typename LhsNested, typename RhsNested>
00080 class SparseSparseProduct : internal::no_assignment_operator,
00081 public SparseMatrixBase<SparseSparseProduct<LhsNested, RhsNested> >
00082 {
00083 public:
00084
00085 typedef SparseMatrixBase<SparseSparseProduct> Base;
00086 EIGEN_DENSE_PUBLIC_INTERFACE(SparseSparseProduct)
00087
00088 private:
00089
00090 typedef typename internal::traits<SparseSparseProduct>::_LhsNested _LhsNested;
00091 typedef typename internal::traits<SparseSparseProduct>::_RhsNested _RhsNested;
00092
00093 public:
00094
00095 template<typename Lhs, typename Rhs>
00096 EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs)
00097 : m_lhs(lhs), m_rhs(rhs), m_tolerance(0), m_conservative(true)
00098 {
00099 init();
00100 }
00101
00102 template<typename Lhs, typename Rhs>
00103 EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs, const RealScalar& tolerance)
00104 : m_lhs(lhs), m_rhs(rhs), m_tolerance(tolerance), m_conservative(false)
00105 {
00106 init();
00107 }
00108
00109 SparseSparseProduct pruned(const Scalar& reference = 0, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) const
00110 {
00111 using std::abs;
00112 return SparseSparseProduct(m_lhs,m_rhs,abs(reference)*epsilon);
00113 }
00114
00115 template<typename Dest>
00116 void evalTo(Dest& result) const
00117 {
00118 if(m_conservative)
00119 internal::conservative_sparse_sparse_product_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result);
00120 else
00121 internal::sparse_sparse_product_with_pruning_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result,m_tolerance);
00122 }
00123
00124 EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
00125 EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
00126
00127 EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
00128 EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
00129
00130 protected:
00131 void init()
00132 {
00133 eigen_assert(m_lhs.cols() == m_rhs.rows());
00134
00135 enum {
00136 ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic
00137 || _RhsNested::RowsAtCompileTime==Dynamic
00138 || int(_LhsNested::ColsAtCompileTime)==int(_RhsNested::RowsAtCompileTime),
00139 AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime,
00140 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested,_RhsNested)
00141 };
00142
00143
00144
00145 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
00146 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
00147 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
00148 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
00149 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
00150 }
00151
00152 LhsNested m_lhs;
00153 RhsNested m_rhs;
00154 RealScalar m_tolerance;
00155 bool m_conservative;
00156 };
00157
00158
00159 template<typename Derived>
00160 template<typename Lhs, typename Rhs>
00161 inline Derived& SparseMatrixBase<Derived>::operator=(const SparseSparseProduct<Lhs,Rhs>& product)
00162 {
00163 product.evalTo(derived());
00164 return derived();
00165 }
00166
00178 template<typename Derived>
00179 template<typename OtherDerived>
00180 inline const typename SparseSparseProductReturnType<Derived,OtherDerived>::Type
00181 SparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const
00182 {
00183 return typename SparseSparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
00184 }
00185
00186 }
00187
00188 #endif // EIGEN_SPARSEPRODUCT_H