CppAD: A C++ Algorithmic Differentiation Package  20130918
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-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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines