TreePath.hpp 6.37 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
17
  struct RootTreePath {};

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
      template <>
      struct IsPreTreePath<RootTreePath>
        : std::true_type
      {};

51
52
53
54
55
    } // 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
56
57
58
    template <class TP>
    using PreTreePath_t = bool_t<PreTreePath<TP>>;

59
60
61
62
    /** @} **/

  } // end namespace Concepts

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  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

81
82
#ifdef DOXYGEN

83
  /// \brief Converts a sequence of indices into a HybridTreePath
84
  /**
85
86
   * Converts an integer, an integralconstant, a sequence of those, or a TreePath
   * into an \ref Dune::TypeTree::HybridTreePath that is used in GlobalBasis traversal.
87
88
   *
   * **Requirements:**
89
90
91
92
93
94
   * 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
95
96
97
   *
   * **Example:**
   * ```
98
99
100
101
102
   * makeTreePath(0,1,2),
   * makeTreePath(int_<2>, 0),
   * makeTreePath(1, index_<2>),
   * makeTreePath(hybridTreePath(0,1,2)),
   * makeTreePath(std::tuple{0,index_<2>,2})
103
104
105
106
107
108
109
   * ```
   **/
  template <class PreTreePath>
  auto makeTreePath(PreTreePath tp);

#else // DOXYGEN

110
111
112
  template <class... Indices>
  auto makeTreePath(Indices... ii)
    -> decltype( Dune::TypeTree::hybridTreePath(Impl::treePathIndex(ii)...) )
113
  {
114
    return Dune::TypeTree::hybridTreePath(Impl::treePathIndex(ii)...);
115
  }
116

117
  inline auto makeTreePath()
118
  {
119
    return Dune::TypeTree::hybridTreePath();
120
  }
121

122
  inline auto makeTreePath(RootTreePath)
123
  {
124
    return makeTreePath();
125
  }
126

127
128
  template <class Index, Index... I>
  auto makeTreePath(std::integer_sequence<Index, I...>)
129
  {
130
    return makeTreePath(std::integral_constant<std::size_t, std::size_t(I)>{}...);
131
  }
132

133
134
135
136
137
  template <class... T>
  auto makeTreePath(std::tuple<T...> const& tp)
  {
    return std::apply([](auto... ii) { return makeTreePath(ii...); }, tp);
  }
138
139
140
141
142
143
144

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

145
#if DUNE_VERSION_LT(DUNE_TYPETREE,2,7)
146
  template <std::size_t... I>
147
148
  auto makeTreePath(Dune::TypeTree::TreePath<I...>)
  {
149
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
150
  }
151
152
153
154
155
156
157
#else
  template <std::size_t... I>
  auto makeTreePath(Dune::TypeTree::StaticTreePath<I...>)
  {
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
  }
#endif
158

159
#endif // DOXYGEN
Praetorius, Simon's avatar
Praetorius, Simon committed
160

161
162
163

  namespace Impl
  {
164
165
    template <class TreePath, std::size_t... I>
    void printTreePath(std::ostream& os, TreePath const& tp, std::index_sequence<I...>)
166
    {
167
      (void)std::initializer_list<int>{
168
        ((void)(os << treePathIndex(tp, std::integral_constant<std::size_t, I>{}) << ","), 0)...
169
170
      };
    }
171
172
  }

173
174
  template <class T0, class... T>
  std::string to_string(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
175
176
  {
    std::stringstream ss;
177
    Impl::printTreePath(ss, tp, std::make_index_sequence<sizeof...(T)>{});
178
    ss << Dune::TypeTree::treePathEntry<sizeof...(T)>(tp);
179
180
181
    return ss.str();
  }

Praetorius, Simon's avatar
Praetorius, Simon committed
182
  inline std::string to_string(Dune::TypeTree::HybridTreePath<> const&)
183
184
185
186
  {
    return "";
  }

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  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
202
  inline std::array<std::size_t,1> to_array(Dune::TypeTree::HybridTreePath<> const&)
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  {
    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)>{});
  }

235
236
237
238
239
240
  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));
  }
241

242
} // end namespace AMDiS