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

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

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

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

13
14
namespace AMDiS
{
15
16
  struct RootTreePath {};

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

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

      template <int I>
31
      struct IsPreTreePath<std::integral_constant<int, I>>
32
33
34
35
        : std::true_type
      {};

      template <std::size_t I>
36
37
38
39
40
41
      struct IsPreTreePath<std::integral_constant<std::size_t, I>>
        : std::true_type
      {};

      template <int... I>
      struct IsPreTreePath<std::integer_sequence<int, I...>>
42
43
44
45
        : std::true_type
      {};

      template <std::size_t... I>
46
      struct IsPreTreePath<std::index_sequence<I...>>
47
48
49
        : std::true_type
      {};

50
51
52
53
54
      template <>
      struct IsPreTreePath<RootTreePath>
        : std::true_type
      {};

55
56
57
58
59
    } // 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
60
61
62
    template <class TP>
    using PreTreePath_t = bool_t<PreTreePath<TP>>;

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    /** @} **/

  } // end namespace Concepts

#ifdef DOXYGEN

  /// \brief Converts a (pre)TreePath into a HybridTreePath
  /**
   * Converts an integer, an integralconstant or a Dune TreePath into an
   * \ref Dune::TypeTree::HybridTreePath that is used in GlobalBasis traversal.
   *
   * **Requirements:**
   * - `PreTreePath` one of
   *     + integer type (`int, std::size_t`),
   *     + integral constant (`std::integral_constant<[int|std::size_t], i>`)
   *     + any Dune TreePath (`TreePath<std::size_t...>, DynamicTreePath, HybridTreePath<class... T>`)
   *
   * **Example:**
   * ```
   * makeTreePath(1),
   * makeTreePath(int_<2>),
   * makeTreePath(treepath(1, int_<2>))
   * ```
   **/
  template <class PreTreePath>
  auto makeTreePath(PreTreePath tp);

#else // DOXYGEN

92
93
94
  inline auto makeTreePath(int i)         { return Dune::TypeTree::hybridTreePath(std::size_t(i)); }
  inline auto makeTreePath(std::size_t i) { return Dune::TypeTree::hybridTreePath(i); }
  inline auto makeTreePath(RootTreePath)  { return Dune::TypeTree::hybridTreePath(); }
95

96
97

  template <int I>
98
99
100
101
  auto makeTreePath(std::integral_constant<int,I>)
  {
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, std::size_t(I)>{});
  }
102
103

  template <int... I>
104
105
106
107
  auto makeTreePath(std::integer_sequence<int, I...>)
  {
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, std::size_t(I)>{}...);
  }
108
109

  template <std::size_t I>
110
111
112
113
  auto makeTreePath(std::integral_constant<std::size_t,I> _i)
  {
    return Dune::TypeTree::hybridTreePath(_i);
  }
114
115

  template <std::size_t... I>
116
117
118
119
  auto makeTreePath(std::index_sequence<I...>)
  {
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
  }
120

121
122
123
124
125
126
127

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

128
  template <std::size_t... I>
129
130
  auto makeTreePath(Dune::TypeTree::TreePath<I...>)
  {
131
    return Dune::TypeTree::hybridTreePath(std::integral_constant<std::size_t, I>{}...);
132
  }
133
134

  template <class TP>
135
136
  auto makeTreePath(TP const&)
  {
137
    static_assert( Concepts::PreTreePath<TP>,
138
139
140
141
      "Argument must be a valid treepath, or an integer/index-constant");
    return Dune::TypeTree::hybridTreePath();
  }

142
#endif // DOXYGEN
Praetorius, Simon's avatar
Praetorius, Simon committed
143

144
145
146

  namespace Impl
  {
147
148
    template <class TreePath, std::size_t... I>
    void printTreePath(std::ostream& os, TreePath const& tp, std::index_sequence<I...>)
149
    {
150
      (void)std::initializer_list<int>{
151
        ((void)(os << treePathIndex(tp, std::integral_constant<std::size_t, I>{}) << ","), 0)...
152
153
      };
    }
154
155
  }

156
157
  template <class T0, class... T>
  std::string to_string(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
158
159
  {
    std::stringstream ss;
160
    Impl::printTreePath(ss, tp, std::make_index_sequence<sizeof...(T)>{});
161
    ss << Dune::TypeTree::treePathEntry<sizeof...(T)>(tp);
162
163
164
    return ss.str();
  }

165
  inline std::string to_string(Dune::TypeTree::HybridTreePath<> const& tp)
166
167
168
169
  {
    return "";
  }

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  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)>{});
  }

185
  inline std::array<std::size_t,1> to_array(Dune::TypeTree::HybridTreePath<> const& tp)
186
187
188
189
  {
    return {{0u}};
  }

190
191
192
193
194
195
196
  /// \brief Generate a TreePath from a sequence of integers and integral-constants
  /**
   * Converts a sequence of arguments to a \ref Dune::TypeTree::HybridTreePath.
   * The arguments can be one of
   * - integer type (`int, std::size_t`)
   * - integral constant (`std::integral_constant<std::size_t,i>, index_t<i>`)
   **/
197
198
199
200
201
202
  template <class... T>
  constexpr Dune::TypeTree::HybridTreePath<T...> treepath(T const&... t)
  {
    return Dune::TypeTree::HybridTreePath<T...>(t...);
  }

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

  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)>{});
  }

231
232
233
234
235
236
  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));
  }
237

238
} // end namespace AMDiS