TreePath.hpp 5.69 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>

11
12
#include <amdis/common/Mpl.hpp>

Praetorius, Simon's avatar
Praetorius, Simon committed
13

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

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  namespace Concepts
  {
    /** \addtogroup Concepts
     *  @{
     **/

    namespace Definition
    {
      template <class TP>
      struct IsPreTreePath
        : any_of_t<std::is_same<TP, int>::value, std::is_same<TP,std::size_t>::value>
      {};

      template <int I>
      struct IsPreTreePath<int_t<I>>
        : std::true_type
      {};

      template <std::size_t I>
      struct IsPreTreePath<index_t<I>>
        : std::true_type
      {};

      template <std::size_t... I>
      struct IsPreTreePath<Indices<I...>>
        : std::true_type
      {};

46
47
48
49
50
      template <>
      struct IsPreTreePath<RootTreePath>
        : std::true_type
      {};

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    } // end namespace Definition

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

    /** @} **/

  } // 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

85
86
87
  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(); }
88

89
90

  template <int I>
91
92
93
94
  auto makeTreePath(int_t<I>)      { return Dune::TypeTree::hybridTreePath(index_<std::size_t(I)>); }

  template <int... I>
  auto makeTreePath(Ints<I...>)    { return Dune::TypeTree::hybridTreePath(index_<std::size_t(I)>...); }
95
96
97
98
99
100
101

  template <std::size_t I>
  auto makeTreePath(index_t<I> _i) { return Dune::TypeTree::hybridTreePath(_i); }

  template <std::size_t... I>
  auto makeTreePath(Indices<I...>) { return Dune::TypeTree::hybridTreePath(index_<I>...); }

102
103
104
105
106
107
108

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

109
  template <std::size_t... I>
110
111
112
113
  auto makeTreePath(Dune::TypeTree::TreePath<I...>)
  {
    return Dune::TypeTree::hybridTreePath(index_<I>...);
  }
114
115

  template <class TP>
116
117
  auto makeTreePath(TP const&)
  {
118
    static_assert( Concepts::PreTreePath<TP>,
119
120
121
122
      "Argument must be a valid treepath, or an integer/index-constant");
    return Dune::TypeTree::hybridTreePath();
  }

123
#endif // DOXYGEN
Praetorius, Simon's avatar
Praetorius, Simon committed
124

125
126
127

  namespace Impl
  {
128
129
    template <class TreePath, std::size_t... I>
    void printTreePath(std::ostream& os, TreePath const& tp, std::index_sequence<I...>)
130
    {
131
132
133
134
      (void)std::initializer_list<int>{
        ((void)(os << treePathIndex(tp, index_<I>) << ","), 0)...
      };
    }
135
136
  }

137
138
  template <class T0, class... T>
  std::string to_string(Dune::TypeTree::HybridTreePath<T0,T...> const& tp)
139
140
  {
    std::stringstream ss;
141
    Impl::printTreePath(ss, tp, std::make_index_sequence<sizeof...(T)>{});
142
    ss << Dune::TypeTree::treePathEntry<sizeof...(T)>(tp);
143
144
145
    return ss.str();
  }

146
  inline std::string to_string(Dune::TypeTree::HybridTreePath<> const& tp)
147
148
149
150
  {
    return "";
  }

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  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)>{});
  }

  std::array<std::size_t,1> to_array(Dune::TypeTree::HybridTreePath<> const& tp)
  {
    return {{0u}};
  }

171
172
173
174
175
176
177
  /// \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>`)
   **/
178
179
180
181
182
183
  template <class... T>
  constexpr Dune::TypeTree::HybridTreePath<T...> treepath(T const&... t)
  {
    return Dune::TypeTree::HybridTreePath<T...>(t...);
  }

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

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


213
} // end namespace AMDiS