1#ifndef __DUNE_ACFEM_EXPRESSIONS_TRANSFORM_HH__
2#define __DUNE_ACFEM_EXPRESSIONS_TRANSFORM_HH__
4#include "../common/typetraits.hh"
7#include "treeoperand.hh"
10namespace Dune::ACFem::Expressions {
19 template<
class Optimize = OptimizeTop>
22 template<
class F,
class... Arg>
23 constexpr decltype(
auto)
operator()(F&& f, Arg&&... arg)
const
25 return operate(Optimize{}, std::forward<F>(f), std::forward<Arg>(arg)...);
32 template<
class Optimize = OptimizeTop>
35 template<
class F,
class... Arg>
36 constexpr decltype(
auto)
operator()(F&& f, Arg&&... arg)
const
38 return operate(Optimize{}, std::forward<F>(f), std::decay_t<Arg>(arg)...);
48 template<
class F,
class... Arg>
49 constexpr decltype(
auto)
operator()(F&& f, Arg&&... arg)
const
59 template<
class F,
class E,
class TreePos,
class Parent>
60 struct IsTransformInvocable
61 : std::is_invocable<F, E, TreePos, Parent>
64 template<
class F,
class E,
class TreePos>
65 struct IsTransformInvocable<F, E, TreePos,
FalseType>
66 : std::is_invocable<F, E, TreePos>
69 template<
class F,
class E,
class Parent>
70 struct IsTransformInvocable<F, E,
FalseType, Parent>
71 : std::is_invocable<F, E, Parent>
74 template<
class F,
class E>
76 : std::is_invocable<F, E>
81 template<
class TreePos, std::
size_t Idx>
82 struct AppendTreePosHelper
84 using Type = PushBack<Idx, TreePos>;
87 template<std::
size_t Idx>
88 struct AppendTreePosHelper<
FalseType, Idx>
95 template<
class TreePos, std::
size_t Idx>
96 using AppendTreePos =
typename AppendTreePosHelper<TreePos, Idx>::Type;
100 class Operation = Operate<OptimizeTop>,
101 class TreePos = NoTreePos,
102 class Parent = NoParent,
103 std::enable_if_t<IsTransformInvocable<F, E, TreePos, Parent>::value,
int> = 0>
104 constexpr decltype(
auto) transform(E&& e, F&& f, Operation&& op = Operation{}, TreePos = TreePos{}, Parent&& parent = Parent{})
109 if constexpr (std::is_same<Parent, FalseType>::value) {
110 if constexpr (std::is_same<TreePos, FalseType>::value) {
111 return std::forward<F>(f)(std::forward<E>(e));
113 return std::forward<F>(f)(std::forward<E>(e), TreePos{});
116 return std::forward<F>(f)(std::forward<E>(e), TreePos{}, std::forward<Parent>(parent));
122 template<
class E,
class F,
class Operation,
class TreePos,
class Parent>
123 constexpr bool doNotTransform()
125 if constexpr (IsTransformInvocable<F, E, TreePos, Parent>::value) {
127 }
else if constexpr (!IsExpression<E>::value) {
129 }
else if constexpr (IsSelfExpression<E>::value) {
131 }
else if constexpr (IsPlaceholderExpression<E>::value) {
133 }
else if constexpr (std::is_same<F, FalseType>::value) {
135 }
else if constexpr (ExamineTreeOr<E, TreePos, Parent, IsApplicableTo, F>::value) {
143 template<
class E,
class F,
class Operation,
class TreePos,
class Parent>
144 struct DoNotTransform
151 class Operation = Operate<OptimizeTop>,
152 class TreePos = NoTreePos,
153 class Parent = NoParent,
156 doNotTransform<E, F, Operation, TreePos, Parent>()
158 !IsTransformInvocable<F, E, TreePos, Parent>::value
159 && ((!std::is_same<F, FalseType>::value
160 && !ExamineTreeOr<E, TreePos, Parent, IsApplicableTo, F>::value)
162 || !IsExpression<E>::value
164 || IsSelfExpression<E>::value
166 || IsPlaceholderExpression<E>::value
170 constexpr decltype(
auto) transform(E&& e, F&& f, Operation&& op = Operation{}, TreePos = TreePos{}, Parent&& = Parent{})
174 return forwardReturnValue<E>(e);
179 template<
class E,
class F,
180 class Operation,
class TreePos,
class Parent,
181 std::size_t... ArgIndex>
182 decltype(
auto) transformHelper(E&& e, F&& f, Operation&& op, TreePos, Parent&&, IndexSequence<ArgIndex...>)
184 static_assert(IsExpression<E>::value && Arity<E>::value ==
sizeof...(ArgIndex),
185 "Internal error: helper function called with inconsistent arguments.");
188 if constexpr (std::is_same<Parent, FalseType>::value) {
190 std::forward<Operation>(op)(
191 std::forward<E>(e).operation(),
193 std::forward<E>(e).
template operand<ArgIndex>(),
195 std::forward<Operation>(op),
196 AppendTreePos<TreePos, ArgIndex>{},
202 std::forward<Operation>(op)(
203 std::forward<E>(e).operation(),
205 std::forward<E>(e).
template operand<ArgIndex>(),
207 std::forward<Operation>(op),
208 AppendTreePos<TreePos, ArgIndex>{},
218 template<
class E,
class F,
class Operation,
class TreePos,
class Parent>
219 constexpr bool doTransformRecurse()
221 if constexpr (IsTransformInvocable<F, E, TreePos, Parent>::value) {
223 }
else if constexpr (!IsExpression<E>::value) {
225 }
else if constexpr (IsSelfExpression<E>::value) {
227 }
else if constexpr (IsPlaceholderExpression<E>::value) {
229 }
else if constexpr (std::is_same<F, FalseType>::value) {
231 }
else if constexpr (ExamineTreeOr<E, TreePos, Parent, IsApplicableTo, F>::value) {
242 class Operation = Operate<OptimizeTop>,
243 class TreePos = NoTreePos,
244 class Parent = NoParent,
247 doTransformRecurse<E, F, Operation, TreePos, Parent>()
249 !IsTransformInvocable<F, E, TreePos, Parent>::value
250 && (std::is_same<F, FalseType>::value
251 || ExamineTreeOr<E, TreePos, Parent, IsApplicableTo, F>::value
254 && IsExpression<E>::value
257 && !IsSelfExpression<E>::value
260 && !IsPlaceholderExpression<E>::value
263 decltype(
auto) transform(E&& e, F&& f, Operation&& op = Operation{}, TreePos = TreePos{}, Parent&& parent = Parent{})
267 return transformHelper(
270 std::forward<Operation>(op),
272 std::forward<Parent>(parent),
273 MakeIndexSequence<Arity<E>::value>{}
281 template<class E, class F, class TreePos = NoTreePos, class Parent = NoParent, std::enable_if_t<IsExpression<E>::value,
int> = 0>
282 auto traverse(E&& e, F&& f, TreePos = TreePos{}, Parent&& parent = Parent{})
284 return transform(std::forward<E>(e), std::forward<F>(f), DontOperate{}, TreePos{}, std::forward<Parent>(parent));
290 template<
class E,
class Optimize = OptimizeTop,
class TreePos = IndexSequence<> >
291 auto deepCopy(E&& e, Optimize = Optimize{}, TreePos = TreePos{})
293 return transform(std::forward<E>(e),
FalseType{}, OperateClone<Optimize>{}, TreePos{});
300 template<
class T,
class...>
303 || IsIndeterminateExpression<T>::value
319 template<
class From,
class To,
320 template<
class...>
class When = std::is_same,
324 using FromType = From;
327 : to_(std::forward<To>(to))
331 std::enable_if_t<(!When<T, FromType>::value
332 && Ignore<T, FromType>::value
334 constexpr decltype(
auto) operator()(T&& t)
const
336 return forwardReturnValue<T>(t);
339 template<
class T, std::size_t... TreePos,
340 std::enable_if_t<(!When<MPL::TypeTuple<T,
IndexSequence<TreePos...> >, FromType>::value
341 && (Ignore<MPL::TypeTuple<T,
IndexSequence<TreePos...> >, FromType>::value
342 || Ignore<T, FromType>::value
345 constexpr decltype(
auto)
operator()(T&& t,
IndexSequence<TreePos...>)
const
347 return forwardReturnValue<T>(t);
350 template<
class T,
class Parent,
352 && !When<MPL::TypeTuple<T, Parent>, FromType>::value
353 && (Ignore<MPL::TypeTuple<T, Parent>, FromType>::value
354 || Ignore<T, FromType>::value
357 constexpr decltype(
auto)
operator()(T&& t, Parent&& parent)
const
359 return forwardReturnValue<T>(t);
362 template<
class T,
class TreePos,
class Parent,
363 std::enable_if_t<(!When<MPL::TypeTuple<T, TreePos, Parent>, FromType>::value
364 && (Ignore<MPL::TypeTuple<T, TreePos, Parent>, FromType>::value
365 || Ignore<MPL::TypeTuple<T, TreePos>, FromType>::value
366 || Ignore<T, FromType>::value
369 constexpr decltype(
auto)
operator()(T&& t, TreePos, Parent&& parent)
const
371 return forwardReturnValue<T>(t);
374 template<class T, std::enable_if_t<When<T, FromType>::value,
int> = 0>
375 constexpr decltype(
auto)
operator()(T&& t)
const
380 template<
class T, std::size_t... TreePos, std::enable_if_t<When<MPL::TypeTuple<T,
IndexSequence<TreePos...> >, FromType>::value,
int> = 0>
381 constexpr decltype(
auto)
operator()(T&& t,
IndexSequence<TreePos...>)
const
386 template<class T, class Parent, std::enable_if_t<!IsIndexSequence<Parent>::value && When<MPL::TypeTuple<T, Parent>, FromType>::value,
int> = 0>
387 constexpr decltype(
auto)
operator()(T&&, Parent&&)
const
392 template<
class T,
class TreePos,
class Parent, std::enable_if_t<When<MPL::TypeTuple<T, TreePos, Parent>, FromType>::value,
int> = 0>
393 constexpr decltype(
auto)
operator()(T&&, TreePos, Parent&&)
const
405 template<
class...>
class When,
408 :
ReplaceFunctor<void, To, PredicateProxy<When>::template ForwardFirst, Ignore>
417 template<
class E,
class Dummy,
class SFINAE =
void>
420 || IsSelfExpression<E>::value
421 || ReplaceDefaultIgnore<E>::value)>
424 template<
class E,
class Dummy>
432 template<
template<
class...>
class TerminalPredicate = DefaultTerminalPredicate>
440 template<std::size_t N,
441 template<
class...>
class When,
446 std::enable_if_t<(!When<T>::value
447 && Ignore<T, void>::value
449 constexpr decltype(
auto) operator()(T&& t)
const
451 return std::forward<T>(t);
454 template<
class T,
class TreePos,
455 std::enable_if_t<(!When<MPL::TypeTuple<T, TreePos> >::value
456 && (Ignore<MPL::TypeTuple<T, TreePos>,
void>::value || Ignore<T, void>::value)
458 constexpr decltype(
auto)
operator()(T&& t, TreePos)
const
460 return std::forward<T>(t);
463 template<class T, std::enable_if_t<When<T>::value,
int> = 0>
464 constexpr decltype(
auto)
operator()(T&& t)
const
466 return std::forward<T>(t).template operand<N>();
469 template<
class T,
class TreePos, std::enable_if_t<When<MPL::TypeTuple<T, TreePos> >::value,
int> = 0>
470 constexpr decltype(
auto)
operator()(T&& t, TreePos)
const
472 return std::forward<T>(t).template operand<N>();
477 class From,
class To,
class E,
class Optimize =
OptimizeTop,
478 class TreePos = NoTreePos,
class Parent = NoParent>
479 auto replace(E&& e, To&& to, From&& = From(), Optimize = Optimize{}, TreePos = TreePos{}, Parent&& parent = Parent{})
483 ReplaceFunctor<AsExpression<From>, AsExpression<To> >(
488 std::forward<Parent>(parent));
492 template<std::size_t Id,
class To,
class E,
class Optimize =
OptimizeTop,
493 class TreePos = NoTreePos,
class Parent = NoParent>
494 decltype(
auto) replaceIndeterminate(E&& e, To&& to, IndexConstant<Id> = IndexConstant<Id>{}, Optimize = Optimize{}, TreePos = TreePos{}, Parent&& parent = Parent{})
500 ReplaceFunctor<IndexConstant<Id>, AsExpression<To>, IndeterminateMatch>(
505 std::forward<Parent>(parent)
513 template<
template<
class...>
class Predicate,
template<
class...>
class Ignore,
515 class Optimize =
OptimizeTop,
class TreePos = NoTreePos,
class Parent = NoParent>
516 decltype(
auto) replaceMatching(E&& e, To&& to, Optimize = Optimize{}, TreePos = TreePos{}, Parent&& parent = Parent{})
518 using Replace = ReplaceFunctor<
519 To, To, Predicate, PredicateProxy<Ignore>::template ForwardFirst>;
521 return transform(std::forward<E>(e), Replace(std::forward<To>(to)),
522 Operate<Optimize>{}, TreePos{}, std::forward<Parent>(parent));
527 template<
template<
class...>
class Predicate,
529 class Optimize =
OptimizeTop,
class TreePos = NoTreePos,
class Parent = NoParent>
530 decltype(
auto) replaceMatching(E&& e, To&& to, Optimize = Optimize{}, TreePos = TreePos{}, Parent&& parent = Parent{})
532 return replaceMatching<Predicate, AlwaysFalse>(std::forward<E>(e), std::forward<To>(to),
533 Optimize{}, TreePos{}, std::forward<Parent>(parent));
constexpr decltype(auto) asExpression(T &&t)
Return a non-closure expression as is.
Definition: interface.hh:122
OptimizeTag< Policy::OptimizationLevelMax::value > OptimizeTop
The top-level optmization tag.
Definition: optimizationbase.hh:59
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
Constant< bool, V > BoolConstant
Short-cut for integral constant of type bool.
Definition: types.hh:48
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
Definition: transform.hh:422
Operation functor which does not operate and collapes the entire expression to a dummy return value o...
Definition: transform.hh:47
Operation functor for transform().
Definition: transform.hh:34
Default operation functor for transform.
Definition: transform.hh:21
Replace matching expressions by their operand no.
Definition: transform.hh:444
Definition: transform.hh:305
Replace all expression operands of type T where When<T, From> is std::true_type by an instance of To.
Definition: transform.hh:323
Variant o ReplaceFunctor where When may be a simple unary IsSomething trait.
Definition: transform.hh:409
Definition: transform.hh:435
Wrap the given predicate class F into another one with spcial requirements.
Definition: types.hh:218