CppAD: A C++ Algorithmic Differentiation Package 20110419
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-10 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 CPPAD_BEGIN_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_rec_var_;
00037 
00038         /// Number of operators in the recording. 
00039         size_t    num_rec_op_;
00040 
00041         /// The operators in the recording.
00042         OpCode   *rec_op_;
00043 
00044         /// Number of VecAD indices in the recording. 
00045         size_t    num_rec_vecad_ind_;
00046 
00047         /// Number of VecAD vectors in the recording
00048         size_t    num_rec_vecad_vec_;
00049 
00050         /// The VecAD indices in the recording.
00051         size_t   *rec_vecad_ind_;
00052 
00053         /// Number of operation arguments indices in the recording. 
00054         size_t    num_rec_op_arg_;
00055 
00056         /// The operation argument indices in the recording
00057         size_t   *rec_op_arg_;
00058 
00059         /// Number of parameters in the recording.
00060         size_t    num_rec_par_;
00061 
00062         /// The parameters in the recording.
00063         Base     *rec_par_;
00064 
00065         /// Number of text characters in the recording.
00066         size_t    num_rec_text_;
00067 
00068         /// Character strings ('\\0' terminated) in the recording.
00069         char     *rec_text_;
00070 
00071 
00072 // --------------- Functions used to create and maniplate a recording -------
00073 public:
00074         /// Default constructor
00075         player(void) 
00076         {       
00077                 num_rec_var_       = 0;
00078 
00079                 num_rec_op_        = 0;
00080                 rec_op_            = CPPAD_NULL;
00081 
00082                 num_rec_vecad_ind_ = 0;
00083                 num_rec_vecad_vec_ = 0;
00084                 rec_vecad_ind_     = CPPAD_NULL;
00085 
00086                 num_rec_op_arg_    = 0;
00087                 rec_op_arg_        = CPPAD_NULL;
00088 
00089                 num_rec_par_       = 0;
00090                 rec_par_           = CPPAD_NULL;
00091 
00092                 num_rec_text_      = 0;
00093                 rec_text_          = CPPAD_NULL;
00094 
00095         }
00096 
00097         /// Destructor
00098         ~player(void)
00099         {       if( num_rec_op_ > 0 )
00100                         CPPAD_TRACK_DEL_VEC(rec_op_);
00101                 if( num_rec_vecad_ind_ > 0 )
00102                         CPPAD_TRACK_DEL_VEC(rec_vecad_ind_);
00103                 if( num_rec_op_arg_ > 0 )
00104                         CPPAD_TRACK_DEL_VEC(rec_op_arg_);
00105                 if( num_rec_par_ > 0 )
00106                         CPPAD_TRACK_DEL_VEC(rec_par_);
00107                 if( num_rec_text_ > 0 )
00108                         CPPAD_TRACK_DEL_VEC(rec_text_);
00109         }
00110 
00111         // ===============================================================
00112         // Begin two functions with idential code but different argument types.
00113         /*!  
00114         Moving an operation sequence from a recorder to a player
00115  
00116         \param rec
00117         the object that was used to record the operation sequence.
00118         */
00119         void operator=(const recorder<Base> &rec)
00120         {       size_t i;
00121 
00122                 if( num_rec_op_ > 0 )
00123                         CPPAD_TRACK_DEL_VEC(rec_op_);
00124                 if( num_rec_vecad_ind_ > 0 )
00125                         CPPAD_TRACK_DEL_VEC(rec_vecad_ind_);
00126                 if( num_rec_op_arg_ > 0 )
00127                         CPPAD_TRACK_DEL_VEC(rec_op_arg_);
00128                 if( num_rec_par_ > 0 )
00129                         CPPAD_TRACK_DEL_VEC(rec_par_);
00130                 if( num_rec_text_ > 0 )
00131                         CPPAD_TRACK_DEL_VEC(rec_text_);
00132 
00133                 // Var
00134                 num_rec_var_        = rec.num_rec_var_;
00135 
00136                 // Op
00137                 num_rec_op_         = rec.num_rec_op_;
00138 
00139                 // VecInd
00140                 num_rec_vecad_ind_  = rec.num_rec_vecad_ind_;
00141 
00142                 // Arg
00143                 num_rec_op_arg_     = rec.num_rec_op_arg_;
00144 
00145                 // Par
00146                 num_rec_par_        = rec.num_rec_par_;
00147 
00148                 // Txt
00149                 num_rec_text_       = rec.num_rec_text_;
00150 
00151                 // Allocate the memory
00152                 if( num_rec_op_ == 0 )
00153                         rec_op_ = CPPAD_NULL;
00154                 else    rec_op_ = 
00155                         CPPAD_TRACK_NEW_VEC(num_rec_op_,        rec_op_);
00156                 if( num_rec_vecad_ind_ == 0 )
00157                         rec_vecad_ind_ = CPPAD_NULL;
00158                 else    rec_vecad_ind_ = 
00159                         CPPAD_TRACK_NEW_VEC(num_rec_vecad_ind_, rec_vecad_ind_);
00160                 if( num_rec_op_arg_ == 0 )
00161                         rec_op_arg_ = CPPAD_NULL;
00162                 else    rec_op_arg_ = 
00163                         CPPAD_TRACK_NEW_VEC(num_rec_op_arg_,    rec_op_arg_);
00164                 if( num_rec_par_ == 0 )
00165                         rec_par_ = CPPAD_NULL;
00166                 else    rec_par_ = 
00167                         CPPAD_TRACK_NEW_VEC(num_rec_par_,       rec_par_);
00168                 if( num_rec_text_ == 0 )
00169                         rec_text_ = CPPAD_NULL;
00170                 else    rec_text_ = 
00171                         CPPAD_TRACK_NEW_VEC(num_rec_text_,      rec_text_);
00172 
00173                 // Copy the data
00174                 i = num_rec_op_;
00175                 while(i--)
00176                         rec_op_[i] = rec.rec_op_[i];
00177                 i = num_rec_vecad_ind_;
00178                 while(i--)
00179                         rec_vecad_ind_[i] = rec.rec_vecad_ind_[i];
00180                 i = num_rec_op_arg_;
00181                 while(i--)
00182                         rec_op_arg_[i] = rec.rec_op_arg_[i];
00183                 i = num_rec_par_;
00184                 while(i--)
00185                         rec_par_[i] = rec.rec_par_[i];
00186                 i = num_rec_text_;
00187                 while(i--)
00188                         rec_text_[i] = rec.rec_text_[i];
00189 
00190                 // set the number of VecAD vectors
00191                 num_rec_vecad_vec_ = 0;
00192                 for(i = 0; i < num_rec_vecad_ind_; i += rec_vecad_ind_[i] + 1)
00193                         num_rec_vecad_vec_++;
00194         }
00195 
00196         /*!  
00197         Copying an operation sequence from one player to another
00198  
00199         \param play
00200         the object that contains the operatoion sequence to copy.
00201         */
00202         void operator=(const player& play)
00203         {       size_t i;
00204 
00205                 if( num_rec_op_ > 0 )
00206                         CPPAD_TRACK_DEL_VEC(rec_op_);
00207                 if( num_rec_vecad_ind_ > 0 )
00208                         CPPAD_TRACK_DEL_VEC(rec_vecad_ind_);
00209                 if( num_rec_op_arg_ > 0 )
00210                         CPPAD_TRACK_DEL_VEC(rec_op_arg_);
00211                 if( num_rec_par_ > 0 )
00212                         CPPAD_TRACK_DEL_VEC(rec_par_);
00213                 if( num_rec_text_ > 0 )
00214                         CPPAD_TRACK_DEL_VEC(rec_text_);
00215 
00216                 // Var
00217                 num_rec_var_        = play.num_rec_var_;
00218 
00219                 // Op
00220                 num_rec_op_         = play.num_rec_op_;
00221 
00222                 // VecInd
00223                 num_rec_vecad_ind_  = play.num_rec_vecad_ind_;
00224 
00225                 // Arg
00226                 num_rec_op_arg_     = play.num_rec_op_arg_;
00227 
00228                 // Par
00229                 num_rec_par_        = play.num_rec_par_;
00230 
00231                 // Txt
00232                 num_rec_text_       = play.num_rec_text_;
00233 
00234                 // Allocate the memory
00235                 if( num_rec_op_ == 0 )
00236                         rec_op_ = CPPAD_NULL;
00237                 else    rec_op_ = 
00238                         CPPAD_TRACK_NEW_VEC(num_rec_op_,        rec_op_);
00239                 if( num_rec_vecad_ind_ == 0 )
00240                         rec_vecad_ind_ = CPPAD_NULL;
00241                 else    rec_vecad_ind_ = 
00242                         CPPAD_TRACK_NEW_VEC(num_rec_vecad_ind_, rec_vecad_ind_);
00243                 if( num_rec_op_arg_ == 0 )
00244                         rec_op_arg_ = CPPAD_NULL;
00245                 else    rec_op_arg_ = 
00246                         CPPAD_TRACK_NEW_VEC(num_rec_op_arg_,    rec_op_arg_);
00247                 if( num_rec_par_ == 0 )
00248                         rec_par_ = CPPAD_NULL;
00249                 else    rec_par_ = 
00250                         CPPAD_TRACK_NEW_VEC(num_rec_par_,       rec_par_);
00251                 if( num_rec_text_ == 0 )
00252                         rec_text_ = CPPAD_NULL;
00253                 else    rec_text_ = 
00254                         CPPAD_TRACK_NEW_VEC(num_rec_text_,      rec_text_);
00255 
00256                 // Copy the data
00257                 i = num_rec_op_;
00258                 while(i--)
00259                         rec_op_[i] = play.rec_op_[i];
00260                 i = num_rec_vecad_ind_;
00261                 while(i--)
00262                         rec_vecad_ind_[i] = play.rec_vecad_ind_[i];
00263                 i = num_rec_op_arg_;
00264                 while(i--)
00265                         rec_op_arg_[i] = play.rec_op_arg_[i];
00266                 i = num_rec_par_;
00267                 while(i--)
00268                         rec_par_[i] = play.rec_par_[i];
00269                 i = num_rec_text_;
00270                 while(i--)
00271                         rec_text_[i] = play.rec_text_[i];
00272 
00273                 // set the number of VecAD vectors
00274                 num_rec_vecad_vec_ = 0;
00275                 for(i = 0; i < num_rec_vecad_ind_; i += rec_vecad_ind_[i] + 1)
00276                         num_rec_vecad_vec_++;
00277         }
00278         // End two functions with idential code but different argument types.
00279         // ===============================================================
00280 
00281         /// Erase all information in an operation sequence player.
00282         void Erase(void)
00283         {       
00284                 num_rec_var_       = 0;
00285                 num_rec_op_        = 0;
00286                 num_rec_vecad_ind_ = 0;
00287                 num_rec_op_arg_    = 0;
00288                 num_rec_par_       = 0;
00289                 num_rec_text_      = 0;
00290 
00291                 if( num_rec_op_ > 0 )
00292                         CPPAD_TRACK_DEL_VEC(rec_op_);
00293                 if( num_rec_vecad_ind_ > 0 )
00294                         CPPAD_TRACK_DEL_VEC(rec_vecad_ind_);
00295                 if( num_rec_op_arg_ > 0 )
00296                         CPPAD_TRACK_DEL_VEC(rec_op_arg_);
00297                 if( num_rec_par_ > 0 )
00298                         CPPAD_TRACK_DEL_VEC(rec_par_);
00299                 if( num_rec_text_ > 0 )
00300                         CPPAD_TRACK_DEL_VEC(rec_text_);
00301 
00302                 num_rec_op_        = 0;
00303                 num_rec_vecad_ind_ = 0;
00304                 num_rec_vecad_vec_ = 0;
00305                 num_rec_op_arg_    = 0;
00306                 num_rec_par_       = 0;
00307                 num_rec_text_      = 0;
00308         }
00309 
00310 // ------------------ Old method of palying back a recording -----------------
00311 public:
00312         /*! 
00313         \brief 
00314         Fetch an operator from the recording.
00315 
00316         \return 
00317         the i-th operator in the recording.
00318 
00319         \param i
00320         the index of the operator in recording
00321         */
00322         OpCode GetOp (size_t i) const
00323         {       CPPAD_ASSERT_UNKNOWN(i < num_rec_op_);
00324                 return rec_op_[i];
00325         }
00326 
00327         /*! 
00328         \brief 
00329         Fetch a VecAD index from the recording.
00330 
00331         \return 
00332         the i-th VecAD index in the recording.
00333 
00334         \param i
00335         the index of the VecAD index in recording
00336         */
00337         size_t GetVecInd (size_t i) const
00338         {       CPPAD_ASSERT_UNKNOWN(i < num_rec_vecad_ind_);
00339                 return rec_vecad_ind_[i];
00340         }
00341 
00342         /*! 
00343         \brief 
00344         Fetch a parameter from the recording.
00345 
00346         \return 
00347         the i-th parameter in the recording.
00348 
00349         \param i
00350         the index of the parameter in recording
00351         */
00352         Base GetPar(size_t i) const
00353         {       CPPAD_ASSERT_UNKNOWN(i < num_rec_par_);
00354                 return rec_par_[i];
00355         }
00356 
00357         /*! 
00358         \brief 
00359         Fetch entire parameter vector from the recording.
00360 
00361         \return 
00362         the entire parameter vector.
00363 
00364         */
00365         const Base* GetPar(void) const
00366         {       return rec_par_; }
00367 
00368         /*! 
00369         \brief 
00370         Fetch a '\\0' terminated string from the recording.
00371 
00372         \return 
00373         the beginning of the string.
00374 
00375         \param i
00376         the index where the string begins. 
00377         */
00378         const char *GetTxt(size_t i) const
00379         {       CPPAD_ASSERT_UNKNOWN(i < num_rec_text_);
00380                 return rec_text_ + i;
00381         }
00382         
00383         /*!
00384         \brief
00385         Replace an argument index in the recording.
00386 
00387         \param i
00388         is the index, in argument indices, that is to be replaced.
00389 
00390         \param value
00391         is the new normal index value.
00392         */
00393         void ReplaceInd(size_t i, size_t value)
00394         {       CPPAD_ASSERT_UNKNOWN( i < num_rec_op_arg_);
00395                 rec_op_arg_[i] = value;
00396         }
00397 
00398         /// Fetch number of variables in the recording.
00399         size_t num_rec_var(void) const
00400         {       return num_rec_var_; }
00401 
00402         /// Fetch number of operators in the recording.
00403         size_t num_rec_op(void) const
00404         {       return num_rec_op_; }
00405 
00406         /// Fetch number of VecAD indices in the recording.
00407         size_t num_rec_vecad_ind(void) const
00408         {       return num_rec_vecad_ind_; }
00409 
00410         /// Fetch number of VecAD vectors in the recording
00411         size_t num_rec_vecad_vec(void) const
00412         {       return num_rec_vecad_vec_; }
00413 
00414         /// Fetch number of argument indices in the recording.
00415         size_t num_rec_op_arg(void) const
00416         {       return num_rec_op_arg_; }
00417 
00418         /// Fetch number of parameters in the recording.
00419         size_t num_rec_par(void) const
00420         {       return num_rec_par_; }
00421 
00422         /// Fetch number of characters (representing strings) in the recording.
00423         size_t num_rec_text(void) const
00424         {       return num_rec_text_; }
00425 
00426         /// Fetch a rough measure of amount of memory used by the recording. 
00427         size_t Memory(void) const
00428         {       return num_rec_op_        * sizeof(OpCode) 
00429                      + num_rec_op_arg_    * sizeof(size_t)
00430                      + num_rec_par_       * sizeof(Base)
00431                      + num_rec_text_      * sizeof(char)
00432                      + num_rec_vecad_ind_ * sizeof(size_t)
00433                 ;
00434         }
00435 
00436 // ------------- Variables used for new methog of playing back a recording ---
00437 private:
00438         /// Current operator
00439         OpCode    op_;
00440 
00441         /// Index in recording corresponding to current operator
00442         size_t    op_index_;
00443 
00444         /// Current offser of the argument indices in rec_op_arg_ 
00445         size_t    op_arg_;
00446 
00447         /// Index for primary (last) variable corresponding to current operator
00448         size_t    var_index_;
00449 
00450 // ----------- Functions used in new method for palying back a recording ---
00451 public:
00452         /*!
00453         Start a play back of the recording during a forward sweep.
00454 
00455         Use repeated calls to next_forward to play back one operator at a time.
00456 
00457         \param op
00458         The input value of op does not matter. Its output value is the
00459         first operator in the recording; i.e., BeginOp.
00460 
00461         \param op_arg
00462         The input value of *op_arg does not matter. Its output value is the
00463         beginning of the vector of argument indices for the first operation;
00464         i.e., 0
00465 
00466         \param op_index
00467         The input value of op_index does not matter. Its output value
00468         is the index of the next first operator in the recording; i.e., 0.
00469 
00470         \param var_index
00471         The input value of var_index does not matter. Its output value is the
00472         index of the primary (last) result corresponding to the the first
00473         operator (which must be a BeginOp); i.e., 0.
00474         */
00475         void start_forward(
00476         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00477         {
00478                 op        = op_          = rec_op_[0]; 
00479                 op_arg_   = 0;
00480                 op_arg    = rec_op_arg_;
00481                 op_index  = op_index_    = 0;
00482                 var_index = var_index_   = 0;
00483 
00484                 CPPAD_ASSERT_UNKNOWN( op_  == BeginOp );
00485                 CPPAD_ASSERT_NARG_NRES(op_, 0, 1);
00486 
00487                 return;
00488         }
00489 
00490         /*!
00491         Fetch the next operator during a forward sweep.
00492 
00493         Use start_forward to initialize to the first operator; i.e.,
00494         the BeginOp at the beginning of the recording. 
00495 
00496         \param op
00497         The input value of op does not matter. Its output value is the
00498         next operator in the recording.
00499         For speed, \c next_forward does not check for the special case
00500         of <tt>op == CSumOp</tt>. In this case, the other return values
00501         from \c next_forward must be corrected by a call to \c forward_csum.
00502 
00503         \param op_arg
00504         The input value of *op_arg does not matter. Its output value is the
00505         beginning of the vector of argument indices for this operation.
00506 
00507         \param op_index
00508         The input value of op_index does not matter. Its output value
00509         is the index of the next operator in the recording. Thus the ouput
00510         value following the previous call to start_forward is one. In addition,
00511         the output value increases by one with each call to next_forward. 
00512 
00513         \param var_index
00514         The input value of var_index does not matter. Its output value is the
00515         index of the primary (last) result corresponding to the operator op.
00516         */
00517 
00518         void next_forward(
00519         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00520         {       using CppAD::NumRes;
00521                 using CppAD::NumArg;
00522 
00523                 // index for the next operator 
00524                 op_index    = ++op_index_;
00525 
00526                 // first argument for next operator 
00527                 op_arg_    += NumArg(op_);            // index
00528                 op_arg      = op_arg_ + rec_op_arg_;  // pointer
00529 
00530                 // next operator
00531                 op          = op_         = rec_op_[ op_index_ ];
00532 
00533                 // index for last result for next operator
00534                 var_index   = var_index_ += NumRes(op);
00535 
00536                 CPPAD_ASSERT_UNKNOWN( op_index_  < num_rec_op_ );
00537                 CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= num_rec_op_arg_ );
00538                 CPPAD_ASSERT_UNKNOWN( var_index_  < num_rec_var_ );
00539         }
00540         /*!
00541         Correct \c next_forward return values when <tt>op == CSumOp</tt>.
00542 
00543         \param op
00544         The input value of op must be the return value from the previous
00545         call to \c next_forward and must be \c CSumOp.
00546 
00547         \param op_arg
00548         The input value of *op_arg must be the return value from the 
00549         previous call to \c next_forward. Its output value is the
00550         beginning of the vector of argument indices for this operation.
00551 
00552         \param op_index
00553         The input value of op_index does must be the return value from the
00554         previous call to \c next_forward. Its output value
00555         is the index of this operator in the recording. 
00556 
00557         \param var_index
00558         The input value of var_index must be the return value from the
00559         previous call to \c next_forward. Its output value is the
00560         index of the primary (last) result corresponding to this.
00561         */
00562         void forward_csum(
00563         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00564         {       using CppAD::NumRes;
00565                 using CppAD::NumArg;
00566                 CPPAD_ASSERT_UNKNOWN( op == CSumOp );
00567                 CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
00568                 CPPAD_ASSERT_UNKNOWN(
00569                 op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ]
00570                 );
00571                 /*
00572                 The only thing that really needs fixing is op_arg_.
00573                 Actual number of arugments for this operator is
00574                         op_arg[0] + op_arg[1] + 4.
00575                 We must change op_arg_ so that when you add NumArg(CSumOp)
00576                 you get first argument for next operator in sequence.
00577                 */
00578                 op_arg_    += op_arg[0] + op_arg[1] + 4;
00579 
00580                 CPPAD_ASSERT_UNKNOWN( op_index_  < num_rec_op_ );
00581                 CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= num_rec_op_arg_ );
00582                 CPPAD_ASSERT_UNKNOWN( var_index_  < num_rec_var_ );
00583         }
00584         /*!
00585         Get a non-constant version of op_arg returned by previous next_forward
00586 
00587         \return
00588         The return value is equal to the return value of op_arg 
00589         corresponding to the previous call to next_forward.
00590         */
00591         size_t* forward_non_const_arg(void)
00592         {       return op_arg_ + rec_op_arg_; }
00593 
00594         /*!
00595         Start a play back of the recording during a reverse sweep.
00596 
00597         Use repeated calls to next_reverse to play back one operator at a time.
00598 
00599         \param op
00600         The input value of op does not matter. Its output value is the
00601         last operator in the recording; i.e., EndOp.
00602 
00603         \param op_arg
00604         The input value of *op_arg does not matter. Its output value is the
00605         beginning of the vector of argument indices for the last operation;
00606         (there are no arguments for the last operation so \a op_arg is invalid).
00607 
00608         \param op_index
00609         The input value of op_index does not matter. Its output value
00610         is the index of the last operator in the recording.
00611 
00612         \param var_index
00613         The input value of var_index does not matter. Its output value is the
00614         index of the primary (last) result corresponding to the the last
00615         operator (which must be a EndOp).
00616         (there are no results for the last operation 
00617         so \a var_index is invalid).
00618         */
00619 
00620         void start_reverse(
00621         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00622         {
00623                 op_arg_     = num_rec_op_arg_;                // index
00624                 op_arg      = op_arg_ + rec_op_arg_;          // pointer
00625 
00626                 op_index    = op_index_   = num_rec_op_ - 1; 
00627                 var_index   = var_index_  = num_rec_var_ - 1;
00628 
00629                 op          = op_         = rec_op_[ op_index_ ];
00630                 CPPAD_ASSERT_UNKNOWN( op_ == EndOp );
00631                 CPPAD_ASSERT_NARG_NRES(op, 0, 0);
00632                 return;
00633         }
00634 
00635         /*!
00636         Fetch the next operator during a reverse sweep.
00637 
00638         Use start_reverse to initialize to reverse play back.
00639         The first call to next_reverse (after start_reverse) will give the 
00640         last operator in the recording.
00641 
00642         \param op
00643         The input value of op does not matter. Its output value is the
00644         next operator in the recording (in reverse order).
00645         The last operator sets op equal to EndOp.
00646 
00647         \param op_arg
00648         The input value of *op_arg does not matter. Its output value is the
00649         beginning of the vector of argument indices for this operation.
00650         The last operator sets op_arg equal to the beginning of the 
00651         argument indices for the entire recording.
00652         For speed, \c next_reverse does not check for the special case
00653         of <tt>op == CSumOp</tt>. In this case, the other return values
00654         from \c next_reverse must be corrected by a call to \c reverse_csum.
00655 
00656 
00657         \param op_index
00658         The input value of op_index does not matter. Its output value
00659         is the index of this operator in the recording. Thus the output
00660         value following the previous call to start_reverse is equal to 
00661         the number of variables in the recording minus one.
00662         In addition, the output value decreases by one with each call to
00663         next_reverse.
00664         The last operator sets op_index equal to 0.
00665 
00666         \param var_index
00667         The input value of var_index does not matter. Its output value is the
00668         index of the primary (last) result corresponding to the operator op.
00669         The last operator sets var_index equal to 0 (corresponding to BeginOp
00670         at beginning of operation sequence).
00671         */
00672 
00673         void next_reverse(
00674         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00675         {       using CppAD::NumRes;
00676                 using CppAD::NumArg;
00677 
00678                 // index of the last result for the next operator
00679                 CPPAD_ASSERT_UNKNOWN( var_index_ >= NumRes(op_) );
00680                 var_index   = var_index_ -= NumRes(op_);
00681 
00682                 // next operator
00683                 CPPAD_ASSERT_UNKNOWN( op_index_  > 0 );
00684                 op_index    = --op_index_;                           // index
00685                 op          = op_         = rec_op_[ op_index_ ];    // value
00686 
00687                 // first argument for next operator
00688                 CPPAD_ASSERT_UNKNOWN( op_arg_ >= NumArg(op)  );
00689                 op_arg_    -= NumArg(op);                            // index
00690                 op_arg      = op_arg_ + rec_op_arg_;                 // pointer
00691         }
00692         /*!
00693         Correct \c next_reverse return values when <tt>op == CSumOp</tt>.
00694 
00695         \param op
00696         The input value of op must be the return value from the previous
00697         call to \c next_reverse and must be \c CSumOp.
00698 
00699         \param op_arg
00700         The input value of *op_arg must be the return value from the 
00701         previous call to \c next_reverse. Its output value is the
00702         beginning of the vector of argument indices for this operation.
00703 
00704         \param op_index
00705         The input value of op_index must be the return value from the
00706         previous call to \c next_reverse. Its output value
00707         is the index of the this operator in the recording. 
00708 
00709         \param var_index
00710         The input value of var_index must be the return value from the 
00711         previous call to \c next_reverse. Its output value is the
00712         index of the primary (last) result corresponding to this operator.
00713         */
00714 
00715         void reverse_csum(
00716         OpCode& op, const size_t*& op_arg, size_t& op_index, size_t& var_index)
00717         {       using CppAD::NumRes;
00718                 using CppAD::NumArg;
00719                 CPPAD_ASSERT_UNKNOWN( op == CSumOp );
00720                 CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
00721                 /*
00722                 The things needs fixing are op_arg_ and op_arg. Currently, 
00723                 op_arg points first arugment for the previous operator.
00724                 */
00725                 --op_arg;
00726                 op_arg_    -= (op_arg[0] + 4);
00727                 op_arg      = op_arg_ + rec_op_arg_;
00728 
00729                 CPPAD_ASSERT_UNKNOWN(
00730                 op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ]
00731                 );
00732                 CPPAD_ASSERT_UNKNOWN( op_index_  < num_rec_op_ );
00733                 CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= num_rec_op_arg_ );
00734                 CPPAD_ASSERT_UNKNOWN( var_index_  < num_rec_var_ );
00735         }
00736 
00737 };
00738 
00739 CPPAD_END_NAMESPACE
00740 # endif