CppAD: A C++ Algorithmic Differentiation Package 20110419
vec_ad.hpp
Go to the documentation of this file.
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