00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H
00026 #define EIGEN_SPARSE_CWISE_BINARY_OP_H
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 template<typename BinaryOp, typename Lhs, typename Rhs>
00046 struct ei_traits<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00047 {
00048 typedef typename ei_result_of<
00049 BinaryOp(
00050 typename Lhs::Scalar,
00051 typename Rhs::Scalar
00052 )
00053 >::type Scalar;
00054 typedef typename Lhs::Nested LhsNested;
00055 typedef typename Rhs::Nested RhsNested;
00056 typedef typename ei_unref<LhsNested>::type _LhsNested;
00057 typedef typename ei_unref<RhsNested>::type _RhsNested;
00058 enum {
00059 LhsCoeffReadCost = _LhsNested::CoeffReadCost,
00060 RhsCoeffReadCost = _RhsNested::CoeffReadCost,
00061 LhsFlags = _LhsNested::Flags,
00062 RhsFlags = _RhsNested::Flags,
00063 RowsAtCompileTime = Lhs::RowsAtCompileTime,
00064 ColsAtCompileTime = Lhs::ColsAtCompileTime,
00065 MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
00066 MaxColsAtCompileTime = Lhs::MaxColsAtCompileTime,
00067 Flags = (int(LhsFlags) | int(RhsFlags)) & HereditaryBits,
00068 CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
00069 };
00070 };
00071
00072 template<typename BinaryOp, typename Lhs, typename Rhs>
00073 class SparseCwiseBinaryOp : ei_no_assignment_operator,
00074 public SparseMatrixBase<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00075 {
00076 public:
00077
00078 class InnerIterator;
00079
00080 EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseBinaryOp)
00081 typedef typename ei_traits<SparseCwiseBinaryOp>::LhsNested LhsNested;
00082 typedef typename ei_traits<SparseCwiseBinaryOp>::RhsNested RhsNested;
00083 typedef typename ei_unref<LhsNested>::type _LhsNested;
00084 typedef typename ei_unref<RhsNested>::type _RhsNested;
00085
00086 EIGEN_STRONG_INLINE SparseCwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
00087 : m_lhs(lhs), m_rhs(rhs), m_functor(func)
00088 {
00089 EIGEN_STATIC_ASSERT((_LhsNested::Flags&RowMajorBit)==(_RhsNested::Flags&RowMajorBit),
00090 BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER)
00091 EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret
00092 ? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret)
00093 : int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)),
00094 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00095
00096 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
00097 ei_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
00098 }
00099
00100 EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
00101 EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
00102
00103 EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
00104 EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
00105 EIGEN_STRONG_INLINE const BinaryOp& functor() const { return m_functor; }
00106
00107 protected:
00108 const LhsNested m_lhs;
00109 const RhsNested m_rhs;
00110 const BinaryOp m_functor;
00111 };
00112
00113 template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
00114 int _LhsStorageMode = int(Lhs::Flags) & SparseBit,
00115 int _RhsStorageMode = int(Rhs::Flags) & SparseBit>
00116 class ei_sparse_cwise_binary_op_inner_iterator_selector;
00117
00118 template<typename BinaryOp, typename Lhs, typename Rhs>
00119 class SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
00120 : public ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs, typename SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
00121 {
00122 public:
00123 typedef ei_sparse_cwise_binary_op_inner_iterator_selector<
00124 BinaryOp,Lhs,Rhs, InnerIterator> Base;
00125
00126 EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseBinaryOp& binOp, int outer)
00127 : Base(binOp,outer)
00128 {}
00129 private:
00130 InnerIterator& operator=(const InnerIterator&);
00131 };
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
00144 class ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, IsSparse, IsSparse>
00145 {
00146 typedef SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
00147 typedef typename ei_traits<CwiseBinaryXpr>::Scalar Scalar;
00148 typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
00149 typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
00150 typedef typename _LhsNested::InnerIterator LhsIterator;
00151 typedef typename _RhsNested::InnerIterator RhsIterator;
00152 public:
00153
00154 EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
00155 : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
00156 {
00157 this->operator++();
00158 }
00159
00160 EIGEN_STRONG_INLINE Derived& operator++()
00161 {
00162 if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
00163 {
00164 m_id = m_lhsIter.index();
00165 m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
00166 ++m_lhsIter;
00167 ++m_rhsIter;
00168 }
00169 else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
00170 {
00171 m_id = m_lhsIter.index();
00172 m_value = m_functor(m_lhsIter.value(), Scalar(0));
00173 ++m_lhsIter;
00174 }
00175 else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
00176 {
00177 m_id = m_rhsIter.index();
00178 m_value = m_functor(Scalar(0), m_rhsIter.value());
00179 ++m_rhsIter;
00180 }
00181 else
00182 {
00183 m_id = -1;
00184 }
00185 return *static_cast<Derived*>(this);
00186 }
00187
00188 EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
00189
00190 EIGEN_STRONG_INLINE int index() const { return m_id; }
00191 EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
00192 EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
00193
00194 EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
00195
00196 protected:
00197 LhsIterator m_lhsIter;
00198 RhsIterator m_rhsIter;
00199 const BinaryOp& m_functor;
00200 Scalar m_value;
00201 int m_id;
00202
00203 private:
00204 ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
00205 };
00206
00207
00208 template<typename T, typename Lhs, typename Rhs, typename Derived>
00209 class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsSparse>
00210 {
00211 typedef ei_scalar_product_op<T> BinaryFunc;
00212 typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
00213 typedef typename CwiseBinaryXpr::Scalar Scalar;
00214 typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
00215 typedef typename _LhsNested::InnerIterator LhsIterator;
00216 typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
00217 typedef typename _RhsNested::InnerIterator RhsIterator;
00218 public:
00219
00220 EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
00221 : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
00222 {
00223 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
00224 {
00225 if (m_lhsIter.index() < m_rhsIter.index())
00226 ++m_lhsIter;
00227 else
00228 ++m_rhsIter;
00229 }
00230 }
00231
00232 EIGEN_STRONG_INLINE Derived& operator++()
00233 {
00234 ++m_lhsIter;
00235 ++m_rhsIter;
00236 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
00237 {
00238 if (m_lhsIter.index() < m_rhsIter.index())
00239 ++m_lhsIter;
00240 else
00241 ++m_rhsIter;
00242 }
00243 return *static_cast<Derived*>(this);
00244 }
00245
00246 EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
00247
00248 EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
00249 EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
00250 EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
00251
00252 EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
00253
00254 protected:
00255 LhsIterator m_lhsIter;
00256 RhsIterator m_rhsIter;
00257 const BinaryFunc& m_functor;
00258
00259 private:
00260 ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
00261 };
00262
00263
00264 template<typename T, typename Lhs, typename Rhs, typename Derived>
00265 class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsDense>
00266 {
00267 typedef ei_scalar_product_op<T> BinaryFunc;
00268 typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
00269 typedef typename CwiseBinaryXpr::Scalar Scalar;
00270 typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
00271 typedef typename ei_traits<CwiseBinaryXpr>::RhsNested RhsNested;
00272 typedef typename _LhsNested::InnerIterator LhsIterator;
00273 enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
00274 public:
00275
00276 EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
00277 : m_rhs(xpr.rhs()), m_lhsIter(xpr.lhs(),outer), m_functor(xpr.functor()), m_outer(outer)
00278 {}
00279
00280 EIGEN_STRONG_INLINE Derived& operator++()
00281 {
00282 ++m_lhsIter;
00283 return *static_cast<Derived*>(this);
00284 }
00285
00286 EIGEN_STRONG_INLINE Scalar value() const
00287 { return m_functor(m_lhsIter.value(),
00288 m_rhs.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
00289
00290 EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
00291 EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
00292 EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
00293
00294 EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
00295
00296 protected:
00297 const RhsNested m_rhs;
00298 LhsIterator m_lhsIter;
00299 const BinaryFunc m_functor;
00300 const int m_outer;
00301
00302 private:
00303 ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
00304 };
00305
00306
00307 template<typename T, typename Lhs, typename Rhs, typename Derived>
00308 class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsDense, IsSparse>
00309 {
00310 typedef ei_scalar_product_op<T> BinaryFunc;
00311 typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
00312 typedef typename CwiseBinaryXpr::Scalar Scalar;
00313 typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
00314 typedef typename _RhsNested::InnerIterator RhsIterator;
00315 enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
00316 public:
00317
00318 EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
00319 : m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
00320 {}
00321
00322 EIGEN_STRONG_INLINE Derived& operator++()
00323 {
00324 ++m_rhsIter;
00325 return *static_cast<Derived*>(this);
00326 }
00327
00328 EIGEN_STRONG_INLINE Scalar value() const
00329 { return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
00330
00331 EIGEN_STRONG_INLINE int index() const { return m_rhsIter.index(); }
00332 EIGEN_STRONG_INLINE int row() const { return m_rhsIter.row(); }
00333 EIGEN_STRONG_INLINE int col() const { return m_rhsIter.col(); }
00334
00335 EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
00336
00337 protected:
00338 const CwiseBinaryXpr& m_xpr;
00339 RhsIterator m_rhsIter;
00340 const BinaryFunc& m_functor;
00341 const int m_outer;
00342 };
00343
00344
00345
00346
00347
00348
00349 template<typename Derived>
00350 template<typename OtherDerived>
00351 EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
00352 Derived, OtherDerived>
00353 SparseMatrixBase<Derived>::operator-(const SparseMatrixBase<OtherDerived> &other) const
00354 {
00355 return SparseCwiseBinaryOp<ei_scalar_difference_op<Scalar>,
00356 Derived, OtherDerived>(derived(), other.derived());
00357 }
00358
00359 template<typename Derived>
00360 template<typename OtherDerived>
00361 EIGEN_STRONG_INLINE Derived &
00362 SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
00363 {
00364 return *this = derived() - other.derived();
00365 }
00366
00367 template<typename Derived>
00368 template<typename OtherDerived>
00369 EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
00370 SparseMatrixBase<Derived>::operator+(const SparseMatrixBase<OtherDerived> &other) const
00371 {
00372 return SparseCwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
00373 }
00374
00375 template<typename Derived>
00376 template<typename OtherDerived>
00377 EIGEN_STRONG_INLINE Derived &
00378 SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
00379 {
00380 return *this = derived() + other.derived();
00381 }
00382
00383 template<typename ExpressionType>
00384 template<typename OtherDerived>
00385 EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
00386 SparseCwise<ExpressionType>::operator*(const SparseMatrixBase<OtherDerived> &other) const
00387 {
00388 return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
00389 }
00390
00391 template<typename ExpressionType>
00392 template<typename OtherDerived>
00393 EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
00394 SparseCwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
00395 {
00396 return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 template<typename ExpressionType>
00416 template<typename OtherDerived>
00417 inline ExpressionType& SparseCwise<ExpressionType>::operator*=(const SparseMatrixBase<OtherDerived> &other)
00418 {
00419 return m_matrix.const_cast_derived() = _expression() * other.derived();
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429 template<typename ExpressionType>
00430 template<typename OtherDerived>
00431 EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
00432 SparseCwise<ExpressionType>::min(const SparseMatrixBase<OtherDerived> &other) const
00433 {
00434 return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
00435 }
00436
00437 template<typename ExpressionType>
00438 template<typename OtherDerived>
00439 EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
00440 SparseCwise<ExpressionType>::max(const SparseMatrixBase<OtherDerived> &other) const
00441 {
00442 return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 #endif // EIGEN_SPARSE_CWISE_BINARY_OP_H