CppAD: A C++ Algorithmic Differentiation Package  20130102
pod_vector.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_POD_VECTOR_INCLUDED
00003 # define CPPAD_POD_VECTOR_INCLUDED
00004 
00005 /* --------------------------------------------------------------------------
00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Eclipse Public License Version 1.0.
00011 
00012 A copy of this license is included in the COPYING file of this distribution.
00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00014 -------------------------------------------------------------------------- */
00015 
00016 # include <algorithm>
00017 # include <cppad/thread_alloc.hpp>
00018 # include <cppad/local/cppad_assert.hpp>
00019 # include <cppad/local/op_code.hpp>
00020 
00021 CPPAD_BEGIN_NAMESPACE
00022 /*!
00023 \defgroup pod_vector_hpp pod_vector.hpp
00024 \{
00025 \file pod_vector.hpp
00026 File used to define pod_vector class
00027 */
00028 
00029 /*
00030 A list of which Types pod_vector<Type> consideres to be plain old data
00031 */
00032 /// default value is false
00033 template <class Type> inline bool is_pod(void)           { return false; }   
00034 /// system pod types so far:
00035 template <> inline bool is_pod<bool>(void)               { return true; }
00036 template <> inline bool is_pod<char>(void)               { return true; }
00037 template <> inline bool is_pod<float>(void)              { return true; }
00038 template <> inline bool is_pod<double>(void)             { return true; }
00039 template <> inline bool is_pod<unsigned char>(void)      { return true; }
00040 template <> inline bool is_pod<unsigned short int>(void) { return true; }
00041 template <> inline bool is_pod<unsigned int>(void)       { return true; }
00042 # if ! CPPAD_SIZE_T_SAME_UNSIGNED_INT
00043 template <> inline bool is_pod<size_t>(void)             { return true; }
00044 # endif
00045 /// CppAD pod types so far: 
00046 template <> inline bool is_pod<OpCode>(void)             { return true; }
00047 
00048 // ---------------------------------------------------------------------------
00049 /*!
00050 A vector class with Type element that does not use element constructors
00051 or destructors when Type is Plain Old Data (pod).
00052 */
00053 template <class Type>
00054 class pod_vector {
00055 private:
00056      /// maximum number of elements that should ever be in this vector
00057      size_t max_length_;
00058      /// number of elements currently in this vector
00059      size_t length_;
00060      /// maximum number of Type elements current allocation can hold
00061      size_t capacity_;
00062      /// pointer to the first type elements 
00063      /// (not defined and should not be used when capacity_ = 0)
00064      Type   *data_;
00065      /// do not use the copy constructor
00066      explicit pod_vector(const pod_vector& )
00067      {    CPPAD_ASSERT_UNKNOWN(false); }
00068 public:
00069      /// Constructors set capacity, length, and data to zero.
00070      ///
00071      /// \param max_length
00072      /// value for maximum number of elements in this vector.
00073      inline pod_vector(
00074           size_t max_length = std::numeric_limits<size_t>::max()
00075      ) 
00076      : max_length_(max_length), length_(0), capacity_(0), data_(CPPAD_NULL)
00077      { }
00078      // ----------------------------------------------------------------------
00079      /// Destructor: returns allocated memory to \c thread_alloc; 
00080      /// see \c extend.  If this is not plain old data, 
00081      /// the destructor for each element is called.
00082      ~pod_vector(void)
00083      {    if( capacity_ > 0 )
00084           {    void* v_ptr = reinterpret_cast<void*>( data_ );
00085                if( ! is_pod<Type>() )
00086                {    // call destructor for each element
00087                     size_t i;
00088                     for(i = 0; i < capacity_; i++)
00089                          (data_ + i)->~Type();
00090                }
00091                thread_alloc::return_memory(v_ptr); 
00092           }
00093      }
00094      // ----------------------------------------------------------------------
00095      /// current number of elements in this vector.
00096      inline size_t size(void) const
00097      {    return length_; }
00098      /// current capacity (amount of allocated storage) for this vector.
00099      inline size_t capacity(void) const
00100      {    return capacity_; }
00101      /// current data pointer, no longer valid after any of the following:
00102      /// extend, erase, operator=, and ~pod_vector. 
00103      /// Take extreem care when using this function.
00104      inline Type* data(void)
00105      {    return data_; }
00106      /// const version of \c data pointer
00107      inline const Type* data(void) const
00108      {    return data_; }
00109      // ----------------------------------------------------------------------
00110      /*!
00111      Increase the number of elements the end of this vector. 
00112 
00113      \param n
00114      is the number of elements to add to end of this vector.
00115 
00116      \return
00117      is the number  of elements in the vector before \c extend was extended.
00118 
00119      - If \c Type is plain old data, new elements are not initialized; 
00120      i.e., their constructor is not called. Otherwise, the constructor
00121      is called for each new element.
00122 
00123      - This is the only routine that allocates memory for \c pod_vector.
00124      and it uses thread_alloc for this allocation, hence this determines
00125      which thread corresponds to this vector (when in parallel mode).
00126 
00127      - If the resulting length of the vector would be more than \c max_length_,
00128      and \c NDEBUG is not defined, a CPPAD_ASSERT is generated.
00129      */
00130      inline size_t extend(size_t n)
00131      {    size_t old_length   = length_;
00132           length_            += n;
00133           CPPAD_ASSERT_KNOWN(
00134                length_ <= max_length_ ,
00135                "pod_vector.hpp: attempt to create to large a vector.\n"
00136                "If Type is CPPAD_TYPE_ADDR_TYPE, tape is too long for Type."
00137           );
00138           // check if we can use current memory
00139           if( capacity_ >= length_ )
00140                return old_length;
00141 
00142           // save more old information
00143           size_t old_capacity = capacity_;
00144           Type* old_data      = data_;
00145 
00146           // get new memory and set capacity
00147           size_t length_bytes = length_ * sizeof(Type);
00148           size_t capacity_bytes;
00149           void* v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes);
00150           capacity_   = capacity_bytes / sizeof(Type);
00151           data_       = reinterpret_cast<Type*>(v_ptr);
00152           CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
00153 
00154           size_t i;
00155           if( ! is_pod<Type>() )
00156           {    // call constructor for each new element
00157                for(i = 0; i < capacity_; i++)
00158                     new(data_ + i) Type();
00159           }
00160           
00161           // copy old data to new data
00162           for(i = 0; i < old_length; i++)
00163                data_[i] = old_data[i];
00164 
00165           // return old memory to available pool
00166           if( old_capacity > 0 )
00167           {    v_ptr = reinterpret_cast<void*>( old_data );
00168                if( ! is_pod<Type>() )
00169                {    for(i = 0; i < old_capacity; i++)
00170                          (old_data + i)->~Type();
00171                } 
00172                thread_alloc::return_memory(v_ptr); 
00173           }
00174 
00175           // return value for extend(n) is the old length
00176           return old_length;
00177      }
00178      // ----------------------------------------------------------------------
00179      /// non-constant element access; i.e., we can change this element value
00180      Type& operator[](
00181           /// element index, must be less than length
00182           size_t i
00183      )
00184      {    CPPAD_ASSERT_UNKNOWN( i < length_ );
00185           return data_[i]; 
00186      }
00187      // ----------------------------------------------------------------------
00188      /// constant element access; i.e., we cannot change this element value
00189      const Type& operator[](
00190           /// element index, must be less than length
00191           size_t i
00192      ) const
00193      {    CPPAD_ASSERT_UNKNOWN( i < length_ );
00194           return data_[i]; 
00195      }
00196      // ----------------------------------------------------------------------
00197      /*!
00198      Remove all the elements from this vector but leave the capacity
00199      and data pointer as is.
00200 
00201      */
00202      void erase(void)
00203      {    length_ = 0;
00204           return;
00205      }    
00206      // ----------------------------------------------------------------------
00207      /*!
00208      Remove all the elements from this vector and delete its memory.
00209      */
00210      void free(void)
00211      {    if( capacity_ > 0 )
00212           {    void* v_ptr = reinterpret_cast<void*>( data_ );
00213                if( ! is_pod<Type>() )
00214                {    // call destructor for each element
00215                     size_t i;
00216                     for(i = 0; i < capacity_; i++)
00217                          (data_ + i)->~Type();
00218                }
00219                thread_alloc::return_memory(v_ptr); 
00220           }
00221           data_     = CPPAD_NULL;
00222           capacity_ = 0;
00223           length_   = 0;
00224      }
00225      /// vector assignment operator
00226      /// If the resulting length of the vector would be more than 
00227      /// \c max_length_, and \c NDEBUG is not defined, 
00228      /// a CPPAD_ASSERT is generated.
00229      void operator=(
00230           /// right hand size of the assingment operation
00231           const pod_vector& x
00232      )
00233      {    size_t i;
00234      
00235           if( x.length_ <= capacity_ )
00236           {    // use existing allocation for this vector
00237                length_ = x.length_;
00238                CPPAD_ASSERT_KNOWN(
00239                     length_ <= max_length_ ,
00240                     "pod_vector.hpp: attempt to create to large a vector.\n"
00241                     "If Type is CPPAD_TYPE_ADDR_TYPE, tape long for Type."
00242                );
00243           }
00244           else
00245           {    // free old memory and get new memory of sufficient length
00246                if( capacity_ > 0 )
00247                {    void* v_ptr = reinterpret_cast<void*>( data_ );
00248                     if( ! is_pod<Type>() )
00249                     {    // call destructor for each element
00250                          for(i = 0; i < capacity_; i++)
00251                               (data_ + i)->~Type();
00252                     }
00253                     thread_alloc::return_memory(v_ptr); 
00254                }
00255                length_ = capacity_ = 0;
00256                extend( x.length_ );
00257           }
00258           CPPAD_ASSERT_UNKNOWN( length_   == x.length_ );
00259           for(i = 0; i < length_; i++)
00260           {    data_[i] = x.data_[i]; }
00261      }
00262      /*!
00263      Swap all properties of this vector with another.
00264 
00265      \param other
00266      is the other vector that we are swapping this vector with.
00267      */
00268      void swap(pod_vector& other)
00269      {    std::swap(capacity_, other.capacity_);
00270           std::swap(length_,   other.length_);
00271           std::swap(data_,     other.data_);
00272      }
00273 };
00274 
00275 /*! \} */
00276 CPPAD_END_NAMESPACE
00277 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines