Add a Symbolic::FixedExpr helper expression to make sure the compiler fully optimize the usage of last and end.

This commit is contained in:
Gael Guennebaud 2017-01-18 23:16:32 +01:00
parent 15471432fe
commit f3ccbe0419
3 changed files with 15 additions and 1 deletions

View File

@ -378,6 +378,7 @@ public:
Index size() const { return (m_last-m_first+m_incr)/m_incr; }
Index operator[](Index i) const { return m_first + i * m_incr; }
Index first() const { return m_first; }
const FirstType& firstObject() const { return m_first; }
const LastType& lastObject() const { return m_last; }

View File

@ -58,7 +58,9 @@ static const Symbolic::SymbolExpr<internal::symbolic_last_tag> last;
#ifdef EIGEN_PARSED_BY_DOXYGEN
static const auto end = last+1;
#else
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::ValueExpr> end(last+1);
// Using a FixedExpr<1> expression is important here to make sure the compiler
// can fully optimize the computation starting indices with zero overhead.
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::FixedExpr<1> > end(last+Symbolic::FixedExpr<1>());
#endif
} // end namespace placeholders

View File

@ -124,6 +124,17 @@ struct is_symbolic {
enum { value = internal::is_convertible<T,BaseExpr<T> >::value };
};
// Simple wrapper around a compile-time value,
// It is similar to ValueExpr(N) but this version helps the compiler to generate better code.
template<int N>
class FixedExpr : public BaseExpr<FixedExpr<N> > {
public:
FixedExpr() {}
template<typename T>
Index eval_impl(const T&) const { return N; }
};
/** Represents the actual value of a symbol identified by its tag
*
* It is the return type of SymbolValue::operator=, and most of the time this is only way it is used.