Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
mdspan.hpp
Go to the documentation of this file.
1 // Copyright (c) 2018 Maikel Nadolski
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 /// @file This file introduces `extents<E0, ..., En>`, a compact
22 /// multi-dimensional size type. Each integral extent `Ei` stands an upper bound
23 /// in dimension `i` and can either be a compile-time constant signed integral
24 /// value or `dynamic_extent`. Each compile-time sized extent does not take any
25 /// extra byte.
26 
27 #ifndef FUB_CORE_MDSPAN_HPP
28 #define FUB_CORE_MDSPAN_HPP
29 
30 #include "fub/core/assert.hpp"
32 #include "fub/core/span.hpp"
33 #include "fub/core/type_traits.hpp"
34 
35 #include <array>
36 #include <type_traits>
37 
38 #include <boost/mp11/tuple.hpp>
39 
40 namespace fub {
41 /// This is the storage type for the extents class and only takes storage for
42 /// dynamic extents.
43 ///
44 /// This class is also responsible for accessing all extents.
45 template <std::size_t Rank, std::size_t DynamicRank,
46  std::ptrdiff_t... StaticExtents>
47 class ExtentsStorage_;
48 
49 /// This is the class template specialisation if all extents are statically
50 /// known.
51 ///
52 /// In this case no extra storage is going to be used.
53 template <std::size_t Rank, std::ptrdiff_t... StaticExtents>
54 class ExtentsStorage_<Rank, 0, StaticExtents...> {
55 public:
56  static_assert(Rank == sizeof...(StaticExtents),
57  "Rank does not match sizeof...(StaticExtents)!");
58  static_assert(
59  conjunction<bool_constant<(StaticExtents != dynamic_extent)>...>::value,
60  "Some static extent is equal to dynamic_extent!");
61 
62  // [mdspan.extents.obs], Observers of the domain multi-index space
63 
64  /// Returns sizeof...(StaticExtents)
65  static constexpr std::size_t rank() noexcept { return Rank; }
66 
67  /// Returns 0.
68  static constexpr std::size_t rank_dynamic() noexcept { return 0; }
69 
70  /// Returns the n-th Static Extent.
71  static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept {
72  const std::ptrdiff_t static_extents[Rank]{StaticExtents...};
73  return static_extents[n];
74  }
75 
76  /// Returns the N-th Extent.
77  ///
78  /// In this case where all extents are known at compile time, this returns
79  /// `static_extent(n)`.
80  constexpr std::ptrdiff_t extent(size_t n) const noexcept {
81  return static_extent(n);
82  }
83 };
84 
85 template <std::size_t Rank, std::ptrdiff_t... StaticExtents>
86 class ExtentsStorage_<Rank, Rank, StaticExtents...> {
87 public:
88  static_assert(Rank == sizeof...(StaticExtents),
89  "Rank does not match sizeof...(StaticExtents)!");
90  static_assert(
92  "Not all static extents are equal to dynamic_extent!");
93 
94  // [mdspan.extents.constructors]
95 
96  ExtentsStorage_() = default;
97 
98  template <typename... IndexType,
99  typename = std::enable_if_t<conjunction<
100  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
101  typename = std::enable_if_t<sizeof...(IndexType) == Rank>>
102  constexpr explicit ExtentsStorage_(IndexType... extent) noexcept
103  : m_dynamic_extents{static_cast<std::ptrdiff_t>(extent)...} {}
104 
105  constexpr explicit ExtentsStorage_(
106  const std::array<std::ptrdiff_t, Rank>& extents) noexcept
108 
109  // [mdspan.extents.obs], Observers of the domain multi-index space
110 
111  /// Returns sizeof...(StaticExtents)
112  static constexpr std::size_t rank() noexcept { return Rank; }
113 
114  /// Returns sizeof...(StaticExtents)
115  static constexpr std::size_t rank_dynamic() noexcept { return Rank; }
116 
117  /// Returns dynamic_extent.
118  static constexpr std::ptrdiff_t static_extent(std::size_t /* n */) noexcept {
119  return dynamic_extent;
120  }
121 
122  /// Returns the N-th Extent.
123  constexpr std::ptrdiff_t extent(size_t n) const noexcept {
124  return m_dynamic_extents[n];
125  }
126 
127 private:
128  std::array<std::ptrdiff_t, Rank> m_dynamic_extents{};
129 };
130 
131 template <std::size_t Rank, std::size_t RankDynamic,
132  std::ptrdiff_t... StaticExtents>
134 public:
135  // [mdspan.extents.constructors]
136 
137  ExtentsStorage_() = default;
138 
139  template <typename... IndexType,
140  typename = std::enable_if_t<conjunction<
141  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
142  typename = std::enable_if_t<sizeof...(IndexType) == RankDynamic>>
143  constexpr explicit ExtentsStorage_(IndexType... extent) noexcept
144  : m_dynamic_extents{static_cast<std::ptrdiff_t>(extent)...} {}
145 
146  constexpr explicit ExtentsStorage_(
147  const std::array<std::ptrdiff_t, RankDynamic>& extents) noexcept
149 
150  // [mdspan.extents.obs], Observers of the domain multi-index space
151 
152  /// Returns sizeof...(StaticExtents)
153  static constexpr std::size_t rank() noexcept { return Rank; }
154 
155  /// Returns sizeof...(StaticExtents)
156  static constexpr std::size_t rank_dynamic() noexcept { return RankDynamic; }
157 
158  /// Returns dynamic_extent.
159  static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept {
160  constexpr std::ptrdiff_t static_extents[Rank]{StaticExtents...};
161  return static_extents[n];
162  }
163 
164  /// Returns the N-th Extent.
165  constexpr std::ptrdiff_t extent(size_t n) const noexcept {
166  constexpr std::ptrdiff_t static_extents[Rank]{StaticExtents...};
167  if (static_extents[n] != dynamic_extent) {
168  return static_extents[n];
169  }
171  }
172 
173 private:
174  std::array<std::ptrdiff_t, RankDynamic> m_dynamic_extents{};
175 
176  static constexpr std::size_t
177  find_dynamic_extent_index(std::size_t n) noexcept {
178  constexpr std::ptrdiff_t static_extents[Rank]{StaticExtents...};
179  std::size_t dynamic_extent_index = 0;
180  for (std::size_t dim = 0; dim < n; ++dim) {
181  if (static_extents[dim] == dynamic_extent) {
182  ++dynamic_extent_index;
183  }
184  }
185  return dynamic_extent_index;
186  }
187 };
188 
189 template <typename... IndexType>
190 constexpr std::size_t count_dynamic_extents(IndexType... extent) noexcept {
191  constexpr std::size_t Rank = sizeof...(IndexType);
192  std::ptrdiff_t extents[Rank]{static_cast<std::ptrdiff_t>(extent)...};
193  std::size_t counter = 0;
194  for (std::size_t dim = 0; dim < Rank; ++dim) {
195  if (extents[dim] == dynamic_extent) {
196  ++counter;
197  }
198  }
199  return counter;
200 }
201 
202 /// \ingroup spans
203 /// An extents object defines a multidimensional index space which is the
204 /// Cartesian product of integers extents `[0..N0) * [0..N1) * ...`
205 template <std::ptrdiff_t... StaticExtents>
206 class extents : private ExtentsStorage_<sizeof...(StaticExtents),
207  count_dynamic_extents(StaticExtents...),
208  StaticExtents...> {
209 private:
210  using base_type = ExtentsStorage_<sizeof...(StaticExtents),
211  count_dynamic_extents(StaticExtents...),
212  StaticExtents...>;
213 
214 public:
215  // Type Definitions
216 
217  using index_type = std::ptrdiff_t;
218 
219  // [mdspan.extents.constructors]
220 
221  using base_type::base_type;
222 
223  // [mdspan.extents.static_observers]
224 
225  /// Returns sizeof...(StaticExtents)
226  static constexpr std::size_t rank() noexcept { return base_type::rank(); }
227 
228  /// Returns sizeof...(StaticExtents)
229  static constexpr std::size_t rank_dynamic() noexcept {
230  return base_type::rank_dynamic();
231  }
232 
233  /// Returns the `n`-th `StaticExtent`.
234  static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept {
235  return base_type::static_extent(n);
236  }
237 
238  // [mdspan.extents.observers]
239 
240  /// Returns the `n`-th run-time extent.
241  constexpr std::ptrdiff_t extent(size_t n) const noexcept {
242  return base_type::extent(n);
243  }
244 };
245 
246 // [mdspan.extents.traits.is_extent]
247 
248 /// \ingroup type-traits
249 /// This is true `std::true_type` iff `E` is `extents<Es...>`
250 /// for some `std::ptrdiff_t... Es`.
251 /// @{
252 template <typename E> struct is_extents : std::false_type {};
253 template <std::ptrdiff_t... StaticExtents>
254 struct is_extents<extents<StaticExtents...>> : std::true_type {};
255 template <typename E> static constexpr bool is_extents_v = is_extents<E>::value;
256 /// @}
257 
258 /// Returns: `true` if `lhs.rank() == rhs.rank()` and `lhs.extents(r) ==
259 /// rhs.extents(r)` for all `r` in the range `[0, lhs.rank())`, or false
260 /// otherwise.
261 template <std::ptrdiff_t... StaticExtentsL, std::ptrdiff_t... StaticExtentsR>
262 constexpr bool operator==(const extents<StaticExtentsL...>& lhs,
263  const extents<StaticExtentsR...>& rhs) noexcept {
264  if (lhs.rank() != rhs.rank()) {
265  return false;
266  }
267  for (std::size_t r = 0; r < lhs.rank(); ++r) {
268  if (lhs.extent(r) != rhs.extent(r)) {
269  return false;
270  }
271  }
272  return true;
273 }
274 
275 template <std::ptrdiff_t... StaticExtentsL, std::ptrdiff_t... StaticExtentsR>
276 constexpr bool operator!=(const extents<StaticExtentsL...>& left,
277  const extents<StaticExtentsR...>& right) noexcept {
278  return !(left == right);
279 }
280 
281 template <std::ptrdiff_t... StaticExtents>
282 constexpr std::ptrdiff_t Size_(const extents<StaticExtents...> e) noexcept {
283  const std::size_t rank = e.rank();
284  std::ptrdiff_t size = 1;
285  for (std::size_t r = 0; r < rank; ++r) {
286  size *= e.extent(r);
287  }
288  return size;
289 }
290 
291 /// \ingroup spans
292 /// This layout creates mappings which do row first indexing (as in Fortran).
293 ///
294 /// It holds for all valid `i` and `j` the equation
295 /// \code mapping(i + 1, j) - mapping(1, j) == 1 \endcode
296 struct layout_left {
297 
298  /// This mapping does row first indexing (as in Fortran).
299  ///
300  /// It holds for all valid `i` and `j` the equation
301  /// \code mapping(i + 1, j) - mapping(1, j) == 1 \endcode
302  template <typename Extents> class mapping : private Extents {
303  public:
304  static_assert(is_extents_v<Extents>,
305  "Extents must satisfy the extents concept.");
306 
307  /// \name Constructors / Destructors
308  /// @{
309  constexpr mapping() = default;
310  constexpr mapping(const mapping&) = default;
311  constexpr mapping(mapping&&) = default;
312  mapping& operator=(const mapping& other) noexcept = default;
313  mapping& operator=(mapping&& other) noexcept = default;
314 
315  /// Implicit Conversion from Extents.
316  ///
317  /// \throws Nothing.
318  ///
319  /// \post extents() == extents.
320  constexpr mapping(const Extents& extents) : Extents{extents} {} // NOLINT
321  /// @}
322 
323  /// \name Observers
324  /// @{
325  constexpr const Extents& extents() const noexcept { return *this; }
326 
327  constexpr std::ptrdiff_t required_span_size() const noexcept {
328  return Size_(extents());
329  }
330 
331  /// \return Returns the codomain index for specified multi dimensional index
332  /// coordinates.
333  ///
334  /// \effect Equivalent to offset in
335  /// \code
336  /// index_type offset = 0;
337  /// for(size_t k = 0; k < Extents::rank(); ++k) {
338  /// offset += i[k] * stride(k);
339  /// }
340  /// \endcode
341  /// \throws Nothing.
342  template <
343  typename... IndexType,
344  typename = std::enable_if_t<conjunction<
345  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
346  typename = std::enable_if_t<(sizeof...(IndexType) == Extents::rank())>>
347  constexpr std::ptrdiff_t operator()(IndexType... indices) const noexcept {
348  return DoMapping_(make_index_sequence<Extents::rank()>(), indices...);
349  }
350 
351  /// \return Returns the stride value in a specified dimension r.
352  ///
353  /// \throws Nothing.
354  constexpr std::ptrdiff_t stride(std::size_t r) const noexcept {
355  std::ptrdiff_t stride = 1;
356  for (std::size_t dim = 0; dim < r; ++dim) {
357  stride *= extents().extent(dim);
358  }
359  return stride;
360  }
361 
362  static constexpr bool is_always_unique() noexcept { return true; }
363  static constexpr bool is_always_contiguous() noexcept { return true; }
364  static constexpr bool is_always_strided() noexcept { return true; }
365 
366  constexpr bool is_unique() const noexcept { return true; }
367  constexpr bool is_contiguous() const noexcept { return true; }
368  constexpr bool is_strided() const noexcept { return true; }
369 
370  template <class OtherExtents>
371  constexpr bool operator==(const mapping<OtherExtents>& other) const
372  noexcept {
373  return extents() == other.extents();
374  }
375 
376  template <class OtherExtents>
377  constexpr bool operator!=(const mapping<OtherExtents>& other) const
378  noexcept {
379  return !(*this == other);
380  }
381  /// @}
382 
383  private:
384  template <std::size_t... Is, typename... IndexType>
385  constexpr std::ptrdiff_t DoMapping_(index_sequence<Is...>,
386  IndexType... indices) const noexcept {
387  const std::ptrdiff_t is[Extents::rank()]{
388  static_cast<std::ptrdiff_t>(indices)...};
389  const std::ptrdiff_t strides[Extents::rank()]{stride(Is)...};
390  std::ptrdiff_t index = 0;
391  for (std::size_t r = 0; r < Extents::rank(); ++r) {
392  index += strides[r] * is[r];
393  }
394  return index;
395  }
396  };
397 };
398 
399 
400 /// \ingroup spans
401 struct layout_right {
402  template <typename Extents> class mapping : private Extents {
403  public:
404  constexpr mapping() = default;
405  constexpr mapping(const mapping&) = default;
406  constexpr mapping(mapping&&) = default;
407  mapping& operator=(const mapping&) noexcept = default;
408  mapping& operator=(mapping&&) noexcept = default;
409 
410  constexpr mapping(const Extents& extents) : Extents{extents} {}
411 
412  constexpr const Extents& extents() const noexcept { return *this; }
413 
414  constexpr std::ptrdiff_t required_span_size() const noexcept {
415  return Size_(extents());
416  }
417 
418  template <
419  typename... IndexType,
420  typename = std::enable_if_t<conjunction<
421  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
422  typename = std::enable_if_t<(sizeof...(IndexType) == Extents::rank())>>
423  constexpr std::ptrdiff_t operator()(IndexType... indices) const noexcept {
424  return DoMapping_(make_index_sequence<Extents::rank()>(), indices...);
425  }
426 
427  constexpr std::ptrdiff_t stride(std::size_t r) const noexcept {
428  std::ptrdiff_t stride = 1;
429  for (std::size_t dim = r + 1; dim < Extents::rank(); ++dim) {
430  stride *= extents().extent(dim);
431  }
432  return stride;
433  }
434 
435  static constexpr bool is_always_unique() noexcept { return true; }
436  static constexpr bool is_always_contiguous() noexcept { return true; }
437  static constexpr bool is_always_strided() noexcept { return true; }
438 
439  constexpr bool is_unique() const noexcept { return true; }
440  constexpr bool is_contiguous() const noexcept { return true; }
441  constexpr bool is_strided() const noexcept { return true; }
442 
443  template <class OtherExtents>
444  constexpr bool operator==(const mapping<OtherExtents>& other) const
445  noexcept {
446  return extents() == other.extents();
447  }
448 
449  template <class OtherExtents>
450  constexpr bool operator!=(const mapping<OtherExtents>& other) const
451  noexcept {
452  return !(*this == other);
453  }
454 
455  private:
456  template <std::size_t... Is, typename... IndexType>
457  constexpr std::ptrdiff_t DoMapping_(index_sequence<Is...>,
458  IndexType... indices) const noexcept {
459  const std::ptrdiff_t is[Extents::rank()]{
460  static_cast<std::ptrdiff_t>(indices)...};
461  const std::ptrdiff_t strides[Extents::rank()]{stride(Is)...};
462  std::ptrdiff_t index = 0;
463  for (std::size_t r = 0; r < Extents::rank(); ++r) {
464  index += strides[r] * is[r];
465  }
466  return index;
467  }
468  };
469 };
470 
471 /// \ingroup spans
473  template <class Extents> class mapping : private Extents {
474  public:
475  // [mdspan.layout.stride.cons], layout_stride::mapping constructors
476  constexpr mapping() = default;
477 
478  constexpr mapping(
479  const Extents& e,
480  const std::array<std::ptrdiff_t, Extents::rank()>& s) noexcept
481  : Extents(e), strides_(s) {}
482 
483  std::array<std::ptrdiff_t, Extents::rank()>
485  std::array<std::ptrdiff_t, Extents::rank()> strides;
486  for (std::size_t s = 0; s < Extents::rank(); ++s) {
487  strides[s] = other.stride(s);
488  }
489  return strides;
490  }
491 
492  constexpr mapping(const layout_left::mapping<Extents>& other)
493  : mapping(other.extents(), MakeStrides(other)) {}
494 
495  // [mdspan.layout.stride.ops], layout_stride::mapping operations
496  constexpr const Extents& extents() const noexcept { return *this; }
497 
498  constexpr const std::array<std::ptrdiff_t, Extents::rank()>& strides() const
499  noexcept {
500  return strides_;
501  }
502 
503  constexpr std::ptrdiff_t required_span_size() const noexcept {
504  std::ptrdiff_t max = extents().extent(0) * strides_[0];
505  for (std::size_t r = 1; r < Extents::rank(); ++r) {
506  max = std::max(extents().extent(r) * strides_[r], max);
507  }
508  return max;
509  }
510 
511  template <
512  typename... IndexType,
513  typename = std::enable_if_t<conjunction<
514  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
515  typename = std::enable_if_t<(sizeof...(IndexType) == Extents::rank())>>
516  std::ptrdiff_t operator()(IndexType... is) const {
517  const std::array<std::ptrdiff_t, Extents::rank()> idx{
518  static_cast<std::ptrdiff_t>(is)...};
519  std::ptrdiff_t offset = 0;
520  for (std::size_t r = 0; r < Extents::rank(); ++r) {
521  offset += idx[r] * strides_[r];
522  }
523  return offset;
524  }
525 
526  static constexpr bool is_always_unique() noexcept { return true; }
527  static constexpr bool is_always_contiguous() noexcept { return false; }
528  static constexpr bool is_always_strided() noexcept { return true; }
529 
530  constexpr bool is_unique() const noexcept { return true; }
531  constexpr bool is_contiguous() const noexcept { return false; }
532  constexpr bool is_strided() const noexcept { return true; }
533 
534  std::ptrdiff_t stride(size_t rank) const noexcept { return strides_[rank]; }
535 
536  template <class OtherExtents>
537  constexpr bool operator==(const mapping<OtherExtents>& other) const
538  noexcept {
539  return extents() == other.extents();
540  }
541  template <class OtherExtents>
542  constexpr bool operator!=(const mapping<OtherExtents>& other) const
543  noexcept {
544  return !(*this == other);
545  }
546 
547  private:
548  std::array<std::ptrdiff_t, Extents::rank()> strides_;
549  };
550 };
551 
552 /// \ingroup spans
553 template <class ElementType> struct accessor_basic {
555  using element_type = ElementType;
556  using reference = ElementType&;
557  using pointer = ElementType*;
558 
559  constexpr pointer offset(pointer p, ptrdiff_t i) const noexcept {
560  return p + i;
561  }
562 
563  constexpr reference access(pointer p, ptrdiff_t i) const noexcept {
564  return *offset(p, i);
565  }
566 
567  constexpr pointer decay(pointer p) const noexcept { return p; }
568 };
569 
570 /// \ingroup spans
571 template <class ElementType, class Extents, class LayoutPolicy = layout_right,
572  class AccessorPolicy = accessor_basic<ElementType>>
573 class basic_mdspan : AccessorPolicy, LayoutPolicy::template mapping<Extents> {
574 public:
575  // Domain and codomain types
577  using layout_type = LayoutPolicy;
578  using accessor_type = AccessorPolicy;
579  using mapping_type = typename layout_type::template mapping<extents_type>;
580  using element_type = typename accessor_type::element_type;
581  using value_type = std::remove_cv_t<element_type>;
582  using index_type = std::ptrdiff_t;
583  using difference_type = std::ptrdiff_t;
584  using pointer = typename accessor_type::pointer;
585  using reference = typename accessor_type::reference;
586 
587  // [mdspan.basic.cons], basic_mdspan constructors, assignment, and destructor
588  constexpr basic_mdspan() noexcept = default;
589  constexpr basic_mdspan(const basic_mdspan&) noexcept = default;
590  constexpr basic_mdspan(basic_mdspan&&) noexcept = default;
591 
592  template <class... IndexType,
593  typename = std::enable_if_t<conjunction<
594  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>,
595  typename = std::enable_if_t<sizeof...(IndexType) ==
596  Extents::rank_dynamic()>>
597  explicit constexpr basic_mdspan(pointer p, IndexType... dynamic_extents)
599 
600  template <class IndexType, std::size_t N>
601  explicit constexpr basic_mdspan(
602  pointer p, const std::array<IndexType, N>& dynamic_extents)
604 
605  constexpr basic_mdspan(pointer p, const mapping_type& m)
606  : accessor_type(), mapping_type(m), ptr_(p) {}
607 
608  constexpr basic_mdspan(pointer p, const mapping_type& m,
609  const accessor_type& a)
610  : accessor_type(a), mapping_type(m), ptr_(p) {}
611 
612  template <class OtherElementType, class OtherExtents, class OtherLayoutPolicy,
613  class OtherAccessorPolicy>
614  constexpr basic_mdspan(
615  const basic_mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy,
616  OtherAccessorPolicy>& other)
617  : accessor_type(), mapping_type(other.mapping()), ptr_(other.data()) {}
618 
619  ~basic_mdspan() = default;
620 
621  constexpr basic_mdspan& operator=(const basic_mdspan&) noexcept = default;
622  constexpr basic_mdspan& operator=(basic_mdspan&&) noexcept = default;
623 
624  template <class OtherElementType, class OtherExtents, class OtherLayoutPolicy,
625  class OtherAccessorPolicy>
626  constexpr basic_mdspan& operator=(
627  const basic_mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy,
628  OtherAccessorPolicy>& other) noexcept {
629  static_cast<mapping_type&>(*this) = other.mapping();
630  ptr_ = other.data();
631  return *this;
632  }
633 
634  // [mdspan.basic.mapping], basic_mdspan mapping domain multi-index to access
635  // codomain element
636  constexpr reference operator[](index_type i) const noexcept {
637  return this->operator()(i);
638  }
639 
640  template <class... IndexType>
641  constexpr reference operator()(IndexType... indices) const noexcept {
642  const accessor_type acc = accessor();
643  const mapping_type map = mapping();
644  return acc.access(ptr_, map(indices...));
645  }
646 
647  template <class IndexType, size_t N>
648  constexpr reference operator()(const std::array<IndexType, N>& indices) const
649  noexcept {
650  const accessor_type acc = accessor();
651  const mapping_type map = mapping();
652  return acc.access(ptr_, boost::mp11::tuple_apply(map, indices));
653  }
654 
655  // [mdspan.basic.domobs], basic_mdspan observers of the domain
656  // multidimensional index space
657 
658  static constexpr int rank() noexcept { return Extents::rank(); }
659 
660  static constexpr int rank_dynamic() noexcept {
661  return Extents::rank_dynamic();
662  }
663 
664  static constexpr index_type static_extent(std::size_t rank) noexcept {
665  return Extents::static_extent(rank);
666  }
667 
668  constexpr Extents extents() const noexcept { return mapping().extents(); }
669 
670  constexpr index_type extent(std::size_t rank) const noexcept {
671  return extents().extent(rank);
672  }
673 
674  constexpr index_type size() const noexcept { return Size_(extents()); }
675 
676  constexpr index_type unique_size() const noexcept { return size(); }
677 
678  // [mdspan.basic.codomain], basic_mdspan observers of the codomain
679  constexpr span<element_type> get_span() const noexcept {
680  return {accessor().decay(ptr_), mapping().required_span_size()};
681  }
682 
683  constexpr pointer data() const noexcept { return ptr_; }
684 
685  // [mdspan.basic.obs], basic_mdspan observers of the mapping
686  static constexpr bool is_always_unique() noexcept {
687  return mapping_type::is_always_unique();
688  }
689  static constexpr bool is_always_contiguous() noexcept {
690  return mapping_type::is_always_contiguous();
691  }
692  static constexpr bool is_always_strided() noexcept {
693  return mapping_type::is_always_strided();
694  }
695 
696  constexpr mapping_type mapping() const noexcept { return *this; }
697  constexpr accessor_type accessor() const noexcept { return *this; }
698  constexpr bool is_unique() const noexcept { return mapping().is_unique(); }
699  constexpr bool is_contiguous() const noexcept {
700  return mapping().is_contiguous();
701  }
702  constexpr bool is_strided() const noexcept { return mapping().is_strided(); }
703 
704  constexpr index_type stride(std::size_t r) const {
705  return mapping().stride(r);
706  }
707 
708 private:
710 };
711 
712 /// \ingroup spans
713 template <typename T, ptrdiff_t... Extents>
715 
716 template <typename T> struct dynamic_extents_;
717 
718 template <typename I, I... Is>
720  using type = extents<((void)Is, fub::dynamic_extent)...>;
721 };
722 
723 template <std::size_t Rank>
726 
727 // template <typename T, std::size_t Rank, typename Layout = layout_right>
728 // using DynamicMdSpan = basic_mdspan<T, dynamic_extents<Rank>, Layout>;
729 
730 /// \ingroup spans
731 template <typename T, std::size_t Rank, typename Layout = layout_left>
733 
734 /// \ingroup spans
735 template <typename T, typename E, typename A = accessor_basic<T>>
737 
738 struct all_type {
739  explicit all_type() = default;
740 };
741 static constexpr all_type all = all_type{};
742 
743 /// \cond INTERNAL
744 template <typename T>
745 struct IsSliceRange_
746  : disjunction<
747  std::is_convertible<T, std::pair<std::ptrdiff_t, std::ptrdiff_t>>,
748  std::is_convertible<T, all_type>> {};
749 
750 template <typename I, typename... Is> constexpr I Accumulate_(I x0, Is... xi) {
751  const I x[] = {x0, xi...};
752  constexpr int size = 1 + static_cast<int>(sizeof...(Is));
753  I total = I{};
754  for (int i = 0; i < size; ++i) {
755  total += x[i];
756  }
757  return total;
758 }
759 
760 template <typename... SliceSpecifiers>
761 static constexpr std::size_t SliceRank_ =
762  Accumulate_(static_cast<int>(IsSliceRange_<SliceSpecifiers>::value)...);
763 /// \endcond
764 
765 // [mdspan.subspan], subspan creation
766 template <class ElementType, class Extents, class LayoutPolicy,
767  class AccessorPolicy, class... SliceSpecifiers>
768 struct mdspan_subspan { // exposition only
769  static constexpr std::size_t slice_rank = SliceRank_<SliceSpecifiers...>;
772  using type = basic_mdspan<ElementType, extents_t, layout_t,
773  typename AccessorPolicy::offset_policy>;
774 };
775 
776 template <class ElementType, class Extents, class LayoutPolicy,
777  class AccessorPolicy, class... SliceSpecifiers>
778 using mdspan_subspan_t = // exposition only
779  typename mdspan_subspan<ElementType, Extents, LayoutPolicy, AccessorPolicy,
780  SliceSpecifiers...>::type;
781 
782 constexpr std::ptrdiff_t
783 SliceExtent_(const std::pair<std::ptrdiff_t, std::ptrdiff_t>& p) {
784  FUB_ASSERT(p.first <= p.second);
785  FUB_ASSERT(0 <= p.first);
786  return p.second - p.first;
787 }
788 
789 /// \cond INTERNAL
790 constexpr std::ptrdiff_t SliceExtent_(all_type) { return dynamic_extent; }
791 
792 template <typename T, typename = std::enable_if_t<!IsSliceRange_<T>::value>>
793 constexpr std::ptrdiff_t SliceExtent_(T) {
794  return 0;
795 }
796 
797 template <std::size_t Rank, typename Slice>
798 constexpr std::array<std::ptrdiff_t, Rank + 1>
799 SlicePushBack__(std::true_type, std::array<std::ptrdiff_t, Rank> array,
800  Slice slice) {
801  std::array<std::ptrdiff_t, Rank + 1> grown{};
802  for (std::size_t i = 0; i < Rank; ++i) {
803  grown[i] = array[i];
804  }
805  grown[Rank] = SliceExtent_(slice);
806  return grown;
807 }
808 
809 template <std::size_t Rank, typename Slice>
810 constexpr std::array<std::ptrdiff_t, Rank>
811 SlicePushBack__(std::false_type, std::array<std::ptrdiff_t, Rank> array,
812  Slice /* slice */) {
813  return array;
814 }
815 
816 template <std::size_t Rank, typename Slice>
817 constexpr auto SlicePushBack_(std::array<std::ptrdiff_t, Rank> array,
818  Slice slice) {
819  return SlicePushBack__(IsSliceRange_<Slice>(), array, slice);
820 }
821 
822 template <std::size_t Rank>
823 constexpr auto MakeSliceExtents__(std::array<std::ptrdiff_t, Rank> result) {
824  return result;
825 }
826 
827 template <std::size_t Rank, typename Slice, typename... Rest>
828 constexpr auto MakeSliceExtents__(std::array<std::ptrdiff_t, Rank> prev,
829  Slice slice, Rest... slices) {
830  return MakeSliceExtents__(SlicePushBack_(prev, slice), slices...);
831 }
832 
833 template <typename... Slices>
834 constexpr auto MakeSliceExtents_(Slices... slices) {
835  return MakeSliceExtents__(std::array<std::ptrdiff_t, 0>{}, slices...);
836 }
837 
838 template <class ElementType, class Extents, class LayoutPolicy,
839  class AccessorPolicy, std::size_t... Is>
840 constexpr std::array<std::ptrdiff_t, sizeof...(Is)> MakeStrideArray_(
841  const basic_mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
842  index_sequence<Is...>) {
843  return {src.stride(Is)...};
844 }
845 
846 template <typename T> struct Type_ {};
847 
848 template <std::size_t N, std::size_t... Is>
849 constexpr std::array<std::size_t, N> AsStdArray__(const std::size_t (&array)[N],
850  index_sequence<Is...>) {
851  return {array[Is]...};
852 }
853 
854 template <std::size_t N>
855 constexpr std::array<std::size_t, N>
856 AsStdArray_(const std::size_t (&array)[N]) {
857  return AsStdArray__(array, make_index_sequence<N>());
858 }
859 
860 template <typename... Slices>
861 constexpr std::array<std::size_t, SliceRank_<Slices...>>
862 MakeRangeIndices__(Type_<Slices>... /* slices */) {
863  constexpr std::size_t is_range[] = {IsSliceRange_<Slices>::value...};
864  std::size_t ranges[SliceRank_<Slices...>]{};
865  std::size_t ri = 0;
866  for (std::size_t i = 0; i < sizeof...(Slices); ++i) {
867  if (is_range[i]) {
868  ranges[ri++] = i;
869  }
870  }
871  return AsStdArray_(ranges);
872 }
873 
874 template <typename... Slices, std::size_t... Is>
875 constexpr auto MakeRangeIndices_(index_sequence<Is...>,
876  Type_<Slices>... /* slices */) {
877  constexpr std::array<std::size_t, SliceRank_<Slices...>> indices{
878  MakeRangeIndices__(Type_<Slices>{}...)};
879  return index_sequence<indices[Is]...>{};
880 }
881 
882 template <typename... Slices>
883 constexpr auto MakeRangeIndices_(Type_<Slices>... slices) {
884  return MakeRangeIndices_(make_index_sequence<SliceRank_<Slices...>>{},
885  slices...);
886 }
887 
888 template <typename... Slices> constexpr auto MakeRangeIndices(Slices...) {
889  return MakeRangeIndices_(Type_<Slices>{}...);
890 }
891 
892 template <class ElementType, class Extents, class LayoutPolicy,
893  class AccessorPolicy, typename... Slices>
894 constexpr auto MakeSliceArray_(
895  const basic_mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
896  Slices...) {
897  constexpr auto range_indices = MakeRangeIndices_(Type_<Slices>{}...);
898  return MakeStrideArray_(src, range_indices);
899 }
900 
901 constexpr std::ptrdiff_t MakeOrigin__(std::ptrdiff_t n) { return n; }
902 
903 constexpr std::ptrdiff_t
904 MakeOrigin__(std::pair<std::ptrdiff_t, std::ptrdiff_t> p) {
905  return p.first;
906 }
907 
908 constexpr std::ptrdiff_t MakeOrigin__(all_type /* all */) { return 0; }
909 
910 template <typename... Slices>
911 constexpr std::array<std::ptrdiff_t, sizeof...(Slices)>
912 MakeOrigin_(Slices... slices) {
913  return {MakeOrigin__(slices)...};
914 }
915 
916 template <std::size_t... Is, typename F, std::size_t N>
917 constexpr auto Apply_(index_sequence<Is...>, F fn,
918  std::array<std::ptrdiff_t, N> indices) {
919  return fn(indices[Is]...);
920 }
921 
922 template <typename F, std::size_t N>
923 constexpr auto Apply_(F fn, std::array<std::ptrdiff_t, N> indices) {
924  return Apply_(make_index_sequence<N>{}, fn, indices);
925 }
926 
927 constexpr std::ptrdiff_t MapToLength_(all_type) { return -1; }
928 
929 constexpr std::ptrdiff_t
930 MapToLength_(const std::pair<std::ptrdiff_t, std::ptrdiff_t>& rng) {
931  return rng.second - rng.first;
932 }
933 
934 template <typename T, typename = std::enable_if_t<!IsSliceRange_<T>()>>
935 constexpr std::ptrdiff_t MapToLength_(T) {
936  return 0;
937 }
938 
939 template <typename Extents, typename... SliceSpecifiers>
940 constexpr std::array<std::ptrdiff_t, SliceRank_<SliceSpecifiers...>>
941 MakeSliceExtents2_(const Extents& e, SliceSpecifiers... slices) {
942  const std::array<std::ptrdiff_t, Extents::rank()> length{
943  MapToLength_(slices)...};
944  std::array<std::ptrdiff_t, Extents::rank()> dyn_length{};
945  for (std::size_t i = 0; i < Extents::rank(); ++i) {
946  if (length[i] < 0) {
947  dyn_length[i] = e.extent(i);
948  } else {
949  dyn_length[i] = length[i];
950  }
951  }
952  std::array<std::ptrdiff_t, SliceRank_<SliceSpecifiers...>> extents{};
953  std::size_t slice = 0;
954  for (std::size_t i = 0; i < Extents::rank(); ++i) {
955  if (dyn_length[i] > 0) {
956  extents[slice] = dyn_length[i];
957  slice = slice + 1;
958  }
959  }
960  return extents;
961 }
962 /// \endcond
963 
964 template <class ElementType, class Extents, class LayoutPolicy,
965  class AccessorPolicy, class... SliceSpecifiers>
966 mdspan_subspan_t<ElementType, Extents, LayoutPolicy, AccessorPolicy,
967  SliceSpecifiers...>
970  SliceSpecifiers... slices) noexcept {
971  const std::array<std::ptrdiff_t, Extents::rank()> origin =
972  MakeOrigin_(slices...);
973  const auto map = src.mapping();
974  const auto acc = src.accessor();
975  constexpr std::size_t slice_rank = SliceRank_<SliceSpecifiers...>;
976  using SliceExtents = dynamic_extents<slice_rank>;
977  const SliceExtents extents{MakeSliceExtents2_(src.extents(), slices...)};
978  const std::array<std::ptrdiff_t, slice_rank> slice_array =
979  MakeSliceArray_(src, slices...);
980  const layout_stride::mapping<SliceExtents> slice_mapping(extents,
981  slice_array);
982  return {acc.offset(src.data(), Apply_(map, origin)), slice_mapping};
983 }
984 
985 template <typename> struct is_mdspan : std::false_type {};
986 
987 template <typename T, typename E, typename L, typename A>
988 struct is_mdspan<basic_mdspan<T, E, L, A>> : std::true_type {};
989 
990 template <typename T> static constexpr bool is_mdspan_v = is_mdspan<T>::value;
991 
992 } // namespace fub
993 
994 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
static constexpr std::size_t rank() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:65
static constexpr std::size_t rank_dynamic() noexcept
Returns 0.
Definition: mdspan.hpp:68
static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept
Returns the n-th Static Extent.
Definition: mdspan.hpp:71
constexpr std::ptrdiff_t extent(size_t n) const noexcept
Returns the N-th Extent.
Definition: mdspan.hpp:80
constexpr ExtentsStorage_(const std::array< std::ptrdiff_t, Rank > &extents) noexcept
Definition: mdspan.hpp:105
constexpr std::ptrdiff_t extent(size_t n) const noexcept
Returns the N-th Extent.
Definition: mdspan.hpp:123
static constexpr std::size_t rank() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:112
static constexpr std::size_t rank_dynamic() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:115
constexpr ExtentsStorage_(IndexType... extent) noexcept
Definition: mdspan.hpp:102
static constexpr std::ptrdiff_t static_extent(std::size_t) noexcept
Returns dynamic_extent.
Definition: mdspan.hpp:118
This is the storage type for the extents class and only takes storage for dynamic extents.
Definition: mdspan.hpp:133
std::array< std::ptrdiff_t, RankDynamic > m_dynamic_extents
Definition: mdspan.hpp:174
static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept
Returns dynamic_extent.
Definition: mdspan.hpp:159
constexpr std::ptrdiff_t extent(size_t n) const noexcept
Returns the N-th Extent.
Definition: mdspan.hpp:165
static constexpr std::size_t rank_dynamic() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:156
static constexpr std::size_t find_dynamic_extent_index(std::size_t n) noexcept
Definition: mdspan.hpp:177
static constexpr std::size_t rank() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:153
ExtentsStorage_()=default
constexpr ExtentsStorage_(const std::array< std::ptrdiff_t, RankDynamic > &extents) noexcept
Definition: mdspan.hpp:146
constexpr ExtentsStorage_(IndexType... extent) noexcept
Definition: mdspan.hpp:143
Definition: mdspan.hpp:573
static constexpr int rank() noexcept
Definition: mdspan.hpp:658
constexpr Extents extents() const noexcept
Definition: mdspan.hpp:668
constexpr index_type stride(std::size_t r) const
Definition: mdspan.hpp:704
static constexpr bool is_always_strided() noexcept
Definition: mdspan.hpp:692
std::ptrdiff_t difference_type
Definition: mdspan.hpp:583
constexpr bool is_contiguous() const noexcept
Definition: mdspan.hpp:699
constexpr basic_mdspan(pointer p, const std::array< IndexType, N > &dynamic_extents)
Definition: mdspan.hpp:601
constexpr reference operator[](index_type i) const noexcept
Definition: mdspan.hpp:636
constexpr basic_mdspan() noexcept=default
constexpr basic_mdspan & operator=(basic_mdspan &&) noexcept=default
std::ptrdiff_t index_type
Definition: mdspan.hpp:582
pointer ptr_
Definition: mdspan.hpp:709
constexpr basic_mdspan(pointer p, const mapping_type &m)
Definition: mdspan.hpp:605
static constexpr index_type static_extent(std::size_t rank) noexcept
Definition: mdspan.hpp:664
constexpr basic_mdspan & operator=(const basic_mdspan &) noexcept=default
constexpr accessor_type accessor() const noexcept
Definition: mdspan.hpp:697
constexpr index_type extent(std::size_t rank) const noexcept
Definition: mdspan.hpp:670
constexpr bool is_strided() const noexcept
Definition: mdspan.hpp:702
~basic_mdspan()=default
constexpr basic_mdspan(const basic_mdspan< OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessorPolicy > &other)
Definition: mdspan.hpp:614
constexpr span< element_type > get_span() const noexcept
Definition: mdspan.hpp:679
constexpr bool is_unique() const noexcept
Definition: mdspan.hpp:698
LayoutPolicy layout_type
Definition: mdspan.hpp:577
constexpr mapping_type mapping() const noexcept
Definition: mdspan.hpp:696
constexpr basic_mdspan(pointer p, const mapping_type &m, const accessor_type &a)
Definition: mdspan.hpp:608
AccessorPolicy accessor_type
Definition: mdspan.hpp:578
Extents extents_type
Definition: mdspan.hpp:576
constexpr index_type unique_size() const noexcept
Definition: mdspan.hpp:676
constexpr reference operator()(IndexType... indices) const noexcept
Definition: mdspan.hpp:641
std::remove_cv_t< element_type > value_type
Definition: mdspan.hpp:581
static constexpr bool is_always_unique() noexcept
Definition: mdspan.hpp:686
constexpr reference operator()(const std::array< IndexType, N > &indices) const noexcept
Definition: mdspan.hpp:648
constexpr pointer data() const noexcept
Definition: mdspan.hpp:683
constexpr index_type size() const noexcept
Definition: mdspan.hpp:674
typename layout_type::template mapping< extents_type > mapping_type
Definition: mdspan.hpp:579
static constexpr bool is_always_contiguous() noexcept
Definition: mdspan.hpp:689
static constexpr int rank_dynamic() noexcept
Definition: mdspan.hpp:660
An extents object defines a multidimensional index space which is the Cartesian product of integers e...
Definition: mdspan.hpp:208
std::ptrdiff_t index_type
Definition: mdspan.hpp:217
constexpr std::ptrdiff_t extent(size_t n) const noexcept
Returns the n-th run-time extent.
Definition: mdspan.hpp:241
static constexpr std::size_t rank_dynamic() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:229
static constexpr std::ptrdiff_t static_extent(std::size_t n) noexcept
Returns the n-th StaticExtent.
Definition: mdspan.hpp:234
static constexpr std::size_t rank() noexcept
Returns sizeof...(StaticExtents)
Definition: mdspan.hpp:226
This mapping does row first indexing (as in Fortran).
Definition: mdspan.hpp:302
constexpr bool is_contiguous() const noexcept
Definition: mdspan.hpp:367
constexpr bool operator!=(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:377
constexpr mapping()=default
Implicit Conversion from Extents.
constexpr mapping(const Extents &extents)
Implicit Conversion from Extents.
Definition: mdspan.hpp:320
mapping & operator=(const mapping &other) noexcept=default
Implicit Conversion from Extents.
constexpr std::ptrdiff_t required_span_size() const noexcept
Definition: mdspan.hpp:327
constexpr mapping(const mapping &)=default
Implicit Conversion from Extents.
static constexpr bool is_always_contiguous() noexcept
Definition: mdspan.hpp:363
constexpr const Extents & extents() const noexcept
Definition: mdspan.hpp:325
constexpr bool is_strided() const noexcept
Definition: mdspan.hpp:368
mapping & operator=(mapping &&other) noexcept=default
Implicit Conversion from Extents.
constexpr bool operator==(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:371
constexpr bool is_unique() const noexcept
Definition: mdspan.hpp:366
constexpr std::ptrdiff_t DoMapping_(index_sequence< Is... >, IndexType... indices) const noexcept
Definition: mdspan.hpp:385
static constexpr bool is_always_unique() noexcept
Definition: mdspan.hpp:362
static constexpr bool is_always_strided() noexcept
Definition: mdspan.hpp:364
constexpr std::ptrdiff_t stride(std::size_t r) const noexcept
Definition: mdspan.hpp:354
constexpr mapping(mapping &&)=default
Implicit Conversion from Extents.
Definition: mdspan.hpp:402
static constexpr bool is_always_unique() noexcept
Definition: mdspan.hpp:435
constexpr const Extents & extents() const noexcept
Definition: mdspan.hpp:412
mapping & operator=(mapping &&) noexcept=default
constexpr mapping(mapping &&)=default
constexpr mapping(const mapping &)=default
constexpr std::ptrdiff_t DoMapping_(index_sequence< Is... >, IndexType... indices) const noexcept
Definition: mdspan.hpp:457
constexpr std::ptrdiff_t required_span_size() const noexcept
Definition: mdspan.hpp:414
static constexpr bool is_always_strided() noexcept
Definition: mdspan.hpp:437
constexpr bool operator!=(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:450
constexpr mapping()=default
constexpr bool operator==(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:444
constexpr bool is_contiguous() const noexcept
Definition: mdspan.hpp:440
static constexpr bool is_always_contiguous() noexcept
Definition: mdspan.hpp:436
constexpr std::ptrdiff_t stride(std::size_t r) const noexcept
Definition: mdspan.hpp:427
constexpr bool is_unique() const noexcept
Definition: mdspan.hpp:439
constexpr bool is_strided() const noexcept
Definition: mdspan.hpp:441
mapping & operator=(const mapping &) noexcept=default
Definition: mdspan.hpp:473
static constexpr bool is_always_contiguous() noexcept
Definition: mdspan.hpp:527
std::array< std::ptrdiff_t, Extents::rank()> strides_
Definition: mdspan.hpp:548
constexpr const std::array< std::ptrdiff_t, Extents::rank()> & strides() const noexcept
Definition: mdspan.hpp:498
std::ptrdiff_t stride(size_t rank) const noexcept
Definition: mdspan.hpp:534
constexpr std::ptrdiff_t required_span_size() const noexcept
Definition: mdspan.hpp:503
static constexpr bool is_always_strided() noexcept
Definition: mdspan.hpp:528
constexpr bool is_contiguous() const noexcept
Definition: mdspan.hpp:531
constexpr bool is_unique() const noexcept
Definition: mdspan.hpp:530
static constexpr bool is_always_unique() noexcept
Definition: mdspan.hpp:526
constexpr const Extents & extents() const noexcept
Definition: mdspan.hpp:496
constexpr bool operator!=(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:542
constexpr mapping(const Extents &e, const std::array< std::ptrdiff_t, Extents::rank()> &s) noexcept
Definition: mdspan.hpp:478
constexpr mapping(const layout_left::mapping< Extents > &other)
Definition: mdspan.hpp:492
std::array< std::ptrdiff_t, Extents::rank()> MakeStrides(const layout_left::mapping< Extents > &other)
Definition: mdspan.hpp:484
constexpr mapping()=default
constexpr bool operator==(const mapping< OtherExtents > &other) const noexcept
Definition: mdspan.hpp:537
constexpr bool is_strided() const noexcept
Definition: mdspan.hpp:532
A span is a view over a contiguous sequence of objects, the storage of which is owned by some other o...
Definition: span.hpp:81
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
integer_sequence< std::size_t, Is... > index_sequence
Definition: type_traits.hpp:156
constexpr std::ptrdiff_t Size_(const extents< StaticExtents... > e) noexcept
Definition: mdspan.hpp:282
typename dynamic_extents_< make_index_sequence< Rank > >::type dynamic_extents
Definition: mdspan.hpp:725
make_integer_sequence< std::size_t, N > make_index_sequence
Definition: type_traits.hpp:173
std::integral_constant< bool, Bool > bool_constant
Definition: type_traits.hpp:181
mdspan_subspan_t< ElementType, Extents, LayoutPolicy, AccessorPolicy, SliceSpecifiers... > subspan(const basic_mdspan< ElementType, Extents, LayoutPolicy, AccessorPolicy > &src, SliceSpecifiers... slices) noexcept
Definition: mdspan.hpp:968
static constexpr bool is_mdspan_v
Definition: mdspan.hpp:990
bool operator==(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:63
constexpr std::size_t count_dynamic_extents(IndexType... extent) noexcept
Definition: mdspan.hpp:190
static constexpr std::ptrdiff_t dynamic_extent
This is a magic value to denote runtime-known extents.
Definition: dynamic_extent.hpp:28
constexpr std::ptrdiff_t SliceExtent_(const std::pair< std::ptrdiff_t, std::ptrdiff_t > &p)
Definition: mdspan.hpp:783
typename mdspan_subspan< ElementType, Extents, LayoutPolicy, AccessorPolicy, SliceSpecifiers... >::type mdspan_subspan_t
Definition: mdspan.hpp:780
dynamic_extents< static_cast< std::size_t >Rank)> Extents(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:480
bool operator!=(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:68
auto Slice(const BasicView< T, L, Rank > &view, SliceSpecifier slice)
Definition: State.hpp:688
static constexpr all_type all
Definition: mdspan.hpp:741
std::ptrdiff_t index
Definition: type_traits.hpp:179
static constexpr bool is_extents_v
Definition: mdspan.hpp:255
Definition: mdspan.hpp:553
ElementType element_type
Definition: mdspan.hpp:555
constexpr pointer decay(pointer p) const noexcept
Definition: mdspan.hpp:567
ElementType & reference
Definition: mdspan.hpp:556
ElementType * pointer
Definition: mdspan.hpp:557
constexpr reference access(pointer p, ptrdiff_t i) const noexcept
Definition: mdspan.hpp:563
constexpr pointer offset(pointer p, ptrdiff_t i) const noexcept
Definition: mdspan.hpp:559
Definition: mdspan.hpp:738
all_type()=default
Definition: type_traits.hpp:123
Definition: mdspan.hpp:716
Definition: type_traits.hpp:149
This is true std::true_type iff E is extents<Es...> for some std::ptrdiff_t...
Definition: mdspan.hpp:252
Definition: mdspan.hpp:985
This layout creates mappings which do row first indexing (as in Fortran).
Definition: mdspan.hpp:296
Definition: mdspan.hpp:401
Definition: mdspan.hpp:472
Definition: mdspan.hpp:768
static constexpr std::size_t slice_rank
Definition: mdspan.hpp:769
dynamic_extents< slice_rank > extents_t
Definition: mdspan.hpp:770
layout_stride layout_t
Definition: mdspan.hpp:771
This file adds basic type traits utilities which are not yet implemented in all standard libraries.