Eigen  3.3.3
SparseCwiseBinaryOp.h
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
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends