CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
pod_vector.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_POD_VECTOR_HPP
2 # define CPPAD_LOCAL_POD_VECTOR_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 # if CPPAD_CSTDINT_HAS_8_TO_64
16 # include <cstdint>
17 # endif
18 # include <algorithm>
21 # include <cppad/local/is_pod.hpp>
22 
23 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
24 /*!
25 \file pod_vector.hpp
26 File used to define pod_vector class
27 */
28 // ---------------------------------------------------------------------------
29 /*!
30 A vector class with Type element that does not use element constructors
31 or destructors when Type is Plain Old Data (pod).
32 */
33 template <class Type>
34 class pod_vector {
35 private:
36  /// number of elements currently in this vector
37  size_t length_;
38  //
39  /// maximum number of Type elements current allocation can hold
40  size_t capacity_;
41  //
42  /// pointer to the first type elements
43  /// (not defined and should not be used when capacity_ = 0)
44  Type *data_;
45  //
46  /// do not use the copy constructor
47  explicit pod_vector(const pod_vector& )
48  { CPPAD_ASSERT_UNKNOWN(false); }
49 public:
50  /// default constructor sets capacity_ = length_ = data_ = 0
51  pod_vector(void)
52  : length_(0), capacity_(0), data_(CPPAD_NULL)
53  { CPPAD_ASSERT_UNKNOWN( is_pod<size_t>() );
54  }
55  /// sizing constructor
57  /// number of elements in this vector
58  size_t n
59  ) : length_(0), capacity_(0), data_(CPPAD_NULL)
60  { extend(n); }
61  // ----------------------------------------------------------------------
62  /// Destructor: returns allocated memory to \c thread_alloc;
63  /// see \c extend. If this is not plain old data,
64  /// the destructor for each element is called.
66  { if( capacity_ > 0 )
67  { void* v_ptr = reinterpret_cast<void*>( data_ );
68  if( ! is_pod<Type>() )
69  { // call destructor for each element
70  size_t i;
71  for(i = 0; i < capacity_; i++)
72  (data_ + i)->~Type();
73  }
75  }
76  }
77  // ----------------------------------------------------------------------
78  /// current number of elements in this vector.
79  size_t size(void) const
80  { return length_; }
81  //
82  /// current capacity (amount of allocated storage) for this vector.
83  size_t capacity(void) const
84  { return capacity_; }
85  //
86  /// current data pointer is no longer valid after any of the following:
87  /// extend, erase, operator=, and ~pod_vector.
88  /// Take extreem care when using this function.
89  Type* data(void)
90  { return data_; }
91  //
92  /// const version of data pointer (see non-const documentation)
93  const Type* data(void) const
94  { return data_; }
95  // ----------------------------------------------------------------------
96  /*!
97  Increase the number of elements the end of this vector
98  (existing elements are always preserved).
99 
100  \param n
101  is the number of elements to add to end of this vector.
102 
103  \return
104  is the number of elements in the vector before \c extend was extended.
105  This is the index of the first new element added to the vector.
106 
107  - If \c Type is plain old data, new elements are not initialized;
108  i.e., their constructor is not called. Otherwise, the constructor
109  is called for each new element.
110 
111  - This and resize are the only routine that allocate memory for
112  \c pod_vector. They uses thread_alloc for this allocation, hence this
113  determines which thread corresponds to this vector (when in parallel mode).
114  */
115  size_t extend(size_t n)
116  { size_t old_length = length_;
117  length_ += n;
118 
119  // check if we can use current memory
120  if( capacity_ >= length_ )
121  return old_length;
122 
123  // save more old information
124  size_t old_capacity = capacity_;
125  Type* old_data = data_;
126 
127  // get new memory and set capacity
128  size_t length_bytes = length_ * sizeof(Type);
129  size_t capacity_bytes;
130  void* v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes);
131  capacity_ = capacity_bytes / sizeof(Type);
132  data_ = reinterpret_cast<Type*>(v_ptr);
134 
135  size_t i;
136  if( ! is_pod<Type>() )
137  { // call constructor for each new element
138  for(i = 0; i < capacity_; i++)
139  new(data_ + i) Type();
140  }
141 
142  // copy old data to new data
143  for(i = 0; i < old_length; i++)
144  data_[i] = old_data[i];
145 
146  // return old memory to available pool
147  if( old_capacity > 0 )
148  { v_ptr = reinterpret_cast<void*>( old_data );
149  if( ! is_pod<Type>() )
150  { for(i = 0; i < old_capacity; i++)
151  (old_data + i)->~Type();
152  }
154  }
155 
156  // return value for extend(n) is the old length
157  return old_length;
158  }
159  // ----------------------------------------------------------------------
160  /*!
161  resize the vector (existing elements preserved when n <= capacity_).
162 
163  \param n
164  is the new size for this vector.
165 
166  \par
167  if n <= capacity(), no memory is freed or allocated, the capacity
168  is not changed, and existing elements are preserved.
169  If n > capacity(), new memory is allocates and all the
170  data in the vector is lost.
171 
172  - If \c Type is plain old data, new elements are not initialized;
173  i.e., their constructor is not called. Otherwise, the constructor
174  is called for each new element.
175 
176  - This and extend are the only routine that allocate memory for
177  \c pod_vector. They uses thread_alloc for this allocation, hence this
178  determines which thread corresponds to this vector (when in parallel mode).
179  */
180  void resize(size_t n)
181  { length_ = n;
182 
183  // check if we must allocate new memory
184  if( capacity_ < length_ )
185  { void* v_ptr;
186  //
187  // return old memory to available pool
188  if( capacity_ > 0 )
189  { v_ptr = reinterpret_cast<void*>( data_ );
190  if( ! is_pod<Type>() )
191  { // call destructor for each old element
192  for(size_t i = 0; i < capacity_; i++)
193  (data_ + i)->~Type();
194  }
196  }
197  //
198  // get new memory and set capacity
199  size_t length_bytes = length_ * sizeof(Type);
200  size_t capacity_bytes;
201  v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes);
202  capacity_ = capacity_bytes / sizeof(Type);
203  data_ = reinterpret_cast<Type*>(v_ptr);
204  //
206  //
207  if( ! is_pod<Type>() )
208  { // call constructor for each new element
209  for(size_t i = 0; i < capacity_; i++)
210  new(data_ + i) Type();
211  }
212  }
213  }
214  // ----------------------------------------------------------------------
215  /// non-constant element access; i.e., we can change this element value
216  Type& operator[](
217  /// element index, must be less than length
218  size_t i
219  )
220  { CPPAD_ASSERT_UNKNOWN( i < length_ );
221  return data_[i];
222  }
223  // ----------------------------------------------------------------------
224  /// constant element access; i.e., we cannot change this element value
225  const Type& operator[](
226  /// element index, must be less than length
227  size_t i
228  ) const
229  { CPPAD_ASSERT_UNKNOWN( i < length_ );
230  return data_[i];
231  }
232  // ----------------------------------------------------------------------
233  /*!
234  Remove all the elements from this vector but leave the capacity
235  and data pointer as is.
236 
237  */
238  void erase(void)
239  { length_ = 0;
240  return;
241  }
242  // ----------------------------------------------------------------------
243  /*!
244  Remove all the elements from this vector and free its memory.
245  */
246  void clear(void)
247  { if( capacity_ > 0 )
248  { void* v_ptr = reinterpret_cast<void*>( data_ );
249  if( ! is_pod<Type>() )
250  { // call destructor for each element
251  size_t i;
252  for(i = 0; i < capacity_; i++)
253  (data_ + i)->~Type();
254  }
256  }
257  data_ = CPPAD_NULL;
258  capacity_ = 0;
259  length_ = 0;
260  }
261  // -----------------------------------------------------------------------
262  /// vector assignment operator
263  void operator=(
264  /// right hand size of the assingment operation
265  const pod_vector& x
266  )
267  { size_t i;
268 
269  if( x.length_ <= capacity_ )
270  { // use existing allocation for this vector
271  length_ = x.length_;
272  }
273  else
274  { // free old memory and get new memory of sufficient length
275  if( capacity_ > 0 )
276  { void* v_ptr = reinterpret_cast<void*>( data_ );
277  if( ! is_pod<Type>() )
278  { // call destructor for each element
279  for(i = 0; i < capacity_; i++)
280  (data_ + i)->~Type();
281  }
283  }
284  length_ = capacity_ = 0;
285  extend( x.length_ );
286  }
288  for(i = 0; i < length_; i++)
289  { data_[i] = x.data_[i]; }
290  }
291  // -----------------------------------------------------------------------
292  /*!
293  Swap all properties of this vector with another.
294  This is useful when moving a vector that grows after it has reached
295  its final size (without copying every element).
296 
297  \param other
298  is the other vector that we are swapping this vector with.
299  */
300  void swap(pod_vector& other)
301  { std::swap(capacity_, other.capacity_);
302  std::swap(length_, other.length_);
303  std::swap(data_, other.data_);
304  }
305  // ------------------------------------------------------------------------
306  /*!
307  Add an element to theh back of this vector
308 
309  \param e
310  is the element we are adding to the back of the vector.
311  */
312  void push_back(const Type& e)
313  { size_t i = extend(1);
314  data_[i] = e;
315  }
316 };
317 
318 } } // END_CPPAD_LOCAL_NAMESPACE
319 # endif
void resize(size_t n)
resize the vector (existing elements preserved when n &lt;= capacity_).
Definition: pod_vector.hpp:180
void clear(void)
Remove all the elements from this vector and free its memory.
Definition: pod_vector.hpp:246
size_t extend(size_t n)
Increase the number of elements the end of this vector (existing elements are always preserved)...
Definition: pod_vector.hpp:115
void push_back(const Type &e)
Add an element to theh back of this vector.
Definition: pod_vector.hpp:312
static void return_memory(void *v_ptr)
Return memory that was obtained by get_memory.
A vector class with Type element that does not use element constructors or destructors when Type is P...
Definition: pod_vector.hpp:34
Type * data_
pointer to the first type elements (not defined and should not be used when capacity_ = 0) ...
Definition: pod_vector.hpp:44
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
~pod_vector(void)
Destructor: returns allocated memory to thread_alloc; see extend. If this is not plain old data...
Definition: pod_vector.hpp:65
const Type & operator[](size_t i) const
constant element access; i.e., we cannot change this element value
Definition: pod_vector.hpp:225
static void * get_memory(size_t min_bytes, size_t &cap_bytes)
Use thread_alloc to get a specified amount of memory.
void erase(void)
Remove all the elements from this vector but leave the capacity and data pointer as is...
Definition: pod_vector.hpp:238
void operator=(const pod_vector &x)
vector assignment operator
Definition: pod_vector.hpp:263
size_t length_
number of elements currently in this vector
Definition: pod_vector.hpp:37
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
Type * data(void)
current data pointer is no longer valid after any of the following: extend, erase, operator=, and ~pod_vector. Take extreem care when using this function.
Definition: pod_vector.hpp:89
void swap(pod_vector &other)
Swap all properties of this vector with another.
Definition: pod_vector.hpp:300
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
File used to define the CppAD multi-threading allocator class.
const Type * data(void) const
const version of data pointer (see non-const documentation)
Definition: pod_vector.hpp:93
pod_vector(size_t n)
sizing constructor
Definition: pod_vector.hpp:56
pod_vector(const pod_vector &)
do not use the copy constructor
Definition: pod_vector.hpp:47
size_t capacity(void) const
current capacity (amount of allocated storage) for this vector.
Definition: pod_vector.hpp:83
size_t capacity_
maximum number of Type elements current allocation can hold
Definition: pod_vector.hpp:40
pod_vector(void)
default constructor sets capacity_ = length_ = data_ = 0
Definition: pod_vector.hpp:51
Type & operator[](size_t i)
non-constant element access; i.e., we can change this element value
Definition: pod_vector.hpp:216