]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add an ArrayView class.
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Mon, 21 Dec 2015 04:05:29 +0000 (22:05 -0600)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Mon, 21 Dec 2015 17:58:32 +0000 (11:58 -0600)
doc/news/changes.h
include/deal.II/base/array_view.h [new file with mode: 0644]

index 8518094f0600c2714c666413a03352069105f933..bb3d5772819144996c2df44759fbca0a7ec780ea 100644 (file)
@@ -513,6 +513,19 @@ inconvenience this causes.
 
 
 <ol>
+  <li> New: There is now a new class ArrayView that presents a chunk of
+  memory as if it was an array of fixed size. This is eventually going
+  to replace the VectorSlice class which suffers from the defect that
+  its template argument does not encode the type of objects it points
+  to, but instead the type of the underlying container; consequently,
+  where the VectorSlice class is used as a function argument, it
+  automatically ties the type of object the function can be called
+  with (i.e., the underlying container) even if the called function
+  has no actual use for this kind of information.
+  <br>
+  (Wolfgang Bangerth, 2015/12/20)
+  </li>
+
   <li> Fixed: The implementation of ShiftedMatrixGeneralized contained several
   errors that prevented it from being compiled. These have now been fixed.
   <br>
diff --git a/include/deal.II/base/array_view.h b/include/deal.II/base/array_view.h
new file mode 100644 (file)
index 0000000..444640d
--- /dev/null
@@ -0,0 +1,314 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2004 - 2015 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii__array_view_h
+#define dealii__array_view_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * A class that represents a window of memory locations of type
+ * @p ElementType and presents it as if it was an array that
+ * can be accessed via an <code>operator[]</code>. In essence,
+ * this class is nothing more than just a pointer to the first
+ * location and an integer that represents the length of the array
+ * in elements. The memory remains owned by whoever allocated it,
+ * as this class does not take over ownership.
+ *
+ * The advantage of using this class is that you don't have to pass
+ * around pairs of pointers and that <code>operator[]</code> checks
+ * for the validity of the index with which you subscript this
+ * array view.
+ *
+ * This class can handle views to both non-constant and constant memory
+ * locations. If you want to represent a view of a constant array,
+ * then the template argument type of this class needs to be
+ * @p const as well. The following code snippet gives an example:
+ * @code
+ *   std::vector<int>       array       = get_data();  // a writable array
+ *
+ *   ArrayView<int> view (&array[5], 5);               // a view of elements 5..9 (inclusive)
+ *   view[2] = 42;                                     // array[7] is set to 42
+ *
+ *   ArrayView<const int> const_view (&array[5], 5);   // same view, but read-only
+ *   int element_7 = const_view[2];                    // returns 42
+ *   const_view[2] = 42;                               // error, can't write into this view
+ * @endcode
+ * In either case, accessing an element of a view does not change
+ * the ArrayView object itself, and consequently ArrayView::operator[]
+ * is a @p const function. This corresponds to the notion that a view
+ * simply represents a, well, "view" of memory that is owned by
+ * someone else. Thus, accessing elements of the view changes the
+ * memory managed by some other object, but not the view itself, allowing
+ * us to make ArrayView::operator[] a @p const member function. This is
+ * in contrast to, say, std::vector, which manages the memory it points
+ * to and changing an element of the std::vector therefore changes the
+ * std::vector object itself -- consequently, the std::vector::operator[]
+ * is non-@p const.
+ *
+ * @ingroup data
+ * @author Wolfgang Bangerth, 2015
+ */
+template <typename ElementType>
+class ArrayView
+{
+public:
+  /**
+   * A typedef that denotes the "value_type" of this container-like
+   * class, i.e., the type of the element it "stores" or points to.
+   */
+  typedef ElementType value_type;
+
+  /**
+   * Constructor.
+   *
+   * @param[in] starting_element A pointer to the first element of the array
+   *   this object should represent.
+   * @param[in] n_elements The length (in elements) of the chunk of memory
+   *   this object should represent.
+   *
+   * @note The object that is constructed from these arguments has no knowledge
+   *   how large the object into which it points really is. As a consequence,
+   *   whenever you call ArrayView::operator[], the array view can check that
+   *   the given index is within the range of the view, but it can't check
+   *   that the view is indeed a subset of the valid range of elements of
+   *   the underlying object that allocated that range. In other words, you
+   *   need to ensure that the range of the view specified by the two arguments
+   *   to this constructor is in fact a subset of the elements of the array
+   *   into which it points. The appropriate way to do this is to use the
+   *   make_array_view() functions.
+   */
+  ArrayView (value_type       *starting_element,
+             const std::size_t n_elements);
+
+  /**
+   * Copy constructor from array views that point to non-@p const elements. If
+   * the current object will point to non-@p const elements, then this is a
+   * straight forward copy constructor. On the other hand, if the current type's
+   * @p ElementType template argument is a @p const qualified type, then the
+   * current constructor is a conversion constructor that converts a
+   * non-@p const view to a @p const view, akin to converting a non-@p const
+   * pointer to a @p const pointer.
+   */
+  ArrayView (const ArrayView<typename boost::remove_cv<value_type>::type> &view);
+
+  /**
+   * Return the size (in elements) of the view of memory this object
+   * represents.
+   */
+  std::size_t size() const;
+
+  /**
+   * Return a reference to the $i$th element of the range
+   * represented by the current object.
+   *
+   * This function is marked as @p const because it does not change
+   * the <em>view object</em>. It may however return a reference to
+   * a non-@p const memory location depending on whether the template
+   * type of the class is @p const or not.
+   */
+  value_type &operator[] (const std::size_t i) const;
+
+private:
+  /**
+   * A pointer to the first element of the range of locations in
+   * memory that this object represents.
+   */
+  value_type  *const starting_element;
+
+  /**
+   * The length of the array this object represents.
+   */
+  const std::size_t  n_elements;
+};
+
+
+
+//---------------------------------------------------------------------------
+
+
+template <typename ElementType>
+inline
+ArrayView<ElementType>::ArrayView(value_type        *starting_element,
+                                  const std::size_t  n_elements)
+  :
+  starting_element (starting_element),
+  n_elements(n_elements)
+{}
+
+
+
+template <typename ElementType>
+inline
+ArrayView<ElementType>::ArrayView(const ArrayView<typename boost::remove_cv<value_type>::type> &view)
+  :
+  starting_element (&view[0]),
+  n_elements(view.size())
+{}
+
+
+
+template <typename ElementType>
+inline
+std::size_t
+ArrayView<ElementType>::size() const
+{
+  return n_elements;
+}
+
+
+template <typename ElementType>
+inline
+typename ArrayView<ElementType>::value_type &
+ArrayView<ElementType>::operator[](const std::size_t i) const
+{
+  Assert (i<n_elements, ExcIndexRange(i, 0, n_elements));
+
+  return *(starting_element + i);
+}
+
+
+/**
+ * Create a view to an entire std::vector object. This is equivalent
+ * to initializing an ArrayView object with a pointer to the first
+ * element and the size of the given argument.
+ *
+ * This function is used for non-@p const references to objects of vector type.
+ * Such objects contain elements that can be written. Consequently, the return
+ * type of this function is a view to a set of writable objects.
+ *
+ * @param[in] vector The vector for which we want to have an array
+ *   view object. The array view corresponds to the <em>entire</em>
+ *   vector.
+ *
+ * @relates ArrayView
+ */
+template <typename ElementType>
+inline
+ArrayView<ElementType>
+make_array_view (std::vector<ElementType> &vector)
+{
+  return ArrayView<ElementType> (&vector[0], vector.size());
+}
+
+
+
+/**
+ * Create a view to an entire std::vector object. This is equivalent
+ * to initializing an ArrayView object with a pointer to the first
+ * element and the size of the given argument.
+ *
+ * This function is used for @p const references to objects of vector type
+ * because they contain immutable elements. Consequently, the return type
+ * of this function is a view to a set of @p const objects.
+ *
+ * @param[in] vector The vector for which we want to have an array
+ *   view object. The array view corresponds to the <em>entire</em>
+ *   vector.
+ *
+ * @relates ArrayView
+ */
+template <typename ElementType>
+inline
+ArrayView<const ElementType>
+make_array_view (const std::vector<ElementType> &vector)
+{
+  return ArrayView<const ElementType> (&vector[0], vector.size());
+}
+
+
+
+/**
+ * Create a view to a part of a std::vector object. This is equivalent
+ * to initializing the ArrayView object with a pointer to the
+ * @p starting_index-th element and the @p size_of_view as the length of the view.
+ *
+ * This function is used for non-@p const references to objects of vector type.
+ * Such objects contain elements that can be written. Consequently, the return
+ * type of this function is a view to a set of writable objects.
+ *
+ * @param[in] vector The vector for which we want to have an array
+ *   view object.
+ * @param[in] starting_index The index of the first element of the
+ *   vector that will be part of this view.
+ * @param[in] size_of_view
+ *
+ * @pre <code>starting_index + size_of_view <= vector.size()
+ *
+ * @relates ArrayView
+ */
+template <typename ElementType>
+inline
+ArrayView<ElementType>
+make_array_view (std::vector<ElementType> &vector,
+                 const std::size_t         starting_index,
+                 const std::size_t         size_of_view)
+{
+  Assert (starting_index + size_of_view <= vector.size(),
+          ExcMessage ("The starting index and size of the view you want to "
+                      "create would lead to a view that extends beyond the end "
+                      "of the given vector."));
+  return ArrayView<ElementType> (&vector[starting_index], size_of_view);
+}
+
+
+
+/**
+ * Create a view to a part of a std::vector object. This is equivalent
+ * to initializing the ArrayView object with a pointer to the
+ * @p starting_index-th element and the @p size_of_view as the length of the view.
+ *
+ * This function is used for @p const references to objects of vector type
+ * because they contain immutable elements. Consequently, the return type
+ * of this function is a view to a set of @p const objects.
+ *
+ * @param[in] vector The vector for which we want to have an array
+ *   view object.
+ * @param[in] starting_index The index of the first element of the
+ *   vector that will be part of this view.
+ * @param[in] size_of_view
+ *
+ * @pre <code>starting_index + size_of_view <= vector.size()
+ *
+ * @relates ArrayView
+ */
+template <typename ElementType>
+inline
+ArrayView<const ElementType>
+make_array_view (const std::vector<ElementType> &vector,
+                 const std::size_t         starting_index,
+                 const std::size_t         size_of_view)
+{
+  Assert (starting_index + size_of_view <= vector.size(),
+          ExcMessage ("The starting index and size of the view you want to "
+                      "create would lead to a view that extends beyond the end "
+                      "of the given vector."));
+  return ArrayView<const ElementType> (&vector[starting_index], size_of_view);
+}
+
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.