![]() |
Eigen
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008-2014 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_CWISE_BINARY_OP_H 00011 #define EIGEN_SPARSE_CWISE_BINARY_OP_H 00012 00013 namespace Eigen { 00014 00015 // Here we have to handle 3 cases: 00016 // 1 - sparse op dense 00017 // 2 - dense op sparse 00018 // 3 - sparse op sparse 00019 // We also need to implement a 4th iterator for: 00020 // 4 - dense op dense 00021 // Finally, we also need to distinguish between the product and other operations : 00022 // configuration returned mode 00023 // 1 - sparse op dense product sparse 00024 // generic dense 00025 // 2 - dense op sparse product sparse 00026 // generic dense 00027 // 3 - sparse op sparse product sparse 00028 // generic sparse 00029 // 4 - dense op dense product dense 00030 // generic dense 00031 // 00032 // TODO to ease compiler job, we could specialize product/quotient with a scalar 00033 // and fallback to cwise-unary evaluator using bind1st_op and bind2nd_op. 00034 00035 template<typename BinaryOp, typename Lhs, typename Rhs> 00036 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse> 00037 : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 00038 { 00039 public: 00040 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived; 00041 typedef SparseMatrixBase<Derived> Base; 00042 EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) 00043 CwiseBinaryOpImpl() 00044 { 00045 EIGEN_STATIC_ASSERT(( 00046 (!internal::is_same<typename internal::traits<Lhs>::StorageKind, 00047 typename internal::traits<Rhs>::StorageKind>::value) 00048 || ((internal::evaluator<Lhs>::Flags&RowMajorBit) == (internal::evaluator<Rhs>::Flags&RowMajorBit))), 00049 THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH); 00050 } 00051 }; 00052 00053 namespace internal { 00054 00055 00056 // Generic "sparse OP sparse" 00057 template<typename XprType> struct binary_sparse_evaluator; 00058 00059 template<typename BinaryOp, typename Lhs, typename Rhs> 00060 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased> 00061 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 00062 { 00063 protected: 00064 typedef typename evaluator<Lhs>::InnerIterator LhsIterator; 00065 typedef typename evaluator<Rhs>::InnerIterator RhsIterator; 00066 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType; 00067 typedef typename traits<XprType>::Scalar Scalar; 00068 typedef typename XprType::StorageIndex StorageIndex; 00069 public: 00070 00071 class InnerIterator 00072 { 00073 public: 00074 00075 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) 00076 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor) 00077 { 00078 this->operator++(); 00079 } 00080 00081 EIGEN_STRONG_INLINE InnerIterator& operator++() 00082 { 00083 if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) 00084 { 00085 m_id = m_lhsIter.index(); 00086 m_value = m_functor(m_lhsIter.value(), m_rhsIter.value()); 00087 ++m_lhsIter; 00088 ++m_rhsIter; 00089 } 00090 else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) 00091 { 00092 m_id = m_lhsIter.index(); 00093 m_value = m_functor(m_lhsIter.value(), Scalar(0)); 00094 ++m_lhsIter; 00095 } 00096 else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) 00097 { 00098 m_id = m_rhsIter.index(); 00099 m_value = m_functor(Scalar(0), m_rhsIter.value()); 00100 ++m_rhsIter; 00101 } 00102 else 00103 { 00104 m_value = 0; // this is to avoid a compilation warning 00105 m_id = -1; 00106 } 00107 return *this; 00108 } 00109 00110 EIGEN_STRONG_INLINE Scalar value() const { return m_value; } 00111 00112 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; } 00113 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); } 00114 EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); } 00115 EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); } 00116 00117 EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; } 00118 00119 protected: 00120 LhsIterator m_lhsIter; 00121 RhsIterator m_rhsIter; 00122 const BinaryOp& m_functor; 00123 Scalar m_value; 00124 StorageIndex m_id; 00125 }; 00126 00127 00128 enum { 00129 CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00130 Flags = XprType::Flags 00131 }; 00132 00133 explicit binary_evaluator(const XprType& xpr) 00134 : m_functor(xpr.functor()), 00135 m_lhsImpl(xpr.lhs()), 00136 m_rhsImpl(xpr.rhs()) 00137 { 00138 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00139 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00140 } 00141 00142 inline Index nonZerosEstimate() const { 00143 return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); 00144 } 00145 00146 protected: 00147 const BinaryOp m_functor; 00148 evaluator<Lhs> m_lhsImpl; 00149 evaluator<Rhs> m_rhsImpl; 00150 }; 00151 00152 // dense op sparse 00153 template<typename BinaryOp, typename Lhs, typename Rhs> 00154 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IteratorBased> 00155 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 00156 { 00157 protected: 00158 typedef typename evaluator<Rhs>::InnerIterator RhsIterator; 00159 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType; 00160 typedef typename traits<XprType>::Scalar Scalar; 00161 typedef typename XprType::StorageIndex StorageIndex; 00162 public: 00163 00164 class InnerIterator 00165 { 00166 enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit }; 00167 public: 00168 00169 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) 00170 : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_value(0), m_id(-1), m_innerSize(aEval.m_expr.rhs().innerSize()) 00171 { 00172 this->operator++(); 00173 } 00174 00175 EIGEN_STRONG_INLINE InnerIterator& operator++() 00176 { 00177 ++m_id; 00178 if(m_id<m_innerSize) 00179 { 00180 Scalar lhsVal = m_lhsEval.coeff(IsRowMajor?m_rhsIter.outer():m_id, 00181 IsRowMajor?m_id:m_rhsIter.outer()); 00182 if(m_rhsIter && m_rhsIter.index()==m_id) 00183 { 00184 m_value = m_functor(lhsVal, m_rhsIter.value()); 00185 ++m_rhsIter; 00186 } 00187 else 00188 m_value = m_functor(lhsVal, Scalar(0)); 00189 } 00190 00191 return *this; 00192 } 00193 00194 EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; } 00195 00196 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; } 00197 EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); } 00198 EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; } 00199 EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); } 00200 00201 EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; } 00202 00203 protected: 00204 const evaluator<Lhs> &m_lhsEval; 00205 RhsIterator m_rhsIter; 00206 const BinaryOp& m_functor; 00207 Scalar m_value; 00208 StorageIndex m_id; 00209 StorageIndex m_innerSize; 00210 }; 00211 00212 00213 enum { 00214 CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00215 // Expose storage order of the sparse expression 00216 Flags = (XprType::Flags & ~RowMajorBit) | (int(Rhs::Flags)&RowMajorBit) 00217 }; 00218 00219 explicit binary_evaluator(const XprType& xpr) 00220 : m_functor(xpr.functor()), 00221 m_lhsImpl(xpr.lhs()), 00222 m_rhsImpl(xpr.rhs()), 00223 m_expr(xpr) 00224 { 00225 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00226 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00227 } 00228 00229 inline Index nonZerosEstimate() const { 00230 return m_expr.size(); 00231 } 00232 00233 protected: 00234 const BinaryOp m_functor; 00235 evaluator<Lhs> m_lhsImpl; 00236 evaluator<Rhs> m_rhsImpl; 00237 const XprType &m_expr; 00238 }; 00239 00240 // sparse op dense 00241 template<typename BinaryOp, typename Lhs, typename Rhs> 00242 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IndexBased> 00243 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > 00244 { 00245 protected: 00246 typedef typename evaluator<Lhs>::InnerIterator LhsIterator; 00247 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType; 00248 typedef typename traits<XprType>::Scalar Scalar; 00249 typedef typename XprType::StorageIndex StorageIndex; 00250 public: 00251 00252 class InnerIterator 00253 { 00254 enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit }; 00255 public: 00256 00257 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) 00258 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_value(0), m_id(-1), m_innerSize(aEval.m_expr.lhs().innerSize()) 00259 { 00260 this->operator++(); 00261 } 00262 00263 EIGEN_STRONG_INLINE InnerIterator& operator++() 00264 { 00265 ++m_id; 00266 if(m_id<m_innerSize) 00267 { 00268 Scalar rhsVal = m_rhsEval.coeff(IsRowMajor?m_lhsIter.outer():m_id, 00269 IsRowMajor?m_id:m_lhsIter.outer()); 00270 if(m_lhsIter && m_lhsIter.index()==m_id) 00271 { 00272 m_value = m_functor(m_lhsIter.value(), rhsVal); 00273 ++m_lhsIter; 00274 } 00275 else 00276 m_value = m_functor(Scalar(0),rhsVal); 00277 } 00278 00279 return *this; 00280 } 00281 00282 EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; } 00283 00284 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; } 00285 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); } 00286 EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; } 00287 EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); } 00288 00289 EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; } 00290 00291 protected: 00292 LhsIterator m_lhsIter; 00293 const evaluator<Rhs> &m_rhsEval; 00294 const BinaryOp& m_functor; 00295 Scalar m_value; 00296 StorageIndex m_id; 00297 StorageIndex m_innerSize; 00298 }; 00299 00300 00301 enum { 00302 CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00303 // Expose storage order of the sparse expression 00304 Flags = (XprType::Flags & ~RowMajorBit) | (int(Lhs::Flags)&RowMajorBit) 00305 }; 00306 00307 explicit binary_evaluator(const XprType& xpr) 00308 : m_functor(xpr.functor()), 00309 m_lhsImpl(xpr.lhs()), 00310 m_rhsImpl(xpr.rhs()), 00311 m_expr(xpr) 00312 { 00313 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00314 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00315 } 00316 00317 inline Index nonZerosEstimate() const { 00318 return m_expr.size(); 00319 } 00320 00321 protected: 00322 const BinaryOp m_functor; 00323 evaluator<Lhs> m_lhsImpl; 00324 evaluator<Rhs> m_rhsImpl; 00325 const XprType &m_expr; 00326 }; 00327 00328 template<typename T, 00329 typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind, 00330 typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind, 00331 typename LhsScalar = typename traits<typename T::Lhs>::Scalar, 00332 typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct sparse_conjunction_evaluator; 00333 00334 // "sparse .* sparse" 00335 template<typename T1, typename T2, typename Lhs, typename Rhs> 00336 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IteratorBased> 00337 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> > 00338 { 00339 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType; 00340 typedef sparse_conjunction_evaluator<XprType> Base; 00341 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00342 }; 00343 // "dense .* sparse" 00344 template<typename T1, typename T2, typename Lhs, typename Rhs> 00345 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IndexBased, IteratorBased> 00346 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> > 00347 { 00348 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType; 00349 typedef sparse_conjunction_evaluator<XprType> Base; 00350 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00351 }; 00352 // "sparse .* dense" 00353 template<typename T1, typename T2, typename Lhs, typename Rhs> 00354 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased> 00355 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> > 00356 { 00357 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType; 00358 typedef sparse_conjunction_evaluator<XprType> Base; 00359 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00360 }; 00361 00362 // "sparse ./ dense" 00363 template<typename T1, typename T2, typename Lhs, typename Rhs> 00364 struct binary_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased> 00365 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> > 00366 { 00367 typedef CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> XprType; 00368 typedef sparse_conjunction_evaluator<XprType> Base; 00369 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00370 }; 00371 00372 // "sparse && sparse" 00373 template<typename Lhs, typename Rhs> 00374 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IteratorBased> 00375 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> > 00376 { 00377 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType; 00378 typedef sparse_conjunction_evaluator<XprType> Base; 00379 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00380 }; 00381 // "dense && sparse" 00382 template<typename Lhs, typename Rhs> 00383 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IndexBased, IteratorBased> 00384 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> > 00385 { 00386 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType; 00387 typedef sparse_conjunction_evaluator<XprType> Base; 00388 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00389 }; 00390 // "sparse && dense" 00391 template<typename Lhs, typename Rhs> 00392 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IndexBased> 00393 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> > 00394 { 00395 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType; 00396 typedef sparse_conjunction_evaluator<XprType> Base; 00397 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} 00398 }; 00399 00400 // "sparse ^ sparse" 00401 template<typename XprType> 00402 struct sparse_conjunction_evaluator<XprType, IteratorBased, IteratorBased> 00403 : evaluator_base<XprType> 00404 { 00405 protected: 00406 typedef typename XprType::Functor BinaryOp; 00407 typedef typename XprType::Lhs LhsArg; 00408 typedef typename XprType::Rhs RhsArg; 00409 typedef typename evaluator<LhsArg>::InnerIterator LhsIterator; 00410 typedef typename evaluator<RhsArg>::InnerIterator RhsIterator; 00411 typedef typename XprType::StorageIndex StorageIndex; 00412 typedef typename traits<XprType>::Scalar Scalar; 00413 public: 00414 00415 class InnerIterator 00416 { 00417 public: 00418 00419 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) 00420 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor) 00421 { 00422 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) 00423 { 00424 if (m_lhsIter.index() < m_rhsIter.index()) 00425 ++m_lhsIter; 00426 else 00427 ++m_rhsIter; 00428 } 00429 } 00430 00431 EIGEN_STRONG_INLINE InnerIterator& operator++() 00432 { 00433 ++m_lhsIter; 00434 ++m_rhsIter; 00435 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) 00436 { 00437 if (m_lhsIter.index() < m_rhsIter.index()) 00438 ++m_lhsIter; 00439 else 00440 ++m_rhsIter; 00441 } 00442 return *this; 00443 } 00444 00445 EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); } 00446 00447 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); } 00448 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); } 00449 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); } 00450 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); } 00451 00452 EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); } 00453 00454 protected: 00455 LhsIterator m_lhsIter; 00456 RhsIterator m_rhsIter; 00457 const BinaryOp& m_functor; 00458 }; 00459 00460 00461 enum { 00462 CoeffReadCost = evaluator<LhsArg>::CoeffReadCost + evaluator<RhsArg>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00463 Flags = XprType::Flags 00464 }; 00465 00466 explicit sparse_conjunction_evaluator(const XprType& xpr) 00467 : m_functor(xpr.functor()), 00468 m_lhsImpl(xpr.lhs()), 00469 m_rhsImpl(xpr.rhs()) 00470 { 00471 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00472 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00473 } 00474 00475 inline Index nonZerosEstimate() const { 00476 return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate()); 00477 } 00478 00479 protected: 00480 const BinaryOp m_functor; 00481 evaluator<LhsArg> m_lhsImpl; 00482 evaluator<RhsArg> m_rhsImpl; 00483 }; 00484 00485 // "dense ^ sparse" 00486 template<typename XprType> 00487 struct sparse_conjunction_evaluator<XprType, IndexBased, IteratorBased> 00488 : evaluator_base<XprType> 00489 { 00490 protected: 00491 typedef typename XprType::Functor BinaryOp; 00492 typedef typename XprType::Lhs LhsArg; 00493 typedef typename XprType::Rhs RhsArg; 00494 typedef evaluator<LhsArg> LhsEvaluator; 00495 typedef typename evaluator<RhsArg>::InnerIterator RhsIterator; 00496 typedef typename XprType::StorageIndex StorageIndex; 00497 typedef typename traits<XprType>::Scalar Scalar; 00498 public: 00499 00500 class InnerIterator 00501 { 00502 enum { IsRowMajor = (int(RhsArg::Flags)&RowMajorBit)==RowMajorBit }; 00503 00504 public: 00505 00506 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) 00507 : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer) 00508 {} 00509 00510 EIGEN_STRONG_INLINE InnerIterator& operator++() 00511 { 00512 ++m_rhsIter; 00513 return *this; 00514 } 00515 00516 EIGEN_STRONG_INLINE Scalar value() const 00517 { return m_functor(m_lhsEval.coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); } 00518 00519 EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); } 00520 EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); } 00521 EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); } 00522 EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); } 00523 00524 EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; } 00525 00526 protected: 00527 const LhsEvaluator &m_lhsEval; 00528 RhsIterator m_rhsIter; 00529 const BinaryOp& m_functor; 00530 const Index m_outer; 00531 }; 00532 00533 00534 enum { 00535 CoeffReadCost = evaluator<LhsArg>::CoeffReadCost + evaluator<RhsArg>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00536 // Expose storage order of the sparse expression 00537 Flags = (XprType::Flags & ~RowMajorBit) | (int(RhsArg::Flags)&RowMajorBit) 00538 }; 00539 00540 explicit sparse_conjunction_evaluator(const XprType& xpr) 00541 : m_functor(xpr.functor()), 00542 m_lhsImpl(xpr.lhs()), 00543 m_rhsImpl(xpr.rhs()) 00544 { 00545 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00546 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00547 } 00548 00549 inline Index nonZerosEstimate() const { 00550 return m_rhsImpl.nonZerosEstimate(); 00551 } 00552 00553 protected: 00554 const BinaryOp m_functor; 00555 evaluator<LhsArg> m_lhsImpl; 00556 evaluator<RhsArg> m_rhsImpl; 00557 }; 00558 00559 // "sparse ^ dense" 00560 template<typename XprType> 00561 struct sparse_conjunction_evaluator<XprType, IteratorBased, IndexBased> 00562 : evaluator_base<XprType> 00563 { 00564 protected: 00565 typedef typename XprType::Functor BinaryOp; 00566 typedef typename XprType::Lhs LhsArg; 00567 typedef typename XprType::Rhs RhsArg; 00568 typedef typename evaluator<LhsArg>::InnerIterator LhsIterator; 00569 typedef evaluator<RhsArg> RhsEvaluator; 00570 typedef typename XprType::StorageIndex StorageIndex; 00571 typedef typename traits<XprType>::Scalar Scalar; 00572 public: 00573 00574 class InnerIterator 00575 { 00576 enum { IsRowMajor = (int(LhsArg::Flags)&RowMajorBit)==RowMajorBit }; 00577 00578 public: 00579 00580 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) 00581 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer) 00582 {} 00583 00584 EIGEN_STRONG_INLINE InnerIterator& operator++() 00585 { 00586 ++m_lhsIter; 00587 return *this; 00588 } 00589 00590 EIGEN_STRONG_INLINE Scalar value() const 00591 { return m_functor(m_lhsIter.value(), 00592 m_rhsEval.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); } 00593 00594 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); } 00595 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); } 00596 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); } 00597 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); } 00598 00599 EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; } 00600 00601 protected: 00602 LhsIterator m_lhsIter; 00603 const evaluator<RhsArg> &m_rhsEval; 00604 const BinaryOp& m_functor; 00605 const Index m_outer; 00606 }; 00607 00608 00609 enum { 00610 CoeffReadCost = evaluator<LhsArg>::CoeffReadCost + evaluator<RhsArg>::CoeffReadCost + functor_traits<BinaryOp>::Cost, 00611 // Expose storage order of the sparse expression 00612 Flags = (XprType::Flags & ~RowMajorBit) | (int(LhsArg::Flags)&RowMajorBit) 00613 }; 00614 00615 explicit sparse_conjunction_evaluator(const XprType& xpr) 00616 : m_functor(xpr.functor()), 00617 m_lhsImpl(xpr.lhs()), 00618 m_rhsImpl(xpr.rhs()) 00619 { 00620 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost); 00621 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); 00622 } 00623 00624 inline Index nonZerosEstimate() const { 00625 return m_lhsImpl.nonZerosEstimate(); 00626 } 00627 00628 protected: 00629 const BinaryOp m_functor; 00630 evaluator<LhsArg> m_lhsImpl; 00631 evaluator<RhsArg> m_rhsImpl; 00632 }; 00633 00634 } 00635 00636 /*************************************************************************** 00637 * Implementation of SparseMatrixBase and SparseCwise functions/operators 00638 ***************************************************************************/ 00639 00640 template<typename Derived> 00641 template<typename OtherDerived> 00642 Derived& SparseMatrixBase<Derived>::operator+=(const EigenBase<OtherDerived> &other) 00643 { 00644 call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>()); 00645 return derived(); 00646 } 00647 00648 template<typename Derived> 00649 template<typename OtherDerived> 00650 Derived& SparseMatrixBase<Derived>::operator-=(const EigenBase<OtherDerived> &other) 00651 { 00652 call_assignment(derived(), other.derived(), internal::assign_op<Scalar,typename OtherDerived::Scalar>()); 00653 return derived(); 00654 } 00655 00656 template<typename Derived> 00657 template<typename OtherDerived> 00658 EIGEN_STRONG_INLINE Derived & 00659 SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other) 00660 { 00661 return derived() = derived() - other.derived(); 00662 } 00663 00664 template<typename Derived> 00665 template<typename OtherDerived> 00666 EIGEN_STRONG_INLINE Derived & 00667 SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other) 00668 { 00669 return derived() = derived() + other.derived(); 00670 } 00671 00672 template<typename Derived> 00673 template<typename OtherDerived> 00674 Derived& SparseMatrixBase<Derived>::operator+=(const DiagonalBase<OtherDerived>& other) 00675 { 00676 call_assignment_no_alias(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>()); 00677 return derived(); 00678 } 00679 00680 template<typename Derived> 00681 template<typename OtherDerived> 00682 Derived& SparseMatrixBase<Derived>::operator-=(const DiagonalBase<OtherDerived>& other) 00683 { 00684 call_assignment_no_alias(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>()); 00685 return derived(); 00686 } 00687 00688 template<typename Derived> 00689 template<typename OtherDerived> 00690 EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type 00691 SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const 00692 { 00693 return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived()); 00694 } 00695 00696 template<typename DenseDerived, typename SparseDerived> 00697 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived> 00698 operator+(const MatrixBase<DenseDerived> &a, const SparseMatrixBase<SparseDerived> &b) 00699 { 00700 return CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>(a.derived(), b.derived()); 00701 } 00702 00703 template<typename SparseDerived, typename DenseDerived> 00704 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived> 00705 operator+(const SparseMatrixBase<SparseDerived> &a, const MatrixBase<DenseDerived> &b) 00706 { 00707 return CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>(a.derived(), b.derived()); 00708 } 00709 00710 template<typename DenseDerived, typename SparseDerived> 00711 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived> 00712 operator-(const MatrixBase<DenseDerived> &a, const SparseMatrixBase<SparseDerived> &b) 00713 { 00714 return CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>(a.derived(), b.derived()); 00715 } 00716 00717 template<typename SparseDerived, typename DenseDerived> 00718 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived> 00719 operator-(const SparseMatrixBase<SparseDerived> &a, const MatrixBase<DenseDerived> &b) 00720 { 00721 return CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>(a.derived(), b.derived()); 00722 } 00723 00724 } // end namespace Eigen 00725 00726 #endif // EIGEN_SPARSE_CWISE_BINARY_OP_H