DUNE PDELab (git)

integersequence.hh
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
17namespace Dune {
18
20template <std::size_t pos, class T, T... II,
21 std::enable_if_t<(!(pos >= sizeof...(II))), int> = 0>
22constexpr 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
29template <class T, T... II>
30constexpr 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
37template <class T, T I0, T... II>
38constexpr std::integral_constant<T,I0>
39front (std::integer_sequence<T,I0,II...>) { return {}; }
40
42template <class T, T... II,
43 std::enable_if_t<(sizeof...(II) > 0), int> = 0>
44constexpr auto back (std::integer_sequence<T,II...> seq)
45{
46 return get<sizeof...(II)-1>(seq);
47}
48
49
51template <class T, T I0, T... II>
52constexpr std::integral_constant<T,I0>
53head (std::integer_sequence<T,I0,II...>) { return {}; }
54
56template <class T, T I0, T... II>
57constexpr std::integer_sequence<T,II...>
58tail (std::integer_sequence<T,I0,II...>) { return {}; }
59
60
62template <auto I0, class T, T... II>
63constexpr std::integer_sequence<T,T(I0),II...>
64push_front (std::integer_sequence<T,II...>, std::integral_constant<T,I0> = {}) { return {}; }
65
67template <auto IN, class T, T... II>
68constexpr std::integer_sequence<T,II...,T(IN)>
69push_back (std::integer_sequence<T,II...>, std::integral_constant<T,IN> = {}) { return {}; }
70
71
73template <class T, T... II>
74constexpr std::integral_constant<std::size_t,sizeof...(II)>
75size (std::integer_sequence<T,II...>) { return {}; }
76
78template <class T, T... II>
79constexpr std::bool_constant<(sizeof...(II) == 0)>
80empty (std::integer_sequence<T,II...>) { return {}; }
81
82namespace Impl {
83
84// constexpr version of swap for older compilers
85template <class T>
86constexpr void swapImpl (T& a, T& b)
87{
88 T c = a; a = b; b = c;
89}
90
91// constexpr quick sort implementation
92template <class T, std::size_t N, class Compare>
93constexpr 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
108template <class T, std::size_t N, class Compare>
109constexpr 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
118template <class T, T... II, class Compare>
119constexpr 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
128template <class T, T... II>
129constexpr auto sorted (std::integer_sequence<T,II...> seq)
130{
131 return sorted(seq, std::less<T>{});
132}
133
135template <class T, T... II, T value>
136constexpr std::bool_constant<((II == value) || ...)>
137contains (std::integer_sequence<T,II...>, std::integral_constant<T,value>) { return {}; }
138
139
141template <class T, T... II, T... JJ>
142constexpr 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
156template <std::size_t N, class T, T... JJ,
157 std::enable_if_t<(N >= sizeof...(JJ)), int> = 0>
158constexpr auto difference (std::integer_sequence<T,JJ...> jSeq)
159{
160 return difference(std::make_integer_sequence<T,N>{}, jSeq);
161}
162
163
165template <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>>
168constexpr std::is_same<std::integer_sequence<bool,true,(ST(II) == ST(JJ))...>,
169 std::integer_sequence<bool,(ST(II) == ST(JJ))...,true>>
170equal (std::integer_sequence<S,II...>, std::integer_sequence<T,JJ...>) { return {}; }
171
173template <class S, S... II, class T, T... JJ,
174 std::enable_if_t<(sizeof...(II) != sizeof...(JJ)), int> = 0>
175constexpr std::bool_constant<false>
176equal (std::integer_sequence<S,II...>, std::integer_sequence<T,JJ...>) { return {}; }
177
178
179template <template <auto> class Filter, class T>
180constexpr auto filter (std::integer_sequence<T> jSeq) { return jSeq; }
181
184template <template <auto> class Filter, class T, T J0, T... JJ>
185constexpr 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
193template <class Filter, class T>
194constexpr auto filter (Filter, std::integer_sequence<T> jSeq) { return jSeq; }
195
198template <class Filter, class T, T J0, T... JJ>
199constexpr 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
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
Dune namespace.
Definition: alignedallocator.hh:13
constexpr auto sorted(std::integer_sequence< T, II... > seq, Compare comp)
Sort a given sequence by the comparator comp.
Definition: integersequence.hh:119
constexpr std::integer_sequence< T, II..., T(IN)> push_back(std::integer_sequence< T, II... >, std::integral_constant< T, IN >={})
Append an index IN to the back of the sequence.
Definition: integersequence.hh:69
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 std::integer_sequence< T, T(I0), II... > push_front(std::integer_sequence< T, II... >, std::integral_constant< T, I0 >={})
Append an index I0 to the front of the sequence.
Definition: integersequence.hh:64
constexpr std::bool_constant<(sizeof...(II)==0)> empty(std::integer_sequence< T, II... >)
Checks whether the sequence is empty.
Definition: integersequence.hh:80
constexpr std::integral_constant< T, I0 > front(std::integer_sequence< T, I0, II... >)
Return the first entry of the sequence.
Definition: integersequence.hh:39
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 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
constexpr auto back(std::integer_sequence< T, II... > seq)
Return the last entry of the sequence.
Definition: integersequence.hh:44
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 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 auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 23, 23:29, 2024)