Reference documentation for deal.II version 9.1.1
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
array_view.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2019 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 
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/memory_space.h>
24 #include <deal.II/base/table.h>
25 #include <deal.II/base/tensor.h>
26 
27 #include <deal.II/lac/lapack_full_matrix.h>
28 
29 #include <type_traits>
30 #include <vector>
31 
32 DEAL_II_NAMESPACE_OPEN
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 
148  ArrayView(
149  const std::vector<typename std::remove_cv<value_type>::type> &vector);
150 
165  ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
166 
186  void
187  reinit(value_type *starting_element, const std::size_t n_elements);
188 
194  bool
195  operator==(
196  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
197 
203  bool
204  operator==(const ArrayView<typename std::remove_cv<value_type>::type,
205  MemorySpaceType> &other_view) const;
206 
212  bool
213  operator!=(
214  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
215 
221  bool
222  operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
223  MemorySpaceType> &other_view) const;
224 
229  std::size_t
230  size() const;
231 
236  value_type *
237  data() const noexcept;
238 
242  iterator
243  begin() const;
244 
248  iterator
249  end() const;
250 
255  cbegin() const;
256 
261  cend() const;
262 
275  value_type &operator[](const std::size_t i) const;
276 
277 private:
283 
287  std::size_t n_elements;
288 
289  friend class ArrayView<const ElementType, MemorySpaceType>;
290 };
291 
292 
293 
294 //---------------------------------------------------------------------------
295 
296 
297 namespace internal
298 {
299  namespace ArrayViewHelper
300  {
301  template <typename MemorySpaceType>
302  inline bool
303  is_in_correct_memory_space(const void *const ptr)
304  {
305 #ifndef DEAL_II_COMPILER_CUDA_AWARE
306  (void)ptr;
307  static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
308  "If the compiler doesn't understand CUDA code, "
309  "the only possible memory space is 'MemorySpace::Host'!");
310  return true;
311 #else
312  cudaPointerAttributes attributes;
313  const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
314  if (cuda_error != cudaErrorInvalidValue)
315  {
316  AssertCuda(cuda_error);
317  if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
318  return attributes.memoryType == cudaMemoryTypeHost;
319  else
320  return attributes.memoryType == cudaMemoryTypeDevice;
321  }
322  else
323  {
324  // ignore and reset the error since host pointers produce an error
325  cudaGetLastError();
326  return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
327  }
328 #endif
329  }
330  } // namespace ArrayViewHelper
331 } // namespace internal
332 
333 
334 
335 template <typename ElementType, typename MemorySpaceType>
337  : starting_element(nullptr)
338  , n_elements(0)
339 {}
340 
341 
342 
343 template <typename ElementType, typename MemorySpaceType>
345  value_type * starting_element,
346  const std::size_t n_elements)
347  : starting_element(starting_element)
348  , n_elements(n_elements)
349 {
350  Assert(
351  n_elements == 0 ||
352  internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
354  ExcMessage("The memory space indicated by the template parameter "
355  "and the one derived from the pointer value do not match!"));
356 }
357 
358 
359 
360 template <typename ElementType, typename MemorySpaceType>
361 inline void
363  const std::size_t n_elements)
364 {
365  *this = ArrayView(starting_element, n_elements);
366 }
367 
368 
369 
370 template <typename ElementType, typename MemorySpaceType>
372  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
373  &view)
374  : starting_element(view.starting_element)
375  , n_elements(view.n_elements)
376 {}
377 
378 
379 
380 template <typename ElementType, typename MemorySpaceType>
382  const std::vector<typename std::remove_cv<value_type>::type> &vector)
383  : // use delegating constructor
384  ArrayView(vector.data(), vector.size())
385 {
386  // the following static_assert is not strictly necessary because,
387  // if we got a const std::vector reference argument but ElementType
388  // is not itself const, then the call to the forwarding constructor
389  // above will already have failed: vector.data() will have returned
390  // a const pointer, but we need a non-const pointer.
391  //
392  // nevertheless, leave the static_assert in since it provides a
393  // more descriptive error message that will simply come after the first
394  // error produced above
395  static_assert(std::is_const<value_type>::value == true,
396  "This constructor may only be called if the ArrayView "
397  "object has a const value_type. In other words, you can "
398  "only create an ArrayView to const values from a const "
399  "std::vector.");
400 }
401 
402 
403 
404 template <typename ElementType, typename MemorySpaceType>
406  std::vector<typename std::remove_cv<value_type>::type> &vector)
407  : // use delegating constructor
408  ArrayView(vector.data(), vector.size())
409 {}
410 
411 
412 
413 template <typename ElementType, typename MemorySpaceType>
414 inline bool
417 {
418  return (other_view.data() == starting_element) &&
419  (other_view.size() == n_elements);
420 }
421 
422 
423 
424 template <typename ElementType, typename MemorySpaceType>
425 inline bool
427 operator==(const ArrayView<typename std::remove_cv<value_type>::type,
428  MemorySpaceType> &other_view) const
429 {
430  return (other_view.data() == starting_element) &&
431  (other_view.size() == n_elements);
432 }
433 
434 
435 
436 template <typename ElementType, typename MemorySpaceType>
437 inline bool
440 {
441  return !(*this == other_view);
442 }
443 
444 
445 
446 template <typename ElementType, typename MemorySpaceType>
449 {
450  if (n_elements == 0)
451  return nullptr;
452  else
453  return starting_element;
454 }
455 
456 
457 
458 template <typename ElementType, typename MemorySpaceType>
459 inline bool
461 operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
462  MemorySpaceType> &other_view) const
463 {
464  return !(*this == other_view);
465 }
466 
467 
468 
469 template <typename ElementType, typename MemorySpaceType>
470 inline std::size_t
472 {
473  return n_elements;
474 }
475 
476 
477 
478 template <typename ElementType, typename MemorySpaceType>
481 {
482  return starting_element;
483 }
484 
485 
486 
487 template <typename ElementType, typename MemorySpaceType>
490 {
491  return starting_element + n_elements;
492 }
493 
494 
495 
496 template <typename ElementType, typename MemorySpaceType>
499 {
500  return starting_element;
501 }
502 
503 
504 
505 template <typename ElementType, typename MemorySpaceType>
508 {
509  return starting_element + n_elements;
510 }
511 
512 
513 
514 template <typename ElementType, typename MemorySpaceType>
517 {
518  Assert(i < n_elements, ExcIndexRange(i, 0, n_elements));
519  Assert(
520  (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
521  ExcMessage(
522  "Accessing elements is only allowed if the data is stored in CPU memory!"));
523 
524  return *(starting_element + i);
525 }
526 
527 
528 
529 #ifndef DOXYGEN
530 namespace internal
531 {
532  namespace ArrayViewHelper
533  {
539  template <class Iterator>
540  bool
541  is_contiguous(const Iterator &first, const Iterator &last)
542  {
543  const auto n = std::distance(first, last);
544  for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
545  if (std::addressof(*(std::next(first, i))) !=
546  std::next(std::addressof(*first), i))
547  return false;
548  return true;
549  }
550 
551 
562  template <class T>
563  constexpr bool
564  is_contiguous(T *, T *)
565  {
566  return true;
567  }
568  } // namespace ArrayViewHelper
569 } // namespace internal
570 #endif
571 
572 
573 
590 template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
591 ArrayView<typename std::remove_reference<
592  typename std::iterator_traits<Iterator>::reference>::type,
593  MemorySpaceType>
594 make_array_view(const Iterator begin, const Iterator end)
595 {
596  static_assert(
597  std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
598  typename std::random_access_iterator_tag>::value,
599  "The provided iterator should be a random access iterator.");
600  Assert(begin <= end,
601  ExcMessage(
602  "The beginning of the array view should be before the end."));
603  Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
604  ExcMessage("The provided range isn't contiguous in memory!"));
605  // the reference type, not the value type, knows the constness of the iterator
606  return ArrayView<typename std::remove_reference<
607  typename std::iterator_traits<Iterator>::reference>::type,
608  MemorySpaceType>(std::addressof(*begin), end - begin);
609 }
610 
611 
612 
622 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
624 make_array_view(ElementType *const begin, ElementType *const end)
625 {
626  Assert(begin <= end,
627  ExcMessage(
628  "The beginning of the array view should be before the end."));
629  return ArrayView<ElementType, MemorySpaceType>(begin, end - begin);
630 }
631 
632 
633 
644 template <typename Number, typename MemorySpaceType>
647 {
648  return make_array_view(array_view.cbegin(), array_view.cend());
649 }
650 
651 
652 
663 template <typename Number, typename MemorySpaceType>
666 {
667  return make_array_view(array_view.begin(), array_view.end());
668 }
669 
670 
671 
688 template <int rank, int dim, typename Number>
691 {
692  return make_array_view(tensor.begin_raw(), tensor.end_raw());
693 }
694 
695 
696 
713 template <int rank, int dim, typename Number>
714 inline ArrayView<Number>
716 {
717  return make_array_view(tensor.begin_raw(), tensor.end_raw());
718 }
719 
720 
721 
738 template <int rank, int dim, typename Number>
741 {
742  return make_array_view(tensor.begin_raw(), tensor.end_raw());
743 }
744 
745 
746 
764 template <int rank, int dim, typename Number>
765 inline ArrayView<Number>
767 {
768  return make_array_view(tensor.begin_raw(), tensor.end_raw());
769 }
770 
771 
772 
786 template <typename ElementType, int N>
788 {
789  return ArrayView<ElementType>(array, N);
790 }
791 
792 
793 
808 template <typename ElementType>
810 make_array_view(Vector<ElementType> &vector)
811 {
812  return ArrayView<ElementType>(vector.begin(), vector.size());
813 }
814 
815 
816 
831 template <typename ElementType>
833 make_array_view(const Vector<ElementType> &vector)
834 {
835  return ArrayView<const ElementType>(vector.begin(), vector.size());
836 }
837 
838 
839 
854 template <typename ElementType>
856 make_array_view(std::vector<ElementType> &vector)
857 {
858  return ArrayView<ElementType>(vector.data(), vector.size());
859 }
860 
861 
862 
877 template <typename ElementType>
879 make_array_view(const std::vector<ElementType> &vector)
880 {
881  return ArrayView<const ElementType>(vector.data(), vector.size());
882 }
883 
884 
885 
905 template <typename ElementType>
907 make_array_view(std::vector<ElementType> &vector,
908  const std::size_t starting_index,
909  const std::size_t size_of_view)
910 {
911  Assert(starting_index + size_of_view <= vector.size(),
912  ExcMessage("The starting index and size of the view you want to "
913  "create would lead to a view that extends beyond the end "
914  "of the given vector."));
915  return ArrayView<ElementType>(&vector[starting_index], size_of_view);
916 }
917 
918 
919 
939 template <typename ElementType>
941 make_array_view(const std::vector<ElementType> &vector,
942  const std::size_t starting_index,
943  const std::size_t size_of_view)
944 {
945  Assert(starting_index + size_of_view <= vector.size(),
946  ExcMessage("The starting index and size of the view you want to "
947  "create would lead to a view that extends beyond the end "
948  "of the given vector."));
949  return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
950 }
951 
952 
953 
970 template <typename ElementType>
973  const typename Table<2, ElementType>::size_type row)
974 {
975  AssertIndexRange(row, table.size()[0]);
976  return ArrayView<ElementType>(&table[row][0], table.size()[1]);
977 }
978 
979 
980 
997 template <typename ElementType>
999 {
1000  return ArrayView<ElementType>(&table[0][0], table.n_elements());
1001 }
1002 
1003 
1004 
1021 template <typename ElementType>
1024 {
1025  return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1026 }
1027 
1028 
1046 template <typename ElementType>
1049 {
1050  return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1051 }
1052 
1053 
1054 
1071 template <typename ElementType>
1074 {
1075  return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1076 }
1077 
1078 
1079 
1096 template <typename ElementType>
1099  const typename Table<2, ElementType>::size_type row)
1100 {
1101  AssertIndexRange(row, table.size()[0]);
1102  return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1103 }
1104 
1105 
1106 
1126 template <typename ElementType>
1128  Table<2, ElementType> & table,
1129  const typename Table<2, ElementType>::size_type row,
1130  const typename Table<2, ElementType>::size_type starting_column,
1131  const std::size_t size_of_view)
1132 {
1133  AssertIndexRange(row, table.size()[0]);
1134  AssertIndexRange(starting_column, table.size()[1]);
1135  Assert(starting_column + size_of_view <= table.size()[1],
1136  ExcMessage("The starting index and size of the view you want to "
1137  "create would lead to a view that extends beyond the end "
1138  "of a column of the given table."));
1139  return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1140 }
1141 
1142 
1143 
1163 template <typename ElementType>
1166  const typename Table<2, ElementType>::size_type row,
1167  const typename Table<2, ElementType>::size_type starting_column,
1168  const std::size_t size_of_view)
1169 {
1170  AssertIndexRange(row, table.size()[0]);
1171  AssertIndexRange(starting_column, table.size()[1]);
1172  Assert(starting_column + size_of_view <= table.size()[1],
1173  ExcMessage("The starting index and size of the view you want to "
1174  "create would lead to a view that extends beyond the end "
1175  "of a column of the given table."));
1176  return ArrayView<const ElementType>(&table[row][starting_column],
1177  size_of_view);
1178 }
1179 
1180 
1181 
1182 /*
1183  * Create a view that doesn't allow the container it points to to be modified.
1184  * This is useful if the object passed in is not `const` already and a function
1185  * requires a view to constant memory in its signature.
1186  *
1187  * This function returns an object of type `ArrayView<const T>` where `T` is the
1188  * element type of the container.
1189  *
1190  * @relatesalso ArrayView
1191  */
1192 template <typename Container>
1193 inline auto
1194 make_const_array_view(const Container &container)
1195  -> decltype(make_array_view(container))
1196 {
1197  return make_array_view(container);
1198 }
1199 
1200 
1201 DEAL_II_NAMESPACE_CLOSE
1202 
1203 #endif
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1048
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1073
ArrayView< Number, MemorySpaceType > make_array_view(ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:665
ArrayView< const Number, MemorySpaceType > make_array_view(const ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:646
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:787
const_iterator cbegin() const
Definition: array_view.h:498
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:690
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:907
iterator end() const
Definition: array_view.h:489
#define AssertIndexRange(index, range)
Definition: exceptions.h:1637
STL namespace.
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1165
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:416
std::size_t size() const
Definition: array_view.h:471
std::size_t n_elements
Definition: array_view.h:287
const std::conditional< std::is_const< VectorType >::value, const VectorType::value_type, VectorType::value_type >::type * const_iterator
Definition: array_view.h:94
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:766
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:810
static ::ExceptionBase & ExcMessage(std::string arg1)
value_type & operator[](const std::size_t i) const
Definition: array_view.h:516
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:362
Number * begin_raw()
std::conditional< std::is_const< VectorType >::value, const VectorType::value_type, VectorType::value_type >::type value_type
Definition: array_view.h:84
#define Assert(cond, exc)
Definition: exceptions.h:1407
#define AssertCuda(error_code)
Definition: exceptions.h:1722
Number * end_raw()
Definition: tensor.h:1181
Number * end_raw()
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:972
value_type * data() const noexcept
Definition: array_view.h:448
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:941
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:439
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:740
size_type size(const unsigned int i) const
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:833
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:856
typename AlignedVector< T >::size_type size_type
Definition: table.h:418
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1098
ArrayView< ElementType, MemorySpaceType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:624
Number * begin_raw()
Definition: tensor.h:1161
value_type * starting_element
Definition: array_view.h:282
Definition: table.h:37
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:594
iterator begin() const
Definition: array_view.h:480
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1127
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:715
const_iterator cend() const
Definition: array_view.h:507
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:879
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:1023
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:998