DUNE PDELab (unstable)

hybridmultiindex.hh
1// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=8 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 OR LGPL-3.0-or-later
5
6#ifndef DUNE_TYPETREE_HYBRIDMULTIINDEX_HH
7#define DUNE_TYPETREE_HYBRIDMULTIINDEX_HH
8
9#include <cstddef>
10#include <cassert>
11#include <iostream>
12#include <type_traits>
13
15#include <dune/common/indices.hh>
16#include <dune/common/hybridutilities.hh>
17
18namespace Dune {
19
20 // The Impl namespace collects some free standing functions helper functions
21 namespace Impl {
22
23 template<class T>
24 constexpr bool isHybridSizeT()
25 {
26 if constexpr (std::is_same_v<T, std::size_t>)
27 return true;
28 else
29 {
30 if constexpr (requires { T::value; })
31 return std::is_same_v<T, std::integral_constant<std::size_t, T::value>>;
32 else
33 return false;
34 }
35 }
36
37 template<class T>
38 constexpr auto castToHybridSizeT(T t)
39 {
41 {
42 using VT = typename T::value_type;
43 static_assert(
44 std::is_convertible_v<VT,std::size_t> &&
45 std::is_integral_v<VT> &&
46 T::value >= 0,
47 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
48 return std::integral_constant<std::size_t, T::value>{};
49 }
50 if constexpr (std::is_integral_v<T>)
51 {
52 static_assert(
53 std::is_convertible_v<T,std::size_t> &&
54 std::is_integral_v<T>,
55 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
56 assert(t >= 0 &&
57 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
58 return std::size_t(t);
59 }
60 if constexpr (not (Dune::IsIntegralConstant<T>::value or std::is_integral_v<T>))
61 {
62 return std::size_t(0);
63 }
64 }
65
66 }
67
79 template<typename... T>
81 {
82
83 // make sure that all indices use std::size_t as the underlying number type
84 static_assert((... && Impl::isHybridSizeT<T>()),
85 "HybridMultiIndex index storage must be std::size_t or std::integral_constant<std::size_t,v>");
86
87 public:
88
90 using index_sequence = std::index_sequence_for<T...>;
91
92 constexpr HybridMultiIndex() = default;
93
94 constexpr HybridMultiIndex(const HybridMultiIndex& tp) = default;
95
96 constexpr HybridMultiIndex(HybridMultiIndex&& tp) = default;
97
98 constexpr HybridMultiIndex& operator=(const HybridMultiIndex& tp) = default;
99
100 constexpr HybridMultiIndex& operator=(HybridMultiIndex&& tp) = default;
101
103 explicit constexpr HybridMultiIndex(std::tuple<T...> t)
104 : _data(t)
105 {}
106
108 template<typename... I>
109 requires ((sizeof...(T) > 0 && sizeof...(I) == sizeof...(T))
110 and ((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
111 explicit constexpr HybridMultiIndex(I... i)
112 : _data(Impl::castToHybridSizeT(i)...) // we assume that all arguments are convertible to the types T...
113 {}
114
116 [[nodiscard]] constexpr static index_sequence enumerate()
117 {
118 return {};
119 }
120
122 [[nodiscard]] constexpr static std::size_t size()
123 {
124 return sizeof...(T);
125 }
126
128 [[nodiscard]] constexpr static std::size_t max_size()
129 {
130 return size();
131 }
132
139 template<std::size_t i>
140 requires (sizeof...(T) > i)
141 [[nodiscard]] constexpr auto get() const
142 {
143 return std::get<i>(_data);
144 }
145
147 template<std::size_t i>
148 requires (sizeof...(T) > i)
149 [[nodiscard]] constexpr auto operator[](Dune::index_constant<i>) const
150 {
151 return std::get<i>(_data);
152 }
153
155 [[nodiscard]] constexpr std::size_t operator[](std::size_t pos) const
156 {
157 std::size_t entry = 0;
158 Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
159 if (i==pos)
160 entry = (*this)[i];
161 });
162 return entry;
163 }
164
166 template<std::size_t i>
167 requires (sizeof...(T) > i)
168 [[deprecated("Method will be removed after Dune 2.11. Use operator[] instead.")]]
169 [[nodiscard]] constexpr auto element(Dune::index_constant<i> pos = {}) const
170 {
171 return std::get<i>(_data);
172 }
173
175 [[deprecated("Method will be removed after Dune 2.11. Use operator[] instead.")]]
176 [[nodiscard]] constexpr std::size_t element(std::size_t pos) const
177 {
178 std::size_t entry = 0;
179 Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
180 if (i==pos)
181 entry = (*this)[i];
182 });
183 return entry;
184 }
185
187 template<std::size_t n = sizeof...(T)>
188 requires (n > 0 && n == sizeof...(T))
189 [[nodiscard]] constexpr auto front() const
190 {
191 return std::get<0>(_data);
192 }
193
195 template<std::size_t n = sizeof...(T)>
196 requires (n > 0 && n == sizeof...(T))
197 [[nodiscard]] constexpr auto back() const
198 {
199 return std::get<n-1>(_data);
200 }
201
202 private:
203
204 template<class... Head, class... Other>
205 friend constexpr auto join(const HybridMultiIndex<Head...>&, const Other&...);
206
207 std::tuple<T...> _data;
208
209 };
210
211 template<typename... I>
212 requires (((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
213 HybridMultiIndex(I... i) -> HybridMultiIndex<decltype(Impl::castToHybridSizeT(i))...>;
214
215 template<typename... I>
216 HybridMultiIndex(std::tuple<I...>) -> HybridMultiIndex<I...>;
217
219
224 template<typename... T>
225 [[nodiscard]] constexpr auto back(const HybridMultiIndex<T...>& tp)
226 -> decltype(tp.back())
227 {
228 return tp.back();
229 }
230
232
237 template<typename... T>
238 [[nodiscard]] constexpr auto front(const HybridMultiIndex<T...>& tp)
239 -> decltype(tp.front())
240 {
241 return tp.front();
242 }
243
245
248 template<typename... T>
249 [[nodiscard]] constexpr HybridMultiIndex<T...,std::size_t> push_back(const HybridMultiIndex<T...>& tp, std::size_t i)
250 {
251 return unpackIntegerSequence([&](auto... j){
252 return HybridMultiIndex(tp[j] ..., i);
253 }, tp.enumerate());
254 }
255
257
271 template<std::size_t i, typename... T>
272 [[nodiscard]] constexpr HybridMultiIndex<T...,index_constant<i>> push_back(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
273 {
274 return unpackIntegerSequence([&](auto... j){
275 return HybridMultiIndex(tp[j] ..., iConstant);
276 }, tp.enumerate());
277 }
278
280
283 template<typename... T>
284 [[nodiscard]] constexpr HybridMultiIndex<std::size_t,T...> push_front(const HybridMultiIndex<T...>& tp, std::size_t i)
285 {
286 return unpackIntegerSequence([&](auto... j){
287 return HybridMultiIndex(i, tp[j] ...);
288 }, tp.enumerate());
289 }
290
292
306 template<std::size_t i, typename... T>
307 [[nodiscard]] constexpr HybridMultiIndex<index_constant<i>,T...> push_front(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
308 {
309 return unpackIntegerSequence([&](auto... j){
310 return HybridMultiIndex(iConstant, tp[j] ...);
311 }, tp.enumerate());
312 }
313
315
326 template<typename I, typename... T>
327 requires (sizeof...(T) > 0)
328 [[nodiscard]] constexpr auto accumulate_back(const HybridMultiIndex<T...>& tp, I i) {
330 return push_back(pop_back(tp), plus(back(tp), i));
331 }
332
333
335
346 template<typename I, typename... T>
347 requires (sizeof...(T) > 0)
348 [[nodiscard]] constexpr auto accumulate_front(const HybridMultiIndex<T...>& tp, I i) {
350 return push_front(pop_front(tp), plus(front(tp), i));
351 }
352
354 template<class... Head, class... Other>
355 [[nodiscard]] constexpr auto join(const HybridMultiIndex<Head...>& head, const Other&... tail) {
356 return Dune::HybridMultiIndex{std::tuple_cat(head._data, tail._data...)};
357 }
358
360 template<class... T>
361 [[nodiscard]] constexpr auto reverse(const HybridMultiIndex<T...>& tp) {
362 constexpr std::size_t size = sizeof...(T);
363 return unpackIntegerSequence([&](auto... i){
365 }, std::make_index_sequence<size>{});
366 }
367
369
372 template <class... T>
373 requires (sizeof...(T) > 0)
374 [[nodiscard]] constexpr auto pop_front(const HybridMultiIndex<T...>& tp)
375 {
376 return unpackIntegerSequence([&](auto... i){
377 return HybridMultiIndex{std::make_tuple(tp[Dune::index_constant<i+1>{}]...)};
378 }, std::make_index_sequence<(sizeof...(T) - 1)>{});
379 }
380
382
385 template <class... T>
386 requires (sizeof...(T) > 0)
387 [[nodiscard]] constexpr auto pop_back(const HybridMultiIndex<T...>& tp)
388 {
389 return unpackIntegerSequence([&](auto... i){
390 return HybridMultiIndex{std::make_tuple(tp[i]...)};
391 }, std::make_index_sequence<(sizeof...(T) - 1)>{});
392 }
393
395
403 template <class... S, class... T>
404 [[nodiscard]] constexpr bool operator==(
405 const HybridMultiIndex<S...>& lhs,
406 const HybridMultiIndex<T...>& rhs)
407 {
408 if constexpr (sizeof...(S) == sizeof...(T)) {
409 if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
410 return unpackIntegerSequence([&](auto... i){
411 return ((lhs[i] == rhs[i]) &&...);
412 }, lhs.enumerate());
413 } else {
414 return false;
415 }
416 } else {
417 return false;
418 }
419 }
420
422
427 template <class S, S... lhs, class T, T... rhs>
428 [[nodiscard]] constexpr auto operator==(
429 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
430 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
431 {
432 // If we directly put the expresion into std::bool_constant,
433 // gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
434 constexpr auto result = (HybridMultiIndex(lhs...) == HybridMultiIndex(rhs...));
435 return std::bool_constant<result>{};
436 }
437
438
440 template <class... S, class... T>
441 [[nodiscard]] constexpr auto operator!=(
442 const HybridMultiIndex<S...>& lhs,
443 const HybridMultiIndex<T...>& rhs)
444 {
445 return !(lhs == rhs);
446 }
447
449 template <class S, S... lhs, class T, T... rhs>
450 [[nodiscard]] constexpr auto operator!=(
451 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
452 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
453 {
454 // If we directly put the expresion into std::bool_constant,
455 // gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
456 constexpr auto result = (HybridMultiIndex(lhs...) != HybridMultiIndex(rhs...));
457 return std::bool_constant<result>{};
458 }
459
461 template<typename... T>
462 std::ostream& operator<<(std::ostream& os, const HybridMultiIndex<T...>& tp)
463 {
464 os << "HybridMultiIndex< ";
465 Dune::Hybrid::forEach(tp, [&] (auto tp_i) {
466 os << tp_i << " ";
467 });
468 os << ">";
469 return os;
470 }
471
472} //namespace Dune
473
474
475
476// Implement the tuple-protocol for HybridMultiIndex
477namespace std {
478
479 template<typename... T>
480 struct tuple_size<Dune::HybridMultiIndex<T...>> : public std::integral_constant<std::size_t,sizeof...(T)> {};
481
482 template <size_t i, typename... T>
483 struct tuple_element<i, Dune::HybridMultiIndex<T...> >
484 {
485 using type = std::tuple_element_t<i, std::tuple<T...> >;
486 };
487
488}
489
490
491#endif // DUNE_TYPETREE_HYBRIDMULTIINDEX_HH
A hybrid multi-index class that supports both compile time and run time indices.
Definition: hybridmultiindex.hh:81
static constexpr std::size_t size()
Get the size (length) of this multi-index.
Definition: hybridmultiindex.hh:122
constexpr auto operator[](Dune::index_constant< i >) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:149
static constexpr std::size_t max_size()
Get the size (length) of this multi-index.
Definition: hybridmultiindex.hh:128
constexpr auto front() const
Get the first index value. Only available in non-empty multi-indices.
Definition: hybridmultiindex.hh:189
static constexpr index_sequence enumerate()
Returns an index_sequence for enumerating the components of this HybridMultiIndex.
Definition: hybridmultiindex.hh:116
constexpr auto get() const
Get the index value at position pos.
Definition: hybridmultiindex.hh:141
constexpr HybridMultiIndex(std::tuple< T... > t)
Constructor from a std::tuple
Definition: hybridmultiindex.hh:103
constexpr auto back() const
Get the last index value. Only available in non-empty multi-indices.
Definition: hybridmultiindex.hh:197
constexpr auto element(Dune::index_constant< i > pos={}) const
Get the last index value.
Definition: hybridmultiindex.hh:169
std::index_sequence_for< T... > index_sequence
An index_sequence for the entries in this HybridMultiIndex.
Definition: hybridmultiindex.hh:90
constexpr std::size_t operator[](std::size_t pos) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:155
constexpr HybridMultiIndex(I... i)
Constructor from arguments.
Definition: hybridmultiindex.hh:111
constexpr std::size_t element(std::size_t pos) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:176
Traits for type conversions and type information.
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
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:29
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
constexpr auto plus
Function object for performing addition.
Definition: hybridutilities.hh:529
constexpr EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
constexpr EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:260
Dune namespace.
Definition: alignedallocator.hh:13
constexpr auto join(const HybridMultiIndex< Head... > &head, const Other &... tail)
Join two hybrid multi-indices into one.
Definition: hybridmultiindex.hh:355
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 auto reverse(const HybridMultiIndex< T... > &tp)
Reverses the order of the elements in the multi-index.
Definition: hybridmultiindex.hh:361
constexpr auto pop_back(const HybridMultiIndex< T... > &tp)
Removes last index on a HybridMultiIndex.
Definition: hybridmultiindex.hh:387
constexpr auto pop_front(const HybridMultiIndex< T... > &tp)
Removes first index on a HybridMultiIndex.
Definition: hybridmultiindex.hh:374
constexpr auto accumulate_back(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the back of a multi-index.
Definition: hybridmultiindex.hh:328
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 auto accumulate_front(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the front of a multi-index.
Definition: hybridmultiindex.hh:348
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 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
STL namespace.
Check if T is an std::integral_constant<I, i>
Definition: typetraits.hh:384
Checks whether two types are interoperable.
Definition: typetraits.hh:65
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 3, 22:42, 2025)