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