DUNE-ACFEM (unstable)

subexpression.hh
1#ifndef __DUNE_ACFEM_EXPRESSIONS_SUBEXPRESSION_HH__
2#define __DUNE_ACFEM_EXPRESSIONS_SUBEXPRESSION_HH__
3
4#include "expressionoperations.hh"
5#include "interface.hh"
6#include "densestorage.hh"
7#include "transform.hh"
8#include "../common/literals.hh"
9
10namespace Dune
11{
12
13 namespace ACFem
14 {
15
16 namespace Expressions
17 {
18 using namespace Literals;
19
34 template<class T, std::enable_if_t<IsSubExpressionExpression<T>::value, int> = 0>
35 constexpr decltype(auto) subExpressionExpression(T&& t)
36 {
37 return std::forward<T>(t).template operand<1>();
38 }
39
43 template<
44 class T,
45 std::enable_if_t<(!IsSubExpressionExpression<T>::value
46 && !IsClosure<T>::value
47 ), int> = 0>
48 constexpr decltype(auto) subExpressionExpression(T&& t)
49 {
50 return std::forward<T>(t);
51 }
52
53 template<class T, std::enable_if_t<IsClosure<T>::value, int> = 0>
54 constexpr decltype(auto) subExpressionExpression(T&& t)
55 {
56 return subExpressionExpression(asExpression(std::forward<T>(t)));
57 }
58
59 template<std::size_t... OperandPos, class T, std::enable_if_t<IsExpression<T>::value, int> = 0>
60 auto subExpression(T&& t, IndexSequence<OperandPos...> = IndexSequence<OperandPos...>{})
61 {
62 using TreePos = IndexSequence<OperandPos...>;
63 return subExpression(DenseStorageType<T>{}, std::forward<T>(t), TreePos{});
64 }
65
66 template<template<class...> class Storage, std::size_t... OperandPos, class T, std::enable_if_t<IsExpression<T>::value, int> = 0>
67 auto subExpression(T&& t, IndexSequence<OperandPos...> = IndexSequence<OperandPos...>{})
68 {
69 using TreePos = IndexSequence<OperandPos...>;
70 return subExpression(Storage<T>(), std::forward<T>(t), TreePos{});
71 }
72
74
75 namespace impl {
76 template<class Functor>
77 struct EvaluateSubExpression;
78 template<class Optimize>
79 struct ExpandSubExpression;
80 }
81
89 struct SExpForward
90 {
91 template<class Src>
92 constexpr decltype(auto) operator()(Src&& src) const
93 {
94 return std::forward<Src>(src);
95 }
96 };
97
98 struct SExpZero
99 {
100 template<class Dst>
101 constexpr auto operator()(Dst&& dst) const
102 {
103 return zero(std::forward<Dst>(dst));
104 }
105 };
106
119 template<
120 class T,
121 class Functor = SExpForward,
122 std::enable_if_t<(IsSubExpressionExpression<T>::value
123 && std::is_assignable<decltype(std::declval<T>().operand(0_c)), Operand<1, T> >::value
124 ), int> = 0>
125 void evaluateSubExpression(T&& t, Functor&& f = Functor{})
126 {
127 if constexpr (!IsConstantExprArg<Operand<1, T> >::value) {
128 // The sub-expression might again contain sub-expression which
129 // should be evaluated first in order to finally yield the
130 // correct result.
131 traverse(std::forward<T>(t).operand(1_c), impl::EvaluateSubExpression<Functor>{f});
132 std::forward<T>(t).operand(0_c) = asExpression(std::forward<Functor>(f)(std::forward<T>(t).operand(1_c)));
133 //std::clog << "Evaluate " << asExpression(std::forward<Functor>(f)(std::forward<T>(t).operand(1_c))).name() << std::endl;
134 }
135 }
136
151 template<
152 class T,
153 class Functor = SExpForward,
154 std::enable_if_t<(IsSubExpressionExpression<T>::value
155 && !std::is_assignable<decltype(std::declval<T>().operand(0_c)), Operand<1, T> >::value
156 ), int> = 0>
157 void evaluateSubExpression(T&& t, Functor = Functor{})
158 {}
159
161 template<class T, class Functor = SExpForward, std::enable_if_t<IsClosure<T>::value, int> = 0>
162 void evaluateSubExpression(T&& t, Functor&& f = Functor{})
163 {
164 evaluateSubExpression(asExpression(std::forward<T>(t)), std::forward<Functor>(f));
165 }
166
167 template<class T, class Optimize = OptimizeTop, class Functor = impl::ExpandSubExpression<Optimize> >
168 constexpr decltype(auto) expandSubExpression(T&& t, Optimize = Optimize{}, Functor = Functor{})
169 {
170 static_assert(IsSubExpressionExpression<T>::value,
171 "Attempt to expand subexpression of non subexpression-expression.");
172 // make sure we really get the contained type
173 return transform(static_cast<Operand<1, T> >(std::forward<T>(t).operand(1_c)), Functor{}, Operate<Optimize>{});
174 }
175
176 namespace impl {
177
194 template<class Functor>
196 {
197 template<class T, std::enable_if_t<IsSubExpressionExpression<T>::value, int> = 0>
198 constexpr auto operator()(T&& t) const
199 {
200 evaluateSubExpression(std::forward<T>(t), f_);
201 return 0;
202 }
203
204 Functor f_;
205 };
206
207 template<class Optimize>
208 struct ExpandSubExpression
209 {
210 template<class T, std::enable_if_t<IsSubExpressionExpression<T>::value, int> = 0>
211 constexpr decltype(auto) operator()(T&& t) const
212 {
213 return expandSubExpression(std::forward<T>(t), Optimize{});
214 }
215#if 0
216 template<class T, std::enable_if_t<(IsPlaceholderExpression<T>::value
217 || IsIndeterminateExpression<T>::value
218 ), int> = 0>
219 constexpr decltype(auto) operator()(T&& t) const
220 {
221 return std::forward<T>(t);
222 }
223#endif
224 };
225
226 } // NS impl
227
236 template<class T, class Functor = SExpForward>
237 void evaluateAllSubExpressions(T&& t, Functor&& f = Functor{})
238 {
239 static_assert(IsExpression<T>::value, "Called with something which is not an expression.");
240
241 traverse(std::forward<T>(t), impl::EvaluateSubExpression<Functor>{f});
242 }
243
245 template<class T, class Optimize = OptimizeTop>
246 constexpr auto expandAllSubExpressions(T&& t, Optimize = Optimize{})
247 {
248 return transform(std::forward<T>(t), impl::ExpandSubExpression<Optimize>{}, Operate<Optimize>{});
249 }
250
252
254
255 } // Expressions
256
257 template<class T>
258 struct ExpressionTraits<T, std::enable_if_t<IsSubExpressionExpression<T>::value> >
259 : ExpressionTraits<Expressions::Operand<1, T> >
260 {
261 using BaseType = ExpressionTraits<Expressions::Operand<1, T> >;
262 using ExpressionType = std::decay_t<T>;
263 static constexpr bool isTypedValue = false;
264 static constexpr bool isConstant = BaseType::isConstant || BaseType::isTypedValue;
265 };
266
267
268 } // ACFem
269
270} // Dune
271
272#endif // __DUNE_ACFEM_EXPRESSIONS_SUBEXPRESSION_HH__
constexpr decltype(auto) asExpression(T &&t)
Return a non-closure expression as is.
Definition: interface.hh:122
decltype(operate(std::declval< OptOrF >(), std::declval< Rest >()...)) ExpressionType
Generate the type of an expression by calling operate().
Definition: optimizationbase.hh:256
constexpr decltype(auto) subExpressionExpression(T &&t)
Recurse to the wrapped expression if T fulfills IsSubExpressionExpression<T>.
Definition: subexpression.hh:35
constexpr auto zero(T &&t)
Use the zero fraction as canonical zero element for scalars.
Definition: constantoperations.hh:80
void evaluateSubExpression(T &&t, Functor=Functor{})
Do-nothing dummy for expressions where evaluateSubExpression() would fail otherwise.
Definition: subexpression.hh:157
constexpr auto expandAllSubExpressions(T &&t, Optimize=Optimize{})
Expand all contained sub-expressions.
Definition: subexpression.hh:246
void evaluateAllSubExpressions(T &&t, Functor &&f=Functor{})
Evaluate all contained subexpressions.
Definition: subexpression.hh:237
constexpr bool isConstant(Sequence< T, T0, Ts... >)
Definition: compare.hh:285
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
STL namespace.
Operation functor for transform() which evaluates all contained sub-expressions.
Definition: subexpression.hh:196
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 4, 22:38, 2025)