$darkmode
Eigen  5.0.1-dev
SymbolicIndex.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2017 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_SYMBOLIC_INDEX_H
11 #define EIGEN_SYMBOLIC_INDEX_H
12 
13 // IWYU pragma: private
14 #include "../InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
43 namespace symbolic {
44 
45 template <typename Tag>
46 class Symbol;
47 template <typename Tag, typename Type>
49 template <typename Arg0>
50 class NegateExpr;
51 template <typename Arg1, typename Arg2>
52 class AddExpr;
53 template <typename Arg1, typename Arg2>
54 class ProductExpr;
55 template <typename Arg1, typename Arg2>
56 class QuotientExpr;
57 template <typename IndexType = Index>
58 class ValueExpr;
59 
64 template <typename Derived_>
65 class BaseExpr {
66  public:
67  using Derived = Derived_;
68  constexpr const Derived& derived() const { return *static_cast<const Derived*>(this); }
69 
75  template <typename... Tags, typename... Types>
76  constexpr Index eval(const SymbolValue<Tags, Types>&... values) const {
77  return derived().eval_impl(values...);
78  }
79 
85  template <typename... Tags, typename... Types>
86  static constexpr Index eval_at_compile_time(const SymbolValue<Tags, Types>&...) {
87  return Derived::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
88  }
89 
90  constexpr NegateExpr<Derived> operator-() const { return NegateExpr<Derived>(derived()); }
91 
92  constexpr AddExpr<Derived, ValueExpr<>> operator+(Index b) const {
93  return AddExpr<Derived, ValueExpr<>>(derived(), b);
94  }
95  constexpr AddExpr<Derived, ValueExpr<>> operator-(Index a) const {
96  return AddExpr<Derived, ValueExpr<>>(derived(), -a);
97  }
98  constexpr ProductExpr<Derived, ValueExpr<>> operator*(Index a) const {
99  return ProductExpr<Derived, ValueExpr<>>(derived(), a);
100  }
101  constexpr QuotientExpr<Derived, ValueExpr<>> operator/(Index a) const {
102  return QuotientExpr<Derived, ValueExpr<>>(derived(), a);
103  }
104 
105  friend constexpr AddExpr<Derived, ValueExpr<>> operator+(Index a, const BaseExpr& b) {
106  return AddExpr<Derived, ValueExpr<>>(b.derived(), a);
107  }
108  friend constexpr AddExpr<NegateExpr<Derived>, ValueExpr<>> operator-(Index a, const BaseExpr& b) {
109  return AddExpr<NegateExpr<Derived>, ValueExpr<>>(-b.derived(), a);
110  }
111  friend constexpr ProductExpr<ValueExpr<>, Derived> operator*(Index a, const BaseExpr& b) {
112  return ProductExpr<ValueExpr<>, Derived>(a, b.derived());
113  }
114  friend constexpr QuotientExpr<ValueExpr<>, Derived> operator/(Index a, const BaseExpr& b) {
115  return QuotientExpr<ValueExpr<>, Derived>(a, b.derived());
116  }
117 
118  template <int N>
119  constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator+(internal::FixedInt<N>) const {
120  return AddExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
121  }
122  template <int N>
123  constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<-N>>> operator-(internal::FixedInt<N>) const {
124  return AddExpr<Derived, ValueExpr<internal::FixedInt<-N>>>(derived(), ValueExpr<internal::FixedInt<-N>>());
125  }
126  template <int N>
127  constexpr ProductExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator*(internal::FixedInt<N>) const {
128  return ProductExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
129  }
130  template <int N>
131  constexpr QuotientExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator/(internal::FixedInt<N>) const {
132  return QuotientExpr<Derived, ValueExpr<internal::FixedInt<N>>>(derived(), ValueExpr<internal::FixedInt<N>>());
133  }
134 
135  template <int N>
136  friend constexpr AddExpr<Derived, ValueExpr<internal::FixedInt<N>>> operator+(internal::FixedInt<N>,
137  const BaseExpr& b) {
138  return AddExpr<Derived, ValueExpr<internal::FixedInt<N>>>(b.derived(), ValueExpr<internal::FixedInt<N>>());
139  }
140  template <int N>
141  friend constexpr AddExpr<NegateExpr<Derived>, ValueExpr<internal::FixedInt<N>>> operator-(internal::FixedInt<N>,
142  const BaseExpr& b) {
143  return AddExpr<NegateExpr<Derived>, ValueExpr<internal::FixedInt<N>>>(-b.derived(),
144  ValueExpr<internal::FixedInt<N>>());
145  }
146  template <int N>
147  friend constexpr ProductExpr<ValueExpr<internal::FixedInt<N>>, Derived> operator*(internal::FixedInt<N>,
148  const BaseExpr& b) {
149  return ProductExpr<ValueExpr<internal::FixedInt<N>>, Derived>(ValueExpr<internal::FixedInt<N>>(), b.derived());
150  }
151  template <int N>
152  friend constexpr QuotientExpr<ValueExpr<internal::FixedInt<N>>, Derived> operator/(internal::FixedInt<N>,
153  const BaseExpr& b) {
154  return QuotientExpr<ValueExpr<internal::FixedInt<N>>, Derived>(ValueExpr<internal::FixedInt<N>>(), b.derived());
155  }
156 
157  template <typename OtherDerived>
158  constexpr AddExpr<Derived, OtherDerived> operator+(const BaseExpr<OtherDerived>& b) const {
159  return AddExpr<Derived, OtherDerived>(derived(), b.derived());
160  }
161 
162  template <typename OtherDerived>
163  constexpr AddExpr<Derived, NegateExpr<OtherDerived>> operator-(const BaseExpr<OtherDerived>& b) const {
164  return AddExpr<Derived, NegateExpr<OtherDerived>>(derived(), -b.derived());
165  }
166 
167  template <typename OtherDerived>
168  constexpr ProductExpr<Derived, OtherDerived> operator*(const BaseExpr<OtherDerived>& b) const {
169  return ProductExpr<Derived, OtherDerived>(derived(), b.derived());
170  }
171 
172  template <typename OtherDerived>
173  constexpr QuotientExpr<Derived, OtherDerived> operator/(const BaseExpr<OtherDerived>& b) const {
174  return QuotientExpr<Derived, OtherDerived>(derived(), b.derived());
175  }
176 };
177 
178 template <typename T>
179 struct is_symbolic {
180  // BaseExpr has no conversion ctor, so we only have to check whether T can be statically cast to its base class
181  // BaseExpr<T>.
182  enum { value = internal::is_convertible<T, BaseExpr<T>>::value };
183 };
184 
185 // A simple wrapper around an integral value to provide the eval method.
186 // We could also use a free-function symbolic_eval...
187 template <typename IndexType>
188 class ValueExpr : BaseExpr<ValueExpr<IndexType>> {
189  public:
190  constexpr ValueExpr() = default;
191  constexpr ValueExpr(IndexType val) : value_(val) {}
192  template <typename... Tags, typename... Types>
193  constexpr IndexType eval_impl(const SymbolValue<Tags, Types>&...) const {
194  return value_;
195  }
196  template <typename... Tags, typename... Types>
197  static constexpr IndexType eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
198  return IndexType(Undefined);
199  }
200 
201  protected:
202  IndexType value_;
203 };
204 
205 // Specialization for compile-time value,
206 // It is similar to ValueExpr(N) but this version helps the compiler to generate better code.
207 template <int N>
208 class ValueExpr<internal::FixedInt<N>> : public BaseExpr<ValueExpr<internal::FixedInt<N>>> {
209  public:
210  constexpr ValueExpr() = default;
211  constexpr ValueExpr(internal::FixedInt<N>) {}
212  template <typename... Tags, typename... Types>
213  constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
214  return Index(N);
215  }
216  template <typename... Tags, typename... Types>
217  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
218  return Index(N);
219  }
220 };
221 
226 template <typename Tag, typename Type>
227 class SymbolValue : public BaseExpr<SymbolValue<Tag, Type>> {};
228 
229 template <typename Tag>
230 class SymbolValue<Tag, Index> : public BaseExpr<SymbolValue<Tag, Index>> {
231  public:
232  constexpr SymbolValue() = default;
233 
235  constexpr SymbolValue(Index val) : value_(val) {}
236 
238  constexpr Index value() const { return value_; }
239 
241  static constexpr Index value_at_compile_time() { return Index(Undefined); }
242 
243  template <typename... Tags, typename... Types>
244  constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
245  return value();
246  }
247 
248  template <typename... Tags, typename... Types>
249  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
250  return value_at_compile_time();
251  }
252 
253  protected:
254  Index value_;
255 };
256 
257 template <typename Tag, int N>
258 class SymbolValue<Tag, internal::FixedInt<N>> : public BaseExpr<SymbolValue<Tag, internal::FixedInt<N>>> {
259  public:
260  constexpr SymbolValue() = default;
261 
263  constexpr SymbolValue(internal::FixedInt<N>) {}
264 
266  constexpr Index value() const { return static_cast<Index>(N); }
267 
269  static constexpr Index value_at_compile_time() { return static_cast<Index>(N); }
270 
271  template <typename... Tags, typename... Types>
272  constexpr Index eval_impl(const SymbolValue<Tags, Types>&...) const {
273  return value();
274  }
275 
276  template <typename... Tags, typename... Types>
277  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
278  return value_at_compile_time();
279  }
280 };
281 
282 // Find and return a symbol value based on the tag.
283 template <typename Tag, typename... Types>
284 struct EvalSymbolValueHelper;
285 
286 // Empty base case, symbol not found.
287 template <typename Tag>
288 struct EvalSymbolValueHelper<Tag> {
289  static constexpr Index eval_impl() {
290  eigen_assert(false && "Symbol not found.");
291  return Index(Undefined);
292  }
293  static constexpr Index eval_at_compile_time_impl() { return Index(Undefined); }
294 };
295 
296 // We found a symbol value matching the provided Tag!
297 template <typename Tag, typename Type, typename... OtherTypes>
298 struct EvalSymbolValueHelper<Tag, SymbolValue<Tag, Type>, OtherTypes...> {
299  static constexpr Index eval_impl(const SymbolValue<Tag, Type>& symbol, const OtherTypes&...) {
300  return symbol.value();
301  }
302  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tag, Type>& symbol, const OtherTypes&...) {
303  return symbol.value_at_compile_time();
304  }
305 };
306 
307 // No symbol value in first value, recursive search starting with next.
308 template <typename Tag, typename T1, typename... OtherTypes>
309 struct EvalSymbolValueHelper<Tag, T1, OtherTypes...> {
310  static constexpr Index eval_impl(const T1&, const OtherTypes&... values) {
311  return EvalSymbolValueHelper<Tag, OtherTypes...>::eval_impl(values...);
312  }
313  static constexpr Index eval_at_compile_time_impl(const T1&, const OtherTypes&...) {
314  return EvalSymbolValueHelper<Tag, OtherTypes...>::eval_at_compile_time_impl(OtherTypes{}...);
315  }
316 };
317 
319 template <typename tag>
320 class SymbolExpr : public BaseExpr<SymbolExpr<tag>> {
321  public:
323  typedef tag Tag;
324 
325  constexpr SymbolExpr() = default;
326 
332  constexpr SymbolValue<Tag, Index> operator=(Index val) const { return SymbolValue<Tag, Index>(val); }
333 
334  template <int N>
335  constexpr SymbolValue<Tag, internal::FixedInt<N>> operator=(internal::FixedInt<N>) const {
336  return SymbolValue<Tag, internal::FixedInt<N>>{internal::FixedInt<N>{}};
337  }
338 
339  template <typename... Tags, typename... Types>
340  constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
341  return EvalSymbolValueHelper<Tag, SymbolValue<Tags, Types>...>::eval_impl(values...);
342  }
343 
344  template <typename... Tags, typename... Types>
345  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
346  return EvalSymbolValueHelper<Tag, SymbolValue<Tags, Types>...>::eval_at_compile_time_impl(
347  SymbolValue<Tags, Types>{}...);
348  }
349 };
350 
351 template <typename Arg0>
352 class NegateExpr : public BaseExpr<NegateExpr<Arg0>> {
353  public:
354  constexpr NegateExpr() = default;
355  constexpr NegateExpr(const Arg0& arg0) : m_arg0(arg0) {}
356 
357  template <typename... Tags, typename... Types>
358  constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
359  return -m_arg0.eval_impl(values...);
360  }
361 
362  template <typename... Tags, typename... Types>
363  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
364  constexpr Index v = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
365  return (v == Undefined) ? Undefined : -v;
366  }
367 
368  protected:
369  Arg0 m_arg0;
370 };
371 
372 template <typename Arg0, typename Arg1>
373 class AddExpr : public BaseExpr<AddExpr<Arg0, Arg1>> {
374  public:
375  constexpr AddExpr() = default;
376  constexpr AddExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
377 
378  template <typename... Tags, typename... Types>
379  constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
380  return m_arg0.eval_impl(values...) + m_arg1.eval_impl(values...);
381  }
382 
383  template <typename... Tags, typename... Types>
384  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
385  constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
386  constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
387  return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 + v1;
388  }
389 
390  protected:
391  Arg0 m_arg0;
392  Arg1 m_arg1;
393 };
394 
395 template <typename Arg0, typename Arg1>
396 class ProductExpr : public BaseExpr<ProductExpr<Arg0, Arg1>> {
397  public:
398  constexpr ProductExpr() = default;
399  constexpr ProductExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
400 
401  template <typename... Tags, typename... Types>
402  constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
403  return m_arg0.eval_impl(values...) * m_arg1.eval_impl(values...);
404  }
405 
406  template <typename... Tags, typename... Types>
407  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
408  constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
409  constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
410  return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 * v1;
411  }
412 
413  protected:
414  Arg0 m_arg0;
415  Arg1 m_arg1;
416 };
417 
418 template <typename Arg0, typename Arg1>
419 class QuotientExpr : public BaseExpr<QuotientExpr<Arg0, Arg1>> {
420  public:
421  constexpr QuotientExpr() = default;
422  constexpr QuotientExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {}
423 
424  template <typename... Tags, typename... Types>
425  constexpr Index eval_impl(const SymbolValue<Tags, Types>&... values) const {
426  return m_arg0.eval_impl(values...) / m_arg1.eval_impl(values...);
427  }
428 
429  template <typename... Tags, typename... Types>
430  static constexpr Index eval_at_compile_time_impl(const SymbolValue<Tags, Types>&...) {
431  constexpr Index v0 = Arg0::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
432  constexpr Index v1 = Arg1::eval_at_compile_time_impl(SymbolValue<Tags, Types>{}...);
433  return (v0 == Undefined || v1 == Undefined) ? Undefined : v0 / v1;
434  }
435 
436  protected:
437  Arg0 m_arg0;
438  Arg1 m_arg1;
439 };
440 
441 } // end namespace symbolic
442 
443 } // end namespace Eigen
444 
445 #endif // EIGEN_SYMBOLIC_INDEX_H
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: SymbolicIndex.h:48
tag Tag
Definition: SymbolicIndex.h:323
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
static constexpr Index eval_at_compile_time(const SymbolValue< Tags, Types > &...)
Definition: SymbolicIndex.h:86
const int Undefined
Definition: Constants.h:34
constexpr Index eval(const SymbolValue< Tags, Types > &... values) const
Definition: SymbolicIndex.h:76
constexpr SymbolValue< Tag, Index > operator=(Index val) const
Definition: SymbolicIndex.h:332
Definition: SymbolicIndex.h:65
Definition: SymbolicIndex.h:320