// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2011 Benoit Jacob // Copyright (C) 2011 Gael Guennebaud // Copyright (C) 2011-2012 Jitse Niesen // // 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 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COREEVALUATORS_H #define EIGEN_COREEVALUATORS_H namespace Eigen { namespace internal { // evaluator_traits contains traits for evaluator_impl template struct evaluator_traits { // 1 if evaluator_impl::evalTo() exists // 0 if evaluator_impl allows coefficient-based access static const int HasEvalTo = 0; // 1 if assignment A = B assumes aliasing when B is of type T and thus B needs to be evaluated into a // temporary; 0 if not. static const int AssumeAliasing = 0; }; // expression class for evaluating nested expression to a temporary template class EvalToTemp; // evaluator::type is type of evaluator for T // evaluator::nestedType is type of evaluator if T is nested inside another evaluator template struct evaluator_impl { }; template::HasEvalTo> struct evaluator_nested_type; template struct evaluator_nested_type { typedef evaluator_impl type; }; template struct evaluator_nested_type { typedef evaluator_impl > type; }; template struct evaluator { typedef evaluator_impl type; typedef typename evaluator_nested_type::type nestedType; }; // TODO: Think about const-correctness template struct evaluator : evaluator { }; // ---------- base class for all writable evaluators ---------- // TODO this class does not seem to be necessary anymore template struct evaluator_impl_base { typedef typename ExpressionType::Index Index; // TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices. typedef traits ExpressionTraits; evaluator_impl& derived() { return *static_cast*>(this); } }; // -------------------- Matrix and Array -------------------- // // evaluator_impl is a common base class for the // Matrix and Array evaluators. template struct evaluator_impl > : evaluator_impl_base { typedef PlainObjectBase PlainObjectType; enum { IsRowMajor = PlainObjectType::IsRowMajor, IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime, RowsAtCompileTime = PlainObjectType::RowsAtCompileTime, ColsAtCompileTime = PlainObjectType::ColsAtCompileTime }; evaluator_impl(const PlainObjectType& m) : m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride()) { } typedef typename PlainObjectType::Index Index; typedef typename PlainObjectType::Scalar Scalar; typedef typename PlainObjectType::CoeffReturnType CoeffReturnType; typedef typename PlainObjectType::PacketScalar PacketScalar; typedef typename PlainObjectType::PacketReturnType PacketReturnType; CoeffReturnType coeff(Index row, Index col) const { if (IsRowMajor) return m_data[row * m_outerStride.value() + col]; else return m_data[row + col * m_outerStride.value()]; } CoeffReturnType coeff(Index index) const { return m_data[index]; } Scalar& coeffRef(Index row, Index col) { if (IsRowMajor) return const_cast(m_data)[row * m_outerStride.value() + col]; else return const_cast(m_data)[row + col * m_outerStride.value()]; } Scalar& coeffRef(Index index) { return const_cast(m_data)[index]; } template PacketReturnType packet(Index row, Index col) const { if (IsRowMajor) return ploadt(m_data + row * m_outerStride.value() + col); else return ploadt(m_data + row + col * m_outerStride.value()); } template PacketReturnType packet(Index index) const { return ploadt(m_data + index); } template void writePacket(Index row, Index col, const PacketScalar& x) { if (IsRowMajor) return pstoret (const_cast(m_data) + row * m_outerStride.value() + col, x); else return pstoret (const_cast(m_data) + row + col * m_outerStride.value(), x); } template void writePacket(Index index, const PacketScalar& x) { return pstoret(const_cast(m_data) + index, x); } protected: const Scalar *m_data; // We do not need to know the outer stride for vectors variable_if_dynamic m_outerStride; }; template struct evaluator_impl > : evaluator_impl > > { typedef Matrix XprType; evaluator_impl(const XprType& m) : evaluator_impl >(m) { } }; template struct evaluator_impl > : evaluator_impl > > { typedef Array XprType; evaluator_impl(const XprType& m) : evaluator_impl >(m) { } }; // -------------------- EvalToTemp -------------------- template struct traits > : public traits { }; template class EvalToTemp : public dense_xpr_base >::type { public: typedef typename dense_xpr_base::type Base; EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp) EvalToTemp(const ArgType& arg) : m_arg(arg) { } const ArgType& arg() const { return m_arg; } Index rows() const { return m_arg.rows(); } Index cols() const { return m_arg.cols(); } private: const ArgType& m_arg; }; template struct evaluator_impl > { typedef EvalToTemp XprType; typedef typename ArgType::PlainObject PlainObject; evaluator_impl(const XprType& xpr) : m_result(xpr.rows(), xpr.cols()), m_resultImpl(m_result) { // TODO we should simply do m_result(xpr.arg()); call_dense_assignment_loop(m_result, xpr.arg()); } // This constructor is used when nesting an EvalTo evaluator in another evaluator evaluator_impl(const ArgType& arg) : m_result(arg.rows(), arg.cols()), m_resultImpl(m_result) { // TODO we should simply do m_result(xpr.arg()); call_dense_assignment_loop(m_result, arg); } typedef typename PlainObject::Index Index; typedef typename PlainObject::Scalar Scalar; typedef typename PlainObject::CoeffReturnType CoeffReturnType; typedef typename PlainObject::PacketScalar PacketScalar; typedef typename PlainObject::PacketReturnType PacketReturnType; // All other functions are forwarded to m_resultImpl CoeffReturnType coeff(Index row, Index col) const { return m_resultImpl.coeff(row, col); } CoeffReturnType coeff(Index index) const { return m_resultImpl.coeff(index); } Scalar& coeffRef(Index row, Index col) { return m_resultImpl.coeffRef(row, col); } Scalar& coeffRef(Index index) { return m_resultImpl.coeffRef(index); } template PacketReturnType packet(Index row, Index col) const { return m_resultImpl.template packet(row, col); } template PacketReturnType packet(Index index) const { return m_resultImpl.packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_resultImpl.template writePacket(row, col, x); } template void writePacket(Index index, const PacketScalar& x) { m_resultImpl.template writePacket(index, x); } protected: PlainObject m_result; typename evaluator::nestedType m_resultImpl; }; // -------------------- Transpose -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef Transpose XprType; evaluator_impl(const XprType& t) : m_argImpl(t.nestedExpression()) {} typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; CoeffReturnType coeff(Index row, Index col) const { return m_argImpl.coeff(col, row); } CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(index); } Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(col, row); } typename XprType::Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } template PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(col, row); } template PacketReturnType packet(Index index) const { return m_argImpl.template packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket(col, row, x); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket(index, x); } protected: typename evaluator::nestedType m_argImpl; }; // -------------------- CwiseNullaryOp -------------------- template struct evaluator_impl > { typedef CwiseNullaryOp XprType; evaluator_impl(const XprType& n) : m_functor(n.functor()) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; CoeffReturnType coeff(Index row, Index col) const { return m_functor(row, col); } CoeffReturnType coeff(Index index) const { return m_functor(index); } template PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(row, col); } template PacketScalar packet(Index index) const { return m_functor.packetOp(index); } protected: const NullaryOp m_functor; }; // -------------------- CwiseUnaryOp -------------------- template struct evaluator_impl > { typedef CwiseUnaryOp XprType; evaluator_impl(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; CoeffReturnType coeff(Index row, Index col) const { return m_functor(m_argImpl.coeff(row, col)); } CoeffReturnType coeff(Index index) const { return m_functor(m_argImpl.coeff(index)); } template PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(m_argImpl.template packet(row, col)); } template PacketScalar packet(Index index) const { return m_functor.packetOp(m_argImpl.template packet(index)); } protected: const UnaryOp m_functor; typename evaluator::nestedType m_argImpl; }; // -------------------- CwiseBinaryOp -------------------- template struct evaluator_impl > { typedef CwiseBinaryOp XprType; evaluator_impl(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; CoeffReturnType coeff(Index row, Index col) const { return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col)); } CoeffReturnType coeff(Index index) const { return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index)); } template PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(m_lhsImpl.template packet(row, col), m_rhsImpl.template packet(row, col)); } template PacketScalar packet(Index index) const { return m_functor.packetOp(m_lhsImpl.template packet(index), m_rhsImpl.template packet(index)); } protected: const BinaryOp m_functor; typename evaluator::nestedType m_lhsImpl; typename evaluator::nestedType m_rhsImpl; }; // -------------------- CwiseUnaryView -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef CwiseUnaryView XprType; evaluator_impl(const XprType& op) : m_unaryOp(op.functor()), m_argImpl(op.nestedExpression()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; CoeffReturnType coeff(Index row, Index col) const { return m_unaryOp(m_argImpl.coeff(row, col)); } CoeffReturnType coeff(Index index) const { return m_unaryOp(m_argImpl.coeff(index)); } Scalar& coeffRef(Index row, Index col) { return m_unaryOp(m_argImpl.coeffRef(row, col)); } Scalar& coeffRef(Index index) { return m_unaryOp(m_argImpl.coeffRef(index)); } protected: const UnaryOp m_unaryOp; typename evaluator::nestedType m_argImpl; }; // -------------------- Map -------------------- template struct evaluator_impl > : evaluator_impl_base { typedef MapBase MapType; typedef Derived XprType; typedef typename XprType::PointerType PointerType; typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; evaluator_impl(const XprType& map) : m_data(const_cast(map.data())), m_rowStride(map.rowStride()), m_colStride(map.colStride()) { } enum { RowsAtCompileTime = XprType::RowsAtCompileTime }; CoeffReturnType coeff(Index row, Index col) const { return m_data[col * m_colStride + row * m_rowStride]; } CoeffReturnType coeff(Index index) const { return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } Scalar& coeffRef(Index row, Index col) { return m_data[col * m_colStride + row * m_rowStride]; } Scalar& coeffRef(Index index) { return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template PacketReturnType packet(Index row, Index col) const { PointerType ptr = m_data + row * m_rowStride + col * m_colStride; return internal::ploadt(ptr); } template PacketReturnType packet(Index index) const { return packet(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template void writePacket(Index row, Index col, const PacketScalar& x) { PointerType ptr = m_data + row * m_rowStride + col * m_colStride; return internal::pstoret(ptr, x); } template void writePacket(Index index, const PacketScalar& x) { return writePacket(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, x); } protected: PointerType m_data; int m_rowStride; int m_colStride; }; template struct evaluator_impl > : public evaluator_impl > > { typedef Map XprType; evaluator_impl(const XprType& map) : evaluator_impl >(map) { } }; // -------------------- Block -------------------- template::ret> struct block_evaluator; template struct evaluator_impl > : block_evaluator { typedef Block XprType; typedef block_evaluator block_evaluator_type; evaluator_impl(const XprType& block) : block_evaluator_type(block) {} }; template struct block_evaluator : evaluator_impl_base > { typedef Block XprType; block_evaluator(const XprType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), m_startCol(block.startCol()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; enum { RowsAtCompileTime = XprType::RowsAtCompileTime }; CoeffReturnType coeff(Index row, Index col) const { return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col); } CoeffReturnType coeff(Index index) const { return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col); } Scalar& coeffRef(Index index) { return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(m_startRow.value() + row, m_startCol.value() + col); } template PacketReturnType packet(Index index) const { return packet(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template void writePacket(Index row, Index col, const PacketScalar& x) { return m_argImpl.template writePacket(m_startRow.value() + row, m_startCol.value() + col, x); } template void writePacket(Index index, const PacketScalar& x) { return writePacket(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, x); } protected: typename evaluator::nestedType m_argImpl; const variable_if_dynamic m_startRow; const variable_if_dynamic m_startCol; }; // TODO: This evaluator does not actually use the child evaluator; // all action is via the data() as returned by the Block expression. template struct block_evaluator : evaluator_impl > > { typedef Block XprType; block_evaluator(const XprType& block) : evaluator_impl >(block) { } }; // -------------------- Select -------------------- template struct evaluator_impl > { typedef Select XprType; evaluator_impl(const XprType& select) : m_conditionImpl(select.conditionMatrix()), m_thenImpl(select.thenMatrix()), m_elseImpl(select.elseMatrix()) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; CoeffReturnType coeff(Index row, Index col) const { if (m_conditionImpl.coeff(row, col)) return m_thenImpl.coeff(row, col); else return m_elseImpl.coeff(row, col); } CoeffReturnType coeff(Index index) const { if (m_conditionImpl.coeff(index)) return m_thenImpl.coeff(index); else return m_elseImpl.coeff(index); } protected: typename evaluator::nestedType m_conditionImpl; typename evaluator::nestedType m_thenImpl; typename evaluator::nestedType m_elseImpl; }; // -------------------- Replicate -------------------- template struct evaluator_impl > { typedef Replicate XprType; evaluator_impl(const XprType& replicate) : m_argImpl(replicate.nestedExpression()), m_rows(replicate.nestedExpression().rows()), m_cols(replicate.nestedExpression().cols()) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketReturnType PacketReturnType; CoeffReturnType coeff(Index row, Index col) const { // try to avoid using modulo; this is a pure optimization strategy const Index actual_row = internal::traits::RowsAtCompileTime==1 ? 0 : RowFactor==1 ? row : row % m_rows.value(); const Index actual_col = internal::traits::ColsAtCompileTime==1 ? 0 : ColFactor==1 ? col : col % m_cols.value(); return m_argImpl.coeff(actual_row, actual_col); } template PacketReturnType packet(Index row, Index col) const { const Index actual_row = internal::traits::RowsAtCompileTime==1 ? 0 : RowFactor==1 ? row : row % m_rows.value(); const Index actual_col = internal::traits::ColsAtCompileTime==1 ? 0 : ColFactor==1 ? col : col % m_cols.value(); return m_argImpl.template packet(actual_row, actual_col); } protected: typename evaluator::nestedType m_argImpl; const variable_if_dynamic m_rows; const variable_if_dynamic m_cols; }; // -------------------- PartialReduxExpr -------------------- // // This is a wrapper around the expression object. // TODO: Find out how to write a proper evaluator without duplicating // the row() and col() member functions. template< typename ArgType, typename MemberOp, int Direction> struct evaluator_impl > { typedef PartialReduxExpr XprType; evaluator_impl(const XprType expr) : m_expr(expr) { } typedef typename XprType::Index Index; typedef typename XprType::CoeffReturnType CoeffReturnType; CoeffReturnType coeff(Index row, Index col) const { return m_expr.coeff(row, col); } CoeffReturnType coeff(Index index) const { return m_expr.coeff(index); } protected: const XprType m_expr; }; // -------------------- MatrixWrapper and ArrayWrapper -------------------- // // evaluator_impl_wrapper_base is a common base class for the // MatrixWrapper and ArrayWrapper evaluators. template struct evaluator_impl_wrapper_base : evaluator_impl_base { typedef typename remove_all::type ArgType; evaluator_impl_wrapper_base(const ArgType& arg) : m_argImpl(arg) {} typedef typename ArgType::Index Index; typedef typename ArgType::Scalar Scalar; typedef typename ArgType::CoeffReturnType CoeffReturnType; typedef typename ArgType::PacketScalar PacketScalar; typedef typename ArgType::PacketReturnType PacketReturnType; CoeffReturnType coeff(Index row, Index col) const { return m_argImpl.coeff(row, col); } CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(index); } Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(row, col); } Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } template PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(row, col); } template PacketReturnType packet(Index index) const { return m_argImpl.template packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket(row, col, x); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket(index, x); } protected: typename evaluator::nestedType m_argImpl; }; template struct evaluator_impl > : evaluator_impl_wrapper_base > { typedef MatrixWrapper XprType; evaluator_impl(const XprType& wrapper) : evaluator_impl_wrapper_base >(wrapper.nestedExpression()) { } }; template struct evaluator_impl > : evaluator_impl_wrapper_base > { typedef ArrayWrapper XprType; evaluator_impl(const XprType& wrapper) : evaluator_impl_wrapper_base >(wrapper.nestedExpression()) { } }; // -------------------- Reverse -------------------- // defined in Reverse.h: template struct reverse_packet_cond; template struct evaluator_impl > : evaluator_impl_base > { typedef Reverse XprType; typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; enum { PacketSize = internal::packet_traits::size, IsRowMajor = XprType::IsRowMajor, IsColMajor = !IsRowMajor, ReverseRow = (Direction == Vertical) || (Direction == BothDirections), ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1, OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, ReversePacket = (Direction == BothDirections) || ((Direction == Vertical) && IsColMajor) || ((Direction == Horizontal) && IsRowMajor) }; typedef internal::reverse_packet_cond reverse_packet; evaluator_impl(const XprType& reverse) : m_argImpl(reverse.nestedExpression()), m_rows(ReverseRow ? reverse.nestedExpression().rows() : 0), m_cols(ReverseCol ? reverse.nestedExpression().cols() : 0) { } CoeffReturnType coeff(Index row, Index col) const { return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row, ReverseCol ? m_cols.value() - col - 1 : col); } CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1); } Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row, ReverseCol ? m_cols.value() - col - 1 : col); } Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1); } template PacketScalar packet(Index row, Index col) const { return reverse_packet::run(m_argImpl.template packet( ReverseRow ? m_rows.value() - row - OffsetRow : row, ReverseCol ? m_cols.value() - col - OffsetCol : col)); } template PacketScalar packet(Index index) const { return preverse(m_argImpl.template packet(m_rows.value() * m_cols.value() - index - PacketSize)); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket( ReverseRow ? m_rows.value() - row - OffsetRow : row, ReverseCol ? m_cols.value() - col - OffsetCol : col, reverse_packet::run(x)); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket (m_rows.value() * m_cols.value() - index - PacketSize, preverse(x)); } protected: typename evaluator::nestedType m_argImpl; // If we do not reverse rows, then we do not need to know the number of rows; same for columns const variable_if_dynamic m_rows; const variable_if_dynamic m_cols; }; // -------------------- Diagonal -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef Diagonal XprType; evaluator_impl(const XprType& diagonal) : m_argImpl(diagonal.nestedExpression()), m_index(diagonal.index()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; CoeffReturnType coeff(Index row, Index) const { return m_argImpl.coeff(row + rowOffset(), row + colOffset()); } CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(index + rowOffset(), index + colOffset()); } Scalar& coeffRef(Index row, Index) { return m_argImpl.coeffRef(row + rowOffset(), row + colOffset()); } Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index + rowOffset(), index + colOffset()); } protected: typename evaluator::nestedType m_argImpl; const internal::variable_if_dynamicindex m_index; private: EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); } EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; } }; } // namespace internal } // end namespace Eigen #endif // EIGEN_COREEVALUATORS_H