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