Reference documentation for deal.II version Git f9e0250abc 2021-03-01 16:46:02 +0100
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
array_view.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_array_view_h
17 #define dealii_array_view_h
18 
19 #include <deal.II/base/config.h>
20 
24 #include <deal.II/base/table.h>
25 #include <deal.II/base/tensor.h>
26 
28 
29 #include <type_traits>
30 #include <vector>
31 
33 
34 
76 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
77 class ArrayView
78 {
79 public:
85 
89  using iterator = value_type *;
90 
94  using const_iterator = const ElementType *;
95 
99  ArrayView();
100 
120  ArrayView(value_type *starting_element, const std::size_t n_elements);
121 
131  ArrayView(const ArrayView<typename std::remove_cv<value_type>::type,
132  MemorySpaceType> &view);
133 
138  explicit ArrayView(value_type &element);
139 
154  ArrayView(
155  const std::vector<typename std::remove_cv<value_type>::type> &vector);
156 
171  ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
172 
187  template <std::size_t N>
188  ArrayView(value_type (&array)[N]);
189 
198  template <std::size_t N>
199  ArrayView(
200  const std::array<typename std::remove_cv<value_type>::type, N> &vector);
201 
210  template <std::size_t N>
211  ArrayView(std::array<typename std::remove_cv<value_type>::type, N> &vector);
212 
232  void
233  reinit(value_type *starting_element, const std::size_t n_elements);
234 
240  bool
241  operator==(
242  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
243 
249  bool
250  operator==(const ArrayView<typename std::remove_cv<value_type>::type,
251  MemorySpaceType> &other_view) const;
252 
258  bool
259  operator!=(
260  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
261 
267  bool
268  operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
269  MemorySpaceType> &other_view) const;
270 
275  std::size_t
276  size() const;
277 
282  value_type *
283  data() const noexcept;
284 
288  iterator
289  begin() const;
290 
294  iterator
295  end() const;
296 
301  cbegin() const;
302 
307  cend() const;
308 
321  value_type &operator[](const std::size_t i) const;
322 
323 private:
329 
333  std::size_t n_elements;
334 
335  friend class ArrayView<const ElementType, MemorySpaceType>;
336 };
337 
338 
339 
340 //---------------------------------------------------------------------------
341 
342 
343 namespace internal
344 {
345  namespace ArrayViewHelper
346  {
347  template <typename MemorySpaceType>
348  inline bool
349  is_in_correct_memory_space(const void *const ptr)
350  {
351 #ifndef DEAL_II_COMPILER_CUDA_AWARE
352  (void)ptr;
353  static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
354  "If the compiler doesn't understand CUDA code, "
355  "the only possible memory space is 'MemorySpace::Host'!");
356  return true;
357 #else
358  cudaPointerAttributes attributes;
359  const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
360  if (cuda_error != cudaErrorInvalidValue)
361  {
362  AssertCuda(cuda_error);
363  if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
364  return (attributes.type == cudaMemoryTypeHost) ||
365  (attributes.type == cudaMemoryTypeUnregistered);
366  else
367  return attributes.type == cudaMemoryTypeDevice;
368  }
369  else
370  {
371  // ignore and reset the error since host pointers produce an error
372  cudaGetLastError();
373  return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
374  }
375 #endif
376  }
377  } // namespace ArrayViewHelper
378 } // namespace internal
379 
380 
381 
382 template <typename ElementType, typename MemorySpaceType>
384  : starting_element(nullptr)
385  , n_elements(0)
386 {}
387 
388 
389 
390 template <typename ElementType, typename MemorySpaceType>
393  const std::size_t n_elements)
394  : starting_element(starting_element)
395  , n_elements(n_elements)
396 {
397  Assert(
398  n_elements == 0 ||
399  internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
400  starting_element),
401  ExcMessage("The memory space indicated by the template parameter "
402  "and the one derived from the pointer value do not match!"));
403 }
404 
405 
406 
407 template <typename ElementType, typename MemorySpaceType>
408 inline void
410  const std::size_t n_elements)
411 {
412  *this = ArrayView(starting_element, n_elements);
413 }
414 
415 
416 
417 template <typename ElementType, typename MemorySpaceType>
419  : starting_element(&element)
420  , n_elements(1)
421 {}
422 
423 
424 
425 template <typename ElementType, typename MemorySpaceType>
427  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
428  &view)
430  , n_elements(view.n_elements)
431 {}
432 
433 
434 
435 template <typename ElementType, typename MemorySpaceType>
437  const std::vector<typename std::remove_cv<value_type>::type> &vector)
438  : // use delegating constructor
439  ArrayView(vector.data(), vector.size())
440 {
441  // the following static_assert is not strictly necessary because,
442  // if we got a const std::vector reference argument but ElementType
443  // is not itself const, then the call to the forwarding constructor
444  // above will already have failed: vector.data() will have returned
445  // a const pointer, but we need a non-const pointer.
446  //
447  // nevertheless, leave the static_assert in since it provides a
448  // more descriptive error message that will simply come after the first
449  // error produced above
450  static_assert(std::is_const<value_type>::value == true,
451  "This constructor may only be called if the ArrayView "
452  "object has a const value_type. In other words, you can "
453  "only create an ArrayView to const values from a const "
454  "std::vector.");
455 }
456 
457 
458 
459 template <typename ElementType, typename MemorySpaceType>
461  std::vector<typename std::remove_cv<value_type>::type> &vector)
462  : // use delegating constructor
463  ArrayView(vector.data(), vector.size())
464 {}
465 
466 
467 
468 template <typename ElementType, typename MemorySpaceType>
469 template <std::size_t N>
471  const std::array<typename std::remove_cv<value_type>::type, N> &vector)
472  : // use delegating constructor
473  ArrayView(vector.data(), vector.size())
474 {
475  // the following static_assert is not strictly necessary because,
476  // if we got a const std::array reference argument but ElementType
477  // is not itself const, then the call to the forwarding constructor
478  // above will already have failed: vector.data() will have returned
479  // a const pointer, but we need a non-const pointer.
480  //
481  // nevertheless, leave the static_assert in since it provides a
482  // more descriptive error message that will simply come after the first
483  // error produced above
484  static_assert(std::is_const<value_type>::value == true,
485  "This constructor may only be called if the ArrayView "
486  "object has a const value_type. In other words, you can "
487  "only create an ArrayView to const values from a const "
488  "std::array.");
489 }
490 
491 
492 
493 template <typename ElementType, typename MemorySpaceType>
494 template <std::size_t N>
496  ElementType (&array)[N])
497  : ArrayView(&array[0], N)
498 {}
499 
500 
501 
502 template <typename ElementType, typename MemorySpaceType>
503 template <std::size_t N>
505  std::array<typename std::remove_cv<value_type>::type, N> &vector)
506  : // use delegating constructor
507  ArrayView(vector.data(), vector.size())
508 {}
509 
510 
511 
512 template <typename ElementType, typename MemorySpaceType>
513 inline bool
516 {
517  return (other_view.data() == starting_element) &&
518  (other_view.size() == n_elements);
519 }
520 
521 
522 
523 template <typename ElementType, typename MemorySpaceType>
524 inline bool
526 operator==(const ArrayView<typename std::remove_cv<value_type>::type,
527  MemorySpaceType> &other_view) const
528 {
529  return (other_view.data() == starting_element) &&
530  (other_view.size() == n_elements);
531 }
532 
533 
534 
535 template <typename ElementType, typename MemorySpaceType>
536 inline bool
539 {
540  return !(*this == other_view);
541 }
542 
543 
544 
545 template <typename ElementType, typename MemorySpaceType>
548 {
549  if (n_elements == 0)
550  return nullptr;
551  else
552  return starting_element;
553 }
554 
555 
556 
557 template <typename ElementType, typename MemorySpaceType>
558 inline bool
560 operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
561  MemorySpaceType> &other_view) const
562 {
563  return !(*this == other_view);
564 }
565 
566 
567 
568 template <typename ElementType, typename MemorySpaceType>
569 inline std::size_t
571 {
572  return n_elements;
573 }
574 
575 
576 
577 template <typename ElementType, typename MemorySpaceType>
580 {
581  return starting_element;
582 }
583 
584 
585 
586 template <typename ElementType, typename MemorySpaceType>
589 {
590  return starting_element + n_elements;
591 }
592 
593 
594 
595 template <typename ElementType, typename MemorySpaceType>
598 {
599  return starting_element;
600 }
601 
602 
603 
604 template <typename ElementType, typename MemorySpaceType>
607 {
608  return starting_element + n_elements;
609 }
610 
611 
612 
613 template <typename ElementType, typename MemorySpaceType>
616 {
618  Assert(
619  (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
620  ExcMessage(
621  "Accessing elements is only allowed if the data is stored in CPU memory!"));
622 
623  return *(starting_element + i);
624 }
625 
626 
627 
628 #ifndef DOXYGEN
629 namespace internal
630 {
631  namespace ArrayViewHelper
632  {
638  template <class Iterator>
639  bool
640  is_contiguous(const Iterator &first, const Iterator &last)
641  {
642  const auto n = std::distance(first, last);
643  for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
644  if (std::addressof(*(std::next(first, i))) !=
645  std::next(std::addressof(*first), i))
646  return false;
647  return true;
648  }
649 
650 
661  template <class T>
662  constexpr bool
663  is_contiguous(T *, T *)
664  {
665  return true;
666  }
667  } // namespace ArrayViewHelper
668 } // namespace internal
669 #endif
670 
671 
672 
689 template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
690 ArrayView<typename std::remove_reference<
691  typename std::iterator_traits<Iterator>::reference>::type,
692  MemorySpaceType>
693 make_array_view(const Iterator begin, const Iterator end)
694 {
695  static_assert(
696  std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
697  typename std::random_access_iterator_tag>::value,
698  "The provided iterator should be a random access iterator.");
699  Assert(begin <= end,
700  ExcMessage(
701  "The beginning of the array view should be before the end."));
702  Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
703  ExcMessage("The provided range isn't contiguous in memory!"));
704  // the reference type, not the value type, knows the constness of the iterator
705  return ArrayView<typename std::remove_reference<
706  typename std::iterator_traits<Iterator>::reference>::type,
707  MemorySpaceType>(std::addressof(*begin), end - begin);
708 }
709 
710 
711 
721 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
724 {
725  Assert(begin <= end,
726  ExcMessage(
727  "The beginning of the array view should be before the end."));
729 }
730 
731 
732 
743 template <typename Number, typename MemorySpaceType>
746 {
747  return make_array_view(array_view.cbegin(), array_view.cend());
748 }
749 
750 
751 
762 template <typename Number, typename MemorySpaceType>
765 {
766  return make_array_view(array_view.begin(), array_view.end());
767 }
768 
769 
770 
787 template <int rank, int dim, typename Number>
790 {
791  return make_array_view(tensor.begin_raw(), tensor.end_raw());
792 }
793 
794 
795 
812 template <int rank, int dim, typename Number>
813 inline ArrayView<Number>
815 {
816  return make_array_view(tensor.begin_raw(), tensor.end_raw());
817 }
818 
819 
820 
837 template <int rank, int dim, typename Number>
840 {
841  return make_array_view(tensor.begin_raw(), tensor.end_raw());
842 }
843 
844 
845 
863 template <int rank, int dim, typename Number>
864 inline ArrayView<Number>
866 {
867  return make_array_view(tensor.begin_raw(), tensor.end_raw());
868 }
869 
870 
871 
885 template <typename ElementType, int N>
887 {
888  return ArrayView<ElementType>(array, N);
889 }
890 
891 
892 
907 template <typename ElementType>
909 make_array_view(Vector<ElementType> &vector)
910 {
911  return ArrayView<ElementType>(vector.begin(), vector.size());
912 }
913 
914 
915 
930 template <typename ElementType>
932 make_array_view(const Vector<ElementType> &vector)
933 {
934  return ArrayView<const ElementType>(vector.begin(), vector.size());
935 }
936 
937 
938 
953 template <typename ElementType>
955 make_array_view(std::vector<ElementType> &vector)
956 {
957  return ArrayView<ElementType>(vector.data(), vector.size());
958 }
959 
960 
961 
976 template <typename ElementType>
978 make_array_view(const std::vector<ElementType> &vector)
979 {
980  return ArrayView<const ElementType>(vector.data(), vector.size());
981 }
982 
983 
984 
1004 template <typename ElementType>
1006 make_array_view(std::vector<ElementType> &vector,
1007  const std::size_t starting_index,
1008  const std::size_t size_of_view)
1009 {
1010  Assert(starting_index + size_of_view <= vector.size(),
1011  ExcMessage("The starting index and size of the view you want to "
1012  "create would lead to a view that extends beyond the end "
1013  "of the given vector."));
1014  return ArrayView<ElementType>(&vector[starting_index], size_of_view);
1015 }
1016 
1017 
1018 
1038 template <typename ElementType>
1040 make_array_view(const std::vector<ElementType> &vector,
1041  const std::size_t starting_index,
1042  const std::size_t size_of_view)
1043 {
1044  Assert(starting_index + size_of_view <= vector.size(),
1045  ExcMessage("The starting index and size of the view you want to "
1046  "create would lead to a view that extends beyond the end "
1047  "of the given vector."));
1048  return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
1049 }
1050 
1051 
1052 
1069 template <typename ElementType>
1072  const typename Table<2, ElementType>::size_type row)
1073 {
1074  AssertIndexRange(row, table.size()[0]);
1075  return ArrayView<ElementType>(&table[row][0], table.size()[1]);
1076 }
1077 
1078 
1079 
1096 template <typename ElementType>
1098 {
1099  return ArrayView<ElementType>(&table[0][0], table.n_elements());
1100 }
1101 
1102 
1103 
1120 template <typename ElementType>
1123 {
1124  return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1125 }
1126 
1127 
1145 template <typename ElementType>
1148 {
1149  return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1150 }
1151 
1152 
1153 
1170 template <typename ElementType>
1173 {
1174  return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1175 }
1176 
1177 
1178 
1195 template <typename ElementType>
1198  const typename Table<2, ElementType>::size_type row)
1199 {
1200  AssertIndexRange(row, table.size()[0]);
1201  return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1202 }
1203 
1204 
1205 
1225 template <typename ElementType>
1227  Table<2, ElementType> & table,
1228  const typename Table<2, ElementType>::size_type row,
1229  const typename Table<2, ElementType>::size_type starting_column,
1230  const std::size_t size_of_view)
1231 {
1232  AssertIndexRange(row, table.size()[0]);
1233  AssertIndexRange(starting_column, table.size()[1]);
1234  Assert(starting_column + size_of_view <= table.size()[1],
1235  ExcMessage("The starting index and size of the view you want to "
1236  "create would lead to a view that extends beyond the end "
1237  "of a column of the given table."));
1238  return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1239 }
1240 
1241 
1242 
1262 template <typename ElementType>
1265  const typename Table<2, ElementType>::size_type row,
1266  const typename Table<2, ElementType>::size_type starting_column,
1267  const std::size_t size_of_view)
1268 {
1269  AssertIndexRange(row, table.size()[0]);
1270  AssertIndexRange(starting_column, table.size()[1]);
1271  Assert(starting_column + size_of_view <= table.size()[1],
1272  ExcMessage("The starting index and size of the view you want to "
1273  "create would lead to a view that extends beyond the end "
1274  "of a column of the given table."));
1275  return ArrayView<const ElementType>(&table[row][starting_column],
1276  size_of_view);
1277 }
1278 
1279 
1280 
1281 /*
1282  * Create a view that doesn't allow the container it points to to be modified.
1283  * This is useful if the object passed in is not `const` already and a function
1284  * requires a view to constant memory in its signature.
1285  *
1286  * This function returns an object of type `ArrayView<const T>` where `T` is the
1287  * element type of the container.
1288  *
1289  * @relatesalso ArrayView
1290  */
1291 template <typename Container>
1292 inline auto
1293 make_const_array_view(const Container &container)
1294  -> decltype(make_array_view(container))
1295 {
1296  return make_array_view(container);
1297 }
1298 
1299 
1301 
1302 #endif
bool is_in_correct_memory_space(const void *const ptr)
Definition: array_view.h:349
Number * begin_raw()
auto make_const_array_view(const Container &container) -> decltype(make_array_view(container))
Definition: array_view.h:1293
Contents is actually a matrix.
const_iterator cbegin() const
Definition: array_view.h:597
iterator end() const
Definition: array_view.h:588
#define AssertIndexRange(index, range)
Definition: exceptions.h:1691
STL namespace.
size_type n_elements() const
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:515
std::size_t size() const
Definition: array_view.h:570
std::size_t n_elements
Definition: array_view.h:333
const const Number * const_iterator
Definition: array_view.h:94
Number * end_raw()
static ::ExceptionBase & ExcMessage(std::string arg1)
value_type & operator[](const std::size_t i) const
Definition: array_view.h:615
static const char T
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:409
Number * begin_raw()
const Number value_type
Definition: array_view.h:84
#define Assert(cond, exc)
Definition: exceptions.h:1466
#define AssertCuda(error_code)
Definition: exceptions.h:1773
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:394
Number * end_raw()
value_type * data() const noexcept
Definition: array_view.h:547
Point< 2 > first
Definition: grid_out.cc:4575
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:538
size_type size(const unsigned int i) const
typename AlignedVector< T >::size_type size_type
Definition: table.h:409
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:393
static const char N
value_type * starting_element
Definition: array_view.h:328
Definition: table.h:688
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition: array_view.h:693
iterator begin() const
Definition: array_view.h:579
const_iterator cend() const
Definition: array_view.h:606