aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
diff options
context:
space:
mode:
Diffstat (limited to 'Eigen/src/SparseCore/SparseCwiseBinaryOp.h')
-rw-r--r--Eigen/src/SparseCore/SparseCwiseBinaryOp.h316
1 files changed, 183 insertions, 133 deletions
diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
index 60fdd214a..94ca9b1a4 100644
--- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
+++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -31,12 +31,6 @@ namespace Eigen {
namespace internal {
-template<> struct promote_storage_type<Dense,Sparse>
-{ typedef Sparse ret; };
-
-template<> struct promote_storage_type<Sparse,Dense>
-{ typedef Sparse ret; };
-
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
typename _LhsStorageMode = typename traits<Lhs>::StorageKind,
typename _RhsStorageMode = typename traits<Rhs>::StorageKind>
@@ -44,71 +38,35 @@ class sparse_cwise_binary_op_inner_iterator_selector;
} // end namespace internal
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
- : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
-{
- public:
- class InnerIterator;
- class ReverseInnerIterator;
- typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
- EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
- CwiseBinaryOpImpl()
- {
- typedef typename internal::traits<Lhs>::StorageKind LhsStorageKind;
- typedef typename internal::traits<Rhs>::StorageKind RhsStorageKind;
- EIGEN_STATIC_ASSERT((
- (!internal::is_same<LhsStorageKind,RhsStorageKind>::value)
- || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
- THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
- }
-};
-
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator
- : public internal::sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs,typename CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator>
-{
- public:
- typedef internal::sparse_cwise_binary_op_inner_iterator_selector<
- BinaryOp,Lhs,Rhs, InnerIterator> Base;
-
- EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, Index outer)
- : Base(binOp.derived(),outer)
- {}
-};
-
-/***************************************************************************
-* Implementation of inner-iterators
-***************************************************************************/
-
-// template<typename T> struct internal::func_is_conjunction { enum { ret = false }; };
-// template<typename T> struct internal::func_is_conjunction<internal::scalar_product_op<T> > { enum { ret = true }; };
-
-// TODO generalize the internal::scalar_product_op specialization to all conjunctions if any !
-
namespace internal {
-// sparse - sparse (generic)
-template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, Sparse, Sparse>
+
+// Generic "sparse OP sparse"
+template<typename BinaryOp, typename Lhs, typename Rhs>
+struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
+ : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
- typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename traits<CwiseBinaryXpr>::Scalar Scalar;
- typedef typename traits<CwiseBinaryXpr>::Index Index;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- typedef typename _RhsNested::InnerIterator RhsIterator;
+protected:
+ typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
+ typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
+public:
+ typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
+
+ class ReverseInnerIterator;
+ class InnerIterator
+ {
+ typedef typename traits<XprType>::Scalar Scalar;
+ typedef typename XprType::Index Index;
public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
+
+ EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
+ : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
{
this->operator++();
}
- EIGEN_STRONG_INLINE Derived& operator++()
+ EIGEN_STRONG_INLINE InnerIterator& operator++()
{
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
{
@@ -134,7 +92,7 @@ class sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived
m_value = 0; // this is to avoid a compilation warning
m_id = -1;
}
- return *static_cast<Derived*>(this);
+ return *this;
}
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
@@ -151,24 +109,48 @@ class sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived
const BinaryOp& m_functor;
Scalar m_value;
Index m_id;
+ };
+
+
+ enum {
+ CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
+ Flags = XprType::Flags
+ };
+
+ explicit binary_evaluator(const XprType& xpr)
+ : m_functor(xpr.functor()),
+ m_lhsImpl(xpr.lhs()),
+ m_rhsImpl(xpr.rhs())
+ { }
+
+protected:
+ const BinaryOp m_functor;
+ typename evaluator<Lhs>::nestedType m_lhsImpl;
+ typename evaluator<Rhs>::nestedType m_rhsImpl;
};
-// sparse - sparse (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Sparse, Sparse>
+// "sparse .* sparse"
+template<typename T, typename Lhs, typename Rhs>
+struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IteratorBased, IteratorBased>
+ : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename CwiseBinaryXpr::Index Index;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _RhsNested::InnerIterator RhsIterator;
- public:
+protected:
+ typedef scalar_product_op<T> BinaryOp;
+ typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
+ typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
+public:
+ typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
+
+ class ReverseInnerIterator;
+ class InnerIterator
+ {
+ typedef typename traits<XprType>::Scalar Scalar;
+ typedef typename XprType::Index Index;
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
+ public:
+
+ EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
+ : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
{
while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
{
@@ -179,7 +161,7 @@ class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs,
}
}
- EIGEN_STRONG_INLINE Derived& operator++()
+ EIGEN_STRONG_INLINE InnerIterator& operator++()
{
++m_lhsIter;
++m_rhsIter;
@@ -190,9 +172,9 @@ class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs,
else
++m_rhsIter;
}
- return *static_cast<Derived*>(this);
+ return *this;
}
-
+
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
EIGEN_STRONG_INLINE Index index() const { return m_lhsIter.index(); }
@@ -204,91 +186,159 @@ class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs,
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
- const BinaryFunc& m_functor;
+ const BinaryOp& m_functor;
+ };
+
+
+ enum {
+ CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
+ Flags = XprType::Flags
+ };
+
+ explicit binary_evaluator(const XprType& xpr)
+ : m_functor(xpr.functor()),
+ m_lhsImpl(xpr.lhs()),
+ m_rhsImpl(xpr.rhs())
+ { }
+
+protected:
+ const BinaryOp m_functor;
+ typename evaluator<Lhs>::nestedType m_lhsImpl;
+ typename evaluator<Rhs>::nestedType m_rhsImpl;
};
-// sparse - dense (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Sparse, Dense>
+// "dense .* sparse"
+template<typename T, typename Lhs, typename Rhs>
+struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IndexBased, IteratorBased>
+ : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename CwiseBinaryXpr::Index Index;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename traits<CwiseBinaryXpr>::RhsNested RhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
- public:
+protected:
+ typedef scalar_product_op<T> BinaryOp;
+ typedef typename evaluator<Lhs>::type LhsEvaluator;
+ typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
+public:
+ typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
+
+ class ReverseInnerIterator;
+ class InnerIterator
+ {
+ typedef typename traits<XprType>::Scalar Scalar;
+ typedef typename XprType::Index Index;
+ enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_rhs(xpr.rhs()), m_lhsIter(xpr.lhs(),typename _LhsNested::Index(outer)), m_functor(xpr.functor()), m_outer(outer)
+ public:
+
+ EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
+ : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer)
{}
- EIGEN_STRONG_INLINE Derived& operator++()
+ EIGEN_STRONG_INLINE InnerIterator& operator++()
{
- ++m_lhsIter;
- return *static_cast<Derived*>(this);
+ ++m_rhsIter;
+ return *this;
}
EIGEN_STRONG_INLINE Scalar value() const
- { return m_functor(m_lhsIter.value(),
- m_rhs.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
+ { return m_functor(m_lhsEval.coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
- EIGEN_STRONG_INLINE Index index() const { return m_lhsIter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
+ EIGEN_STRONG_INLINE Index index() const { return m_rhsIter.index(); }
+ EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
+ EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
- EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
+ EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
protected:
- RhsNested m_rhs;
- LhsIterator m_lhsIter;
- const BinaryFunc m_functor;
+ const LhsEvaluator &m_lhsEval;
+ RhsIterator m_rhsIter;
+ const BinaryOp& m_functor;
const Index m_outer;
+ };
+
+
+ enum {
+ CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
+ Flags = XprType::Flags
+ };
+
+ explicit binary_evaluator(const XprType& xpr)
+ : m_functor(xpr.functor()),
+ m_lhsImpl(xpr.lhs()),
+ m_rhsImpl(xpr.rhs())
+ { }
+
+protected:
+ const BinaryOp m_functor;
+ typename evaluator<Lhs>::nestedType m_lhsImpl;
+ typename evaluator<Rhs>::nestedType m_rhsImpl;
};
-// sparse - dense (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Dense, Sparse>
+// "sparse .* dense"
+template<typename T, typename Lhs, typename Rhs>
+struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IteratorBased, IndexBased>
+ : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename CwiseBinaryXpr::Index Index;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _RhsNested::InnerIterator RhsIterator;
+protected:
+ typedef scalar_product_op<T> BinaryOp;
+ typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
+ typedef typename evaluator<Rhs>::type RhsEvaluator;
+public:
+ typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
+
+ class ReverseInnerIterator;
+ class InnerIterator
+ {
+ typedef typename traits<XprType>::Scalar Scalar;
+ typedef typename XprType::Index Index;
+ enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
- enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
+
+ EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
+ : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer)
{}
- EIGEN_STRONG_INLINE Derived& operator++()
+ EIGEN_STRONG_INLINE InnerIterator& operator++()
{
- ++m_rhsIter;
- return *static_cast<Derived*>(this);
+ ++m_lhsIter;
+ return *this;
}
EIGEN_STRONG_INLINE Scalar value() const
- { return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
+ { return m_functor(m_lhsIter.value(),
+ m_rhsEval.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
- EIGEN_STRONG_INLINE Index index() const { return m_rhsIter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
+ EIGEN_STRONG_INLINE Index index() const { return m_lhsIter.index(); }
+ EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
+ EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
- EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
+ EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
protected:
- const CwiseBinaryXpr& m_xpr;
- RhsIterator m_rhsIter;
- const BinaryFunc& m_functor;
+ LhsIterator m_lhsIter;
+ const RhsEvaluator &m_rhsEval;
+ const BinaryOp& m_functor;
const Index m_outer;
+ };
+
+
+ enum {
+ CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
+ Flags = XprType::Flags
+ };
+
+ explicit binary_evaluator(const XprType& xpr)
+ : m_functor(xpr.functor()),
+ m_lhsImpl(xpr.lhs()),
+ m_rhsImpl(xpr.rhs())
+ { }
+
+protected:
+ const BinaryOp m_functor;
+ typename evaluator<Lhs>::nestedType m_lhsImpl;
+ typename evaluator<Rhs>::nestedType m_rhsImpl;
};
-} // end namespace internal
+}
/***************************************************************************
* Implementation of SparseMatrixBase and SparseCwise functions/operators