CppAD: A C++ Algorithmic Differentiation Package  20130918
player.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_PLAYER_INCLUDED
00003 # define CPPAD_PLAYER_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 namespace CppAD { // BEGIN_CPPAD_NAMESPACE
00017 /*!
00018 \file player.hpp
00019 File used to define the player class.
00020 */
00021 
00022 
00023 /*!
00024 Class used to store and play back an operation sequence recording.
00025 
00026 \tparam Base
00027 These were AD< \a Base > operations when recorded. Operations during playback
00028 are done using the type  \a Base .
00029 */
00030 template <class Base>
00031 class player {
00032 
00033 // -------------- Variables that define the recording -----------------------
00034 private:
00035      /// Number of variables in the recording.
00036      size_t    num_var_rec_;
00037 
00038      /// number of vecad load opeations in the reconding
00039      size_t    num_load_op_rec_;
00040 
00041      /// Number of VecAD vectors in the recording
00042      size_t    num_vecad_vec_rec_;
00043 
00044      /// The operators in the recording.
00045      pod_vector<CPPAD_OP_CODE_TYPE> op_rec_;
00046 
00047      /// The VecAD indices in the recording.
00048      pod_vector<addr_t> vecad_ind_rec_;
00049 
00050      /// The operation argument indices in the recording
00051      pod_vector<addr_t> op_arg_rec_;
00052 
00053      /// The parameters in the recording.
00054      /// Note that Base may not be plain old data, so use false in consructor.
00055      pod_vector<Base> par_rec_;
00056 
00057      /// Character strings ('\\0' terminated) in the recording.
00058      pod_vector<char> text_rec_;
00059 
00060 
00061 // --------------- Functions used to create and maniplate a recording -------
00062 public:
00063      /// Default constructor
00064      player(void) : 
00065      num_var_rec_(0)                                      ,
00066      num_load_op_rec_(0)                                      ,
00067      op_rec_( std::numeric_limits<addr_t>::max() )        ,
00068      vecad_ind_rec_( std::numeric_limits<addr_t>::max() ) ,
00069      op_arg_rec_( std::numeric_limits<addr_t>::max() )    ,
00070      par_rec_( std::numeric_limits<addr_t>::max() )       ,
00071      text_rec_( std::numeric_limits<addr_t>::max() )
00072      { }
00073 
00074      /// Destructor
00075      ~player(void)
00076      { }
00077 
00078      // ===============================================================
00079      /*!  
00080      Moving an operation sequence from a recorder to a player
00081  
00082      \param rec
00083      the object that was used to record the operation sequence.  After this 
00084      operation, the state of the recording is no longer defined. For example,
00085      the \c pod_vector member variables in \c this have been swapped with
00086      \c rec .
00087      */
00088      void get(recorder<Base>& rec)
00089      {    size_t i;
00090 
00091           // just set size_t values
00092           num_var_rec_        = rec.num_var_rec_;
00093           num_load_op_rec_    = rec.num_load_op_rec_; 
00094 
00095           // op_rec_
00096           op_rec_.swap(rec.op_rec_);
00097 
00098           // vec_ind_rec_
00099           vecad_ind_rec_.swap(rec.vecad_ind_rec_);
00100 
00101           // op_arg_rec_
00102           op_arg_rec_.swap(rec.op_arg_rec_);
00103 
00104           // par_rec_
00105           par_rec_.swap(rec.par_rec_);
00106 
00107           // text_rec_
00108           text_rec_.swap(rec.text_rec_);
00109 
00110           // set the number of VecAD vectors
00111           num_vecad_vec_rec_ = 0;
00112           for(i = 0; i < vecad_ind_rec_.size(); i += vecad_ind_rec_[i] + 1)
00113                num_vecad_vec_rec_++;
00114 
00115           // vecad_ind_rec_ contains size of each VecAD followed by
00116           // the parameter indices used to iniialize it.
00117           CPPAD_ASSERT_UNKNOWN( i == vecad_ind_rec_.size() );
00118      }
00119      // ===============================================================
00120      /*!  
00121      Copying an operation sequence from one player to another
00122  
00123      \param play
00124      the object that contains the operatoion sequence to copy.
00125      */
00126      void operator=(const player& play)
00127      {    
00128           num_var_rec_        = play.num_var_rec_;
00129           num_load_op_rec_    = play.num_load_op_rec_;
00130           op_rec_             = play.op_rec_;
00131           num_vecad_vec_rec_  = play.num_vecad_vec_rec_;
00132           vecad_ind_rec_      = play.vecad_ind_rec_;
00133           op_arg_rec_         = play.op_arg_rec_;
00134           par_rec_            = play.par_rec_;
00135           text_rec_           = play.text_rec_;
00136      }
00137      // ===============================================================
00138 
00139      /// Erase all information in an operation sequence player.
00140      void Erase(void)
00141      {    
00142           num_var_rec_       = 0;
00143           num_load_op_rec_   = 0;
00144           num_vecad_vec_rec_ = 0;
00145 
00146           op_rec_.erase();
00147           vecad_ind_rec_.erase();
00148           op_arg_rec_.erase();
00149           par_rec_.erase();
00150           text_rec_.erase();
00151      }
00152 
00153 public:
00154      /*! 
00155      \brief 
00156      Old method of fetching an operator from the recording.
00157 
00158      \return 
00159      the i-th operator in the recording.
00160 
00161      \param i
00162      the index of the operator in recording
00163      */
00164      OpCode GetOp (size_t i) const
00165      {    return OpCode(op_rec_[i]); }
00166 
00167      /*! 
00168      \brief 
00169      Fetch a VecAD index from the recording.
00170 
00171      \return 
00172      the i-th VecAD index in the recording.
00173 
00174      \param i
00175      the index of the VecAD index in recording
00176      */
00177      size_t GetVecInd (size_t i) const
00178      {    return vecad_ind_rec_[i]; }
00179 
00180      /*! 
00181      \brief 
00182      Fetch a parameter from the recording.
00183 
00184      \return 
00185      the i-th parameter in the recording.
00186 
00187      \param i
00188      the index of the parameter in recording
00189      */
00190      Base GetPar(size_t i) const
00191      {    return par_rec_[i]; }
00192 
00193      /*! 
00194      \brief 
00195      Fetch entire parameter vector from the recording.
00196 
00197      \return 
00198      the entire parameter vector.
00199 
00200      */
00201      const Base* GetPar(void) const
00202      {    return par_rec_.data(); }
00203 
00204      /*! 
00205      \brief 
00206      Fetch a '\\0' terminated string from the recording.
00207 
00208      \return 
00209      the beginning of the string.
00210 
00211      \param i
00212      the index where the string begins. 
00213      */
00214      const char *GetTxt(size_t i) const
00215      {    CPPAD_ASSERT_UNKNOWN(i < text_rec_.size() );
00216           return text_rec_.data() + i;
00217      }
00218 
00219      /// Fetch number of variables in the recording.
00220      size_t num_var_rec(void) const
00221      {    return num_var_rec_; }
00222 
00223      /// Fetch number of vecad load operations
00224      size_t num_load_op_rec(void) const
00225      {    return num_load_op_rec_; }
00226 
00227      /// Fetch number of operators in the recording.
00228      size_t num_op_rec(void) const
00229      {    return op_rec_.size(); }
00230 
00231      /// Fetch number of VecAD indices in the recording.
00232      size_t num_vec_ind_rec(void) const
00233      {    return vecad_ind_rec_.size(); }
00234 
00235      /// Fetch number of VecAD vectors in the recording
00236      size_t num_vecad_vec_rec(void) const
00237      {    return num_vecad_vec_rec_; }
00238 
00239      /// Fetch number of argument indices in the recording.
00240      size_t num_op_arg_rec(void) const
00241      {    return op_arg_rec_.size(); }
00242 
00243      /// Fetch number of parameters in the recording.
00244      size_t num_par_rec(void) const
00245      {    return par_rec_.size(); }
00246 
00247      /// Fetch number of characters (representing strings) in the recording.
00248      size_t num_text_rec(void) const
00249      {    return text_rec_.size(); }
00250 
00251      /// Fetch a rough measure of amount of memory used to store recording
00252      /// (just lengths, not capacities). 
00253      size_t Memory(void) const
00254      {    return op_rec_.size()        * sizeof(OpCode) 
00255                + op_arg_rec_.size()    * sizeof(addr_t)
00256                + par_rec_.size()       * sizeof(Base)
00257                + text_rec_.size()      * sizeof(char)
00258                + vecad_ind_rec_.size() * sizeof(addr_t)
00259           ;
00260      }
00261 
00262 // ------------- Variables used for new methog of playing back a recording ---
00263 private:
00264      /// Current operator
00265      OpCode    op_;
00266 
00267      /// Index in recording corresponding to current operator
00268      size_t    op_index_;
00269 
00270      /// Current offset of the argument indices in op_arg_rec_ 
00271      const addr_t*   op_arg_;
00272 
00273      /// Index for primary (last) variable corresponding to current operator
00274      size_t    var_index_;
00275 
00276 // ----------- Functions used in new method for palying back a recording ---
00277 public:
00278      /*!
00279      Start a play back of the recording during a forward sweep.
00280 
00281      Use repeated calls to forward_next to play back one operator at a time.
00282 
00283      \param op [out]
00284      The input value of \c op does not matter. Its output value is the
00285      first operator in the recording; i.e., BeginOp.
00286 
00287      \param op_arg [out]
00288      The input value of \c op_arg does not matter. Its output value is the
00289      beginning of the vector of argument indices for the first operation;
00290      i.e., 0
00291 
00292      \param op_index [out]
00293      The input value of \c op_index does not matter. Its output value
00294      is the index of the next first operator in the recording; i.e., 0.
00295 
00296      \param var_index [out]
00297      The input value of \c var_index does not matter. Its output value is the
00298      index of the primary (last) result corresponding to the the first
00299      operator (which must be a BeginOp); i.e., 0.
00300      */
00301      void forward_start(
00302      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00303      {
00304           op        = op_          = OpCode( op_rec_[0] ); 
00305           op_arg    = op_arg_      = op_arg_rec_.data();
00306           op_index  = op_index_    = 0;
00307           var_index = var_index_   = 0;
00308 
00309           CPPAD_ASSERT_UNKNOWN( op_  == BeginOp );
00310           CPPAD_ASSERT_NARG_NRES(op_, 1, 1);
00311 
00312           return;
00313      }
00314 
00315      /*!
00316      Fetch the next operator during a forward sweep.
00317 
00318      Use forward_start to initialize to the first operator; i.e.,
00319      the BeginOp at the beginning of the recording. 
00320      We use the notation forward_routine to denote the set
00321      forward_start, forward_next, forward_csum, forward_cskip.
00322 
00323      \param op [in,out]
00324      The input value of \c op must be its output value from the 
00325      previous call to a forward_routine.
00326      Its output value is the next operator in the recording.
00327      For speed, \c forward_next does not check for the special cases
00328      where  <tt>op == CSumOp</tt> or <tt>op == CSkipOp</tt>. In these cases, 
00329      the other return values from \c forward_next must be corrected by a call 
00330      to \c forward_csum or \c forward_cskip respectively.
00331 
00332      \param op_arg [in,out]
00333      The input value of \c op_arg must be its output value form the
00334      previous call to a forward routine. 
00335      Its output value is the
00336      beginning of the vector of argument indices for this operation.
00337 
00338      \param op_index [in,out]
00339      The input value of \c op_index must be its output value form the
00340      previous call to a forward routine. 
00341      Its output value is the index of the next operator in the recording. 
00342      Thus the ouput value following the previous call to forward_start is one.
00343      In addition,
00344      the output value increases by one with each call to forward_next. 
00345 
00346      \param var_index [in,out]
00347      The input value of \c var_index must be its output value form the
00348      previous call to a forward routine. 
00349      Its output value is the
00350      index of the primary (last) result corresponding to the operator op.
00351      */
00352      void forward_next(
00353      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00354      {    using CppAD::NumRes;
00355           using CppAD::NumArg;
00356           CPPAD_ASSERT_UNKNOWN( op_       == op );
00357           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00358           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00359           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00360 
00361           // index for the next operator 
00362           op_index    = ++op_index_;
00363 
00364           // first argument for next operator 
00365           op_arg      = op_arg_    += NumArg(op_);
00366 
00367           // next operator
00368           op          = op_         = OpCode( op_rec_[ op_index_ ] );
00369 
00370           // index for last result for next operator
00371           var_index   = var_index_ += NumRes(op);
00372           
00373 
00374           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00375           CPPAD_ASSERT_UNKNOWN( 
00376                op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() 
00377           );
00378           CPPAD_ASSERT_UNKNOWN( var_index_  < num_var_rec_ );
00379      }
00380      /*!
00381      Correct \c forward_next return values when <tt>op == CSumOp</tt>.
00382 
00383      \param op [in]
00384      The input value of op must be the return value from the previous
00385      call to \c forward_next and must be \c CSumOp. It is not modified.
00386 
00387      \param op_arg [in,out]
00388      The input value of \c op_arg must be the return value from the 
00389      previous call to \c forward_next. Its output value is the
00390      beginning of the vector of argument indices for the next operation.
00391 
00392      \param op_index [in]
00393      The input value of \c op_index does must be the return value from the
00394      previous call to \c forward_next. Its is not modified.
00395 
00396      \param var_index [in,out]
00397      The input value of \c var_index must be the return value from the
00398      previous call to \c forward_next. It is not modified.
00399      */
00400      void forward_csum(
00401      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00402      {    using CppAD::NumRes;
00403           using CppAD::NumArg;
00404           CPPAD_ASSERT_UNKNOWN( op_       == op );
00405           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00406           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00407           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00408 
00409           CPPAD_ASSERT_UNKNOWN( op == CSumOp );
00410           CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
00411           CPPAD_ASSERT_UNKNOWN(
00412           op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ]
00413           );
00414           /*
00415           The only thing that really needs fixing is op_arg_.
00416           Actual number of arugments for this operator is
00417                op_arg[0] + op_arg[1] + 4.
00418           We must change op_arg_ so that when you add NumArg(CSumOp)
00419           you get first argument for next operator in sequence.
00420           */
00421           op_arg = op_arg_   += op_arg[0] + op_arg[1] + 4;
00422 
00423           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00424           CPPAD_ASSERT_UNKNOWN( 
00425                op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size()
00426           );
00427           CPPAD_ASSERT_UNKNOWN( var_index_  < num_var_rec_ );
00428      }
00429      /*!
00430      Correct \c forward_next return values when <tt>op == CSkipOp</tt>.
00431 
00432      \param op [in]
00433      The input value of op must be the return value from the previous
00434      call to \c forward_next and must be \c CSkipOp. It is not modified.
00435 
00436      \param op_arg [in,out]
00437      The input value of \c op_arg must be the return value from the 
00438      previous call to \c forward_next. Its output value is the
00439      beginning of the vector of argument indices for the next operation.
00440 
00441      \param op_index [in]
00442      The input value of \c op_index does must be the return value from the
00443      previous call to \c forward_next. Its is not modified.
00444 
00445      \param var_index [in,out]
00446      The input value of \c var_index must be the return value from the
00447      previous call to \c forward_next. It is not modified.
00448      */
00449      void forward_cskip(
00450      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00451      {    using CppAD::NumRes;
00452           using CppAD::NumArg;
00453           CPPAD_ASSERT_UNKNOWN( op_       == op );
00454           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00455           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00456           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00457 
00458           CPPAD_ASSERT_UNKNOWN( op == CSkipOp );
00459           CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 );
00460           CPPAD_ASSERT_UNKNOWN(
00461           op_arg[4] + op_arg[5] == op_arg[ 6 + op_arg[4] + op_arg[5] ]
00462           );
00463           /*
00464           The only thing that really needs fixing is op_arg_.
00465           Actual number of arugments for this operator is
00466                7 + op_arg[4] + op_arg[5]
00467           We must change op_arg_ so that when you add NumArg(CSkipOp)
00468           you get first argument for next operator in sequence.
00469           */
00470           op_arg  = op_arg_  += 7 + op_arg[4] + op_arg[5];
00471 
00472           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00473           CPPAD_ASSERT_UNKNOWN( 
00474                op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size()
00475           );
00476           CPPAD_ASSERT_UNKNOWN( var_index_  < num_var_rec_ );
00477      }
00478      /*!
00479      Start a play back of the recording during a reverse sweep.
00480 
00481      Use repeated calls to reverse_next to play back one operator at a time.
00482 
00483      \param op [out]
00484      The input value of \c op does not matter. Its output value is the
00485      last operator in the recording; i.e., EndOp.
00486 
00487      \param op_arg [out]
00488      The input value of \c op_arg does not matter. Its output value is the
00489      beginning of the vector of argument indices for the last operation;
00490      (there are no arguments for the last operation so \a op_arg is invalid).
00491 
00492      \param op_index [out[
00493      The input value of \c op_index does not matter. Its output value
00494      is the index of the last operator in the recording.
00495 
00496      \param var_index [out]
00497      The input value of \c var_index does not matter. Its output value is the
00498      index of the primary (last) result corresponding to the the last
00499      operator (which must be a EndOp).
00500      (there are no results for the last operation so \a var_index is invalid).
00501      */
00502 
00503      void reverse_start(
00504      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00505      {
00506           op_arg      = op_arg_     = op_arg_rec_.data() + op_arg_rec_.size();
00507           op_index    = op_index_   = op_rec_.size() - 1; 
00508           var_index   = var_index_  = num_var_rec_ - 1;
00509           op          = op_         = OpCode( op_rec_[ op_index_ ] );
00510           CPPAD_ASSERT_UNKNOWN( op_ == EndOp );
00511           CPPAD_ASSERT_NARG_NRES(op, 0, 0);
00512           return;
00513      }
00514 
00515      /*!
00516      Fetch the next operator during a reverse sweep.
00517 
00518      Use reverse_start to initialize to reverse play back.
00519      The first call to reverse_next (after reverse_start) will give the 
00520      last operator in the recording.
00521      We use the notation reverse_routine to denote the set
00522      reverse_start, reverse_next, reverse_csum, reverse_cskip.
00523 
00524      \param op [in,out]
00525      The input value of \c op must be its output value from the 
00526      previous call to a reverse_routine.
00527      Its output value is the next operator in the recording (in reverse order).
00528      The last operator sets op equal to EndOp.
00529 
00530      \param op_arg [in,out]
00531      The input value of \c op_arg must be its output value from the 
00532      previous call to a reverse_routine.
00533      Its output value is the
00534      beginning of the vector of argument indices for this operation.
00535      The last operator sets op_arg equal to the beginning of the 
00536      argument indices for the entire recording.
00537      For speed, \c reverse_next does not check for the special cases
00538      <tt>op == CSumOp</tt> or <tt>op == CSkipOp</tt>. In these cases, the other
00539      return values from \c reverse_next must be corrected by a call to 
00540      \c reverse_csum or \c reverse_cskip respectively.
00541 
00542 
00543      \param op_index [in,out]
00544      The input value of \c op_index must be its output value from the 
00545      previous call to a reverse_routine.
00546      Its output value
00547      is the index of this operator in the recording. Thus the output
00548      value following the previous call to reverse_start is equal to 
00549      the number of variables in the recording minus one.
00550      In addition, the output value decreases by one with each call to
00551      reverse_next.
00552      The last operator sets op_index equal to 0.
00553 
00554      \param var_index [in,out]
00555      The input value of \c var_index must be its output value from the 
00556      previous call to a reverse_routine.
00557      Its output value is the
00558      index of the primary (last) result corresponding to the operator op.
00559      The last operator sets var_index equal to 0 (corresponding to BeginOp
00560      at beginning of operation sequence).
00561      */
00562      void reverse_next(
00563      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00564      {    using CppAD::NumRes;
00565           using CppAD::NumArg;
00566           CPPAD_ASSERT_UNKNOWN( op_       == op );
00567           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00568           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00569           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00570 
00571           // index of the last result for the next operator
00572           CPPAD_ASSERT_UNKNOWN( var_index_ >= NumRes(op_) );
00573           var_index   = var_index_ -= NumRes(op_);
00574 
00575           // next operator
00576           CPPAD_ASSERT_UNKNOWN( op_index_  > 0 );
00577           op_index    = --op_index_;                                  // index
00578           op          = op_         = OpCode( op_rec_[ op_index_ ] ); // value
00579 
00580           // first argument for next operator
00581           op_arg      = op_arg_    -= NumArg(op);
00582           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00583           CPPAD_ASSERT_UNKNOWN( 
00584                op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() 
00585           );
00586      }
00587      /*!
00588      Correct \c reverse_next return values when <tt>op == CSumOp</tt>.
00589 
00590      \param op [in]
00591      The input value of \c op must be the return value from the previous
00592      call to \c reverse_next and must be \c CSumOp. It is not modified.
00593 
00594      \param op_arg [in,out]
00595      The input value of \c op_arg must be the return value from the 
00596      previous call to \c reverse_next. Its output value is the
00597      beginning of the vector of argument indices for this operation.
00598 
00599      \param op_index [in]
00600      The input value of \c op_index must be the return value from the
00601      previous call to \c reverse_next. It is not modified.
00602 
00603      \param var_index [in]
00604      The input value of \c var_index must be the return value from the 
00605      previous call to \c reverse_next. It is not modified.
00606      */
00607 
00608      void reverse_csum(
00609      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00610      {    using CppAD::NumRes;
00611           using CppAD::NumArg;
00612           CPPAD_ASSERT_UNKNOWN( op_       == op );
00613           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00614           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00615           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00616 
00617           CPPAD_ASSERT_UNKNOWN( op == CSumOp );
00618           CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
00619           /*
00620           The variables that need fixing are op_arg_ and op_arg. Currently, 
00621           op_arg points first argument for the previous operator.
00622           */
00623           --op_arg;
00624           op_arg      = op_arg_    -= (op_arg[0] + 4);
00625 
00626           CPPAD_ASSERT_UNKNOWN(
00627           op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ]
00628           );
00629           CPPAD_ASSERT_UNKNOWN( op_index_  < op_rec_.size() );
00630           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00631           CPPAD_ASSERT_UNKNOWN( var_index_  < num_var_rec_ );
00632      }
00633      /*!
00634      Correct \c reverse_next return values when <tt>op == CSkipOp</tt>.
00635 
00636 
00637      \param op [int]
00638      The input value of \c op must be the return value from the previous
00639      call to \c reverse_next and must be \c CSkipOp. It is not modified.
00640 
00641      \param op_arg [in,out]
00642      The input value of \c op_arg must be the return value from the 
00643      previous call to \c reverse_next. Its output value is the
00644      beginning of the vector of argument indices for this operation.
00645 
00646      \param op_index [in]
00647      The input value of \c op_index must be the return value from the
00648      previous call to \c reverse_next. It is not modified.
00649 
00650      \param var_index [in]
00651      The input value of \c var_index must be the return value from the 
00652      previous call to \c reverse_next. It is not modified.
00653      */
00654 
00655      void reverse_cskip(
00656      OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index)
00657      {    using CppAD::NumRes;
00658           using CppAD::NumArg;
00659           CPPAD_ASSERT_UNKNOWN( op_       == op );
00660           CPPAD_ASSERT_UNKNOWN( op_arg    == op_arg_ );
00661           CPPAD_ASSERT_UNKNOWN( op_index  == op_index_ );
00662           CPPAD_ASSERT_UNKNOWN( var_index == var_index_ );
00663 
00664           CPPAD_ASSERT_UNKNOWN( op == CSkipOp );
00665           CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 );
00666           /*
00667           The variables that need fixing are op_arg_ and op_arg. Currently, 
00668           op_arg points first arugment for the previous operator.
00669           */
00670           --op_arg;
00671           op_arg      = op_arg_    -= (op_arg[0] + 4);
00672 
00673           CPPAD_ASSERT_UNKNOWN(
00674           op_arg[1] + op_arg[2] == op_arg[ 3 + op_arg[1] + op_arg[2] ]
00675           );
00676           CPPAD_ASSERT_UNKNOWN( op_index_  < op_rec_.size() );
00677           CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ );
00678           CPPAD_ASSERT_UNKNOWN( var_index_  < num_var_rec_ );
00679      }
00680 
00681 };
00682 
00683 } // END_CPPAD_NAMESPACE
00684 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines