CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_VEC_AD_INCLUDED 00003 # define CPPAD_VEC_AD_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Common 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 $begin VecAD$$ 00017 $spell 00018 cppad.hpp 00019 CondExpGt 00020 grep 00021 Ld 00022 vp 00023 Lu 00024 wc 00025 op 00026 Ldp 00027 Ldv 00028 Taylor 00029 VecAD 00030 const 00031 Cpp 00032 $$ 00033 00034 $index VecAD$$ 00035 $index vector, AD index$$ 00036 $index record, AD index$$ 00037 $index tape, AD index$$ 00038 $index index, AD record$$ 00039 00040 $section AD Vectors that Record Index Operations$$ 00041 00042 00043 $head Syntax$$ 00044 $syntax%VecAD<%Base%> %v%(%n%)%$$ 00045 $pre 00046 $$ 00047 $syntax%%v%.size()%$$ 00048 $pre 00049 $$ 00050 $syntax%%b% = %v%[%i%]%$$ 00051 $pre 00052 $$ 00053 $syntax%%r% = %v%[%x%]%$$ 00054 00055 00056 $head Purpose$$ 00057 If either $italic v$$ or $italic x$$ is a 00058 $cref/variable/glossary/Variable/$$, 00059 the indexing operation 00060 $syntax% 00061 %y% = %v%[%x%] 00062 %$$ 00063 is recorded in the corresponding 00064 AD of $italic Base$$ 00065 $xref/glossary/Operation/Sequence/operation sequence/1/$$ and 00066 transferred to the corresponding $xref/ADFun/$$ object $italic f$$. 00067 Such an index can change each time 00068 zero order $xref/Forward//f.Forward/$$ is used; i.e., 00069 $italic f$$ is evaluated with new value for the 00070 $cref/independent variables/glossary/Tape/Independent Variable/$$. 00071 Note that the value of $italic y$$ depends on the value of $italic x$$ 00072 in a discrete fashion and CppAD computes its partial derivative with 00073 respect to $italic x$$ as zero. 00074 00075 $head Alternatives$$ 00076 If only the values in the vector, 00077 and not the indices, 00078 depend on the independent variables, 00079 the class $syntax%%Vector%< AD<%Base%> >%$$ is much more efficient for 00080 storing AD values where $italic Vector$$ is any 00081 $xref/SimpleVector/$$ template class, 00082 If only the indices, 00083 and not the values in the vector, 00084 depend on the independent variables, 00085 The $xref/Discrete/$$ functions are a much more efficient 00086 way to represent these vectors. 00087 00088 $head VecAD<Base>::reference$$ 00089 $index VecAD<Base>::reference$$ 00090 $index reference, VecAD<Base>$$ 00091 The result $italic y$$ has type 00092 $syntax% 00093 VecAD<%Base%>::reference 00094 %$$ 00095 which is very much like the $syntax%AD<%Base%>%$$ type 00096 with some notable exceptions: 00097 00098 $subhead Exceptions$$ 00099 $list number$$ 00100 The object $italic y$$ cannot be used with the 00101 $xref/Value/$$ function to compute the corresponding $italic Base$$ value. 00102 If $italic v$$ is not a $cref/variable/glossary/Variable/$$ 00103 $syntax% 00104 v[%i%] 00105 %$$ 00106 can be used to compute the corresponding $italic Base$$ value. 00107 00108 $lnext 00109 The object $italic y$$ cannot be used 00110 with the $xref/Arithmetic//computed assignments operators/$$ 00111 $code +=$$, 00112 $code -=$$, 00113 $code *=$$, or 00114 $code /=$$. 00115 For example, the following syntax is not valid: 00116 $syntax% 00117 %v%[%x%] += %z%; 00118 %$$ 00119 no matter what the types of $italic z$$. 00120 00121 $lnext 00122 Assignment to $italic y$$ returns a $code void$$. 00123 For example, the following syntax is not valid: 00124 $syntax% 00125 %z% = %v%[%x%] = %u%; 00126 %$$ 00127 no matter what the types of $italic z$$, and $italic u$$. 00128 00129 $lnext 00130 The $xref/CondExp/$$ functions do not accept 00131 $syntax%VecAD<%Base%>::reference%$$ arguments. 00132 For example, the following syntax is not valid: 00133 $syntax% 00134 CondExpGt(%y%, %z%, %u%, %v%) 00135 %$$ 00136 no matter what the types of $italic z$$, $italic u$$, and $italic v$$. 00137 00138 $lnext 00139 The $xref/ParVar//Parameter and Variable/$$ functions cannot be used with 00140 $syntax%VecAD<%Base%>::reference%$$ arguments 00141 (use the entire $syntax%VecAD<%Base%>%$$ vector instead). 00142 00143 $lnext 00144 The vectors passed to $xref/Independent/$$ must have elements 00145 of type $syntax%AD<%Base%>%$$; i.e., $xref/VecAD/$$ vectors 00146 cannot be passed to $code Independent$$. 00147 00148 $lnext 00149 If one uses this type in a 00150 AD of $italic Base$$ 00151 $xref/glossary/Operation/Sequence/operation sequence/1/$$, 00152 $xref/glossary/Sparsity Pattern/sparsity pattern/$$ calculations 00153 ($xref/Sparse/$$) 00154 are less efficient because the dependence of different 00155 elements of the vector cannot be separated. 00156 00157 $lend 00158 00159 $head Constructor$$ 00160 00161 $subhead v$$ 00162 The syntax 00163 $syntax% 00164 VecAD<%Base%> %v%(%n%) 00165 %$$ 00166 creates an $code VecAD$$ object $italic v$$ with 00167 $italic n$$ elements. 00168 The initial value of the elements of $italic v$$ is unspecified. 00169 00170 $head n$$ 00171 The argument $italic n$$ has prototype 00172 $syntax% 00173 size_t %n% 00174 %$$ 00175 00176 $head size$$ 00177 The syntax 00178 $syntax% 00179 %v%.size() 00180 %$$ 00181 returns the number of elements in the vector $italic v$$; 00182 i.e., the value of $italic n$$ when it was constructed. 00183 00184 $head size_t Indexing$$ 00185 We refer to the syntax 00186 $syntax% 00187 %b% = %v%[%i%] 00188 %$$ 00189 as $code size_t$$ indexing of a $code VecAD$$ object. 00190 This indexing is only valid if the vector $italic v$$ is a 00191 $cref/parameter/ParVar/$$; i.e., 00192 it does not depend on the independent variables. 00193 00194 $subhead i$$ 00195 The operand $italic i$$ has prototype 00196 $syntax% 00197 size_t %i% 00198 %$$ 00199 It must be greater than or equal zero 00200 and less than $italic n$$; i.e., less than 00201 the number of elements in $italic v$$. 00202 00203 $subhead b$$ 00204 The result $italic b$$ has prototype 00205 $syntax% 00206 %Base% %b% 00207 %$$ 00208 and is a reference to the $th i$$ element in the vector $italic v$$. 00209 It can be used to change the element value; 00210 for example, 00211 $syntax% 00212 %v%[%i%] = %c% 00213 %$$ 00214 is valid where $italic c$$ is a $italic Base$$ object. 00215 The reference $italic b$$ is no longer valid once the 00216 destructor for $italic v$$ is called; for example, 00217 when $italic v$$ falls out of scope. 00218 00219 $head AD Indexing$$ 00220 We refer to the syntax 00221 $syntax% 00222 %r% = %v%[%x%] 00223 %$$ 00224 as AD indexing of a $code VecAD$$ object. 00225 00226 $subhead x$$ 00227 The argument $italic x$$ has prototype 00228 $syntax% 00229 const AD<%Base%> &%x% 00230 %$$ 00231 The value of $italic x$$ must be greater than or equal zero 00232 and less than $italic n$$; i.e., less than 00233 the number of elements in $italic v$$. 00234 00235 $subhead r$$ 00236 The result $italic y$$ has prototype 00237 $syntax% 00238 VecAD<%Base%>::reference %r% 00239 %$$ 00240 The object $italic r$$ has an AD type and its 00241 operations are recorded as part of the same 00242 AD of $italic Base$$ 00243 $xref/glossary/Operation/Sequence/operation sequence/1/$$ as 00244 for $syntax%AD<%Base%>%$$ objects. 00245 It acts as a reference to the 00246 element with index $latex {\rm floor} (x)$$ in the vector $italic v$$ 00247 ($latex {\rm floor} (x)$$ is 00248 the greatest integer less than or equal $italic x$$). 00249 Because it is a reference, it can be used to change the element value; 00250 for example, 00251 $syntax% 00252 %v%[%x%] = %z% 00253 %$$ 00254 is valid where $italic z$$ is an 00255 $syntax%VecAD<%Base%>::reference%$$ object. 00256 As a reference, $italic r$$ is no longer valid once the 00257 destructor for $italic v$$ is called; for example, 00258 when $italic v$$ falls out of scope. 00259 00260 $head Example$$ 00261 $children% 00262 example/vec_ad.cpp 00263 %$$ 00264 The file 00265 $xref/vec_ad.cpp/$$ 00266 contains an example and test using $code VecAD$$ vectors. 00267 It returns true if it succeeds and false otherwise. 00268 00269 00270 $head Speed and Memory$$ 00271 The $xref/VecAD/$$ vector type is inefficient because every 00272 time an element of a vector is accessed, a new CppAD 00273 $xref/glossary/Variable/variable/$$ is created on the tape 00274 using either the $code Ldp$$ or $code Ldv$$ operation 00275 (unless all of the elements of the vector are 00276 $xref/glossary/Parameter/parameters/$$). 00277 The effect of this can be seen by executing the following steps: 00278 00279 $list number$$ 00280 In the file $code cppad/local/forward_sweep.h$$, 00281 change the definition of $code CPPAD_FORWARD_SWEEP_TRACE$$ to 00282 $codep 00283 # define CPPAD_FORWARD_SWEEP_TRACE 1 00284 $$ 00285 $lnext 00286 In the $code Example$$ directory, execute the command 00287 $codep 00288 ./OneTest LuVecADOk "lu_vec_ad.cpp -DNDEBUG" > LuVecADOk.log 00289 $$ 00290 This will write a trace of all the forward tape operations, 00291 for the test case $xref/LuVecADOk.cpp/$$, 00292 to the file $code LuVecADOk.log$$. 00293 $lnext 00294 In the $code Example$$ directory execute the commands 00295 $codep 00296 grep "op=" LuVecADOk.log | wc -l 00297 grep "op=Ld[vp]" LuVecADOk.log | wc -l 00298 grep "op=St[vp][vp]" LuVecADOk.log | wc -l 00299 $$ 00300 The first command counts the number of operators in the tracing, 00301 the second counts the number of VecAD load operations, 00302 and the third counts the number of VecAD store operations. 00303 (For CppAD version 05-11-20 these counts were 956, 348, and 118 00304 respectively.) 00305 $lend 00306 00307 $end 00308 ------------------------------------------------------------------------ 00309 */ 00310 00311 # define CPPAD_VEC_AD_COMPUTED_ASSIGNMENT(op, name) \ 00312 VecAD_reference& operator op (const VecAD_reference<Base> &right) \ 00313 { CPPAD_ASSERT_KNOWN( \ 00314 0, \ 00315 "Cannot use a ADVec element on left side of" name \ 00316 ); \ 00317 return *this; \ 00318 } \ 00319 VecAD_reference& operator op (const AD<Base> &right) \ 00320 { CPPAD_ASSERT_KNOWN( \ 00321 0, \ 00322 "Cannot use a ADVec element on left side of" name \ 00323 ); \ 00324 return *this; \ 00325 } \ 00326 VecAD_reference& operator op (const Base &right) \ 00327 { CPPAD_ASSERT_KNOWN( \ 00328 0, \ 00329 "Cannot use a ADVec element on left side of" name \ 00330 ); \ 00331 return *this; \ 00332 } 00333 00334 00335 // BEGIN CppAD namespace 00336 namespace CppAD { 00337 00338 // Element of VecAD 00339 template <class Base> 00340 class VecAD_reference { 00341 friend bool Parameter<Base> (const VecAD<Base> &vec); 00342 friend bool Variable<Base> (const VecAD<Base> &vec); 00343 friend class VecAD<Base>; 00344 friend class ADTape<Base>; 00345 00346 private: 00347 VecAD<Base> *vec_; // pointer to entire vector 00348 mutable AD<Base> x_; // index for this element 00349 public: 00350 VecAD_reference(VecAD<Base> *v, const AD<Base> &x) 00351 : vec_( v ) , x_(x) 00352 { } 00353 00354 // assignment operators 00355 inline void operator = (const VecAD_reference<Base> &right); 00356 void operator = (const AD<Base> &right); 00357 void operator = (const Base &right); 00358 void operator = (int right); 00359 00360 // computed assignments 00361 CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( += , " += " ) 00362 CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( -= , " -= " ) 00363 CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( *= , " *= " ) 00364 CPPAD_VEC_AD_COMPUTED_ASSIGNMENT( /= , " /= " ) 00365 00366 00367 // AD<Base> constructor 00368 AD<Base> ADBase(void) const 00369 { AD<Base> result; 00370 00371 size_t i = static_cast<size_t>( Integer(x_) ); 00372 CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); 00373 00374 // AD<Base> value corresponding to this element 00375 result.value_ = *(vec_->data_ + i); 00376 00377 // this address will be recorded in tape and must be 00378 // zero for parameters 00379 CPPAD_ASSERT_UNKNOWN( Parameter(result) ); 00380 result.taddr_ = 0; 00381 00382 // index corresponding to this element 00383 if( Variable(*vec_) ) 00384 { 00385 ADTape<Base> *tape = AD<Base>::tape_ptr(vec_->id_); 00386 CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); 00387 CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); 00388 00389 if( IdenticalPar(x_) ) 00390 { CPPAD_ASSERT_UNKNOWN( NumRes(LdpOp) == 1 ); 00391 CPPAD_ASSERT_UNKNOWN( NumArg(LdpOp) == 3 ); 00392 00393 // put operand addresses in tape 00394 // (value of third arugment does not matter) 00395 tape->Rec_.PutArg( 00396 vec_->offset_, i, 0 00397 ); 00398 // put operator in the tape, x_ is a parameter 00399 result.taddr_ = tape->Rec_.PutOp(LdpOp); 00400 // change result to variable for this load 00401 result.id_ = tape->id_; 00402 } 00403 else 00404 { CPPAD_ASSERT_UNKNOWN( NumRes(LdvOp) == 1 ); 00405 CPPAD_ASSERT_UNKNOWN( NumArg(LdvOp) == 3 ); 00406 00407 if( Parameter(x_) ) 00408 { // kludge that should not be needed 00409 // if x_ instead of i is used for index 00410 // in the tape 00411 x_.id_ = vec_->id_; 00412 x_.taddr_ = tape->RecordParOp( 00413 x_.value_ 00414 ); 00415 } 00416 CPPAD_ASSERT_UNKNOWN( Variable(x_) ); 00417 CPPAD_ASSERT_UNKNOWN( x_.taddr_ > 0 ); 00418 00419 // put operand addresses in tape 00420 // (value of third arugment does not matter) 00421 tape->Rec_.PutArg( 00422 vec_->offset_, x_.taddr_, 0 00423 ); 00424 // put operator in the tape, x_ is a variable 00425 result.taddr_ = tape->Rec_.PutOp(LdvOp); 00426 // change result to variable for this load 00427 result.id_ = tape->id_; 00428 } 00429 } 00430 return result; 00431 } 00432 }; 00433 00434 // VecAD 00435 template <class Base> 00436 class VecAD { 00437 friend bool Parameter<Base> (const VecAD<Base> &vec); 00438 friend bool Variable<Base> (const VecAD<Base> &vec); 00439 friend class ADTape<Base>; 00440 friend class VecAD_reference<Base>; 00441 00442 friend std::ostream& operator << <Base> 00443 (std::ostream &os, const VecAD<Base> &vec_); 00444 private: 00445 // size of this VecAD vector 00446 const size_t length_; 00447 00448 // elements of this vector 00449 Base *data_; 00450 00451 // offset in cummulate vector corresponding to this object 00452 size_t offset_; 00453 00454 // tape id corresponding to the offset 00455 size_t id_; 00456 public: 00457 // declare the user's view of this type here 00458 typedef VecAD_reference<Base> reference; 00459 00460 // default constructor 00461 // initialize id_ same as for default constructor; see default.hpp 00462 VecAD(void) 00463 : length_(0) 00464 , data_(CPPAD_NULL) 00465 , offset_(0) 00466 , id_(CPPAD_MAX_NUM_THREADS) 00467 { CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); } 00468 00469 // constructor 00470 // initialize id_ same as for parameters; see ad_copy.hpp 00471 VecAD(size_t n) 00472 : length_(n) 00473 , offset_(0) 00474 , id_(CPPAD_MAX_NUM_THREADS) 00475 { data_ = CPPAD_NULL; 00476 if( length_ > 0 ) 00477 { size_t i; 00478 Base zero(0); 00479 data_ = CPPAD_TRACK_NEW_VEC(length_, data_); 00480 00481 // Initialize data to zero so all have same value. 00482 // This uses less memory and avoids a valgrind error 00483 // during TapeRec<Base>::PutPar 00484 for(i = 0; i < length_; i++) 00485 data_[i] = zero; 00486 } 00487 CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); 00488 } 00489 00490 // destructor 00491 ~VecAD(void) 00492 { if( data_ != CPPAD_NULL ) 00493 CPPAD_TRACK_DEL_VEC(data_); 00494 } 00495 00496 // size 00497 size_t size(void) 00498 { return length_; } 00499 00500 // not taped element access 00501 Base &operator[](size_t i) 00502 { 00503 CPPAD_ASSERT_KNOWN( 00504 Parameter(*this), 00505 "VecAD: cannot use size_t indexing because this" 00506 " VecAD vector is a variable." 00507 ); 00508 CPPAD_ASSERT_KNOWN( 00509 i < length_, 00510 "VecAD: element index is >= vector length" 00511 ); 00512 00513 return data_[i]; 00514 } 00515 00516 // taped elemement access 00517 VecAD_reference<Base> operator[](const AD<Base> &x) 00518 { 00519 CPPAD_ASSERT_KNOWN( 00520 0 <= Integer(x), 00521 "VecAD: element index is less than zero" 00522 ); 00523 CPPAD_ASSERT_KNOWN( 00524 static_cast<size_t>( Integer(x) ) < length_, 00525 "VecAD: element index is >= vector length" 00526 ); 00527 00528 // if no need to track indexing operation, return now 00529 if( Parameter(*this) & Parameter(x) ) 00530 return VecAD_reference<Base>(this, x); 00531 00532 CPPAD_ASSERT_KNOWN( 00533 Parameter(*this) | Parameter(x) | (id_ == x.id_), 00534 "VecAD: vector and index are variables for" 00535 " different tapes." 00536 ); 00537 00538 if( Parameter(*this) ) 00539 { // must place a copy of vector in tape 00540 offset_ = 00541 AD<Base>::tape_ptr(x.id_)->AddVec(length_, data_); 00542 00543 // advance pointer by one so is always > 0 00544 offset_++; 00545 00546 // tape id corresponding to this offest 00547 id_ = x.id_; 00548 } 00549 00550 return VecAD_reference<Base>(this, x); 00551 } 00552 00553 }; 00554 00555 00556 template <class Base> 00557 void VecAD_reference<Base>::operator=(const AD<Base> &y) 00558 { 00559 if( Parameter(y) ) 00560 { // fold into the Base type assignment 00561 *this = y.value_; 00562 return; 00563 } 00564 CPPAD_ASSERT_UNKNOWN( y.taddr_ > 0 ); 00565 00566 CPPAD_ASSERT_KNOWN( 00567 Parameter(*vec_) | (vec_->id_ == y.id_), 00568 "VecAD assignment: vector and new element value are variables" 00569 "\nfor different tapes." 00570 ); 00571 00572 ADTape<Base> *tape = AD<Base>::tape_ptr(y.id_); 00573 CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); 00574 if( Parameter(*vec_) ) 00575 { // must place a copy of vector in tape 00576 vec_->offset_ = tape->AddVec(vec_->length_, vec_->data_); 00577 00578 // advance offset to be start of vector plus one 00579 (vec_->offset_)++; 00580 00581 // tape id corresponding to this offest 00582 vec_->id_ = y.id_; 00583 } 00584 CPPAD_ASSERT_UNKNOWN( Variable(*vec_) ); 00585 00586 00587 // index in vector for this element 00588 size_t i = static_cast<size_t>( Integer(x_) ); 00589 CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); 00590 00591 // assign value for this element (as an AD<Base> object) 00592 *(vec_->data_ + i) = y.value_; 00593 00594 // record the setting of this array element 00595 CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); 00596 if( Parameter(x_) ) 00597 { CPPAD_ASSERT_UNKNOWN( NumArg(StpvOp) == 3 ); 00598 CPPAD_ASSERT_UNKNOWN( NumRes(StpvOp) == 0 ); 00599 00600 // put operand addresses in tape 00601 tape->Rec_.PutArg(vec_->offset_, i, y.taddr_); 00602 00603 // put operator in the tape, x_ is parameter, y is variable 00604 tape->Rec_.PutOp(StpvOp); 00605 } 00606 else 00607 { CPPAD_ASSERT_UNKNOWN( NumArg(StvvOp) == 3 ); 00608 CPPAD_ASSERT_UNKNOWN( NumRes(StvvOp) == 0 ); 00609 CPPAD_ASSERT_UNKNOWN( x_.taddr_ > 0 ); 00610 00611 // put operand addresses in tape 00612 tape->Rec_.PutArg(vec_->offset_, x_.taddr_, y.taddr_); 00613 00614 // put operator in the tape, x_ is variable, y is variable 00615 tape->Rec_.PutOp(StvvOp); 00616 } 00617 } 00618 00619 template <class Base> 00620 void VecAD_reference<Base>::operator=(const Base &y) 00621 { 00622 size_t i = static_cast<size_t>( Integer(x_) ); 00623 CPPAD_ASSERT_UNKNOWN( i < vec_->length_ ); 00624 00625 // assign value for this element (target is an AD<Base> object) 00626 *(vec_->data_ + i) = y; 00627 00628 // check if this ADVec object is a parameter 00629 if( Parameter(*vec_) ) 00630 return; 00631 00632 ADTape<Base> *tape = AD<Base>::tape_ptr(vec_->id_); 00633 CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); 00634 00635 // put value of the parameter y in the tape 00636 size_t p = tape->Rec_.PutPar(y); 00637 00638 // record the setting of this array element 00639 CPPAD_ASSERT_UNKNOWN( vec_->offset_ > 0 ); 00640 if( Parameter(x_) ) 00641 { CPPAD_ASSERT_UNKNOWN( NumArg(StppOp) == 3 ); 00642 CPPAD_ASSERT_UNKNOWN( NumRes(StppOp) == 0 ); 00643 00644 // put operand addresses in tape 00645 tape->Rec_.PutArg(vec_->offset_, i, p); 00646 00647 // put operator in the tape, x_ is parameter, y is parameter 00648 tape->Rec_.PutOp(StppOp); 00649 } 00650 else 00651 { CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 ); 00652 CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 ); 00653 CPPAD_ASSERT_UNKNOWN( x_.taddr_ > 0 ); 00654 00655 // put operand addresses in tape 00656 tape->Rec_.PutArg(vec_->offset_, x_.taddr_, p); 00657 00658 // put operator in the tape, x_ is variable, y is parameter 00659 tape->Rec_.PutOp(StvpOp); 00660 } 00661 } 00662 00663 // fold this case into AD<Base> case above 00664 template <class Base> 00665 CPPAD_INLINE void VecAD_reference<Base>::operator= 00666 (const VecAD_reference<Base> &y) 00667 { *this = y.ADBase(); } 00668 00669 // fold this case into Base case above 00670 template <class Base> 00671 CPPAD_INLINE void VecAD_reference<Base>::operator=(int y) 00672 { *this = Base(y); } 00673 00674 template <class Base> 00675 CPPAD_INLINE std::ostream& operator << (std::ostream &os, const VecAD<Base> &v) 00676 { 00677 os << "vecAD( length = " << v.length_ 00678 << ", offset = " << v.offset_ << ")"; 00679 return os; 00680 } 00681 00682 00683 } // END CppAD namespace 00684 00685 # undef CPPAD_VEC_AD_COMPUTED_ASSIGNMENT 00686 00687 # endif