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