CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
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
22namespace CppAD {
23namespace cg {
24
29template<class Type>
30class ArrayView {
31public:
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;
43private:
47 pointer _data;
51 size_type _length;
52public:
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
384public:
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
448template<class Type>
449inline 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
ArrayView(const std::vector< typename std::remove_const< value_type >::type > &vector, typename std::enable_if< std::is_const< TT >::value >::type *=0)
ArrayView(const ArrayView< typename std::remove_const< value_type >::type > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
ArrayView(const ArrayView &x)=default
ArrayView(const CppAD::vector< typename std::remove_const< value_type >::type > &vector, typename std::enable_if< std::is_const< TT >::value >::type *=0)
ArrayView< const value_type > tail(size_t n) const
ArrayView< value_type > tail(size_t n)
ArrayView(pointer array, size_type n)
ArrayView(std::valarray< value_type > &array)
ArrayView(std::array< value_type, S > &array)
ArrayView(const std::valarray< typename std::remove_const< value_type >::type > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
size_type max_size() const noexcept
size_t size() const noexcept
const_pointer data() const noexcept
ArrayView< const value_type > segment(size_t start, size_t n) const
ArrayView(CppAD::vector< value_type > &vector)
virtual ~ArrayView()=default
ArrayView< value_type > head(size_t n)
ArrayView< value_type > segment(size_t start, size_t n)
ArrayView(const std::array< typename std::remove_const< value_type >::type, S > &array, typename std::enable_if< std::is_const< TT >::value >::type *=0)
pointer data() noexcept
ArrayView< const value_type > head(size_t n) const
ArrayView(std::vector< value_type > &vector)