Add support for fixed-value in symbolic expression, c++11 only for now.

This commit is contained in:
Gael Guennebaud 2017-01-19 19:25:29 +01:00
parent e84ed7b6ef
commit 7691723e34
3 changed files with 41 additions and 13 deletions

View File

@ -354,8 +354,8 @@ using std::ptrdiff_t;
#include "src/Core/util/StaticAssert.h"
#include "src/Core/util/XprHelper.h"
#include "src/Core/util/Memory.h"
#include "src/Core/util/SymbolicIndex.h"
#include "src/Core/util/IntegralConstant.h"
#include "src/Core/util/SymbolicIndex.h"
#include "src/Core/NumTraits.h"

View File

@ -60,7 +60,7 @@ static const auto end = last+1;
#else
// 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>());
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::FixedExpr<1> > end(last+fix<1>());
#endif
} // end namespace placeholders

View File

@ -57,6 +57,17 @@ protected:
Index m_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:
FixedExpr() {}
template<typename T>
Index eval_impl(const T&) const { return N; }
};
/** \class BaseExpr
* \ingroup Core_Module
* Common base class of any symbolic expressions
@ -101,6 +112,34 @@ public:
friend QuotientExpr<ValueExpr,Derived> operator/(Index a, const BaseExpr& b)
{ return QuotientExpr<ValueExpr,Derived>(a,b.derived()); }
template<int N>
AddExpr<Derived,FixedExpr<N> > operator+(internal::fix_t<N>) const
{ return AddExpr<Derived,FixedExpr<N> >(derived(), FixedExpr<N>()); }
template<int N>
AddExpr<Derived,FixedExpr<N> > operator-(internal::fix_t<N>) const
{ return AddExpr<Derived,FixedExpr<-N> >(derived(), FixedExpr<-N>()); }
template<int N>
ProductExpr<Derived,FixedExpr<N> > operator*(internal::fix_t<N>) const
{ return ProductExpr<Derived,FixedExpr<N> >(derived(),FixedExpr<N>()); }
template<int N>
QuotientExpr<Derived,FixedExpr<N> > operator/(internal::fix_t<N>) const
{ return QuotientExpr<Derived,FixedExpr<N> >(derived(),FixedExpr<N>()); }
template<int N>
friend AddExpr<Derived,FixedExpr<N> > operator+(internal::fix_t<N>, const BaseExpr& b)
{ return AddExpr<Derived,FixedExpr<N> >(b.derived(), FixedExpr<N>()); }
template<int N>
friend AddExpr<NegateExpr<Derived>,FixedExpr<N> > operator-(internal::fix_t<N>, const BaseExpr& b)
{ return AddExpr<NegateExpr<Derived>,FixedExpr<N> >(-b.derived(), FixedExpr<N>()); }
template<int N>
friend ProductExpr<FixedExpr<N>,Derived> operator*(internal::fix_t<N>, const BaseExpr& b)
{ return ProductExpr<FixedExpr<N>,Derived>(FixedExpr<N>(),b.derived()); }
template<int N>
friend QuotientExpr<FixedExpr<N>,Derived> operator/(internal::fix_t<N>, const BaseExpr& b)
{ return QuotientExpr<FixedExpr<N> ,Derived>(FixedExpr<N>(),b.derived()); }
template<typename OtherDerived>
AddExpr<Derived,OtherDerived> operator+(const BaseExpr<OtherDerived> &b) const
{ return AddExpr<Derived,OtherDerived>(derived(), b.derived()); }
@ -124,17 +163,6 @@ 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.