DUNE-ACFEM (unstable)

extract.hh
1#ifndef __DUNE_ACFEM_EXPRESSIONS_EXTRACT_HH__
2#define __DUNE_ACFEM_EXPRESSIONS_EXTRACT_HH__
3
4#include "transform.hh"
5#include "examine.hh"
6#include "../common/typetraits.hh"
7#include "../common/literals.hh"
8#include "../mpl/conditionaljoin.hh"
9
10namespace Dune::ACFem::Expressions {
11
12 using namespace Literals;
13
16 {
17 template<class E, class Parent>
18 constexpr decltype(auto) operator()(E&& e, NoTreePos, Parent&&) const
19 {
20 return std::forward<E>(e);
21 }
22
23 template<class E, class TreePos, class Parent>
24 constexpr decltype(auto) operator()(E&& e, TreePos, Parent&&) const
25 {
26 return std::pair<E, TreePos>(std::forward<E>(e), TreePos{});
27 }
28 };
29
30 using Recursive = TrueType;
31 using NonRecursive = FalseType;
32
33 namespace {
34
35
37 template<class E, class Extracts, class ArgIndices, class F, class Recursive, class Unique, class TreePos, class Parent, class PackData,
38 std::enable_if_t<(IsTransformInvocable<F, E, TreePos, Parent>::value
39 && (!Recursive::value || IsSelfExpression<E>::value)
40 ), int> = 0>
41 constexpr auto extractTupleHelper(E&& e, const Extracts& t, ArgIndices, F&&, Recursive, Unique, TreePos, Parent&& parent, PackData&& packData)
42 {
43// std::clog << "helper invocable non recursive" << std::endl;
44// std::clog << e.name() << std::endl;
46 t,
47 packData(std::forward<E>(e), TreePos{}, std::forward<Parent>(parent)),
48 Unique{});
49 }
50
52 template<class E, class Extracts, std::size_t... ArgIndex, class F, class Recursive, class Unique, class TreePos, class Parent, class PackData,
53 std::enable_if_t<(IsTransformInvocable<F, E, TreePos, Parent>::value
54 && !IsSelfExpression<E>::value
55 && Recursive::value
56 ), int> = 0>
57 constexpr auto extractTupleHelper(E&& e, const Extracts& t, IndexSequence<ArgIndex...>, F&& f, Recursive, Unique, TreePos, Parent&& parent, PackData&& packData)
58 {
59 if constexpr (!std::is_same<Parent, FalseType>::value) {
60 return TupleUtilities::joinUnless<Unique::template Predicate>(
61 TupleUtilities::addFrontUnless(t, packData(std::forward<E>(e), TreePos{}, std::forward<Parent>(parent)), Unique{}),
62 extract(
63 std::forward<E>(e).template operand<ArgIndex>(),
64 std::forward<F>(f), Recursive{}, Unique{}, AppendTreePos<TreePos, ArgIndex>{},
65 std::forward<E>(e)
66 )...);
67 } else {
68 return TupleUtilities::joinUnless<Unique::template Predicate>(
69 TupleUtilities::addFrontUnless(t, packData(std::forward<E>(e), TreePos{}, std::forward<Parent>(parent)), Unique{}),
70 extract(
71 std::forward<E>(e).template operand<ArgIndex>(),
72 std::forward<F>(f), Recursive{}, Unique{}, AppendTreePos<TreePos, ArgIndex>{},
73 FalseType{}
74 )...);
75 }
76 }
77
78 // ignore terminals
79 template<class E, class Extracts, class ArgIndices, class F, class Recursive, class Unique, class TreePos, class Parent, class PackData,
80 std::enable_if_t<(!IsTransformInvocable<F, E, TreePos, Parent>::value
81 && IsSelfExpression<E>::value
82 ), int> = 0>
83 constexpr auto extractTupleHelper(E&& e, const Extracts& t, ArgIndices, F&&, Recursive, Unique, TreePos, Parent&&, PackData&&)
84 {
85 //std::clog << "helper !invocable terminal" << std::endl;
86 //std::clog << e.name() << std::endl;
87 return t;
88 }
89
90 // recurse into subexpressions
91 template<class E, class... P, std::size_t... ArgIndex, class F, class Recursive, class Unique,
92 class TreePos, class Parent, class PackData,
93 std::enable_if_t<(!IsTransformInvocable<F, E, TreePos, Parent>::value
94 && !IsSelfExpression<E>::value
95 ), int> = 0>
96 constexpr auto extractTupleHelper(E&& e, const std::tuple<P...>& t, IndexSequence<ArgIndex...>, F&& f, Recursive, Unique, TreePos, Parent&&, PackData&& packData)
97 {
98 //std::clog << "helper !invocable !terminal" << std::endl;
99 //std::clog << e.name() << std::endl;
100 //std::clog << typeString(f) << std::endl;
101 if constexpr (!std::is_same<Parent, FalseType>::value) {
102 return TupleUtilities::joinUnless<Unique::template Predicate>(
103 t,
104 extract(
105 std::forward<E>(e).template operand<ArgIndex>(),
106 std::forward<F>(f), Recursive{}, Unique{}, AppendTreePos<TreePos, ArgIndex>{},
107 std::forward<E>(e),
108 std::forward<PackData>(packData)
109 )...
110 );
111 } else {
112 return TupleUtilities::joinUnless<Unique::template Predicate>(
113 t,
114 extract(
115 std::forward<E>(e).template operand<ArgIndex>(),
116 std::forward<F>(f), Recursive{}, Unique{}, AppendTreePos<TreePos, ArgIndex>{},
117 FalseType{},
118 std::forward<PackData>(packData)
119 )...
120 );
121 }
122 }
123
124 }
125
143 template<class E,
144 class F,
145 class... P,
146 bool Recursive = false,
147 class Unique = PredicateProxy<AlwaysFalse>,
148 class TreePos = NoTreePos,
149 class Parent = NoParent,
150 class PackData = ExtractDataDefaultFunctor,
151 std::enable_if_t<IsExpression<E>::value, int> = 0>
152 constexpr auto extract(E&& e, F&& f,
153 const std::tuple<P...>& initial,
154 BoolConstant<Recursive> r = BoolConstant<Recursive>{},
155 Unique = Unique{},
156 TreePos tp = TreePos{},
157 Parent&& parent = Parent{},
158 PackData&& packData = PackData{})
159 {
160 if constexpr (std::is_same<TreePos, TrueType>::value) {
161 using UniqueWrapper =
162 ConditionalType<std::is_same<PackData, ExtractDataDefaultFunctor>::value,
163 PredicateWrapper<PredicateProxy<Unique::template Predicate>::template BinaryFirstOfPair>,
164 Unique>;
165 return extractTupleHelper(std::forward<E>(e),
166 initial, MakeIndexSequence<Arity<E>::value>{}, std::forward<F>(f),
167 r, UniqueWrapper{}, IndexSequence<>{},
168 std::forward<Parent>(parent),
169 std::forward<PackData>(packData));
170 } else {
171 return extractTupleHelper(std::forward<E>(e),
172 initial, MakeIndexSequence<Arity<E>::value>{}, std::forward<F>(f),
173 r, Unique{}, tp,
174 std::forward<Parent>(parent),
175 std::forward<PackData>(packData));
176 }
177 }
178
180 template<class E,
181 class F,
182 class Recursive = FalseType,
183 class Unique = PredicateWrapper<AlwaysFalse>,
184 class TreePos = NoTreePos,
185 class Parent = NoParent,
186 class PackData = ExtractDataDefaultFunctor,
187 std::enable_if_t<IsExpression<E>::value, int> = 0>
188 constexpr auto extract(E&& e, F&& f,
189 Recursive r = Recursive{},
190 Unique u = Unique{},
191 TreePos tp = TreePos{},
192 Parent&& parent = Parent{},
193 PackData&& packData = PackData{})
194 {
195 if constexpr (std::is_same<TreePos, TrueType>::value) {
196 using UniqueWrapper =
197 ConditionalType<std::is_same<PackData, ExtractDataDefaultFunctor>::value,
198 PredicateWrapper<PredicateProxy<Unique::template Predicate>::template BinaryFirstOfPair>,
199 Unique>;
200 return extract(std::forward<E>(e), std::forward<F>(f), std::tuple<>{},
201 r, UniqueWrapper{},
202 IndexSequence<>{},
203 std::forward<Parent>(parent),
204 std::forward<PackData>(packData));
205 } else {
206 return extract(std::forward<E>(e), std::forward<F>(f), std::tuple<>{},
207 r, u, tp,
208 std::forward<Parent>(parent),
209 std::forward<PackData>(packData));
210 }
211 }
212
220 template<template<class T, class...> class F,
221 class E,
222 class... P,
223 bool Recursive = false,
224 class Unique = PredicateWrapper<AlwaysFalse>,
225 class TreePos = NoTreePos,
226 class Parent = NoParent,
227 class PackData = ExtractDataDefaultFunctor,
228 std::enable_if_t<IsExpression<E>::value && ExamineTreeOr<E, TreePos, Parent, F>::value, int> = 0>
229 constexpr auto extract(E&& e,
230 const std::tuple<P...>& initial,
231 BoolConstant<Recursive> r = BoolConstant<Recursive>{},
232 Unique u = Unique{},
233 TreePos tp = TreePos{},
234 Parent&& parent = Parent{},
235 PackData&& packData = PackData{})
236 {
237 // AlwaysFalse is the ignore-functor for the transform machinery
238 // which would cause a match if left to the default.
239 using FunctorType = SimpleReplaceFunctor<int, PredicateProxy<F>::template ForwardFirst, AlwaysFalse>;
240
241 if constexpr (std::is_same<TreePos, TrueType>::value) {
242 using UniqueWrapper =
243 ConditionalType<std::is_same<PackData, ExtractDataDefaultFunctor>::value,
244 PredicateWrapper<PredicateProxy<Unique::template Predicate>::template BinaryFirstOfPair>,
245 Unique>;
246 return extract(std::forward<E>(e), FunctorType{}, initial,
247 r, UniqueWrapper{},
248 IndexSequence<>{},
249 std::forward<Parent>(parent),
250 std::forward<PackData>(packData));
251 } else {
252 return extract(std::forward<E>(e), FunctorType{}, initial,
253 r, u, tp,
254 std::forward<Parent>(parent),
255 std::forward<PackData>(packData));
256 }
257 }
258
260 template<template<class T, class...> class F,
261 class E,
262 class... P,
263 bool Recursive = false,
264 class Unique = PredicateWrapper<AlwaysFalse>,
265 class TreePos = NoTreePos,
266 class Parent = NoParent,
267 class PackData = ExtractDataDefaultFunctor,
268 std::enable_if_t<(IsExpression<E>::value
269 && !ExamineTreeOr<E, TreePos, Parent, F>::value
270 ), int> = 0>
271 constexpr auto extract(E&& e,
272 const std::tuple<P...>& initial,
273 BoolConstant<Recursive> = BoolConstant<Recursive>{},
274 Unique = Unique{},
275 TreePos = TreePos{},
276 Parent&& parent = Parent{},
277 PackData&& packData = PackData{})
278 {
279 //std::clog << "!examine" << std::endl;
280 //std::clog << e.name() << std::endl;
281 //std::clog << "exa: " << ExamineTreeOr<Operand<0, E>, TreePos, E, F>::value << std::endl;
282
283 return initial;
284 }
285
287 template<template<class T, class...> class F,
288 class E,
289 bool Recursive = false,
290 class Unique = PredicateWrapper<AlwaysFalse>,
291 class TreePos = NoTreePos,
292 class Parent = NoParent,
293 class PackData = ExtractDataDefaultFunctor,
294 std::enable_if_t<IsExpression<E>::value, int> = 0>
295 constexpr auto extract(E&& e,
296 BoolConstant<Recursive> r = BoolConstant<Recursive>{},
297 Unique u = Unique{},
298 TreePos tp = TreePos{},
299 Parent&& parent = Parent{},
300 PackData&& packData = PackData{})
301 {
302 if constexpr (std::is_same<TreePos, TrueType>::value) {
303 using UniqueWrapper =
304 ConditionalType<std::is_same<PackData, ExtractDataDefaultFunctor>::value,
305 PredicateWrapper<PredicateProxy<Unique::template Predicate>::template BinaryFirstOfPair>,
306 Unique>;
307 return extract<F>(std::forward<E>(e), std::tuple<>{},
308 r, UniqueWrapper{},
309 IndexSequence<>{},
310 std::forward<Parent>(parent),
311 std::forward<PackData>(packData));
312 } else {
313 return extract<F>(std::forward<E>(e), std::tuple<>{},
314 r, u, tp,
315 std::forward<Parent>(parent),
316 std::forward<PackData>(packData));
317 }
318 }
319
321 template<template<class...> class Predicate, class E, template<class...> class DescendUntil = AlwaysFalse>
322 constexpr decltype(auto) extractLeftMost(E&& e, PredicateWrapper<DescendUntil> = PredicateWrapper<DescendUntil>{})
323 {
324 if constexpr (IsSelfExpression<E>::value || DescendUntil<E>::value) {
325 if constexpr (Predicate<E>::value) {
326 return std::forward<E>(e);
327 } else {
328 return FalseType{};
329 }
330 } else {
331 return extractLeftMost<Predicate>(std::forward<E>(e).operand(0_c), PredicateWrapper<DescendUntil>{});
332 }
333 }
334
335 template<class E, template<class...> class Predicate = AlwaysTrue, template<class...> class DescendUntil = AlwaysFalse>
336 using LeftMostOperand = decltype(extractLeftMost<Predicate>(std::declval<E>(), PredicateWrapper<DescendUntil>
337 {}));
338
340 template<class E, class Initial = std::tuple<>, template<class...> class Unique = AlwaysFalse>
341 constexpr auto extractPlaceholders(E&& e,
342 Initial&& initial = Initial{},
343 PredicateWrapper<Unique> u = PredicateWrapper<Unique>{})
344 {
345 return extract<IsPlaceholderExpression>(std::forward<E>(e), std::forward<Initial>(initial), NoTreePos{}, u);
346 }
347
351 template<std::size_t Id, class E>
352 constexpr auto extractIndeterminates(E&& e)
353 {
354 // AlwaysFalse is the ignore-functor for the transform machinery
355 // which would cause a match if left to the default.
356 using FunctorType = ReplaceFunctor<IndexConstant<Id>, int, IndeterminateMatch, AlwaysFalse>;
357 return extract(std::forward<E>(e), FunctorType{});
358 }
359
361 template<class E>
362 constexpr auto extractTerminals(E&& e)
363 {
364 return extract<IsTerminal>(std::forward<E>(e));
365 }
366
367 template<class E>
368 using TerminalOperands = decltype(extractTerminals(std::declval<E>()));
369
370 template<class F, class... T>
371 using OperationTerminals = TerminalOperands<ExpressionType<F, T...> >;
372
374 template<template<class T, class...> class F, class E, class Recursive = FalseType>
375 using MatchingExpressionTuple = std::decay_t<decltype(extract<F>(std::declval<E>(), Recursive{}))>;
376
378 template<class E>
379 using PlaceholderTuple = std::decay_t<decltype(extractPlaceholders(std::declval<E>()))>;
380
382 template<std::size_t Id, class E>
383 using IndeterminateTuple = std::decay_t<decltype(extractIndeterminates<Id>(std::declval<E>()))>;
384
388 template<class E>
390 : BoolConstant<(size<PlaceholderTuple<E>() > > 0)>
391 {};
392
393} // NS Expressions
394
395#endif // __DUNE_ACFEM_EXPRESSIONS_EXTRACT_HH__
decltype(operate(std::declval< OptOrF >(), std::declval< Rest >()...)) ExpressionType
Generate the type of an expression by calling operate().
Definition: optimizationbase.hh:256
MakeSequence< std::size_t, N, Offset, Stride, Repeat > MakeIndexSequence
Make a sequence of std::size_t elements.
Definition: generators.hh:34
constexpr auto addFrontUnless(Tuple &&t, E &&e, PredicateWrapper< F >=PredicateWrapper< F >{})
Enforce kind of uniqueness.
Definition: conditionaljoin.hh:99
Constant< bool, V > BoolConstant
Short-cut for integral constant of type bool.
Definition: types.hh:48
typename MakeType< FalseType, Other... >::Type AlwaysFalse
Generate FalseType regardless of the template argument list.
Definition: types.hh:155
typename MakeType< TrueType, Other... >::Type AlwaysTrue
Generate TrueType regardless of the template argument list.
Definition: types.hh:159
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
FalseType by default.
Definition: runtimeequal.hh:103
Yields std::true_type if the expression E contains placeholders.
Definition: extract.hh:391
Default pack-data functor.
Definition: extract.hh:16
Identify self-contained terminals, see SelfExpression.
Definition: terminal.hh:60
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 4, 22:38, 2025)