#ifndef EIGEN_SYMBOLIC_INDEX_H
#define EIGEN_SYMBOLIC_INDEX_H
#include "../InternalHeaderCheck.h"
namespace Eigen {
namespace symbolic {
template <typename Tag>
class Symbol;
template <typename Tag, typename Type>
class SymbolValue;
template <typename Arg0>
class NegateExpr;
template <typename Arg1, typename Arg2>
class AddExpr;
template <typename Arg1, typename Arg2>
class ProductExpr;
template <typename Arg1, typename Arg2>
class QuotientExpr;
template <typename IndexType = Index>
class ValueExpr;
template <typename Derived_>
class BaseExpr {
public:
using Derived = Derived_;
constexpr const Derived& derived() const { return *static_cast<const Derived*>(this); }
template <typename... Tags, typename... Types>
constexpr Index eval(const SymbolValue<Tags, Types>&... values) const {
return derived().eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time(const SymbolValue<Tags, Types>&...) {
return Derived::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
}
constexpr NegateExpr<Derived> operator-() const { return NegateExpr<Derived>(derived()); }
constexpr AddExpr<Derived, ValueExpr<>> operator+(Index b) const {
return AddExpr<Derived, ValueExpr<>>(derived(), b);
}
constexpr AddExpr<Derived, ValueExpr<>> operator-(Index a) const {
return AddExpr<Derived, ValueExpr<>>(derived(), -a);
}
constexpr ProductExpr<Derived, ValueExpr<>> operator*(Index a) const {
return ProductExpr<Derived, ValueExpr<>>(derived(), a);
}
constexpr QuotientExpr<Derived, ValueExpr<>> operator/(Index a) const {
return QuotientExpr<Derived, ValueExpr<>>(derived(), a);
}
friend constexpr AddExpr<Derived, ValueExpr<>> operator+(Index a, const BaseExpr& b) {
return AddExpr<Derived, ValueExpr<>>(b.derived(), a);
}
friend constexpr AddExpr<NegateExpr<Derived>, ValueExpr<>> operator-(Index a, const BaseExpr& b) {
return AddExpr<NegateExpr<Derived>, ValueExpr<>>(-b.derived(), a);
}
friend constexpr ProductExpr<ValueExpr<>, Derived> operator*(Index a, const BaseExpr& b) {
return ProductExpr<ValueExpr<>, Derived>(a, b.derived());
}
friend constexpr QuotientExpr<ValueExpr<>, Derived> operator/(Index a, const BaseExpr& b) {
return QuotientExpr<ValueExpr<>, Derived>(a, b.derived());
}
template <int N>
constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator+(internal::FixedInt<N>) const {
return AddExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
}
template <int N>
constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<-N>>> operator-(internal::FixedInt<N>) const {
return AddExpr<Derived, ValueExpr<internal::FixedInt<-N>>>(derived(), ValueExpr<internal::FixedInt<-N>>());
}
template <int N>
constexpr ProductExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator*(internal::FixedInt<N>) const {
return ProductExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
}
template <int N>
constexpr QuotientExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator/(internal::FixedInt<N>) const {
return QuotientExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
}
template <int N>
friend constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator+(internal::FixedInt<N>,
const BaseExpr& b) {
return AddExpr<Derived, ValueExpr<internal::FixedInt<N>>>(b.derived(), ValueExpr<internal::FixedInt<N>>());
}
template <int N>
friend constexpr AddExpr<NegateExpr<Derived>, ValueExpr<internal::FixedInt<N>>> operator-(internal::FixedInt<N>,
const BaseExpr& b) {
return AddExpr<NegateExpr<Derived>, ValueExpr<internal::FixedInt<N>>>(-b.derived(),
ValueExpr<internal::FixedInt<N>>());
}
template <int N>
friend constexpr ProductExpr<ValueExpr<internal::FixedInt<N>>, Derived> operator*(internal::FixedInt<N>,
const BaseExpr& b) {
return ProductExpr<ValueExpr<internal::FixedInt<N>>, Derived>(ValueExpr<internal::FixedInt<N>>(), b.derived());
}
template <int N>
friend constexpr QuotientExpr<ValueExpr<internal::FixedInt<N>>, Derived> operator/(internal::FixedInt<N>,
const BaseExpr& b) {
return QuotientExpr<ValueExpr<internal::FixedInt<N>>, Derived>(ValueExpr<internal::FixedInt<N>>(), b.derived());
}
template <typename OtherDerived>
constexpr AddExpr<Derived, OtherDerived> operator+(const BaseExpr<OtherDerived>& b) const {
return AddExpr<Derived, OtherDerived>(derived(), b.derived());
}
template <typename OtherDerived>
constexpr AddExpr<Derived, NegateExpr<OtherDerived>> operator-(const BaseExpr<OtherDerived>& b) const {
return AddExpr<Derived, NegateExpr<OtherDerived>>(derived(), -b.derived());
}
template <typename OtherDerived>
constexpr ProductExpr<Derived, OtherDerived> operator*(const BaseExpr<OtherDerived>& b) const {
return ProductExpr<Derived, OtherDerived>(derived(), b.derived());
}
template <typename OtherDerived>
constexpr QuotientExpr<Derived, OtherDerived> operator/(const BaseExpr<OtherDerived>& b) const {
return QuotientExpr<Derived, OtherDerived>(derived(), b.derived());
}
};
template <typename T>
struct is_symbolic {
enum { value = internal::is_convertible<T, BaseExpr<T>>::value };
};
template <typename IndexType>
class ValueExpr : BaseExpr<ValueExpr<IndexType>> {
public:
constexpr ValueExpr() = default;
constexpr ValueExpr(IndexType val) : value_(val) {}
template <typename... Tags, typename... Types>
constexpr IndexType eval_impl(const SymbolValue<Tags, Types>&...) const {
return value_;
}
template <typename... Tags, typename... Types>
static constexpr IndexType eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
return IndexType(Undefined);
}
protected:
IndexType value_;
};
template <int N>
class ValueExpr<internal::FixedInt<N>> : public BaseExpr<ValueExpr<internal::FixedInt<N>>> {
public:
constexpr ValueExpr() = default;
constexpr ValueExpr(internal::FixedInt<N>) {}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
return Index(N);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
return Index(N);
}
};
template <typename Tag, typename Type>
class SymbolValue : public BaseExpr<SymbolValue<Tag, Type>> {};
template <typename Tag>
class SymbolValue<Tag, Index> : public BaseExpr<SymbolValue<Tag, Index>> {
public:
constexpr SymbolValue() = default;
constexpr SymbolValue(Index val) : value_(val) {}
constexpr Index value() const { return value_; }
static constexpr Index value_at_compile_time() { return Index(Undefined); }
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
return value();
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
return value_at_compile_time();
}
protected:
Index value_;
};
template <typename Tag, int N>
class SymbolValue<Tag, internal::FixedInt<N>> : public BaseExpr<SymbolValue<Tag, internal::FixedInt<N>>> {
public:
constexpr SymbolValue() = default;
constexpr SymbolValue(internal::FixedInt<N>) {}
constexpr Index value() const { return static_cast<Index>(N); }
static constexpr Index value_at_compile_time() { return static_cast<Index>(N); }
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
return value();
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
return value_at_compile_time();
}
};
template <typename Tag, typename... Types>
struct EvalSymbolValueHelper;
template <typename Tag>
struct EvalSymbolValueHelper<Tag> {
static constexpr Index eval_impl() {
eigen_assert(false && "Symbol not found.");
return Index(Undefined);
}
static constexpr Index eval_at_compile_time_impl() { return Index(Undefined); }
};
template <typename Tag, typename Type, typename... OtherTypes>
struct EvalSymbolValueHelper<Tag, SymbolValue<Tag, Type>, OtherTypes...> {
static constexpr Index eval_impl(const SymbolValue<Tag, Type>& symbol, const OtherTypes&...) {
return symbol.value();
}
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tag, Type>& symbol, const OtherTypes&...) {
return symbol.value_at_compile_time();
}
};
template <typename Tag, typename T1, typename... OtherTypes>
struct EvalSymbolValueHelper<Tag, T1, OtherTypes...> {
static constexpr Index eval_impl(const T1&, const OtherTypes&... values) {
return EvalSymbolValueHelper<Tag, OtherTypes...>::eval_impl(values...);
}
static constexpr Index eval_at_compile_time_impl(const T1&, const OtherTypes&...) {
return EvalSymbolValueHelper<Tag, OtherTypes...>::eval_at_compile_time_impl(OtherTypes{}...);
}
};
template <typename tag>
class SymbolExpr : public BaseExpr<SymbolExpr<tag>> {
public:
typedef tag Tag;
constexpr SymbolExpr() = default;
constexpr SymbolValue<Tag, Index> operator=(Index val) const { return SymbolValue<Tag, Index>(val); }
template <int N>
constexpr SymbolValue<Tag, internal::FixedInt<N>> operator=(internal::FixedInt<N>) const {
return SymbolValue<Tag, internal::FixedInt<N>>{internal::FixedInt<N>{}};
}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
return EvalSymbolValueHelper<Tag, SymbolValue<Tags, Types>...>::eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
return EvalSymbolValueHelper<Tag, SymbolValue<Tags, Types>...>::eval_at_compile_time_impl(
SymbolValue<Tags, Types>{}...);
}
};
template <typename Arg0>
class NegateExpr : public BaseExpr<NegateExpr<Arg0>> {
public:
constexpr NegateExpr() = default;
constexpr NegateExpr(const Arg0& arg0) : m_arg0(arg0) {}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
return -m_arg0.eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
constexpr Index v = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
return (v == Undefined) ? Undefined : -v;
}
protected:
Arg0 m_arg0;
};
template <typename Arg0, typename Arg1>
class AddExpr : public BaseExpr<AddExpr<Arg0, Arg1>> {
public:
constexpr AddExpr() = default;
constexpr AddExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
return m_arg0.eval_impl(values...) + m_arg1.eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 + v1;
}
protected:
Arg0 m_arg0;
Arg1 m_arg1;
};
template <typename Arg0, typename Arg1>
class ProductExpr : public BaseExpr<ProductExpr<Arg0, Arg1>> {
public:
constexpr ProductExpr() = default;
constexpr ProductExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
return m_arg0.eval_impl(values...) * m_arg1.eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 * v1;
}
protected:
Arg0 m_arg0;
Arg1 m_arg1;
};
template <typename Arg0, typename Arg1>
class QuotientExpr : public BaseExpr<QuotientExpr<Arg0, Arg1>> {
public:
constexpr QuotientExpr() = default;
constexpr QuotientExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
template <typename... Tags, typename... Types>
constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
return m_arg0.eval_impl(values...) / m_arg1.eval_impl(values...);
}
template <typename... Tags, typename... Types>
static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 / v1;
}
protected:
Arg0 m_arg0;
Arg1 m_arg1;
};
}
}
#endif