DUNE-FEM (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_COMMON_HYBRIDMULTIINDEX_HH
7#define DUNE_COMMON_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 n = sizeof...(T)>
167 requires (n > 0 && n == sizeof...(T))
168 [[nodiscard]] constexpr auto front() const
169 {
170 return std::get<0>(_data);
171 }
172
174 template<std::size_t n = sizeof...(T)>
175 requires (n > 0 && n == sizeof...(T))
176 [[nodiscard]] constexpr auto back() const
177 {
178 return std::get<n-1>(_data);
179 }
180
181 private:
182
183 template<class... Head, class... Other>
184 friend constexpr auto join(const HybridMultiIndex<Head...>&, const Other&...);
185
186 std::tuple<T...> _data;
187
188 };
189
190 template<typename... I>
191 requires (((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
192 HybridMultiIndex(I... i) -> HybridMultiIndex<decltype(Impl::castToHybridSizeT(i))...>;
193
194 template<typename... I>
195 HybridMultiIndex(std::tuple<I...>) -> HybridMultiIndex<I...>;
196
198
203 template<typename... T>
204 [[nodiscard]] constexpr auto back(const HybridMultiIndex<T...>& tp)
205 -> decltype(tp.back())
206 {
207 return tp.back();
208 }
209
211
216 template<typename... T>
217 [[nodiscard]] constexpr auto front(const HybridMultiIndex<T...>& tp)
218 -> decltype(tp.front())
219 {
220 return tp.front();
221 }
222
224
227 template<typename... T>
228 [[nodiscard]] constexpr HybridMultiIndex<T...,std::size_t> push_back(const HybridMultiIndex<T...>& tp, std::size_t i)
229 {
230 return unpackIntegerSequence([&](auto... j){
231 return HybridMultiIndex(tp[j] ..., i);
232 }, tp.enumerate());
233 }
234
236
250 template<std::size_t i, typename... T>
251 [[nodiscard]] constexpr HybridMultiIndex<T...,index_constant<i>> push_back(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
252 {
253 return unpackIntegerSequence([&](auto... j){
254 return HybridMultiIndex(tp[j] ..., iConstant);
255 }, tp.enumerate());
256 }
257
259
262 template<typename... T>
263 [[nodiscard]] constexpr HybridMultiIndex<std::size_t,T...> push_front(const HybridMultiIndex<T...>& tp, std::size_t i)
264 {
265 return unpackIntegerSequence([&](auto... j){
266 return HybridMultiIndex(i, tp[j] ...);
267 }, tp.enumerate());
268 }
269
271
285 template<std::size_t i, typename... T>
286 [[nodiscard]] constexpr HybridMultiIndex<index_constant<i>,T...> push_front(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
287 {
288 return unpackIntegerSequence([&](auto... j){
289 return HybridMultiIndex(iConstant, tp[j] ...);
290 }, tp.enumerate());
291 }
292
294
305 template<typename I, typename... T>
306 requires (sizeof...(T) > 0)
307 [[nodiscard]] constexpr auto accumulate_back(const HybridMultiIndex<T...>& tp, I i) {
309 return push_back(pop_back(tp), plus(back(tp), i));
310 }
311
312
314
325 template<typename I, typename... T>
326 requires (sizeof...(T) > 0)
327 [[nodiscard]] constexpr auto accumulate_front(const HybridMultiIndex<T...>& tp, I i) {
329 return push_front(pop_front(tp), plus(front(tp), i));
330 }
331
333 template<class... Head, class... Other>
334 [[nodiscard]] constexpr auto join(const HybridMultiIndex<Head...>& head, const Other&... tail) {
335 return Dune::HybridMultiIndex{std::tuple_cat(head._data, tail._data...)};
336 }
337
339 template<class... T>
340 [[nodiscard]] constexpr auto reverse(const HybridMultiIndex<T...>& tp) {
341 constexpr std::size_t size = sizeof...(T);
342 return unpackIntegerSequence([&](auto... i){
344 }, std::make_index_sequence<size>{});
345 }
346
348
351 template <class... T>
352 requires (sizeof...(T) > 0)
353 [[nodiscard]] constexpr auto pop_front(const HybridMultiIndex<T...>& tp)
354 {
355 return unpackIntegerSequence([&](auto... i){
356 return HybridMultiIndex{std::make_tuple(tp[Dune::index_constant<i+1>{}]...)};
357 }, std::make_index_sequence<(sizeof...(T) - 1)>{});
358 }
359
361
364 template <class... T>
365 requires (sizeof...(T) > 0)
366 [[nodiscard]] constexpr auto pop_back(const HybridMultiIndex<T...>& tp)
367 {
368 return unpackIntegerSequence([&](auto... i){
369 return HybridMultiIndex{std::make_tuple(tp[i]...)};
370 }, std::make_index_sequence<(sizeof...(T) - 1)>{});
371 }
372
374
382 template <class... S, class... T>
383 [[nodiscard]] constexpr bool operator==(
384 const HybridMultiIndex<S...>& lhs,
385 const HybridMultiIndex<T...>& rhs)
386 {
387 if constexpr (sizeof...(S) == sizeof...(T)) {
388 if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
389 return unpackIntegerSequence([&](auto... i){
390 return ((lhs[i] == rhs[i]) &&...);
391 }, lhs.enumerate());
392 } else {
393 return false;
394 }
395 } else {
396 return false;
397 }
398 }
399
401
406 template <class S, S... lhs, class T, T... rhs>
407 [[nodiscard]] constexpr auto operator==(
408 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
409 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
410 {
411 // If we directly put the expression into std::bool_constant,
412 // gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
413 constexpr auto result = (HybridMultiIndex(lhs...) == HybridMultiIndex(rhs...));
414 return std::bool_constant<result>{};
415 }
416
417
419 template <class... S, class... T>
420 [[nodiscard]] constexpr auto operator!=(
421 const HybridMultiIndex<S...>& lhs,
422 const HybridMultiIndex<T...>& rhs)
423 {
424 return !(lhs == rhs);
425 }
426
428 template <class S, S... lhs, class T, T... rhs>
429 [[nodiscard]] constexpr auto operator!=(
430 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
431 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
432 {
433 // If we directly put the expression into std::bool_constant,
434 // gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
435 constexpr auto result = (HybridMultiIndex(lhs...) != HybridMultiIndex(rhs...));
436 return std::bool_constant<result>{};
437 }
438
440 template<typename... T>
441 std::ostream& operator<<(std::ostream& os, const HybridMultiIndex<T...>& tp)
442 {
443 os << "HybridMultiIndex< ";
444 Dune::Hybrid::forEach(tp, [&] (auto tp_i) {
445 os << tp_i << " ";
446 });
447 os << ">";
448 return os;
449 }
450
451} //namespace Dune
452
453
454
455// Implement the tuple-protocol for HybridMultiIndex
456namespace std {
457
458 template<typename... T>
459 struct tuple_size<Dune::HybridMultiIndex<T...>> : public std::integral_constant<std::size_t,sizeof...(T)> {};
460
461 template <size_t i, typename... T>
462 struct tuple_element<i, Dune::HybridMultiIndex<T...> >
463 {
464 using type = std::tuple_element_t<i, std::tuple<T...> >;
465 };
466
467}
468
469
470#endif // DUNE_COMMON_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:168
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:176
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
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:261
constexpr auto plus
Function object for performing addition.
Definition: hybridutilities.hh:533
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:334
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 reverse(const HybridMultiIndex< T... > &tp)
Reverses the order of the elements in the multi-index.
Definition: hybridmultiindex.hh:340
constexpr auto pop_back(const HybridMultiIndex< T... > &tp)
Removes last index on a HybridMultiIndex.
Definition: hybridmultiindex.hh:366
constexpr auto pop_front(const HybridMultiIndex< T... > &tp)
Removes first index on a HybridMultiIndex.
Definition: hybridmultiindex.hh:353
constexpr auto accumulate_back(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the back of a multi-index.
Definition: hybridmultiindex.hh:307
constexpr auto back(const HybridMultiIndex< T... > &tp) -> decltype(tp.back())
Returns a copy of the last element of the HybridMultiIndex.
Definition: hybridmultiindex.hh:204
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:263
constexpr auto accumulate_front(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the front of a multi-index.
Definition: hybridmultiindex.hh:327
constexpr auto operator!=(const HybridMultiIndex< S... > &lhs, const HybridMultiIndex< T... > &rhs)
Compare two HybridMultiIndexs for inequality.
Definition: hybridmultiindex.hh:420
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 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:228
constexpr auto front(const HybridMultiIndex< T... > &tp) -> decltype(tp.front())
Returns a copy of the first element of the HybridMultiIndex.
Definition: hybridmultiindex.hh:217
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 bool operator==(const HybridMultiIndex< S... > &lhs, const HybridMultiIndex< T... > &rhs)
Compare two HybridMultiIndexs for value equality.
Definition: hybridmultiindex.hh:383
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
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Feb 16, 23:40, 2026)