TreePath.hpp 6.23 KB
Newer Older
1
2
#pragma once

3
4
#include <sstream>
#include <string>
5
#include <type_traits>
6

7
#include <dune/common/version.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
8
#include <dune/common/std/apply.hh>
9
10
11
#include <dune/typetree/treepath.hh>
#include <dune/typetree/typetraits.hh>

Praetorius, Simon's avatar
Praetorius, Simon committed
12
13
#include <amdis/common/Logical.hpp>

14
15
namespace AMDiS
{
16
  using RootTreePath = Dune::TypeTree::HybridTreePath<>;
17

18
19
20
21
22
23
24
25
  namespace Concepts
  {
    /** \addtogroup Concepts
     *  @{
     **/

    namespace Definition
    {
26
      template <class Index>
27
      struct IsPreTreePath
28
        : std::is_integral<Index>
29
30
      {};

31
32
33
      template <class Index, Index I>
      struct IsPreTreePath<std::integral_constant<Index, I>>
        : std::is_integral<Index>
34
35
      {};

36
37
38
      template <class Index, Index... I>
      struct IsPreTreePath<std::integer_sequence<Index, I...>>
        : std::is_integral<Index>
39
40
      {};

41
42
43
      template <class... Indices>
      struct IsPreTreePath<std::tuple<Indices...>>
        : std::conjunction<std::is_integral<Indices>...>
44
45
46
47
48
49
50
      {};

    } // end namespace Definition

    template <class TP>
    constexpr bool PreTreePath = Dune::TypeTree::IsTreePath<TP>::value || Definition::IsPreTreePath<TP>::value;

Praetorius, Simon's avatar
Praetorius, Simon committed
51
52
53
    template <class TP>
    using PreTreePath_t = bool_t<PreTreePath<TP>>;

54
55
56
57
    /** @} **/

  } // end namespace Concepts

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  namespace Impl
  {
    template <class Index,
      std::enable_if_t<std::is_integral_v<Index>, int> = 0>
    std::size_t treePathIndex(Index i)
    {
      return std::size_t(i);
    }

    template <class Index, Index i,
      std::enable_if_t<std::is_integral_v<Index>, int> = 0>
    auto treePathIndex(std::integral_constant<Index,i>)
    {
      return std::integral_constant<std::size_t,std::size_t(i)>{};
    }

  } // end namespace Impl

76
77
#ifdef DOXYGEN

78
  /// \brief Converts a sequence of indices into a HybridTreePath
79
  /**
80
81
   * Converts an integer, an integralconstant, a sequence of those, or a TreePath
   * into an \ref Dune::TypeTree::HybridTreePath that is used in GlobalBasis traversal.
82
83
   *
   * **Requirements:**
84
85
86
87
88
89
   * The arguments can be one or more of
   * - integer type (`int, std::size_t`)
   * - integral constant (`std::integral_constant<[int|std::size_t],i>, index_t<i>`)
   * or one of dune treepath types, e.g.
   * - any Dune TreePath (`TreePath<std::size_t...>, HybridTreePath<class... T>`)
   * - a `std::tuple` type
90
91
92
   *
   * **Example:**
   * ```
93
94
95
96
97
   * makeTreePath(0,1,2),
   * makeTreePath(int_<2>, 0),
   * makeTreePath(1, index_<2>),
   * makeTreePath(hybridTreePath(0,1,2)),
   * makeTreePath(std::tuple{0,index_<2>,2})
98
99
100
101
102
103
104
   * ```
   **/
  template <class PreTreePath>
  auto makeTreePath(PreTreePath tp);

#else // DOXYGEN

105
106
107
  template <class... Indices>
  auto makeTreePath(Indices... ii)
    -> decltype( Dune::TypeTree::hybridTreePath(Impl::treePathIndex(ii)...) )
108
  {
109
    return Dune::TypeTree::hybridTreePath(Impl::treePathIndex(ii)...);
110
  }
111

112
  inline auto makeTreePath()
113
  {
114
    return Dune::TypeTree::hybridTreePath();
115
  }
116

117
118
  template <class Index, Index... I>
  auto makeTreePath(std::integer_sequence<Index, I...>)
119
  {
120
    return makeTreePath(std::integral_constant<std::size_t, std::size_t(I)>{}...);
121
  }
122

123
124
125
126
127
  template <class... T>
  auto makeTreePath(std::tuple<T...> const& tp)
  {
    return std::apply([](auto... ii) { return makeTreePath(ii...); }, tp);
  }
128
129
130
131
132
133
134

  template <class... T>
  auto const& makeTreePath(Dune::TypeTree::HybridTreePath<T...> const& tp)
  {
    return tp;
  }

135
#if DUNE_VERSION_LT(DUNE_TYPETREE,2,7)
136
  template <std::size_t... I>
137
138
  auto makeTreePath(Dune::TypeTree::TreePath<I...>)
  {
139
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
140
  }
141
142
143
144
145
146
147
#else
  template <std::size_t... I>
  auto makeTreePath(Dune::TypeTree::StaticTreePath<I...>)
  {
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
  }
#endif
148

149
#endif // DOXYGEN
Praetorius, Simon's avatar
Praetorius, Simon committed
150

151
152
153

  namespace Impl
  {
154
155
    template <class TreePath, std::size_t... I>
    void printTreePath(std::ostream& os, TreePath const& tp, std::index_sequence<I...>)
156
    {
157
      (void)std::initializer_list<int>{
158
        ((void)(os << treePathIndex(tp, std::integral_constant<std::size_t, I>{}) << ","), 0)...
159
160
      };
    }
161
162
  }

163
164
  template <class T0, class... T>
  std::string to_string(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
165
166
  {
    std::stringstream ss;
167
    Impl::printTreePath(ss, tp, std::make_index_sequence<sizeof...(T)>{});
168
    ss << Dune::TypeTree::treePathEntry<sizeof...(T)>(tp);
169
170
171
    return ss.str();
  }

Praetorius, Simon's avatar
Praetorius, Simon committed
172
  inline std::string to_string(Dune::TypeTree::HybridTreePath<> const&)
173
174
175
176
  {
    return "";
  }

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  namespace Impl
  {
    template <class TreePath, std::size_t... I>
    std::array<std::size_t, sizeof...(I)> toArrayImpl(TreePath const& tp, std::index_sequence<I...>)
    {
      return {{std::size_t(Dune::TypeTree::treePathEntry<I>(tp))...}};
    }
  }

  template <class T0, class... T>
  auto to_array(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
  {
    return Impl::toArrayImpl(tp, std::make_index_sequence<1+sizeof...(T)>{});
  }

Praetorius, Simon's avatar
Praetorius, Simon committed
192
  inline std::array<std::size_t,1> to_array(Dune::TypeTree::HybridTreePath<> const&)
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  {
    return {{0u}};
  }


  namespace Impl
  {
    template <class TreePath, std::size_t... I>
    auto popFrontImpl(TreePath const& tp, std::index_sequence<I...>)
    {
      return Dune::TypeTree::hybridTreePath(Dune::TypeTree::treePathEntry<I+1>(tp)...);
    }

    template <class TreePath, std::size_t... I>
    auto popBackImpl(TreePath const& tp, std::index_sequence<I...>)
    {
      return Dune::TypeTree::hybridTreePath(Dune::TypeTree::treePathEntry<I>(tp)...);
    }
  }

  template <class T0, class... T>
  Dune::TypeTree::HybridTreePath<T...> pop_front(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
  {
    return Impl::popFrontImpl(tp, std::make_index_sequence<sizeof...(T)>{});
  }

  template <class... T, class TN>
  Dune::TypeTree::HybridTreePath<T...> pop_front(Dune::TypeTree::HybridTreePath<T...,TN> const& tp)
  {
    return Impl::popBackImpl(tp, std::make_index_sequence<sizeof...(T)>{});
  }

225
226
227
228
229
230
  template <class... S, class... T>
  Dune::TypeTree::HybridTreePath<S...,T...> cat(Dune::TypeTree::HybridTreePath<S...> const& tp0,
                                                Dune::TypeTree::HybridTreePath<T...> const& tp1)
  {
    return Dune::TypeTree::HybridTreePath<S...,T...>(std::tuple_cat(tp0._data,tp1._data));
  }
231

232
} // end namespace AMDiS