dune-common  2.11
integersequence.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_COMMON_INTEGERSEQUENCE_HH
6 #define DUNE_COMMON_INTEGERSEQUENCE_HH
7 
8 #include <algorithm>
9 #include <array>
10 #include <cassert>
11 #include <functional>
12 #include <type_traits>
13 #include <utility>
14 
15 #include <dune/common/indices.hh>
16 
17 namespace Dune {
18 
20 template <std::size_t pos, class T, T... II,
21  std::enable_if_t<(!(pos >= sizeof...(II))), int> = 0>
22 constexpr auto get (std::integer_sequence<T,II...>, std::integral_constant<std::size_t,pos> = {})
23 {
24  constexpr T entry = std::array<T,sizeof...(II)>{II...}[pos];
25  return std::integral_constant<T,entry>{};
26 }
27 
29 template <class T, T... II>
30 constexpr T get (std::integer_sequence<T,II...>, std::size_t pos)
31 {
32  assert(pos < sizeof...(II));
33  return std::array<T,sizeof...(II)>{II...}[pos];
34 }
35 
37 template <class T, T I0, T... II>
38 constexpr std::integral_constant<T,I0>
39 front (std::integer_sequence<T,I0,II...>) { return {}; }
40 
42 template <class T, T... II,
43  std::enable_if_t<(sizeof...(II) > 0), int> = 0>
44 constexpr auto back (std::integer_sequence<T,II...> seq)
45 {
46  return get<sizeof...(II)-1>(seq);
47 }
48 
49 
51 template <class T, T I0, T... II>
52 constexpr std::integral_constant<T,I0>
53 head (std::integer_sequence<T,I0,II...>) { return {}; }
54 
56 template <class T, T I0, T... II>
57 constexpr std::integer_sequence<T,II...>
58 tail (std::integer_sequence<T,I0,II...>) { return {}; }
59 
60 
62 template <auto I0, class T, T... II>
63 constexpr std::integer_sequence<T,T(I0),II...>
64 push_front (std::integer_sequence<T,II...>, std::integral_constant<T,I0> = {}) { return {}; }
65 
67 template <auto IN, class T, T... II>
68 constexpr std::integer_sequence<T,II...,T(IN)>
69 push_back (std::integer_sequence<T,II...>, std::integral_constant<T,IN> = {}) { return {}; }
70 
71 
73 template <class T, T... II>
74 constexpr std::integral_constant<std::size_t,sizeof...(II)>
75 size (std::integer_sequence<T,II...>) { return {}; }
76 
78 template <class T, T... II>
79 constexpr std::bool_constant<(sizeof...(II) == 0)>
80 empty (std::integer_sequence<T,II...>) { return {}; }
81 
82 namespace Impl {
83 
84 // constexpr version of swap for older compilers
85 template <class T>
86 constexpr void swapImpl (T& a, T& b)
87 {
88  T c = a; a = b; b = c;
89 }
90 
91 // constexpr quick sort implementation
92 template <class T, std::size_t N, class Compare>
93 constexpr void sortImpl (std::array<T, N>& array, Compare comp, std::size_t left = 0, std::size_t right = N)
94 {
95  // based on https://stackoverflow.com/a/40030044
96  if (left < right) {
97  std::size_t m = left;
98  for (std::size_t i = left + 1; i < right; ++i)
99  if (comp(array[i], array[left]))
100  swapImpl(array[++m], array[i]);
101  swapImpl(array[left], array[m]);
102  sortImpl(array, comp, left, m);
103  sortImpl(array, comp, m + 1, right);
104  }
105 }
106 
107 // return the sorted array
108 template <class T, std::size_t N, class Compare>
109 constexpr std::array<T, N> sortedImpl (std::array<T, N> array, Compare comp)
110 {
111  sortImpl(array, comp);
112  return array;
113 }
114 
115 } // end namespace Impl
116 
118 template <class T, T... II, class Compare>
119 constexpr auto sorted (std::integer_sequence<T,II...> /*seq*/, Compare comp)
120 {
121  constexpr auto sorted = Impl::sortedImpl(std::array<T,sizeof...(II)>{II...}, comp);
122  return unpackIntegerSequence([&](auto... i) {
123  return std::integer_sequence<T,sorted[i]...>{};
124  }, std::make_index_sequence<sizeof...(II)>{});
125 }
126 
128 template <class T, T... II>
129 constexpr auto sorted (std::integer_sequence<T,II...> seq)
130 {
131  return sorted(seq, std::less<T>{});
132 }
133 
135 template <class T, T... II, T value>
136 constexpr std::bool_constant<((II == value) || ...)>
137 contains (std::integer_sequence<T,II...>, std::integral_constant<T,value>) { return {}; }
138 
139 
141 template <class T, T... II, T... JJ>
142 constexpr auto difference (std::integer_sequence<T,II...> iSeq, std::integer_sequence<T,JJ...> jSeq)
143 {
144  if constexpr(iSeq.size() == 0 || jSeq.size() == 0)
145  return iSeq;
146  else {
147  constexpr auto I0 = head(iSeq);
148  if constexpr(!contains(jSeq,I0))
149  return push_front<I0.value>(difference(tail(iSeq),jSeq));
150  else
151  return difference(tail(iSeq),jSeq);
152  }
153 }
154 
156 template <std::size_t N, class T, T... JJ,
157  std::enable_if_t<(N >= sizeof...(JJ)), int> = 0>
158 constexpr auto difference (std::integer_sequence<T,JJ...> jSeq)
159 {
160  return difference(std::make_integer_sequence<T,N>{}, jSeq);
161 }
162 
163 
165 template <class S, S... II, class T, T... JJ,
166  std::enable_if_t<(sizeof...(II) == sizeof...(JJ)), int> = 0,
167  class ST = std::common_type_t<S,T>>
168 constexpr std::is_same<std::integer_sequence<bool,true,(ST(II) == ST(JJ))...>,
169  std::integer_sequence<bool,(ST(II) == ST(JJ))...,true>>
170 equal (std::integer_sequence<S,II...>, std::integer_sequence<T,JJ...>) { return {}; }
171 
173 template <class S, S... II, class T, T... JJ,
174  std::enable_if_t<(sizeof...(II) != sizeof...(JJ)), int> = 0>
175 constexpr std::bool_constant<false>
176 equal (std::integer_sequence<S,II...>, std::integer_sequence<T,JJ...>) { return {}; }
177 
178 
179 template <template <auto> class Filter, class T>
180 constexpr auto filter (std::integer_sequence<T> jSeq) { return jSeq; }
181 
184 template <template <auto> class Filter, class T, T J0, T... JJ>
185 constexpr auto filter (std::integer_sequence<T,J0,JJ...> jSeq)
186 {
187  if constexpr(Filter<J0>::value)
188  return push_front(filter<Filter>(tail(jSeq)), head(jSeq));
189  else
190  return filter<Filter>(tail(jSeq));
191 }
192 
193 template <class Filter, class T>
194 constexpr auto filter (Filter, std::integer_sequence<T> jSeq) { return jSeq; }
195 
198 template <class Filter, class T, T J0, T... JJ>
199 constexpr auto filter (Filter f, std::integer_sequence<T,J0,JJ...> jSeq)
200 {
201  constexpr auto jHead = head(jSeq);
202  if constexpr(f(jHead))
203  return push_front(filter(f, tail(jSeq)), jHead);
204  else
205  return filter(f, tail(jSeq));
206 }
207 
208 } // end namespace Dune
209 
210 #endif // DUNE_COMMON_INTEGERSEQUENCE_HH
constexpr auto back(const HybridMultiIndex< T... > &tp) -> decltype(tp.back())
Returns a copy of the last element of the HybridMultiIndex.
Definition: hybridmultiindex.hh:225
constexpr std::bool_constant<((II==value)||...)> contains(std::integer_sequence< T, II... >, std::integral_constant< T, value >)
Checks whether or not a given sequence contains a value.
Definition: integersequence.hh:137
constexpr std::is_same< std::integer_sequence< bool, true,(ST(II)==ST(JJ))... >, std::integer_sequence< bool,(ST(II)==ST(JJ))..., true > > equal(std::integer_sequence< S, II... >, std::integer_sequence< T, JJ... >)
Checks whether two sequences are identical.
Definition: integersequence.hh:170
decltype(auto) constexpr unpackIntegerSequence(F &&f, [[maybe_unused]] std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
constexpr auto front(const HybridMultiIndex< T... > &tp) -> decltype(tp.front())
Returns a copy of the first element of the HybridMultiIndex.
Definition: hybridmultiindex.hh:238
constexpr HybridMultiIndex< std::size_t, T... > push_front(const HybridMultiIndex< T... > &tp, std::size_t i)
Prepends a run time index to a HybridMultiIndex.
Definition: hybridmultiindex.hh:284
I i
Definition: hybridmultiindex.hh:328
Dune namespace
Definition: alignedallocator.hh:12
constexpr std::bool_constant<(sizeof...(II)==0)> empty(std::integer_sequence< T, II... >)
Checks whether the sequence is empty.
Definition: integersequence.hh:80
constexpr auto difference(std::integer_sequence< T, II... > iSeq, std::integer_sequence< T, JJ... > jSeq)
Return the elements from the sequence [II...) which are not found in the sequence [JJ...
Definition: integersequence.hh:142
constexpr std::integral_constant< T, I0 > head(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the single head element.
Definition: integersequence.hh:53
constexpr auto sorted(std::integer_sequence< T, II... >, Compare comp)
Sort a given sequence by the comparator comp.
Definition: integersequence.hh:119
constexpr std::integer_sequence< T, II... > tail(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the tail sequence.
Definition: integersequence.hh:58
constexpr auto filter(std::integer_sequence< T > jSeq)
Definition: integersequence.hh:180
constexpr HybridMultiIndex< T..., std::size_t > push_back(const HybridMultiIndex< T... > &tp, std::size_t i)
Appends a run time index to a HybridMultiIndex.
Definition: hybridmultiindex.hh:249