Reference documentation for deal.II version 9.3.3
\(\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 - 2021 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/tensor.h>
25
26#include <type_traits>
27#include <vector>
28
30
31// Forward declaration
32template <int N, typename T>
33class Table;
34
35template <typename number>
37
38
80template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
82{
83public:
89
94
98 using const_iterator = const ElementType *;
99
104
125
135 ArrayView(const ArrayView<typename std::remove_cv<value_type>::type,
136 MemorySpaceType> &view);
137
142 explicit ArrayView(value_type &element);
143
159 const std::vector<typename std::remove_cv<value_type>::type> &vector);
160
175 ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
176
191 template <std::size_t N>
193
202 template <std::size_t N>
204 const std::array<typename std::remove_cv<value_type>::type, N> &vector);
205
214 template <std::size_t N>
215 ArrayView(std::array<typename std::remove_cv<value_type>::type, N> &vector);
216
236 void
238
244 bool
246 const ArrayView<const value_type, MemorySpaceType> &other_view) const;
247
253 bool
254 operator==(const ArrayView<typename std::remove_cv<value_type>::type,
255 MemorySpaceType> &other_view) const;
256
262 bool
264 const ArrayView<const value_type, MemorySpaceType> &other_view) const;
265
271 bool
272 operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
273 MemorySpaceType> &other_view) const;
274
279 std::size_t
280 size() const;
281
286 value_type *
287 data() const noexcept;
288
293 begin() const;
294
299 end() const;
300
305 cbegin() const;
306
311 cend() const;
312
325 value_type &operator[](const std::size_t i) const;
326
327private:
333
338
339 friend class ArrayView<const ElementType, MemorySpaceType>;
340};
341
342
343
344//---------------------------------------------------------------------------
345
346
347namespace internal
348{
349 namespace ArrayViewHelper
350 {
351 template <typename MemorySpaceType>
352 inline bool
353 is_in_correct_memory_space(const void *const ptr)
354 {
355#ifndef DEAL_II_COMPILER_CUDA_AWARE
356 (void)ptr;
357 static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
358 "If the compiler doesn't understand CUDA code, "
359 "the only possible memory space is 'MemorySpace::Host'!");
360 return true;
361#else
362 cudaPointerAttributes attributes;
363 const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
364 if (cuda_error != cudaErrorInvalidValue)
365 {
366 AssertCuda(cuda_error);
367 if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
368 return (attributes.type == cudaMemoryTypeHost) ||
369 (attributes.type == cudaMemoryTypeUnregistered);
370 else
371 return attributes.type == cudaMemoryTypeDevice;
372 }
373 else
374 {
375 // ignore and reset the error since host pointers produce an error
376 cudaGetLastError();
377 return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
378 }
379#endif
380 }
381 } // namespace ArrayViewHelper
382} // namespace internal
383
384
385
386template <typename ElementType, typename MemorySpaceType>
388 : starting_element(nullptr)
389 , n_elements(0)
390{}
391
392
393
394template <typename ElementType, typename MemorySpaceType>
396 value_type * starting_element,
397 const std::size_t n_elements)
398 : starting_element(starting_element)
399 , n_elements(n_elements)
400{
401 Assert(
402 n_elements == 0 ||
403 internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
405 ExcMessage("The memory space indicated by the template parameter "
406 "and the one derived from the pointer value do not match!"));
407}
408
409
410
411template <typename ElementType, typename MemorySpaceType>
412inline void
414 const std::size_t n_elements)
415{
416 *this = ArrayView(starting_element, n_elements);
417}
418
419
420
421template <typename ElementType, typename MemorySpaceType>
423 : starting_element(&element)
424 , n_elements(1)
425{}
426
427
428
429template <typename ElementType, typename MemorySpaceType>
431 const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
432 &view)
433 : starting_element(view.starting_element)
434 , n_elements(view.n_elements)
435{}
436
437
438
439template <typename ElementType, typename MemorySpaceType>
441 const std::vector<typename std::remove_cv<value_type>::type> &vector)
442 : // use delegating constructor
443 ArrayView(vector.data(), vector.size())
444{
445 // the following static_assert is not strictly necessary because,
446 // if we got a const std::vector reference argument but ElementType
447 // is not itself const, then the call to the forwarding constructor
448 // above will already have failed: vector.data() will have returned
449 // a const pointer, but we need a non-const pointer.
450 //
451 // nevertheless, leave the static_assert in since it provides a
452 // more descriptive error message that will simply come after the first
453 // error produced above
454 static_assert(std::is_const<value_type>::value == true,
455 "This constructor may only be called if the ArrayView "
456 "object has a const value_type. In other words, you can "
457 "only create an ArrayView to const values from a const "
458 "std::vector.");
459}
460
461
462
463template <typename ElementType, typename MemorySpaceType>
465 std::vector<typename std::remove_cv<value_type>::type> &vector)
466 : // use delegating constructor
467 ArrayView(vector.data(), vector.size())
468{}
469
470
471
472template <typename ElementType, typename MemorySpaceType>
473template <std::size_t N>
475 const std::array<typename std::remove_cv<value_type>::type, N> &vector)
476 : // use delegating constructor
477 ArrayView(vector.data(), vector.size())
478{
479 // the following static_assert is not strictly necessary because,
480 // if we got a const std::array reference argument but ElementType
481 // is not itself const, then the call to the forwarding constructor
482 // above will already have failed: vector.data() will have returned
483 // a const pointer, but we need a non-const pointer.
484 //
485 // nevertheless, leave the static_assert in since it provides a
486 // more descriptive error message that will simply come after the first
487 // error produced above
488 static_assert(std::is_const<value_type>::value == true,
489 "This constructor may only be called if the ArrayView "
490 "object has a const value_type. In other words, you can "
491 "only create an ArrayView to const values from a const "
492 "std::array.");
493}
494
495
496
497template <typename ElementType, typename MemorySpaceType>
498template <std::size_t N>
500 ElementType (&array)[N])
501 : ArrayView(&array[0], N)
502{}
503
504
505
506template <typename ElementType, typename MemorySpaceType>
507template <std::size_t N>
509 std::array<typename std::remove_cv<value_type>::type, N> &vector)
510 : // use delegating constructor
511 ArrayView(vector.data(), vector.size())
512{}
513
514
515
516template <typename ElementType, typename MemorySpaceType>
517inline bool
520{
521 return (other_view.data() == starting_element) &&
522 (other_view.size() == n_elements);
523}
524
525
526
527template <typename ElementType, typename MemorySpaceType>
528inline bool
530operator==(const ArrayView<typename std::remove_cv<value_type>::type,
531 MemorySpaceType> &other_view) const
532{
533 return (other_view.data() == starting_element) &&
534 (other_view.size() == n_elements);
535}
536
537
538
539template <typename ElementType, typename MemorySpaceType>
540inline bool
543{
544 return !(*this == other_view);
545}
546
547
548
549template <typename ElementType, typename MemorySpaceType>
552{
553 if (n_elements == 0)
554 return nullptr;
555 else
556 return starting_element;
557}
558
559
560
561template <typename ElementType, typename MemorySpaceType>
562inline bool
564operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
565 MemorySpaceType> &other_view) const
566{
567 return !(*this == other_view);
568}
569
570
571
572template <typename ElementType, typename MemorySpaceType>
573inline std::size_t
575{
576 return n_elements;
577}
578
579
580
581template <typename ElementType, typename MemorySpaceType>
584{
585 return starting_element;
586}
587
588
589
590template <typename ElementType, typename MemorySpaceType>
593{
594 return starting_element + n_elements;
595}
596
597
598
599template <typename ElementType, typename MemorySpaceType>
602{
603 return starting_element;
604}
605
606
607
608template <typename ElementType, typename MemorySpaceType>
611{
612 return starting_element + n_elements;
613}
614
615
616
617template <typename ElementType, typename MemorySpaceType>
620{
621 AssertIndexRange(i, n_elements);
622 Assert(
623 (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
625 "Accessing elements is only allowed if the data is stored in CPU memory!"));
626
627 return *(starting_element + i);
628}
629
630
631
632#ifndef DOXYGEN
633namespace internal
634{
635 namespace ArrayViewHelper
636 {
642 template <class Iterator>
643 bool
644 is_contiguous(const Iterator &first, const Iterator &last)
645 {
646 const auto n = std::distance(first, last);
647 for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
648 if (std::addressof(*(std::next(first, i))) !=
649 std::next(std::addressof(*first), i))
650 return false;
651 return true;
652 }
653
654
665 template <class T>
666 constexpr bool
667 is_contiguous(T *, T *)
668 {
669 return true;
670 }
671 } // namespace ArrayViewHelper
672} // namespace internal
673#endif
674
675
676
693template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
694ArrayView<typename std::remove_reference<
695 typename std::iterator_traits<Iterator>::reference>::type,
696 MemorySpaceType>
697make_array_view(const Iterator begin, const Iterator end)
698{
699 static_assert(
700 std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
701 typename std::random_access_iterator_tag>::value,
702 "The provided iterator should be a random access iterator.");
703 Assert(begin <= end,
705 "The beginning of the array view should be before the end."));
706 Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
707 ExcMessage("The provided range isn't contiguous in memory!"));
708 // the reference type, not the value type, knows the constness of the iterator
709 return ArrayView<typename std::remove_reference<
710 typename std::iterator_traits<Iterator>::reference>::type,
711 MemorySpaceType>(std::addressof(*begin), end - begin);
712}
713
714
715
725template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
728{
729 Assert(begin <= end,
731 "The beginning of the array view should be before the end."));
733}
734
735
736
747template <typename Number, typename MemorySpaceType>
750{
751 return make_array_view(array_view.cbegin(), array_view.cend());
752}
753
754
755
766template <typename Number, typename MemorySpaceType>
769{
770 return make_array_view(array_view.begin(), array_view.end());
771}
772
773
774
791template <int rank, int dim, typename Number>
794{
795 return make_array_view(tensor.begin_raw(), tensor.end_raw());
796}
797
798
799
816template <int rank, int dim, typename Number>
819{
820 return make_array_view(tensor.begin_raw(), tensor.end_raw());
821}
822
823
824
841template <int rank, int dim, typename Number>
844{
845 return make_array_view(tensor.begin_raw(), tensor.end_raw());
846}
847
848
849
867template <int rank, int dim, typename Number>
870{
871 return make_array_view(tensor.begin_raw(), tensor.end_raw());
872}
873
874
875
889template <typename ElementType, int N>
891{
892 return ArrayView<ElementType>(array, N);
893}
894
895
896
911template <typename ElementType>
914{
915 return ArrayView<ElementType>(vector.begin(), vector.size());
916}
917
918
919
934template <typename ElementType>
937{
938 return ArrayView<const ElementType>(vector.begin(), vector.size());
939}
940
941
942
957template <typename ElementType>
959make_array_view(std::vector<ElementType> &vector)
960{
961 return ArrayView<ElementType>(vector.data(), vector.size());
962}
963
964
965
980template <typename ElementType>
982make_array_view(const std::vector<ElementType> &vector)
983{
984 return ArrayView<const ElementType>(vector.data(), vector.size());
985}
986
987
988
1008template <typename ElementType>
1010make_array_view(std::vector<ElementType> &vector,
1011 const std::size_t starting_index,
1012 const std::size_t size_of_view)
1013{
1014 Assert(starting_index + size_of_view <= vector.size(),
1015 ExcMessage("The starting index and size of the view you want to "
1016 "create would lead to a view that extends beyond the end "
1017 "of the given vector."));
1018 return ArrayView<ElementType>(&vector[starting_index], size_of_view);
1019}
1020
1021
1022
1042template <typename ElementType>
1044make_array_view(const std::vector<ElementType> &vector,
1045 const std::size_t starting_index,
1046 const std::size_t size_of_view)
1047{
1048 Assert(starting_index + size_of_view <= vector.size(),
1049 ExcMessage("The starting index and size of the view you want to "
1050 "create would lead to a view that extends beyond the end "
1051 "of the given vector."));
1052 return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
1053}
1054
1055
1056
1073template <typename ElementType>
1076 const typename Table<2, ElementType>::size_type row)
1077{
1078 AssertIndexRange(row, table.size()[0]);
1079 return ArrayView<ElementType>(&table[row][0], table.size()[1]);
1080}
1081
1082
1083
1100template <typename ElementType>
1102{
1103 return ArrayView<ElementType>(&table[0][0], table.n_elements());
1104}
1105
1106
1107
1124template <typename ElementType>
1127{
1128 return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1129}
1130
1131
1149template <typename ElementType>
1152{
1153 return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1154}
1155
1156
1157
1174template <typename ElementType>
1177{
1178 return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1179}
1180
1181
1182
1199template <typename ElementType>
1202 const typename Table<2, ElementType>::size_type row)
1203{
1204 AssertIndexRange(row, table.size()[0]);
1205 return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1206}
1207
1208
1209
1229template <typename ElementType>
1231 Table<2, ElementType> & table,
1232 const typename Table<2, ElementType>::size_type row,
1233 const typename Table<2, ElementType>::size_type starting_column,
1234 const std::size_t size_of_view)
1235{
1236 AssertIndexRange(row, table.size()[0]);
1237 AssertIndexRange(starting_column, table.size()[1]);
1238 Assert(starting_column + size_of_view <= table.size()[1],
1239 ExcMessage("The starting index and size of the view you want to "
1240 "create would lead to a view that extends beyond the end "
1241 "of a column of the given table."));
1242 return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1243}
1244
1245
1246
1266template <typename ElementType>
1269 const typename Table<2, ElementType>::size_type row,
1270 const typename Table<2, ElementType>::size_type starting_column,
1271 const std::size_t size_of_view)
1272{
1273 AssertIndexRange(row, table.size()[0]);
1274 AssertIndexRange(starting_column, table.size()[1]);
1275 Assert(starting_column + size_of_view <= table.size()[1],
1276 ExcMessage("The starting index and size of the view you want to "
1277 "create would lead to a view that extends beyond the end "
1278 "of a column of the given table."));
1279 return ArrayView<const ElementType>(&table[row][starting_column],
1280 size_of_view);
1281}
1282
1283
1284
1285/*
1286 * Create a view that doesn't allow the container it points to to be modified.
1287 * This is useful if the object passed in is not `const` already and a function
1288 * requires a view to constant memory in its signature.
1289 *
1290 * This function returns an object of type `ArrayView<const T>` where `T` is the
1291 * element type of the container.
1292 *
1293 * @relatesalso ArrayView
1294 */
1295template <typename Container>
1296inline auto
1297make_const_array_view(const Container &container)
1298 -> decltype(make_array_view(container))
1299{
1300 return make_array_view(container);
1301}
1302
1303
1305
1306#endif
auto make_const_array_view(const Container &container) -> decltype(make_array_view(container))
Definition: array_view.h:1297
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:936
ArrayView(value_type &element)
Definition: array_view.h:422
iterator begin() const
Definition: array_view.h:583
ArrayView(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &view)
Definition: array_view.h:430
ArrayView< Number, MemorySpaceType > make_array_view(ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:768
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:697
value_type * iterator
Definition: array_view.h:93
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:869
value_type & operator[](const std::size_t i) const
Definition: array_view.h:619
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1176
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:793
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:843
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1151
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:890
ArrayView< ElementType, MemorySpaceType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:727
bool operator!=(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:564
const_iterator cend() const
Definition: array_view.h:610
iterator end() const
Definition: array_view.h:592
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:1044
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:1126
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:1268
ArrayView(const std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:474
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:959
ArrayView(std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:464
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:519
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:1010
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:542
const_iterator cbegin() const
Definition: array_view.h:601
ArrayView(const std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:440
ArrayView(value_type(&array)[N])
Definition: array_view.h:499
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:818
value_type * data() const noexcept
Definition: array_view.h:551
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:1230
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:413
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:1101
value_type * starting_element
Definition: array_view.h:332
std::size_t size() const
Definition: array_view.h:574
bool operator==(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:530
ElementType value_type
Definition: array_view.h:88
ArrayView(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:395
std::size_t n_elements
Definition: array_view.h:337
ArrayView< const Number, MemorySpaceType > make_array_view(const ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:749
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1201
const ElementType * const_iterator
Definition: array_view.h:98
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:913
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1075
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:982
ArrayView(std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:508
Number * begin_raw()
Number * end_raw()
Definition: tensor.h:472
Number * begin_raw()
Number * end_raw()
Definition: vector.h:110
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
Point< 2 > first
Definition: grid_out.cc:4587
#define Assert(cond, exc)
Definition: exceptions.h:1465
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
#define AssertCuda(error_code)
Definition: exceptions.h:1772
static ::ExceptionBase & ExcMessage(std::string arg1)
size_type size() const
iterator begin()
@ matrix
Contents is actually a matrix.
static const char T
static const char N
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
bool is_in_correct_memory_space(const void *const ptr)
Definition: array_view.h:353
STL namespace.