CppAD: A C++ Algorithmic Differentiation Package  20130102
vector.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_VECTOR_INCLUDED
00003 # define CPPAD_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 /*
00017 $begin CppAD_vector$$
00018 $spell
00019      thread_alloc
00020      cppad.hpp
00021      Bool
00022      resize
00023      cout
00024      endl
00025      std
00026      Cpp
00027      const
00028      vec
00029      ostream
00030      elem
00031 $$
00032 
00033 $index vector, CppAD template class$$
00034 $index class, template CppAD vector$$
00035 $index template, CppAD vector class$$
00036 
00037 $section The CppAD::vector Template Class$$
00038 
00039 $head Syntax$$
00040 $code # include <cppad/vector.hpp>$$
00041 
00042 $head Description$$
00043 The include file $code cppad/vector.hpp$$ defines the
00044 vector template class $code CppAD::vector$$.
00045 This is a $cref SimpleVector$$ template class and in addition
00046 it has the features listed below:
00047 
00048 $head Include$$
00049 The file $code cppad/vector.hpp$$ is included by $code cppad/cppad.hpp$$
00050 but it can also be included separately with out the rest of the 
00051 CppAD include files.
00052 
00053 $head capacity$$
00054 If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$,
00055 and $icode cap$$ is a $code size_t$$ object,
00056 $codei%
00057      %cap% = %x%.capacity()
00058 %$$
00059 set $icode cap$$ to the number of $icode Scalar$$ objects that
00060 could fit in the memory currently allocated for $icode x$$.
00061 Note that
00062 $codei%
00063      %x%.size() <= %x%.capacity()
00064 %$$
00065 
00066 $head Assignment$$
00067 $index assignment, CppAD vector$$
00068 If $icode x$$ and $icode y$$ are 
00069 $codei%CppAD::vector<%Scalar%>%$$ objects,
00070 $codei%
00071      %y% = %x%
00072 %$$
00073 has all the properties listed for a
00074 $cref/simple vector assignment/SimpleVector/Assignment/$$
00075 plus the following:
00076 
00077 $subhead Check Size$$
00078 The $code CppAD::vector$$ template class will check that
00079 the size of $icode x$$ is either zero or the size of $icode y$$
00080 before doing the assignment.
00081 If this is not the case, $code CppAD::vector$$ will use
00082 $cref ErrorHandler$$
00083 to generate an appropriate error report.
00084 Allowing for assignment to a vector with size zero makes the following
00085 code work:
00086 $codei%
00087      CppAD::vector<%Scalar%> %y%;
00088      %y% = %x%;
00089 %$$
00090 
00091 $subhead Return Reference$$
00092 A reference to the vector $icode y$$ is returned.
00093 An example use of this reference is in multiple assignments of the form
00094 $codei%
00095      %z% = %y% = %x%
00096 %$$
00097 
00098 $head Element Access$$
00099 $index [], CppAD vector$$
00100 $index vector, [] CppAD$$
00101 If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object
00102 and $code i$$ has type $code size_t$$,
00103 $codei%
00104      %x%[%i%]
00105 %$$
00106 has all the properties listed for a
00107 $cref/simple vector element access/SimpleVector/Element Access/$$
00108 plus the following:
00109 $pre
00110 
00111 $$
00112 The object $icode%x%[%i%]%$$ has type $icode Scalar$$
00113 (is not possibly a different type that can be converted to $icode Scalar$$).
00114 $pre
00115 
00116 $$
00117 If $icode i$$ is not less than the size of the $icode x$$,
00118 $code CppAD::vector$$ will use
00119 $cref ErrorHandler$$
00120 to generate an appropriate error report.
00121 
00122 $head push_back$$
00123 $index push_back, CppAD vector$$
00124 $index vector, CppAD push_back$$
00125 If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object
00126 with size equal to $icode n$$ and
00127 $icode s$$ has type $icode Scalar$$,
00128 $codei%
00129      %x%.push_back(%s%)
00130 %$$
00131 extends the vector $icode x$$ so that its new size is $icode n$$ plus one
00132 and $icode%x%[%n%]%$$ is equal to $icode s$$
00133 (equal in the sense of the $icode Scalar$$ assignment operator).
00134 
00135 
00136 $head push_vector$$
00137 $index push_vector, CppAD$$
00138 $index vector, CppAD push$$
00139 If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object
00140 with size equal to $icode n$$ and
00141 $icode v$$ is a $cref/simple vector/SimpleVector/$$
00142 with elements of type $icode Scalar$$ and size $icode m$$,
00143 $codei%
00144      %x%.push_vector(%v%)
00145 %$$
00146 extends the vector $icode x$$ so that its new size is $icode%n%+%m%$$
00147 and $icode%x%[%n% + %i%]%$$ is equal to $icode%v%[%i%]%$$
00148 for $icode%i = 1 , ... , m-1%$$
00149 (equal in the sense of the $icode Scalar$$ assignment operator).
00150 
00151 $head Output$$
00152 If $icode x$$ is a $codei%CppAD::vector<%Scalar%>%$$ object
00153 and $icode os$$ is an $code std::ostream$$,
00154 and the operation
00155 $codei%
00156      %os% << %x%
00157 %$$
00158 will output the vector $icode x$$ to the standard
00159 output stream $icode os$$.
00160 The elements of $icode x$$ are enclosed at the beginning by a
00161 $code {$$ character,
00162 they are separated by $code ,$$ characters,
00163 and they are enclosed at the end by $code }$$ character.
00164 It is assumed by this operation that if $icode e$$
00165 is an object with type $icode Scalar$$,
00166 $codei%
00167      %os% << %e%
00168 %$$
00169 will output the value $icode e$$ to the standard
00170 output stream $icode os$$.
00171 
00172 $head resize$$
00173 The call $icode%x%.resize(%n%)%$$ set the size of $icode x$$ equal to 
00174 $icode n$$. 
00175 If $icode%n% <= %x%.capacity()%$$, 
00176 no memory is freed or allocated and the capacity of $icode x$$ does not change.
00177 
00178 $head clear$$
00179 All memory allocated for the vector is freed
00180 and both its size and capacity are set to zero.
00181 The can be useful when using very large vectors
00182 and when checking for memory leaks (and there are global vectors)
00183 see the $cref/memory/CppAD_vector/Memory and Parallel Mode/$$ discussion.
00184 
00185 $head vectorBool$$
00186 $index vectorBool$$
00187 The file $code <cppad/vector.hpp>$$ also defines the class
00188 $code CppAD::vectorBool$$.
00189 This has the same specifications as $code CppAD::vector<bool>$$ 
00190 with the following exceptions
00191 
00192 $list number$$
00193 The class $code vectorBool$$ conserves on memory
00194 (on the other hand, $code CppAD::vector<bool>$$ is expected to be faster
00195 than $code vectorBool$$).
00196 
00197 $lnext
00198 The $code CppAD::vectorBool$$ output operator
00199 prints each boolean value as 
00200 a $code 0$$ for false,
00201 a $code 1$$ for true, 
00202 and does not print any other output; i.e.,
00203 the vector is written a long sequence of zeros and ones with no
00204 surrounding $code {$$, $code }$$ and with no separating commas or spaces. 
00205 
00206 $lnext
00207 If $icode x$$ has type $code vectorBool$$
00208 and $icode i$$ has type $code size_t$$,
00209 the element access value $icode%x%[%i%]%$$ has an unspecified type
00210 (referred to here as $icode elementType$$)
00211 that can be implicitly converted to $code bool$$.
00212 The return value of the assignment operator
00213 $codei%
00214      %x%[%i%] = %y%
00215 %$$
00216 also has type $icode elementType$$. Thus, if $icode z$$
00217 has type $code bool$$, the syntax
00218 $codei%
00219      %z% = %x%[%i%] = %y%
00220 %$$
00221 is valid.
00222 $lend
00223 
00224 $head Memory and Parallel Mode$$
00225 $index thread_alloc, vector$$
00226 $index vector, thread_alloc$$
00227 These vectors use the multi-threaded fast memory allocator 
00228 $cref thread_alloc$$:
00229 
00230 $list number$$
00231 The routine $cref/parallel_setup/ta_parallel_setup/$$ must
00232 be called before these vectors can be used 
00233 $cref/in parallel/ta_in_parallel/$$.
00234 $lnext
00235 Using these vectors affects the amount of memory 
00236 $cref/in_use/ta_inuse/$$ and $cref/available/ta_available/$$.
00237 $lnext
00238 Calling $cref/resize/CppAD_vector/resize/$$ with a zero argument,
00239 makes the corresponding memory available (though $code thread_alloc$$)
00240 to the current thread.
00241 $lnext
00242 Available memory
00243 can then be completely freed using $cref/free_available/ta_free_available/$$.
00244 $lend
00245 
00246 $head Example$$
00247 $children%
00248      example/cppad_vector.cpp%
00249      example/vector_bool.cpp
00250 %$$
00251 The files
00252 $cref cppad_vector.cpp$$ and
00253 $cref vector_bool.cpp$$ each
00254 contain an example and test of this template class.
00255 They return true if they succeed and false otherwise.
00256 
00257 $head Exercise$$
00258 $index exercise, CppAD::vector$$
00259 Create and run a program that contains the following code:
00260 $codep
00261      CppAD::vector<double> x(3);
00262      size_t i;
00263      for(i = 0; i < 3; i++)
00264           x[i] = 4. - i;
00265      std::cout << "x = " << x << std::endl;
00266 $$
00267 
00268 $end
00269 
00270 
00271 $end
00272 
00273 ------------------------------------------------------------------------ 
00274 */
00275 
00276 # include <cstddef>
00277 # include <iostream>
00278 # include <limits>
00279 # include <cppad/local/cppad_assert.hpp>
00280 # include <cppad/check_simple_vector.hpp>
00281 # include <cppad/thread_alloc.hpp>
00282 
00283 CPPAD_BEGIN_NAMESPACE
00284 /*!
00285 \defgroup vector_hpp vector.hpp
00286 \{
00287 \file vector.hpp
00288 File used to define CppAD::vector and CppAD::vectorBool
00289 */
00290 
00291 // ---------------------------------------------------------------------------
00292 /*!
00293 The CppAD Simple Vector template class.
00294 */
00295 template <class Type>
00296 class vector {
00297 private:
00298      /// maximum number of Type elements current allocation can hold
00299      size_t capacity_;
00300      /// number of Type elements currently in this vector
00301      size_t length_;
00302      /// pointer to the first type elements 
00303      /// (not defined and should not be used when capacity_ = 0)
00304      Type   * data_;
00305 public:
00306      /// type of the elements in the vector
00307      typedef Type value_type;
00308 
00309      /// default constructor sets capacity_ = length_ = data_ = 0
00310      inline vector(void) 
00311      : capacity_(0), length_(0), data_(0)
00312      { }
00313      /// sizing constructor
00314      inline vector(
00315           /// number of elements in this vector
00316           size_t n
00317      ) : capacity_(0), length_(n), data_(0)
00318      {    if( length_ > 0 )
00319           {    // set capacity and data
00320                data_ = thread_alloc::create_array<Type>(length_, capacity_); 
00321           }
00322      }
00323      /// copy constructor
00324      inline vector(
00325           /// the *this vector will be a copy of \c x
00326           const vector& x
00327      ) : capacity_(0), length_(x.length_), data_(0)
00328      {    if( length_ > 0 )
00329           {    // set capacity and data 
00330                data_ = thread_alloc::create_array<Type>(length_, capacity_); 
00331 
00332                // copy values using assignment operator
00333                size_t i;
00334                for(i = 0; i < length_; i++)
00335                     data_[i] = x.data_[i];
00336           }
00337      }
00338      /// destructor
00339      ~vector(void)
00340      {    if( capacity_ > 0 )
00341                thread_alloc::delete_array(data_); 
00342      }
00343 
00344      /// maximum number of elements current allocation can store
00345      inline size_t capacity(void) const
00346      {    return capacity_; }
00347 
00348      /// number of elements currently in this vector.
00349      inline size_t size(void) const
00350      {    return length_; }
00351 
00352      /// change the number of elements in this vector.
00353      inline void resize(
00354           /// new number of elements for this vector
00355           size_t n
00356      )
00357      {    length_ = n;
00358           // check if we can use current memory
00359           if( capacity_ >= length_ )
00360                return;
00361           // check if there is old memory to be freed
00362           if( capacity_ > 0 )
00363                thread_alloc::delete_array(data_);
00364           // get new memory and set capacity
00365           data_ = thread_alloc::create_array<Type>(length_, capacity_);
00366      }
00367 
00368      /// free memory and set number of elements to zero 
00369      inline void clear(void)
00370      {    length_ = 0;
00371           // check if there is old memory to be freed
00372           if( capacity_ > 0 )
00373                thread_alloc::delete_array(data_);
00374           capacity_ = 0;
00375      }
00376 
00377      /// vector assignment operator
00378      inline vector& operator=(
00379           /// right hand size of the assingment operation
00380           const vector& x
00381      )
00382      {    size_t i;
00383           // If original lenght is zero, then resize
00384           // otherwise a length mismatch is an error.
00385           if( length_ == 0 )
00386                resize( x.length_ );
00387           CPPAD_ASSERT_KNOWN(
00388                length_ == x.length_ ,
00389                "vector: size miss match in assignment operation"
00390           );
00391           for(i = 0; i < length_; i++)
00392                data_[i] = x.data_[i];
00393           return *this;
00394      }
00395      /// non-constant element access; i.e., we can change this element value
00396      Type& operator[](
00397           /// element index, must be less than length
00398           size_t i
00399      )
00400      {    CPPAD_ASSERT_KNOWN(
00401                i < length_,
00402                "vector: index greater than or equal vector size"
00403           );
00404           return data_[i]; 
00405      }
00406      /// constant element access; i.e., we cannot change this element value
00407      const Type& operator[](
00408           /// element index, must be less than length
00409           size_t i
00410      ) const
00411      {    CPPAD_ASSERT_KNOWN(
00412                i < length_,
00413                "vector: index greater than or equal vector size"
00414           );
00415           return data_[i]; 
00416      }
00417      /// add an element to the back of this vector
00418      void push_back(
00419           /// value of the element
00420           const Type& s
00421      )
00422      {    CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
00423           if( length_ + 1 > capacity_ )
00424           {    // store old capacity and data values
00425                size_t old_capacity = capacity_;
00426                Type*  old_data     = data_;
00427                // set new capacity and data values
00428                data_ = thread_alloc::create_array<Type>(length_ + 1, capacity_);
00429                // copy old data values
00430                size_t i;
00431                for(i = 0; i < length_; i++)
00432                     data_[i] = old_data[i];
00433                // free old data
00434                if( old_capacity > 0 )
00435                     thread_alloc::delete_array(old_data);
00436           }
00437           data_[length_++] = s;
00438           CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
00439      }
00440 
00441      /*! add vector to the back of this vector
00442      (we could not use push_back becasue MS V++ 7.1 did not resolve
00443      to non-template member function when scalar is used.)
00444      */
00445      template <class Vector>
00446      void push_vector(
00447           /// value of the vector that we are adding
00448           const Vector& v
00449      )
00450      {    CheckSimpleVector<Type, Vector>();
00451           CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
00452           size_t m = v.size();
00453           size_t i;
00454           if( length_ + m > capacity_ )
00455           {    // store old capacity and data values
00456                size_t old_capacity = capacity_;
00457                Type*  old_data     = data_;
00458                // set new capacity and data values
00459                data_ = thread_alloc::create_array<Type>(length_ + m, capacity_);
00460                // copy old data values
00461                for(i = 0; i < length_; i++)
00462                     data_[i] = old_data[i];
00463                // free old data
00464                if( old_capacity > 0 )
00465                     thread_alloc::delete_array(old_data);
00466           }
00467           for(i = 0; i < m; i++)
00468                data_[length_++] = v[i];
00469           CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
00470      }
00471 };
00472 
00473 /// output a vector
00474 template <class Type>
00475 inline std::ostream& operator << (
00476      /// stream to write the vector to
00477      std::ostream&              os  , 
00478      /// vector that is output
00479      const CppAD::vector<Type>& vec )
00480 {    size_t i = 0;
00481      size_t n = vec.size();
00482 
00483      os << "{ ";
00484      while(i < n)
00485      {    os << vec[i++]; 
00486           if( i < n )
00487                os << ", ";
00488      }
00489      os << " }";
00490      return os;
00491 }
00492 
00493 // ---------------------------------------------------------------------------
00494 /*!
00495 Class that is used to hold a non-constant element of a vector.
00496 */
00497 class vectorBoolElement {
00498      /// the boolean data is packed with sizeof(UnitType) bits per value
00499      typedef size_t UnitType;
00500 private:
00501      /// pointer to the UnitType value holding this eleemnt
00502      UnitType* unit_;
00503      /// mask for the bit corresponding to this element
00504      /// (all zero except for bit that corresponds to this element)
00505      UnitType mask_;
00506 public:
00507      /// constructor from member values
00508      vectorBoolElement(
00509           /// unit for this element
00510           UnitType* unit , 
00511           /// mask for this element
00512           UnitType mask  )
00513      : unit_(unit) , mask_(mask)
00514      { }
00515      /// constuctor from another element
00516      vectorBoolElement(
00517           /// other element
00518           const vectorBoolElement& e )
00519      : unit_(e.unit_) , mask_(e.mask_)
00520      { }
00521      /// conversion to a boolean value
00522      operator bool() const
00523      {    return (*unit_ & mask_) != 0; }
00524      /// assignment of this element to a bool
00525      vectorBoolElement& operator=(
00526           /// right hand side for assignment
00527           bool bit
00528      )
00529      {    if(bit)
00530                *unit_ |= mask_;
00531           else *unit_ &= ~mask_;
00532           return *this;
00533      } 
00534      /// assignment of this element to another element
00535      vectorBoolElement& operator=(const vectorBoolElement& e)
00536      {    if( *(e.unit_) & e.mask_ )
00537                *unit_ |= mask_;
00538           else *unit_ &= ~mask_;
00539           return *this;
00540      } 
00541 };
00542 
00543 class vectorBool {
00544      /// the boolean data is packed with sizeof(UnitType) bits per value
00545      typedef size_t UnitType;
00546 private:
00547      /// number of bits packed into each UnitType value in data_
00548      static const size_t bit_per_unit_ 
00549           = std::numeric_limits<UnitType>::digits;
00550      /// number of UnitType values in data_
00551      size_t    n_unit_;
00552      /// number of bits currently stored in this vector
00553      size_t    length_;
00554      /// pointer to where the bits are stored
00555      UnitType *data_;
00556 
00557      /// minimum number of UnitType values that can store length_ bits
00558      /// (note that this is really a function of length_)
00559      size_t unit_min(void)
00560      {    if( length_ == 0 )
00561                return 0;
00562           return (length_ - 1) / bit_per_unit_ + 1;
00563      }
00564 public:
00565      /// type corresponding to the elements of this vector
00566      /// (note that non-const elements actually use vectorBoolElement)
00567      typedef bool value_type;
00568 
00569      /// default constructor (sets all member data to zero)
00570      inline vectorBool(void) : n_unit_(0), length_(0), data_(0)
00571      { }
00572      /// sizing constructor
00573      inline vectorBool(
00574           /// number of bits in this vector
00575           size_t n
00576      ) : n_unit_(0), length_(n), data_(0)
00577      {    if( length_ > 0 )
00578           {    // set n_unit and data
00579                size_t min_unit = unit_min();
00580                data_ = thread_alloc::create_array<UnitType>(min_unit, n_unit_);
00581           }
00582      }
00583      /// copy constructor
00584      inline vectorBool(
00585           /// the *this vector will be a copy of \c v
00586           const vectorBool& v
00587      ) : n_unit_(0), length_(v.length_), data_(0)
00588      {    if( length_ > 0 )
00589           {    // set n_unit and data
00590                size_t min_unit = unit_min();
00591                data_ = thread_alloc::create_array<UnitType>(min_unit, n_unit_);
00592 
00593                // copy values using UnitType assignment operator
00594                CPPAD_ASSERT_UNKNOWN( min_unit <= v.n_unit_ ); 
00595                size_t i;
00596                for(i = 0; i < min_unit; i++)
00597                     data_[i] = v.data_[i];
00598           }
00599      }
00600      /// destructor
00601      ~vectorBool(void)
00602      {    if( n_unit_ > 0 )
00603                thread_alloc::delete_array(data_);
00604      }
00605 
00606      /// number of elements in this vector
00607      inline size_t size(void) const
00608      {    return length_; }
00609 
00610      /// maximum number of elements current allocation can store
00611      inline size_t capacity(void) const
00612      {    return n_unit_ * bit_per_unit_; }
00613 
00614      /// change number of elements in this vector
00615      inline void resize(
00616           /// new number of elements for this vector
00617           size_t n
00618      )
00619      {    length_ = n;
00620           // check if we can use the current memory
00621           size_t min_unit = unit_min();
00622           if( n_unit_ >= min_unit )
00623                return;
00624           // check if there is old memory to be freed
00625           if( n_unit_ > 0 )
00626                thread_alloc::delete_array(data_);
00627           // get new memory and set n_unit
00628           data_ = thread_alloc::create_array<UnitType>(min_unit, n_unit_);
00629      }
00630 
00631      /// free memory and set number of elements to zero
00632      inline void clear(void)
00633      {    length_ = 0;
00634           // check if there is old memory to be freed
00635           if( n_unit_ > 0 )
00636                thread_alloc::delete_array(data_);
00637           n_unit_ = 0;
00638      }
00639 
00640      /// vector assignment operator
00641      inline vectorBool& operator=(
00642           /// right hand size of the assingment operation
00643           const vectorBool& v
00644      )
00645      {    size_t i;
00646           CPPAD_ASSERT_KNOWN(
00647                length_ == v.length_ ,
00648                "vectorBool: size miss match in assignment operation"
00649           );
00650           size_t min_unit = unit_min();
00651           CPPAD_ASSERT_UNKNOWN( min_unit <= n_unit_ );
00652           CPPAD_ASSERT_UNKNOWN( min_unit <= v.n_unit_ );
00653           for(i = 0; i < min_unit; i++)
00654                data_[i] = v.data_[i];
00655           return *this;
00656      }
00657      /// non-constant element access; i.e., we can change this element value
00658      vectorBoolElement operator[](
00659           /// element index, must be less than length
00660           size_t k
00661      )
00662      {    size_t i, j;
00663           CPPAD_ASSERT_KNOWN(
00664                k < length_,
00665                "vectorBool: index greater than or equal vector size"
00666           );
00667           i    = k / bit_per_unit_;
00668           j    = k - i * bit_per_unit_;
00669           return vectorBoolElement(data_ + i , UnitType(1) << j );
00670      }
00671      /// constant element access; i.e., we cannot change this element value
00672      bool operator[](size_t k) const
00673      {    size_t i, j;
00674           UnitType unit, mask;
00675           CPPAD_ASSERT_KNOWN(
00676                k < length_,
00677                "vectorBool: index greater than or equal vector size"
00678           );
00679           i    = k / bit_per_unit_;
00680           j    = k - i * bit_per_unit_;
00681           unit = data_[i];
00682           mask = UnitType(1) << j;
00683           return (unit & mask) != 0;
00684      }
00685      /// add an element to the back of this vector
00686      void push_back(
00687           /// value of the element
00688           bool bit
00689      )
00690      {    CPPAD_ASSERT_UNKNOWN( unit_min() <= n_unit_ );
00691           size_t i, j;
00692           UnitType mask;
00693           if( length_ + 1 > n_unit_ * bit_per_unit_ )
00694           {    CPPAD_ASSERT_UNKNOWN( unit_min() == n_unit_ );
00695                // store old n_unit and data values
00696                size_t    old_n_unit = n_unit_;
00697                UnitType* old_data   = data_;
00698                // set new n_unit and data values
00699                data_ = thread_alloc::create_array<UnitType>(n_unit_+1, n_unit_);
00700                // copy old data values
00701                for(i = 0; i < old_n_unit; i++)
00702                     data_[i] = old_data[i]; 
00703                // free old data
00704                if( old_n_unit > 0 )
00705                     thread_alloc::delete_array(old_data);
00706           }
00707           i    = length_ / bit_per_unit_;
00708           j    = length_ - i * bit_per_unit_;
00709           mask = UnitType(1) << j;
00710           if( bit )
00711                data_[i] |= mask;
00712           else data_[i] &= ~mask;
00713           length_++;
00714      }
00715      /// add vector to the back of this vector
00716      template <class Vector>
00717      void push_vector(
00718           /// value of the vector that we are adding
00719           const Vector& v
00720      )
00721      {     CheckSimpleVector<bool, Vector>();
00722           size_t min_unit = unit_min();
00723           CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ );
00724           // some temporaries
00725           size_t i, j, k, ell;
00726           UnitType mask;
00727           bool bit;
00728           // store old length
00729           size_t old_length = length_;
00730           // new length and minium number of units;
00731           length_    = length_ + v.size();
00732           min_unit   = unit_min();
00733           if( length_ >= n_unit_ * bit_per_unit_ )
00734           {    // store old n_unit and data value
00735                size_t  old_n_unit = n_unit_;
00736                UnitType* old_data = data_;
00737                // set new n_unit and data values
00738                data_ = thread_alloc::create_array<UnitType>(min_unit, n_unit_);
00739                // copy old data values
00740                for(i = 0; i < old_n_unit; i++)
00741                     data_[i] = old_data[i]; 
00742                // free old data
00743                if( old_n_unit > 0 )
00744                     thread_alloc::delete_array(old_data);
00745           }
00746           ell = old_length;
00747           for(k = 0; k < v.size(); k++)
00748           {
00749                i    = ell / bit_per_unit_;
00750                j    = ell - i * bit_per_unit_;
00751                bit  = v[k];
00752                mask = UnitType(1) << j;
00753                if( bit )
00754                     data_[i] |= mask;
00755                else data_[i] &= ~mask;
00756                ell++;
00757           }
00758           CPPAD_ASSERT_UNKNOWN( length_ == ell );
00759           CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ );
00760      }
00761 };
00762 
00763 /// output a vector
00764 inline std::ostream& operator << (
00765      /// steam to write the vector to
00766      std::ostream&      os  , 
00767      /// vector that is output
00768      const vectorBool&  v   )
00769 {    size_t i = 0;
00770      size_t n = v.size();
00771 
00772      while(i < n)
00773           os << v[i++]; 
00774      return os;
00775 }
00776 
00777 /*! \} */
00778 CPPAD_END_NAMESPACE
00779 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines