Reference documentation for deal.II version 9.1.0-pre
array_view.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2018 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>
23 #include <deal.II/base/table.h>
24 #include <deal.II/base/tensor.h>
25 
26 #include <deal.II/lac/lapack_full_matrix.h>
27 
28 #include <type_traits>
29 #include <vector>
30 
31 DEAL_II_NAMESPACE_OPEN
32 
33 
75 template <typename ElementType>
76 class ArrayView
77 {
78 public:
83  using value_type = ElementType;
84 
88  using iterator = value_type *;
89 
93  using const_iterator = const ElementType *;
94 
114  ArrayView(value_type *starting_element, const std::size_t n_elements);
115 
125  ArrayView(const ArrayView<typename std::remove_cv<value_type>::type> &view);
126 
141  ArrayView(
142  const std::vector<typename std::remove_cv<value_type>::type> &vector);
143 
158  ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
159 
165  bool
166  operator==(const ArrayView<const value_type> &other_view) const;
167 
173  bool
174  operator==(const ArrayView<typename std::remove_cv<value_type>::type>
175  &other_view) const;
176 
182  bool
183  operator!=(const ArrayView<const value_type> &other_view) const;
184 
190  bool
191  operator!=(const ArrayView<typename std::remove_cv<value_type>::type>
192  &other_view) const;
193 
198  std::size_t
199  size() const;
200 
205  value_type *
206  data() const noexcept;
207 
211  iterator
212  begin() const;
213 
217  iterator
218  end() const;
219 
224  cbegin() const;
225 
230  cend() const;
231 
241  value_type &operator[](const std::size_t i) const;
242 
243 private:
249 
253  const std::size_t n_elements;
254 
255  friend class ArrayView<const ElementType>;
256 };
257 
258 
259 
260 //---------------------------------------------------------------------------
261 
262 
263 
264 template <typename ElementType>
265 inline ArrayView<ElementType>::ArrayView(value_type * starting_element,
266  const std::size_t n_elements)
267  : starting_element(starting_element)
268  , n_elements(n_elements)
269 {}
270 
271 
272 
273 template <typename ElementType>
275  const ArrayView<typename std::remove_cv<value_type>::type> &view)
277  , n_elements(view.n_elements)
278 {}
279 
280 
281 
282 template <typename ElementType>
284  const std::vector<typename std::remove_cv<value_type>::type> &vector)
285  : // use delegating constructor
286  ArrayView(vector.data(), vector.size())
287 {
288  // the following static_assert is not strictly necessary because,
289  // if we got a const std::vector reference argument but ElementType
290  // is not itself const, then the call to the forwarding constructor
291  // above will already have failed: vector.data() will have returned
292  // a const pointer, but we need a non-const pointer.
293  //
294  // nevertheless, leave the static_assert in since it provides a
295  // more descriptive error message that will simply come after the first
296  // error produced above
297  static_assert(std::is_const<value_type>::value == true,
298  "This constructor may only be called if the ArrayView "
299  "object has a const value_type. In other words, you can "
300  "only create an ArrayView to const values from a const "
301  "std::vector.");
302 }
303 
304 
305 
306 template <typename ElementType>
308  std::vector<typename std::remove_cv<value_type>::type> &vector)
309  : // use delegating constructor
310  ArrayView(vector.data(), vector.size())
311 {}
312 
313 
314 
315 template <typename ElementType>
316 inline bool
318 operator==(const ArrayView<const value_type> &other_view) const
319 {
320  return (other_view.data() == starting_element) &&
321  (other_view.size() == n_elements);
322 }
323 
324 
325 
326 template <typename ElementType>
327 inline bool
329  const ArrayView<typename std::remove_cv<value_type>::type> &other_view) const
330 {
331  return (other_view.data() == starting_element) &&
332  (other_view.size() == n_elements);
333 }
334 
335 
336 
337 template <typename ElementType>
338 inline bool
340 operator!=(const ArrayView<const value_type> &other_view) const
341 {
342  return !(*this == other_view);
343 }
344 
345 
346 
347 template <typename ElementType>
348 inline typename ArrayView<ElementType>::value_type *
350 {
351  if (n_elements == 0)
352  return nullptr;
353  else
354  return starting_element;
355 }
356 
357 
358 
359 template <typename ElementType>
360 inline bool
362  const ArrayView<typename std::remove_cv<value_type>::type> &other_view) const
363 {
364  return !(*this == other_view);
365 }
366 
367 
368 
369 template <typename ElementType>
370 inline std::size_t
372 {
373  return n_elements;
374 }
375 
376 template <typename ElementType>
377 inline typename ArrayView<ElementType>::iterator
379 {
380  return starting_element;
381 }
382 
383 
384 
385 template <typename ElementType>
386 inline typename ArrayView<ElementType>::iterator
388 {
389  return starting_element + n_elements;
390 }
391 
392 
393 
394 template <typename ElementType>
397 {
398  return starting_element;
399 }
400 
401 
402 
403 template <typename ElementType>
406 {
407  return starting_element + n_elements;
408 }
409 
410 
411 
412 template <typename ElementType>
414  operator[](const std::size_t i) const
415 {
417 
418  return *(starting_element + i);
419 }
420 
421 
422 
423 #ifndef DOXYGEN
424 namespace internal
425 {
426  namespace ArrayViewHelper
427  {
433  template <class Iterator>
434  bool
435  is_contiguous(const Iterator &first, const Iterator &last)
436  {
437  const auto n = std::distance(first, last);
438  for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
439  if (std::addressof(*(std::next(first, i))) !=
440  std::next(std::addressof(*first), i))
441  return false;
442  return true;
443  }
444 
445 
456  template <class T>
457  constexpr bool
458  is_contiguous(T *, T *)
459  {
460  return true;
461  }
462  } // namespace ArrayViewHelper
463 } // namespace internal
464 #endif
465 
466 
467 
484 template <typename Iterator>
485 ArrayView<typename std::remove_reference<
486  typename std::iterator_traits<Iterator>::reference>::type>
487 make_array_view(const Iterator begin, const Iterator end)
488 {
489  static_assert(
490  std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
491  typename std::random_access_iterator_tag>::value,
492  "The provided iterator should be a random access iterator.");
493  Assert(begin <= end,
494  ExcMessage(
495  "The beginning of the array view should be before the end."));
496  Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
497  ExcMessage("The provided range isn't contiguous in memory!"));
498  // the reference type, not the value type, knows the constness of the iterator
499  return ArrayView<typename std::remove_reference<
500  typename std::iterator_traits<Iterator>::reference>::type>(
501  std::addressof(*begin), end - begin);
502 }
503 
504 
505 
515 template <typename ElementType>
517 make_array_view(ElementType *const begin, ElementType *const end)
518 {
519  Assert(begin <= end,
520  ExcMessage(
521  "The beginning of the array view should be before the end."));
522  return ArrayView<ElementType>(begin, end - begin);
523 }
524 
525 
526 
537 template <typename Number>
540 {
541  return make_array_view(array_view.cbegin(), array_view.cend());
542 }
543 
544 
545 
556 template <typename Number>
557 inline ArrayView<Number>
559 {
560  return make_array_view(array_view.begin(), array_view.end());
561 }
562 
563 
564 
581 template <int rank, int dim, typename Number>
584 {
585  return make_array_view(tensor.begin_raw(), tensor.end_raw());
586 }
587 
588 
589 
606 template <int rank, int dim, typename Number>
607 inline ArrayView<Number>
609 {
610  return make_array_view(tensor.begin_raw(), tensor.end_raw());
611 }
612 
613 
614 
631 template <int rank, int dim, typename Number>
634 {
635  return make_array_view(tensor.begin_raw(), tensor.end_raw());
636 }
637 
638 
639 
657 template <int rank, int dim, typename Number>
658 inline ArrayView<Number>
660 {
661  return make_array_view(tensor.begin_raw(), tensor.end_raw());
662 }
663 
664 
665 
679 template <typename ElementType, int N>
680 inline ArrayView<ElementType> make_array_view(ElementType (&array)[N])
681 {
682  return ArrayView<ElementType>(array, N);
683 }
684 
685 
686 
701 template <typename ElementType>
703 make_array_view(Vector<ElementType> &vector)
704 {
705  return ArrayView<ElementType>(vector.begin(), vector.size());
706 }
707 
708 
709 
724 template <typename ElementType>
726 make_array_view(const Vector<ElementType> &vector)
727 {
728  return ArrayView<const ElementType>(vector.begin(), vector.size());
729 }
730 
731 
732 
747 template <typename ElementType>
749 make_array_view(std::vector<ElementType> &vector)
750 {
751  return ArrayView<ElementType>(vector.data(), vector.size());
752 }
753 
754 
755 
770 template <typename ElementType>
772 make_array_view(const std::vector<ElementType> &vector)
773 {
774  return ArrayView<const ElementType>(vector.data(), vector.size());
775 }
776 
777 
778 
798 template <typename ElementType>
800 make_array_view(std::vector<ElementType> &vector,
801  const std::size_t starting_index,
802  const std::size_t size_of_view)
803 {
804  Assert(starting_index + size_of_view <= vector.size(),
805  ExcMessage("The starting index and size of the view you want to "
806  "create would lead to a view that extends beyond the end "
807  "of the given vector."));
808  return ArrayView<ElementType>(&vector[starting_index], size_of_view);
809 }
810 
811 
812 
832 template <typename ElementType>
834 make_array_view(const std::vector<ElementType> &vector,
835  const std::size_t starting_index,
836  const std::size_t size_of_view)
837 {
838  Assert(starting_index + size_of_view <= vector.size(),
839  ExcMessage("The starting index and size of the view you want to "
840  "create would lead to a view that extends beyond the end "
841  "of the given vector."));
842  return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
843 }
844 
845 
846 
863 template <typename ElementType>
866  const typename Table<2, ElementType>::size_type row)
867 {
868  AssertIndexRange(row, table.size()[0]);
869  return ArrayView<ElementType>(&table[row][0], table.size()[1]);
870 }
871 
872 
873 
890 template <typename ElementType>
892 {
893  return ArrayView<ElementType>(&table[0][0], table.n_elements());
894 }
895 
896 
897 
914 template <typename ElementType>
917 {
918  return ArrayView<const ElementType>(&table[0][0], table.n_elements());
919 }
920 
921 
939 template <typename ElementType>
942 {
943  return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
944 }
945 
946 
947 
964 template <typename ElementType>
967 {
968  return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
969 }
970 
971 
972 
989 template <typename ElementType>
992  const typename Table<2, ElementType>::size_type row)
993 {
994  AssertIndexRange(row, table.size()[0]);
995  return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
996 }
997 
998 
999 
1019 template <typename ElementType>
1021  Table<2, ElementType> & table,
1022  const typename Table<2, ElementType>::size_type row,
1023  const typename Table<2, ElementType>::size_type starting_column,
1024  const std::size_t size_of_view)
1025 {
1026  AssertIndexRange(row, table.size()[0]);
1027  AssertIndexRange(starting_column, table.size()[1]);
1028  Assert(starting_column + size_of_view <= table.size()[1],
1029  ExcMessage("The starting index and size of the view you want to "
1030  "create would lead to a view that extends beyond the end "
1031  "of a column of the given table."));
1032  return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1033 }
1034 
1035 
1036 
1056 template <typename ElementType>
1059  const typename Table<2, ElementType>::size_type row,
1060  const typename Table<2, ElementType>::size_type starting_column,
1061  const std::size_t size_of_view)
1062 {
1063  AssertIndexRange(row, table.size()[0]);
1064  AssertIndexRange(starting_column, table.size()[1]);
1065  Assert(starting_column + size_of_view <= table.size()[1],
1066  ExcMessage("The starting index and size of the view you want to "
1067  "create would lead to a view that extends beyond the end "
1068  "of a column of the given table."));
1069  return ArrayView<const ElementType>(&table[row][starting_column],
1070  size_of_view);
1071 }
1072 
1073 
1074 
1075 DEAL_II_NAMESPACE_CLOSE
1076 
1077 #endif
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:941
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:966
std::size_t size() const
Definition: array_view.h:371
ArrayView< const Number > make_array_view(const ArrayView< Number > &array_view)
Definition: array_view.h:539
const ElementType * const_iterator
Definition: array_view.h:93
const_iterator cend() const
Definition: array_view.h:405
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:680
iterator end() const
Definition: array_view.h:387
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:583
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:800
const std::size_t n_elements
Definition: array_view.h:253
#define AssertIndexRange(index, range)
Definition: exceptions.h:1407
const_iterator cbegin() const
Definition: array_view.h:396
iterator begin() const
Definition: array_view.h:378
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:1058
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:659
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:703
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type > make_array_view(const Iterator begin, const Iterator end)
Definition: array_view.h:487
static::ExceptionBase & ExcMessage(std::string arg1)
ArrayView< ElementType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:517
Number * begin_raw()
size_type size(const unsigned int i) const
#define Assert(cond, exc)
Definition: exceptions.h:1227
value_type & operator[](const std::size_t i) const
Definition: array_view.h:414
Number * end_raw()
Definition: tensor.h:1164
bool operator==(const ArrayView< const value_type > &other_view) const
Definition: array_view.h:318
Number * end_raw()
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:865
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:834
size_type n_elements() const
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:633
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:726
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:749
typename AlignedVector< T >::size_type size_type
Definition: table.h:429
value_type * iterator
Definition: array_view.h:88
ArrayView(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:265
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:991
value_type * data() const noexcept
Definition: array_view.h:349
ArrayView< Number > make_array_view(ArrayView< Number > &array_view)
Definition: array_view.h:558
Number * begin_raw()
Definition: tensor.h:1144
Definition: table.h:37
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:1020
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:608
bool operator!=(const ArrayView< const value_type > &other_view) const
Definition: array_view.h:340
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:772
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:916
ElementType value_type
Definition: array_view.h:83
value_type *const starting_element
Definition: array_view.h:248
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:891