diff --git a/Eigen/SparseCore b/Eigen/SparseCore index 799cb1ba1..4ad6f47a0 100644 --- a/Eigen/SparseCore +++ b/Eigen/SparseCore @@ -44,8 +44,8 @@ struct Sparse {}; #include "src/SparseCore/SparseCwiseUnaryOp.h" #include "src/SparseCore/SparseCwiseBinaryOp.h" #include "src/SparseCore/SparseTranspose.h" -#ifndef EIGEN_TEST_EVALUATORS #include "src/SparseCore/SparseBlock.h" +#ifndef EIGEN_TEST_EVALUATORS #include "src/SparseCore/SparseDot.h" #include "src/SparseCore/SparsePermutation.h" #include "src/SparseCore/SparseRedux.h" diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index 70e457028..0f3ab304a 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -122,6 +122,8 @@ template class typedef Impl Base; EIGEN_GENERIC_PUBLIC_INTERFACE(Block) EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) + + typedef typename internal::remove_all::type NestedExpression; /** Column or Row constructor */ diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index b56c3c635..81b4d63bf 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -737,13 +737,25 @@ struct evaluator > evaluator(const XprType& block) : block_evaluator_type(block) {} }; +// no direct-access => dispatch to a unary evaluator template struct block_evaluator - : evaluator_base > + : unary_evaluator > { typedef Block XprType; block_evaluator(const XprType& block) + : unary_evaluator(block) + {} +}; + +template +struct unary_evaluator, IndexBased> + : evaluator_base > +{ + typedef Block XprType; + + unary_evaluator(const XprType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), m_startCol(block.startCol()) diff --git a/Eigen/src/SparseCore/SparseAssign.h b/Eigen/src/SparseCore/SparseAssign.h index 99a1a8712..d4434e0ae 100644 --- a/Eigen/src/SparseCore/SparseAssign.h +++ b/Eigen/src/SparseCore/SparseAssign.h @@ -181,7 +181,6 @@ void assign_sparse_to_sparse(DstXprType &dst, const SrcXprType &src) typedef typename internal::evaluator::type DstEvaluatorType; typedef typename internal::evaluator::type SrcEvaluatorType; - DstEvaluatorType dstEvaluator(dst); SrcEvaluatorType srcEvaluator(src); const bool transpose = (DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit); diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h index 5b95cc33f..4926f6923 100644 --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2008-2014 Gael Guennebaud // // 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 @@ -12,6 +12,7 @@ namespace Eigen { +// Subset of columns or rows template class BlockImpl : public SparseMatrixBase > @@ -25,6 +26,7 @@ protected: public: EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) +#ifndef EIGEN_TEST_EVALUATORS class InnerIterator: public XprType::InnerIterator { typedef typename BlockImpl::Index Index; @@ -49,6 +51,7 @@ public: protected: Index m_outer; }; +#endif // EIGEN_TEST_EVALUATORS inline BlockImpl(const XprType& xpr, int i) : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize) @@ -63,13 +66,30 @@ public: Index nonZeros() const { - Index nnz = 0; +#ifndef EIGEN_TEST_EVALUATORS + typedef typename internal::evaluator::type EvaluatorType; Index end = m_outerStart + m_outerSize.value(); for(int j=m_outerStart; j::type EvaluatorType; + EvaluatorType matEval(m_matrix); + Index nnz = 0; + Index end = m_outerStart + m_outerSize.value(); + for(int j=m_outerStart; j InnerIterator; class ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator @@ -431,6 +458,14 @@ public: inline operator bool() const { return Base::operator bool() && Base::index() >= m_begin; } }; +#endif // EIGEN_TEST_EVALUATORS + + inline const _MatrixTypeNested& nestedExpression() const { return m_matrix; } + Index startRow() const { return m_startRow.value(); } + Index startCol() const { return m_startCol.value(); } + Index blockRows() const { return m_blockRows.value(); } + Index blockCols() const { return m_blockCols.value(); } + protected: friend class internal::GenericSparseBlockInnerIteratorImpl; friend class ReverseInnerIterator; @@ -535,7 +570,127 @@ namespace internal { inline operator bool() const { return m_outerPos < m_end; } }; + +#ifdef EIGEN_TEST_EVALUATORS + +// +template +struct unary_evaluator, IteratorBased > + : public evaluator_base > +{ + class InnerVectorInnerIterator; + class OuterVectorInnerIterator; + public: + typedef Block XprType; + typedef typename XprType::Index Index; + typedef typename XprType::Scalar Scalar; + + class ReverseInnerIterator; + + enum { + IsRowMajor = XprType::IsRowMajor, + + OuterVector = (BlockCols==1 && ArgType::IsRowMajor) + | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". + // revert to || as soon as not needed anymore. + (BlockRows==1 && !ArgType::IsRowMajor), + + CoeffReadCost = evaluator::CoeffReadCost, + Flags = XprType::Flags + }; + + typedef typename internal::conditional::type InnerIterator; + + unary_evaluator(const XprType& op) + : m_argImpl(op.nestedExpression()), m_block(op) + {} + + protected: + typedef typename evaluator::InnerIterator EvalIterator; + typedef typename evaluator::ReverseInnerIterator EvalReverseIterator; + + typename evaluator::nestedType m_argImpl; + const XprType &m_block; +}; + +template +class unary_evaluator, IteratorBased>::InnerVectorInnerIterator + : public EvalIterator +{ + const XprType& m_block; + Index m_end; +public: + + EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer) + : EvalIterator(aEval.m_argImpl, outer + (IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())), + m_block(aEval.m_block), + m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) + { + while( (EvalIterator::operator bool()) && (EvalIterator::index() < (IsRowMajor ? m_block.startCol() : m_block.startRow())) ) + EvalIterator::operator++(); + } + inline Index index() const { return EvalIterator::index() - (IsRowMajor ? m_block.startCol() : m_block.startRow()); } + inline Index outer() const { return EvalIterator::outer() - (IsRowMajor ? m_block.startRow() : m_block.startCol()); } + inline Index row() const { return EvalIterator::row() - m_block.startRow(); } + inline Index col() const { return EvalIterator::col() - m_block.startCol(); } + + inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; } +}; + +template +class unary_evaluator, IteratorBased>::OuterVectorInnerIterator +{ + const XprType& m_block; + Index m_outerPos; + Index m_innerIndex; + Scalar m_value; + Index m_end; +public: + + EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer) + : m_block(aEval.m_block), + m_outerPos( (IsRowMajor ? aEval.startCol() : aEval.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry + m_innerIndex(IsRowMajor ? aEval.startRow() : aEval.startCol()), + m_end(IsRowMajor ? aEval.startCol()+aEval.blockCols() : aEval.startRow()+aEval.blockRows()) + { + EIGEN_UNUSED_VARIABLE(outer); + eigen_assert(outer==0); + + ++(*this); + } + + inline Index index() const { return m_outerPos - (IsRowMajor ? m_block.startCol() : m_block.startRow()); } + inline Index outer() const { return 0; } + inline Index row() const { return IsRowMajor ? 0 : index(); } + inline Index col() const { return IsRowMajor ? index() : 0; } + + inline Scalar value() const { return m_value; } + + inline OuterVectorInnerIterator& operator++() + { + // search next non-zero entry + while(m_outerPos