CppAD: A C++ Algorithmic Differentiation Package
20130102
|
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