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