Dune TypeTree (unstable)

accumulate_static.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
5
6#ifndef DUNE_TYPETREE_ACCUMULATE_STATIC_HH
7#define DUNE_TYPETREE_ACCUMULATE_STATIC_HH
8
9#include <dune/common/typetraits.hh>
10#include <dune/typetree/nodeinterface.hh>
11#include <dune/typetree/nodetags.hh>
12#include <dune/typetree/traversal.hh>
13#include <dune/typetree/treepath.hh>
14#include <dune/typetree/utility.hh>
15
16
17namespace Dune {
18 namespace TypeTree {
19
26 template<typename result_type>
27 struct or_
28 {
29 template<result_type r1, result_type r2>
30 struct reduce
31 {
32 static const result_type result = r1 || r2;
33 };
34 };
35
37 template<typename result_type>
38 struct and_
39 {
40 template<result_type r1, result_type r2>
41 struct reduce
42 {
43 static const result_type result = r1 && r2;
44 };
45 };
46
48 template<typename result_type>
49 struct plus
50 {
51 template<result_type r1, result_type r2>
52 struct reduce
53 {
54 static const result_type result = r1 + r2;
55 };
56 };
57
59 template<typename result_type>
60 struct minus
61 {
62 template<result_type r1, result_type r2>
63 struct reduce
64 {
65 static const result_type result = r1 - r2;
66 };
67 };
68
70 template<typename result_type>
71 struct multiply
72 {
73 template<result_type r1, result_type r2>
74 struct reduce
75 {
76 static const result_type result = r1 * r2;
77 };
78 };
79
81 template<typename result_type>
82 struct min
83 {
84 template<result_type r1, result_type r2>
85 struct reduce
86 {
87 static const result_type result = r1 < r2 ? r1 : r2;
88 };
89 };
90
92 template<typename result_type>
93 struct max
94 {
95 template<result_type r1, result_type r2>
96 struct reduce
97 {
98 static const result_type result = r1 > r2 ? r1 : r2;
99 };
100 };
101
102
103 namespace {
104
105 // implementation of the traversal algorithm
106
108 template<typename Node, typename Functor, typename Reduction, typename Functor::result_type current_value, typename TreePath, bool doVisit>
109 struct accumulate_node_helper
110 {
111
112 typedef typename Functor::result_type result_type;
113
114 static const result_type result = current_value;
115
116 };
117
119 template<typename Node, typename Functor, typename Reduction, typename Functor::result_type current_value, typename TreePath>
120 struct accumulate_node_helper<Node,Functor,Reduction,current_value,TreePath,true>
121 {
122
123 typedef typename Functor::result_type result_type;
124
125 static const result_type result = Reduction::template reduce<current_value,Functor::template visit<Node,TreePath>::result>::result;
126
127 };
128
130 template<typename Tree, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath, typename Tag>
131 struct accumulate_value;
132
134 template<typename LeafNode, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath>
135 struct accumulate_value<LeafNode,Functor,Reduction,ParentChildReduction,current_value,TreePath,LeafNodeTag>
136 {
137
138 typedef typename Functor::result_type result_type;
139
140 static const result_type result =
141
142 accumulate_node_helper<LeafNode,Functor,Reduction,current_value,TreePath,Functor::template doVisit<LeafNode,TreePath>::value>::result;
143
144 };
145
147 template<typename Node, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath, std::size_t i, std::size_t n>
148 struct accumulate_over_children
149 {
150
151 typedef typename Functor::result_type result_type;
152
153 typedef decltype(push_back(TreePath{},index_constant<i>{})) child_tree_path;
154
155 typedef typename Node::template Child<i>::Type child;
156
157 static const result_type child_result = accumulate_value<child,Functor,Reduction,ParentChildReduction,current_value,child_tree_path,NodeTag<child>>::result;
158
159 static const result_type result = accumulate_over_children<Node,Functor,Reduction,ParentChildReduction,child_result,TreePath,i+1,n>::result;
160
161 };
162
164 template<typename Node, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath, std::size_t n>
165 struct accumulate_over_children<Node,Functor,Reduction,ParentChildReduction,current_value,TreePath,n,n>
166 {
167
168 typedef typename Functor::result_type result_type;
169
170 static const result_type result = current_value;
171
172 };
173
176 template<typename Node, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath>
177 struct accumulate_value_generic_composite_node
178 {
179
180 typedef typename Functor::result_type result_type;
181
182 static const result_type child_result = accumulate_over_children<Node,Functor,Reduction,ParentChildReduction,current_value,TreePath,0,StaticDegree<Node>::value>::result;
183
184 static const result_type result =
185 accumulate_node_helper<Node,Functor,ParentChildReduction,child_result,TreePath,Functor::template doVisit<Node,TreePath>::value>::result;
186
187
188 };
189
191 template<typename PowerNode, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath>
192 struct accumulate_value<PowerNode,Functor,Reduction,ParentChildReduction,current_value,TreePath,PowerNodeTag>
193 : public accumulate_value_generic_composite_node<PowerNode,Functor,Reduction,ParentChildReduction,current_value,TreePath>
194 {};
195
197 template<typename CompositeNode, typename Functor, typename Reduction, typename ParentChildReduction, typename Functor::result_type current_value, typename TreePath>
198 struct accumulate_value<CompositeNode,Functor,Reduction,ParentChildReduction,current_value,TreePath,CompositeNodeTag>
199 : public accumulate_value_generic_composite_node<CompositeNode,Functor,Reduction,ParentChildReduction,current_value,TreePath>
200 {};
201
202 } // anonymous namespace
203
205
261 template<typename Tree, typename Functor, typename Reduction, typename Functor::result_type startValue, typename ParentChildReduction = Reduction>
263 {
264
266 typedef typename Functor::result_type result_type;
267
269 static const result_type result = accumulate_value<Tree,Functor,Reduction,ParentChildReduction,startValue,HybridTreePath<>,NodeTag<Tree>>::result;
270
271 };
272
275 struct flattened_reduction;
276
279 struct bottom_up_reduction;
280
281 namespace {
282
283 // implementation of the traversal algorithm
284
287 template<typename Node, typename Functor, typename Reduction, typename current_type, typename TreePath, bool doVisit>
288 struct accumulate_type_node_helper
289 {
290
291 typedef current_type type;
292
293 };
294
296 template<typename Node, typename Functor, typename Reduction, typename current_type, typename TreePath>
297 struct accumulate_type_node_helper<Node,Functor,Reduction,current_type,TreePath,true>
298 {
299
300 typedef typename Reduction::template reduce<
301 current_type,
302 typename Functor::template visit<
303 Node,
304 TreePath
305 >::type
306 >::type type;
307
308 };
309
311 template<typename Tree, typename Policy, typename current_type, typename TreePath, typename Tag>
312 struct accumulate_type;
313
315 template<typename LeafNode, typename Policy, typename current_type, typename TreePath>
316 struct accumulate_type<LeafNode,Policy,current_type,TreePath,LeafNodeTag>
317 {
318
319 typedef typename accumulate_type_node_helper<
320 LeafNode,
321 typename Policy::functor,
322 typename Policy::sibling_reduction,
323 current_type,
324 TreePath,
325 Policy::functor::template doVisit<
326 LeafNode,
327 TreePath>::value
328 >::type type;
329
330 };
331
332
335 template<typename current_type, typename tree_path, typename start_type, typename reduction_strategy>
336 struct propagate_type_down_tree;
337
339 template<typename current_type, typename tree_path, typename start_type>
340 struct propagate_type_down_tree<
341 current_type,
342 tree_path,
343 start_type,
344 bottom_up_reduction
345 >
346 {
347 typedef current_type type;
348 };
349
351 template<typename current_type, typename tree_path, typename start_type>
352 struct propagate_type_down_tree<
353 current_type,
354 tree_path,
355 start_type,
356 flattened_reduction
357 >
358 {
359 typedef typename std::conditional<
360 tree_path().back() == 0,
361 start_type,
362 current_type
363 >::type type;
364 };
365
366
368 template<typename Node, typename Policy, typename current_type, typename TreePath, std::size_t i, std::size_t n>
369 struct accumulate_type_over_children
370 {
371
372 typedef decltype(push_back(TreePath{},index_constant<i>{})) child_tree_path;
373
374 typedef typename Node::template Child<i>::Type child;
375
376 typedef typename accumulate_type<
377 child,
378 Policy,
379 // apply reduction choice (flat / hierarchic)
380 typename propagate_type_down_tree<
381 current_type,
382 child_tree_path,
383 typename Policy::start_type,
384 typename Policy::reduction_strategy
385 >::type,
386 child_tree_path,
387 NodeTag<child>
388 >::type child_result_type;
389
390 typedef typename accumulate_type_over_children<
391 Node,
392 Policy,
393 child_result_type,
394 TreePath,
395 i+1,
396 n
397 >::type type;
398
399 };
400
402 template<typename Node, typename Policy, typename current_type, typename TreePath, std::size_t n>
403 struct accumulate_type_over_children<Node,Policy,current_type,TreePath,n,n>
404 {
405
406 typedef current_type type;
407
408 };
409
410
413 template<typename Node, typename Policy, typename current_type, typename TreePath>
414 struct accumulate_type_generic_composite_node
415 {
416
417 typedef typename accumulate_type_over_children<
418 Node,
419 Policy,
420 current_type,
421 TreePath,
422 0,
423 StaticDegree<Node>::value
424 >::type children_result_type;
425
426 typedef typename accumulate_type_node_helper<
427 Node,
428 typename Policy::functor,
429 typename Policy::parent_child_reduction,
430 children_result_type,
431 TreePath,
432 Policy::functor::template doVisit<
433 Node,
434 TreePath
435 >::value
436 >::type type;
437
438 };
439
441 template<typename PowerNode, typename Policy, typename current_type, typename TreePath>
442 struct accumulate_type<PowerNode,Policy,current_type,TreePath,PowerNodeTag>
443 : public accumulate_type_generic_composite_node<PowerNode,Policy,current_type,TreePath>
444 {};
445
447 template<typename CompositeNode, typename Policy, typename current_type, typename TreePath>
448 struct accumulate_type<CompositeNode,Policy,current_type,TreePath,CompositeNodeTag>
449 : public accumulate_type_generic_composite_node<CompositeNode,Policy,current_type,TreePath>
450 {};
451
452 } // anonymous namespace
453
454
462 template<
463 typename Functor,
464 typename Reduction,
465 typename StartType,
466 typename ParentChildReduction = Reduction,
467 typename ReductionAlgorithm = flattened_reduction
468 >
470 {
471
499 typedef Functor functor;
500
520 typedef Reduction sibling_reduction;
521
528 typedef ParentChildReduction parent_child_reduction;
529
536 typedef StartType start_type;
537
542 typedef ReductionAlgorithm reduction_strategy;
543 };
544
545
547
555 template<typename Tree, typename Policy>
557 {
558
560 typedef typename accumulate_type<
561 Tree,
562 Policy,
563 typename Policy::start_type,
566 >::type type;
567
568 };
569
570
571
572
573
574 /***************************************************/
575
576 namespace Experimental {
577 namespace Impl {
578
580 template<class T, class TreePath, class V, class U,
581 std::enable_if_t<std::decay_t<T>::isLeaf, int> = 0>
582 auto hybridApplyToTree(T&& tree, TreePath treePath, V&& visitor, U&& current_val)
583 {
584 return visitor.leaf(tree, treePath, std::forward<U>(current_val));
585 }
586
588 template<class T, class TreePath, class V, class U,
589 std::enable_if_t<not std::decay_t<T>::isLeaf, int> = 0>
590 auto hybridApplyToTree(T&& tree, TreePath treePath, V&& visitor, U&& current_val)
591 {
592 using Tree = std::remove_reference_t<T>;
593 using Visitor = std::remove_reference_t<V>;
594 auto pre_val = visitor.pre(tree, treePath, std::forward<U>(current_val));
595
596 // check which type of traversal is supported by the tree
597 using allowDynamicTraversal = Dune::Std::is_detected<Detail::DynamicTraversalConcept,Tree>;
598 using allowStaticTraversal = Dune::Std::is_detected<Detail::StaticTraversalConcept,Tree>;
599
600 // the tree must support either dynamic or static traversal
601 static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
602
603 // the visitor may specify preferred dynamic traversal
604 using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
605
606 // declare rule that applies visitor and current value to a child i. Returns next value
607 auto apply_i = [&](auto&& value, const auto& i){
608 auto&& child = tree.child(i);
609 using Child = std::decay_t<decltype(child)>;
610
611 auto val_before = visitor.beforeChild(tree, child, treePath, i, std::move(value));
612
613 // visits between children
614 auto val_in = Hybrid::ifElse(
615 Hybrid::equal_to(i,Indices::_0),
616 [&](auto id){return std::move(val_before);},
617 [&](auto id){return visitor.in(tree, treePath, std::move(val_before));}
618 );
619
620 constexpr bool visitChild = Visitor::template VisitChild<Tree,Child,TreePath>::value;
621 auto val_visit = [&](){
622 if constexpr (visitChild) {
623 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
624 return hybridApplyToTree(child, childTreePath, visitor, std::move(val_in));
625 }
626 else
627 return std::move(val_in);
628 }();
629
630 return visitor.afterChild(tree, child, treePath, i, std::move(val_visit));
631 };
632
633 // apply visitor to children
634 auto in_val = [&](){
635 if constexpr (allowStaticTraversal::value && not preferDynamicTraversal::value) {
636 // get list of static indices
637 auto indices = std::make_index_sequence<Tree::degree()>{};
638
639 // unfold apply_i left to right
640 return unpackIntegerSequence([&](auto... i) {
660 return left_fold(std::move(apply_i),std::move(pre_val), i...);
661 }, indices);
662
663 } else {
664 // unfold first child to get type
665 auto i_val = apply_i(std::move(pre_val),std::size_t{0});
666 // dynamically loop rest of the children to accumulate remindng values
667 for(std::size_t i = 1; i < tree.degree(); i++)
668 i_val = apply_i(i_val,i);
669 return i_val;
670 }
671 }();
672
673 return visitor.post(tree, treePath, in_val);
674 }
675
676 }
677
701 template<typename Tree, typename Visitor, typename Init>
702 auto hybridApplyToTree(Tree&& tree, Visitor&& visitor, Init&& init)
703 {
704 return Impl::hybridApplyToTree(tree, hybridTreePath(), visitor, init);
705 }
706
707 } // namespace Experimental
708
710 } // namespace TypeTree
711} //namespace Dune
712
713#endif // DUNE_TYPETREE_ACCUMULATE_STATIC_HH
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:79
typename std::decay_t< Node >::NodeTag NodeTag
Returns the node tag of the given Node.
Definition: nodeinterface.hh:70
constexpr auto hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:102
Dune::HybridMultiIndex< T... > HybridTreePath
A type for representing tree paths that supports both compile time and run time indices.
Definition: treepath.hh:85
Statically accumulate a type over the nodes of a TypeTree.
Definition: accumulate_static.hh:557
accumulate_type< Tree, Policy, typenamePolicy::start_type, HybridTreePath<>, NodeTag< Tree > >::type type
The accumulated result of the computation.
Definition: accumulate_static.hh:566
Statically accumulate a value over the nodes of a TypeTree.
Definition: accumulate_static.hh:263
Functor::result_type result_type
The result type of the computation.
Definition: accumulate_static.hh:266
static const result_type result
The accumulated result of the computation.
Definition: accumulate_static.hh:269
Definition: accumulate_static.hh:470
ParentChildReduction parent_child_reduction
Definition: accumulate_static.hh:528
Functor functor
Definition: accumulate_static.hh:499
StartType start_type
Definition: accumulate_static.hh:536
ReductionAlgorithm reduction_strategy
Definition: accumulate_static.hh:542
Reduction sibling_reduction
Definition: accumulate_static.hh:520
Statically combine two values of type result_type using &&.
Definition: accumulate_static.hh:39
Statically combine two values of type result_type by returning their maximum.
Definition: accumulate_static.hh:94
Statically combine two values of type result_type by returning their minimum.
Definition: accumulate_static.hh:83
Statically combine two values of type result_type using -.
Definition: accumulate_static.hh:61
Statically combine two values of type result_type using *.
Definition: accumulate_static.hh:72
Statically combine two values of type result_type using ||.
Definition: accumulate_static.hh:28
Statically combine two values of type result_type using +.
Definition: accumulate_static.hh:50
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jan 10, 23:35, 2026)