TreePath.hpp 5.7 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
#include <amdis/common/Mpl.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
12

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

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

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

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

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

88
89

  template <int I>
90
91
92
93
  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)>...); }
94
95
96
97
98
99
100

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

101
102
103
104
105
106
107

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

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

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

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

124
125
126

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

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

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

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  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)>{});
  }

165
  inline std::array<std::size_t,1> to_array(Dune::TypeTree::HybridTreePath<> const& tp)
166
167
168
169
  {
    return {{0u}};
  }

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

183
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

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


212
} // end namespace AMDiS