CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
array_view.hpp
1 #ifndef CPPAD_CG_ARRAY_VIEW_INCLUDED
2 #define CPPAD_CG_ARRAY_VIEW_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2016 Ciengis
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 # include <cstddef>
19 # include <iostream>
20 # include <limits>
21 
22 namespace CppAD {
23 namespace cg {
24 
29 template<class Type>
30 class ArrayView {
31 public:
32  using value_type = Type;
33  using pointer = value_type*;
34  using const_pointer = const value_type*;
35  using reference = value_type&;
36  using const_reference = const Type&;
37  using iterator = value_type*;
38  using const_iterator = const value_type*;
39  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
40  using reverse_iterator = std::reverse_iterator<iterator>;
41  using size_type = size_t;
42  using difference_type = ptrdiff_t;
43 private:
47  pointer _data;
51  size_type _length;
52 public:
56  inline ArrayView() :
57  _data(nullptr),
58  _length(0) {
59  }
60 
67  inline ArrayView(pointer array,
68  size_type n) :
69  _data(array),
70  _length(n) {
71  CPPAD_ASSERT_KNOWN(array != nullptr || n == 0, "ArrayView: null array with a non-zero size");
72  }
73 
81  inline ArrayView(std::vector<value_type>& vector) :
82  _data(vector.data()),
83  _length(vector.size()) {
84  }
85 
94  _data(vector.data()),
95  _length(vector.size()) {
96  }
97 
104  template<std::size_t S>
105  inline ArrayView(std::array<value_type, S>& array) :
106  _data(array.data()),
107  _length(S) {
108  }
109 
116  inline ArrayView(std::valarray<value_type>& array) :
117  _data(array.size() > 0 ? &array[0] : nullptr),
118  _length(array.size()) {
119  }
120 
127  template<class TT = Type>
128  inline ArrayView(const ArrayView<typename std::remove_const<value_type>::type>& array,
129  typename std::enable_if<std::is_const<TT>::value>::type* = 0) :
130  _data(array.data()),
131  _length(array.size()) {
132  }
133 
141  template<class TT = Type>
142  inline ArrayView(const std::vector<typename std::remove_const<value_type>::type>& vector,
143  typename std::enable_if<std::is_const<TT>::value>::type* = 0) :
144  _data(vector.data()),
145  _length(vector.size()) {
146  }
147 
155  template<class TT = Type>
156  inline ArrayView(const CppAD::vector<typename std::remove_const<value_type>::type>& vector,
157  typename std::enable_if<std::is_const<TT>::value>::type* = 0) :
158  _data(vector.data()),
159  _length(vector.size()) {
160  }
161 
168  template<std::size_t S, class TT = Type>
169  inline ArrayView(const std::array<typename std::remove_const<value_type>::type, S>& array,
170  typename std::enable_if<std::is_const<TT>::value>::type* = 0) :
171  _data(array.data()),
172  _length(S) {
173  }
174 
181  template<class TT = Type>
182  inline ArrayView(const std::valarray<typename std::remove_const<value_type>::type>& array,
183  typename std::enable_if<std::is_const<TT>::value>::type* = 0) :
184  _data(array.size() > 0 ? &array[0] : nullptr),
185  _length(array.size()) {
186  }
187 
192  inline ArrayView(const ArrayView& x) = default;
193 
197  virtual ~ArrayView() = default;
198 
202  inline size_t size() const noexcept {
203  return _length;
204  }
205 
209  inline size_type max_size() const noexcept {
210  return _length;
211  }
212 
213  inline bool empty() const noexcept {
214  return size() == 0;
215  }
216 
220  inline pointer data() noexcept {
221  return _data;
222  }
223 
227  inline const_pointer data() const noexcept {
228  return _data;
229  }
230 
231  inline void fill(const value_type& u) {
232  std::fill_n(begin(), size(), u);
233  }
234 
238  inline ArrayView<value_type> head(size_t n) {
239  CPPADCG_ASSERT_KNOWN(n <= size(), "ArrayView::head() size must be equal to or greater than the array size");
240  return ArrayView<value_type> (_data, n);
241  }
242 
246  inline ArrayView<const value_type> head(size_t n) const {
247  CPPADCG_ASSERT_KNOWN(n <= size(), "ArrayView::head() size must be equal to or greater than the array size");
248  return ArrayView<const value_type> (_data, n);
249  }
250 
254  inline ArrayView<value_type> tail(size_t n) {
255  CPPADCG_ASSERT_KNOWN(n <= size(), "ArrayView::tail() size must be equal to or greater than the array size");
256  return ArrayView<value_type> (_data + (size() - n), n);
257  }
258 
262  inline ArrayView<const value_type> tail(size_t n) const {
263  CPPADCG_ASSERT_KNOWN(n <= size(), "ArrayView::tail() size must be equal to or greater than the array size");
264  return ArrayView<const value_type> (_data + (size() - n), n);
265  }
266 
270  inline ArrayView<value_type> segment(size_t start,
271  size_t n) {
272  CPPADCG_ASSERT_KNOWN(start < size(), "ArrayView::segment() start index must be lower than the array size");
273  CPPADCG_ASSERT_KNOWN(start + n <= size(), "ArrayView::segment() the new segment will end after the end of this array");
274  return ArrayView<value_type> (_data + start, n);
275  }
276 
281  size_t n) const {
282  CPPADCG_ASSERT_KNOWN(start < size(), "ArrayView::segment() start index must be lower than the array size");
283  CPPADCG_ASSERT_KNOWN(start + n <= size(), "ArrayView::segment() the new segment will end after the end of this array");
284  return ArrayView<const value_type> (_data + start, n);
285  }
286 
287  inline void swap(ArrayView& other) noexcept {
288  std::swap(other._data, _data);
289  std::swap(other._length, _length);
290  }
291 
292  // Iterators.
293  inline iterator begin() noexcept {
294  return iterator(data());
295  }
296 
297  inline const_iterator begin() const noexcept {
298  return const_iterator(data());
299  }
300 
301  inline iterator end() noexcept {
302  return iterator(data() + size());
303  }
304 
305  inline const_iterator end() const noexcept {
306  return const_iterator(data() + size());
307  }
308 
309  inline reverse_iterator rbegin() noexcept {
310  return reverse_iterator(end());
311  }
312 
313  inline const_reverse_iterator rbegin() const noexcept {
314  return const_reverse_iterator(end());
315  }
316 
317  inline reverse_iterator rend() noexcept {
318  return reverse_iterator(begin());
319  }
320 
321  inline const_reverse_iterator rend() const noexcept {
322  return const_reverse_iterator(begin());
323  }
324 
325  inline const_iterator cbegin() const noexcept {
326  return const_iterator(data());
327  }
328 
329  inline const_iterator cend() const noexcept {
330  return const_iterator(data() + size());
331  }
332 
333  inline const_reverse_iterator crbegin() const noexcept {
334  return const_reverse_iterator(end());
335  }
336 
337  inline const_reverse_iterator crend() const noexcept {
338  return const_reverse_iterator(begin());
339  }
340 
341  // Element access.
342  inline reference operator[](size_type i) {
343  CPPADCG_ASSERT_KNOWN(i < size(), "ArrayView::operator[] index is equal to or greater than the array size");
344  return _data[i];
345  }
346 
347  inline const_reference operator[](size_type i) const {
348  CPPADCG_ASSERT_KNOWN(i < size(), "ArrayView::operator[] index is equal to or greater than the array size");
349  return _data[i];
350  }
351 
352  inline reference at(size_type i) {
353  if (i >= size())
354  throw CGException("ArrayView::at() index ", i, " is equal to or greater than the array size ", size());
355  return _data[i];
356  }
357 
358  inline const_reference at(size_type i) const {
359  if (i >= size())
360  throw CGException("ArrayView::at() index ", i, " is equal to or greater than the array size ", size());
361  return _data[i];
362  }
363 
364  inline reference front() {
365  CPPADCG_ASSERT_KNOWN(!empty(), "ArrayView: cannot call front for an empty array");
366  return *begin();
367  }
368 
369  inline const_reference front() const {
370  CPPADCG_ASSERT_KNOWN(!empty(), "ArrayView: cannot call front for an empty array");
371  return _data[0];
372  }
373 
374  inline reference back() {
375  CPPADCG_ASSERT_KNOWN(!empty(), "ArrayView: cannot call back for an empty array");
376  return *(end() - 1);
377  }
378 
379  inline const_reference back() const {
380  CPPADCG_ASSERT_KNOWN(!empty(), "ArrayView: cannot call back for an empty array");
381  return _data[size() - 1];
382  }
383 
384 public:
385  inline ArrayView& operator=(const ArrayView& x) {
386  if (&x == this)
387  return *this;
388 
389  if (x.size() != size())
390  throw CGException("ArrayView: assigning an array with different size: the left hand side array has the size ", size(),
391  " while the right hand side array has the size ", x.size(), ".");
392 
393  for(size_t i = 0; i < _length; ++i) {
394  _data[i] = x._data[i];
395  }
396 
397  return *this;
398  }
399 
400  template < typename TT = const Type,
401  typename = typename std::enable_if<!std::is_same<Type, TT>::value && std::is_assignable<Type&, TT&>::value>::type >
402  inline ArrayView& operator=(const ArrayView<TT>& x) {
403  if (x.size() != size())
404  throw CGException("ArrayView: assigning an array with different size: the left hand side array has the size ", size(),
405  " while the right hand side array has the size ", x.size(), ".");
406 
407  const auto* dd = x.data();
408  for (size_t i = 0; i < _length; ++i) {
409  _data[i] = dd[i];
410  }
411 
412  return *this;
413  }
414 
415  inline ArrayView& operator=(const std::vector<Type>& x) {
416  if (x.size() != size())
417  throw CGException("ArrayView: assigning an array with different size: the left hand side array has the size ", size(),
418  " while the right hand side array has the size ", x.size(), ".");
419 
420  for(size_t i = 0; i < _length; ++i) {
421  _data[i] = x[i];
422  }
423 
424  return *this;
425  }
426 
427  inline ArrayView& operator=(const CppAD::vector<Type>& x) {
428  if (x.size() != size())
429  throw CGException("ArrayView: assigning an array with different size: the left hand side array has the size ", size(),
430  " while the right hand side array has the size ", x.size(), ".");
431 
432  for(size_t i = 0; i < _length; ++i) {
433  _data[i] = x[i];
434  }
435 
436  return *this;
437  }
438 
439 };
440 
448 template<class Type>
449 inline std::ostream& operator<<(std::ostream& os,
450  const ArrayView<Type>& array) {
451  size_t i = 0;
452  size_t n = array.size();
453 
454  os << "{ ";
455  while (i < n) {
456  os << array[i++];
457  if (i < n)
458  os << ", ";
459  }
460  os << " }";
461  return os;
462 }
463 
464 } // END cg namespace
465 } // END CppAD namespace
466 
467 # endif
size_type max_size() const noexcept
Definition: array_view.hpp:209
ArrayView< value_type > tail(size_t n)
Definition: array_view.hpp:254
pointer data() noexcept
Definition: array_view.hpp:220
ArrayView(pointer array, size_type n)
Definition: array_view.hpp:67
virtual ~ArrayView()=default
ArrayView(const std::array< typename std::remove_const< value_type >::type, S > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
Definition: array_view.hpp:169
ArrayView< const value_type > head(size_t n) const
Definition: array_view.hpp:246
ArrayView(std::vector< value_type > &vector)
Definition: array_view.hpp:81
ArrayView(const CppAD::vector< typename std::remove_const< value_type >::type > &vector, typename std::enable_if< std::is_const< TT >::value >::type *=0)
Definition: array_view.hpp:156
ArrayView(std::array< value_type, S > &array)
Definition: array_view.hpp:105
const_pointer data() const noexcept
Definition: array_view.hpp:227
ArrayView(const std::vector< typename std::remove_const< value_type >::type > &vector, typename std::enable_if< std::is_const< TT >::value >::type *=0)
Definition: array_view.hpp:142
ArrayView< const value_type > segment(size_t start, size_t n) const
Definition: array_view.hpp:280
ArrayView< value_type > segment(size_t start, size_t n)
Definition: array_view.hpp:270
ArrayView(CppAD::vector< value_type > &vector)
Definition: array_view.hpp:93
ArrayView(const ArrayView< typename std::remove_const< value_type >::type > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
Definition: array_view.hpp:128
ArrayView(const std::valarray< typename std::remove_const< value_type >::type > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
Definition: array_view.hpp:182
size_t size() const noexcept
Definition: array_view.hpp:202
ArrayView(std::valarray< value_type > &array)
Definition: array_view.hpp:116
ArrayView< const value_type > tail(size_t n) const
Definition: array_view.hpp:262
ArrayView< value_type > head(size_t n)
Definition: array_view.hpp:238