CppAD: A C++ Algorithmic Differentiation Package
20130918
|
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