CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_REVERSE_SWEEP_INCLUDED 00003 # define CPPAD_REVERSE_SWEEP_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 00017 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00018 /*! 00019 \file reverse_sweep.hpp 00020 Compute derivatives of arbitrary order Taylor coefficients. 00021 */ 00022 00023 /* 00024 \def CPPAD_ATOMIC_CALL 00025 This avoids warnings when NDEBUG is defined and user_ok is not used. 00026 If \c NDEBUG is defined, this resolves to 00027 \code 00028 user_atom->reverse 00029 \endcode 00030 otherwise, it respolves to 00031 \code 00032 user_ok = user_atom->reverse 00033 \endcode 00034 This maco is undefined at the end of this file to facillitate is 00035 use with a different definition in other files. 00036 */ 00037 # ifdef NDEBUG 00038 # define CPPAD_ATOMIC_CALL user_atom->reverse 00039 # else 00040 # define CPPAD_ATOMIC_CALL user_ok = user_atom->reverse 00041 # endif 00042 00043 /*! 00044 \def CPPAD_REVERSE_SWEEP_TRACE 00045 This value is either zero or one. 00046 Zero is the normal operational value. 00047 If it is one, a trace of every reverse_sweep computation is printed. 00048 */ 00049 # define CPPAD_REVERSE_SWEEP_TRACE 0 00050 00051 /*! 00052 Compute derivative of arbitrary order forward mode Taylor coefficients. 00053 00054 \tparam Base 00055 base type for the operator; i.e., this operation sequence was recorded 00056 using AD< \a Base > and computations by this routine are done using type 00057 \a Base. 00058 00059 \param d 00060 is the highest order Taylor coefficients that 00061 we are computing the derivative of. 00062 00063 \param n 00064 is the number of independent variables on the tape. 00065 00066 \param numvar 00067 is the total number of variables on the tape. 00068 This is also equal to the number of rows in the matrix \a Taylor; i.e., 00069 play->num_var_rec(). 00070 00071 \param play 00072 The information stored in \a play 00073 is a recording of the operations corresponding to the function 00074 \f[ 00075 F : {\bf R}^n \rightarrow {\bf R}^m 00076 \f] 00077 where \f$ n \f$ is the number of independent variables and 00078 \f$ m \f$ is the number of dependent variables. 00079 We define the function 00080 \f$ G : {\bf R}^{n \times d} \rightarrow {\bf R} \f$ by 00081 \f[ 00082 G( u ) = \frac{1}{d !} \frac{ \partial^d }{ \partial t^d } 00083 \left[ 00084 \sum_{i=1}^m w_i F_i ( u^{(0)} + u^{(1)} t + \cdots + u^{(d)} t^d ) 00085 \right]_{t=0} 00086 \f] 00087 Note that the scale factor 1 / a d converts 00088 the \a d-th partial derivative to the \a d-th order Taylor coefficient. 00089 This routine computes the derivative of \f$ G(u) \f$ 00090 with respect to all the Taylor coefficients 00091 \f$ u^{(k)} \f$ for \f$ k = 0 , ... , d \f$. 00092 The vector \f$ w \in {\bf R}^m \f$, and 00093 value of \f$ u \in {\bf R}^{n \times d} \f$ 00094 at which the derivative is computed, 00095 are defined below. 00096 \n 00097 \n 00098 The object \a play is effectly constant. 00099 There is an exception to this, 00100 while palying back the tape 00101 the object \a play holds information about the current location 00102 with in the tape and this changes during palyback. 00103 00104 \param J 00105 Is the number of columns in the coefficient matrix \a Taylor. 00106 This must be greater than or equal \a d + 1. 00107 00108 \param Taylor 00109 For i = 1 , ... , \a numvar, and for k = 0 , ... , \a d, 00110 \a Taylor [ i * J + k ] 00111 is the k-th order Taylor coefficient corresponding to 00112 variable with index i on the tape. 00113 The value \f$ u \in {\bf R}^{n \times d} \f$, 00114 at which the derivative is computed, 00115 is defined by 00116 \f$ u_j^{(k)} \f$ = \a Taylor [ j * J + k ] 00117 for j = 1 , ... , \a n, and for k = 0 , ... , \a d. 00118 00119 \param K 00120 Is the number of columns in the partial derivative matrix \a Partial. 00121 It must be greater than or equal \a d + 1. 00122 00123 \param Partial 00124 \b Input: 00125 The last \f$ m \f$ rows of \a Partial are inputs. 00126 The vector \f$ v \f$, used to define \f$ G(u) \f$, 00127 is specified by these rows. 00128 For i = 0 , ... , m - 1, \a Partial [ ( \a numvar - m + i ) * K + d ] = v_i. 00129 For i = 0 , ... , m - 1 and for k = 0 , ... , d - 1, 00130 \a Partial [ ( \a numvar - m + i ) * K + k ] = 0. 00131 \n 00132 \n 00133 \b Temporary: 00134 For i = n+1 , ... , \a numvar - 1 and for k = 0 , ... , d, 00135 the value of \a Partial [ i * K + k ] is used for temporary work space 00136 and its output value is not defined. 00137 \n 00138 \n 00139 \b Output: 00140 For j = 1 , ... , n and for k = 0 , ... , d, 00141 \a Partial [ j * K + k ] 00142 is the partial derivative of \f$ G( u ) \f$ with 00143 respect to \f$ u_j^{(k)} \f$. 00144 00145 \param cskip_op 00146 Is a vector with size play->num_op_rec(). 00147 If cskip_op[i] is true, the operator index i in the recording 00148 does not affect any of the dependent variable (given the value 00149 of the independent variables). 00150 00151 \param var_by_load_op 00152 is a vector with size play->num_load_op_rec(). 00153 Is the variable index corresponding to each load instruction. 00154 In the case where the index is zero, 00155 the instruction corresponds to a parameter (not variable). 00156 00157 \par Assumptions 00158 The first operator on the tape is a BeginOp, 00159 and the next \a n operators are InvOp operations for the 00160 corresponding independent variables. 00161 */ 00162 template <class Base> 00163 void ReverseSweep( 00164 size_t d, 00165 size_t n, 00166 size_t numvar, 00167 player<Base>* play, 00168 size_t J, 00169 const Base* Taylor, 00170 size_t K, 00171 Base* Partial, 00172 bool* cskip_op, 00173 const pod_vector<addr_t>& var_by_load_op 00174 ) 00175 { 00176 OpCode op; 00177 size_t i_op; 00178 size_t i_var; 00179 00180 const addr_t* arg = CPPAD_NULL; 00181 00182 // check numvar argument 00183 CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); 00184 CPPAD_ASSERT_UNKNOWN( numvar > 0 ); 00185 00186 // length of the parameter vector (used by CppAD assert macros) 00187 const size_t num_par = play->num_par_rec(); 00188 00189 // pointer to the beginning of the parameter vector 00190 const Base* parameter = CPPAD_NULL; 00191 if( num_par > 0 ) 00192 parameter = play->GetPar(); 00193 00194 // work space used by UserOp. 00195 const size_t user_k = d; // highest order we are differentiating 00196 const size_t user_k1 = d+1; // number of orders for this calculation 00197 vector<size_t> user_ix; // variable indices for argument vector 00198 vector<Base> user_tx; // argument vector Taylor coefficients 00199 vector<Base> user_ty; // result vector Taylor coefficients 00200 vector<Base> user_px; // partials w.r.t argument vector 00201 vector<Base> user_py; // partials w.r.t. result vector 00202 size_t user_index = 0; // indentifier for this atomic operation 00203 size_t user_id = 0; // user identifier for this call to operator 00204 size_t user_i = 0; // index in result vector 00205 size_t user_j = 0; // index in argument vector 00206 size_t user_m = 0; // size of result vector 00207 size_t user_n = 0; // size of arugment vector 00208 // 00209 atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator 00210 # ifndef NDEBUG 00211 bool user_ok = false; // atomic op return value 00212 # endif 00213 // 00214 // next expected operator in a UserOp sequence 00215 enum { user_start, user_arg, user_ret, user_end } user_state = user_end; 00216 00217 // temporary indices 00218 size_t j, ell; 00219 00220 // Initialize 00221 play->reverse_start(op, arg, i_op, i_var); 00222 CPPAD_ASSERT_UNKNOWN( op == EndOp ); 00223 # if CPPAD_REVERSE_SWEEP_TRACE 00224 std::cout << std::endl; 00225 # endif 00226 bool more_operators = true; 00227 while(more_operators) 00228 { // next op 00229 play->reverse_next(op, arg, i_op, i_var); 00230 CPPAD_ASSERT_UNKNOWN((i_op > n) | (op == InvOp) | (op == BeginOp)); 00231 CPPAD_ASSERT_UNKNOWN((i_op <= n) | (op != InvOp) | (op != BeginOp)); 00232 CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); 00233 00234 // check if we are skipping this operation 00235 while( cskip_op[i_op] ) 00236 { if( op == CSumOp ) 00237 { // CSumOp has a variable number of arguments 00238 play->reverse_csum(op, arg, i_op, i_var); 00239 } 00240 play->reverse_next(op, arg, i_op, i_var); 00241 CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); 00242 } 00243 00244 // rest of informaiton depends on the case 00245 # if CPPAD_REVERSE_SWEEP_TRACE 00246 size_t i_tmp = i_var; 00247 const Base* Z_tmp = Taylor + i_var * J; 00248 const Base* pZ_tmp = Partial + i_var * K; 00249 00250 printOp( 00251 std::cout, 00252 play, 00253 i_op, 00254 i_tmp, 00255 op, 00256 arg, 00257 d + 1, 00258 Z_tmp, 00259 d + 1, 00260 pZ_tmp 00261 ); 00262 # endif 00263 00264 switch( op ) 00265 { 00266 00267 case AbsOp: 00268 reverse_abs_op( 00269 d, i_var, arg[0], J, Taylor, K, Partial 00270 ); 00271 break; 00272 // -------------------------------------------------- 00273 00274 case AddvvOp: 00275 reverse_addvv_op( 00276 d, i_var, arg, parameter, J, Taylor, K, Partial 00277 ); 00278 break; 00279 // -------------------------------------------------- 00280 00281 case AddpvOp: 00282 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00283 reverse_addpv_op( 00284 d, i_var, arg, parameter, J, Taylor, K, Partial 00285 ); 00286 break; 00287 // -------------------------------------------------- 00288 00289 case AcosOp: 00290 // sqrt(1 - x * x), acos(x) 00291 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00292 reverse_acos_op( 00293 d, i_var, arg[0], J, Taylor, K, Partial 00294 ); 00295 break; 00296 // -------------------------------------------------- 00297 00298 case AsinOp: 00299 // sqrt(1 - x * x), asin(x) 00300 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00301 reverse_asin_op( 00302 d, i_var, arg[0], J, Taylor, K, Partial 00303 ); 00304 break; 00305 // -------------------------------------------------- 00306 00307 case AtanOp: 00308 // 1 + x * x, atan(x) 00309 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00310 reverse_atan_op( 00311 d, i_var, arg[0], J, Taylor, K, Partial 00312 ); 00313 break; 00314 // ------------------------------------------------- 00315 00316 case BeginOp: 00317 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00318 more_operators = false; 00319 break; 00320 // -------------------------------------------------- 00321 00322 case CSkipOp: 00323 // CSkipOp has a variable number of arguments and 00324 // forward_next thinks it one has one argument. 00325 // we must inform reverse_next of this special case. 00326 play->reverse_cskip(op, arg, i_op, i_var); 00327 break; 00328 // ------------------------------------------------- 00329 00330 case CSumOp: 00331 // CSumOp has a variable number of arguments and 00332 // reverse_next thinks it one has one argument. 00333 // We must inform reverse_next of this special case. 00334 play->reverse_csum(op, arg, i_op, i_var); 00335 reverse_csum_op( 00336 d, i_var, arg, K, Partial 00337 ); 00338 // end of a cummulative summation 00339 break; 00340 // ------------------------------------------------- 00341 00342 case CExpOp: 00343 reverse_cond_op( 00344 d, 00345 i_var, 00346 arg, 00347 num_par, 00348 parameter, 00349 J, 00350 Taylor, 00351 K, 00352 Partial 00353 ); 00354 break; 00355 // -------------------------------------------------- 00356 00357 case ComOp: 00358 break; 00359 // -------------------------------------------------- 00360 00361 case CosOp: 00362 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00363 reverse_cos_op( 00364 d, i_var, arg[0], J, Taylor, K, Partial 00365 ); 00366 break; 00367 // -------------------------------------------------- 00368 00369 case CoshOp: 00370 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00371 reverse_cosh_op( 00372 d, i_var, arg[0], J, Taylor, K, Partial 00373 ); 00374 break; 00375 // -------------------------------------------------- 00376 00377 case DisOp: 00378 // Derivative of discrete operation is zero so no 00379 // contribution passes through this operation. 00380 break; 00381 // -------------------------------------------------- 00382 00383 case DivvvOp: 00384 reverse_divvv_op( 00385 d, i_var, arg, parameter, J, Taylor, K, Partial 00386 ); 00387 break; 00388 // -------------------------------------------------- 00389 00390 case DivpvOp: 00391 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00392 reverse_divpv_op( 00393 d, i_var, arg, parameter, J, Taylor, K, Partial 00394 ); 00395 break; 00396 // -------------------------------------------------- 00397 00398 case DivvpOp: 00399 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); 00400 reverse_divvp_op( 00401 d, i_var, arg, parameter, J, Taylor, K, Partial 00402 ); 00403 break; 00404 // -------------------------------------------------- 00405 00406 case ExpOp: 00407 reverse_exp_op( 00408 d, i_var, arg[0], J, Taylor, K, Partial 00409 ); 00410 break; 00411 // -------------------------------------------------- 00412 case LdpOp: 00413 reverse_load_op( 00414 op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() 00415 ); 00416 break; 00417 // ------------------------------------------------- 00418 00419 case LdvOp: 00420 reverse_load_op( 00421 op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() 00422 ); 00423 break; 00424 // ------------------------------------------------- 00425 00426 case InvOp: 00427 break; 00428 // -------------------------------------------------- 00429 00430 case LogOp: 00431 reverse_log_op( 00432 d, i_var, arg[0], J, Taylor, K, Partial 00433 ); 00434 break; 00435 // -------------------------------------------------- 00436 00437 case MulvvOp: 00438 reverse_mulvv_op( 00439 d, i_var, arg, parameter, J, Taylor, K, Partial 00440 ); 00441 break; 00442 // -------------------------------------------------- 00443 00444 case MulpvOp: 00445 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00446 reverse_mulpv_op( 00447 d, i_var, arg, parameter, J, Taylor, K, Partial 00448 ); 00449 break; 00450 // -------------------------------------------------- 00451 00452 case ParOp: 00453 break; 00454 // -------------------------------------------------- 00455 00456 case PowvpOp: 00457 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); 00458 reverse_powvp_op( 00459 d, i_var, arg, parameter, J, Taylor, K, Partial 00460 ); 00461 break; 00462 // ------------------------------------------------- 00463 00464 case PowpvOp: 00465 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00466 reverse_powpv_op( 00467 d, i_var, arg, parameter, J, Taylor, K, Partial 00468 ); 00469 break; 00470 // ------------------------------------------------- 00471 00472 case PowvvOp: 00473 reverse_powvv_op( 00474 d, i_var, arg, parameter, J, Taylor, K, Partial 00475 ); 00476 break; 00477 // -------------------------------------------------- 00478 00479 case PriOp: 00480 // no result so nothing to do 00481 break; 00482 // -------------------------------------------------- 00483 00484 case SignOp: 00485 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00486 reverse_sign_op( 00487 d, i_var, arg[0], J, Taylor, K, Partial 00488 ); 00489 break; 00490 // ------------------------------------------------- 00491 00492 case SinOp: 00493 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00494 reverse_sin_op( 00495 d, i_var, arg[0], J, Taylor, K, Partial 00496 ); 00497 break; 00498 // ------------------------------------------------- 00499 00500 case SinhOp: 00501 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00502 reverse_sinh_op( 00503 d, i_var, arg[0], J, Taylor, K, Partial 00504 ); 00505 break; 00506 // -------------------------------------------------- 00507 00508 case SqrtOp: 00509 reverse_sqrt_op( 00510 d, i_var, arg[0], J, Taylor, K, Partial 00511 ); 00512 break; 00513 // -------------------------------------------------- 00514 00515 case StppOp: 00516 break; 00517 // -------------------------------------------------- 00518 00519 case StpvOp: 00520 break; 00521 // ------------------------------------------------- 00522 00523 case StvpOp: 00524 break; 00525 // ------------------------------------------------- 00526 00527 case StvvOp: 00528 break; 00529 // -------------------------------------------------- 00530 00531 case SubvvOp: 00532 reverse_subvv_op( 00533 d, i_var, arg, parameter, J, Taylor, K, Partial 00534 ); 00535 break; 00536 // -------------------------------------------------- 00537 00538 case SubpvOp: 00539 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00540 reverse_subpv_op( 00541 d, i_var, arg, parameter, J, Taylor, K, Partial 00542 ); 00543 break; 00544 // -------------------------------------------------- 00545 00546 case SubvpOp: 00547 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); 00548 reverse_subvp_op( 00549 d, i_var, arg, parameter, J, Taylor, K, Partial 00550 ); 00551 break; 00552 // ------------------------------------------------- 00553 00554 case TanOp: 00555 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00556 reverse_tan_op( 00557 d, i_var, arg[0], J, Taylor, K, Partial 00558 ); 00559 break; 00560 // ------------------------------------------------- 00561 00562 case TanhOp: 00563 CPPAD_ASSERT_UNKNOWN( i_var < numvar ); 00564 reverse_tanh_op( 00565 d, i_var, arg[0], J, Taylor, K, Partial 00566 ); 00567 break; 00568 // -------------------------------------------------- 00569 00570 case UserOp: 00571 // start or end an atomic operation sequence 00572 CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); 00573 CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); 00574 if( user_state == user_end ) 00575 { user_index = arg[0]; 00576 user_id = arg[1]; 00577 user_n = arg[2]; 00578 user_m = arg[3]; 00579 user_atom = atomic_base<Base>::class_object(user_index); 00580 # ifndef NDEBUG 00581 if( user_atom == CPPAD_NULL ) 00582 { std::string msg = 00583 atomic_base<Base>::class_name(user_index) 00584 + ": atomic_base function has been deleted"; 00585 CPPAD_ASSERT_KNOWN(false, msg.c_str() ); 00586 } 00587 # endif 00588 if(user_ix.size() != user_n) 00589 user_ix.resize(user_n); 00590 if(user_tx.size() != user_n * user_k1) 00591 { user_tx.resize(user_n * user_k1); 00592 user_px.resize(user_n * user_k1); 00593 } 00594 if(user_ty.size() != user_m * user_k1) 00595 { user_ty.resize(user_m * user_k1); 00596 user_py.resize(user_m * user_k1); 00597 } 00598 user_j = user_n; 00599 user_i = user_m; 00600 user_state = user_ret; 00601 } 00602 else 00603 { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); 00604 CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); 00605 CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); 00606 CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); 00607 CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); 00608 00609 // call users function for this operation 00610 user_atom->set_id(user_id); 00611 CPPAD_ATOMIC_CALL( 00612 user_k, user_tx, user_ty, user_px, user_py 00613 ); 00614 # ifndef NDEBUG 00615 if( ! user_ok ) 00616 { std::string msg = 00617 atomic_base<Base>::class_name(user_index) 00618 + ": atomic_base.reverse: returned false"; 00619 CPPAD_ASSERT_KNOWN(false, msg.c_str() ); 00620 } 00621 # endif 00622 for(j = 0; j < user_n; j++) if( user_ix[j] > 0 ) 00623 { for(ell = 0; ell < user_k1; ell++) 00624 Partial[user_ix[j] * K + ell] += 00625 user_px[j * user_k1 + ell]; 00626 } 00627 user_state = user_end; 00628 } 00629 break; 00630 00631 case UsrapOp: 00632 // parameter argument in an atomic operation sequence 00633 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00634 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00635 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00636 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00637 --user_j; 00638 user_ix[user_j] = 0; 00639 user_tx[user_j * user_k1 + 0] = parameter[ arg[0]]; 00640 for(ell = 1; ell < user_k1; ell++) 00641 user_tx[user_j * user_k1 + ell] = Base(0.); 00642 00643 if( user_j == 0 ) 00644 user_state = user_start; 00645 break; 00646 00647 case UsravOp: 00648 // variable argument in an atomic operation sequence 00649 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00650 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00651 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00652 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); 00653 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00654 --user_j; 00655 user_ix[user_j] = arg[0]; 00656 for(ell = 0; ell < user_k1; ell++) 00657 user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell]; 00658 if( user_j == 0 ) 00659 user_state = user_start; 00660 break; 00661 00662 case UsrrpOp: 00663 // parameter result in an atomic operation sequence 00664 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00665 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00666 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00667 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00668 --user_i; 00669 for(ell = 0; ell < user_k1; ell++) 00670 { user_py[user_i * user_k1 + ell] = Base(0.); 00671 user_ty[user_i * user_k1 + ell] = Base(0.); 00672 } 00673 user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ]; 00674 if( user_i == 0 ) 00675 user_state = user_arg; 00676 break; 00677 00678 case UsrrvOp: 00679 // variable result in an atomic operation sequence 00680 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00681 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00682 --user_i; 00683 for(ell = 0; ell < user_k1; ell++) 00684 { user_py[user_i * user_k1 + ell] = 00685 Partial[i_var * K + ell]; 00686 user_ty[user_i * user_k1 + ell] = 00687 Taylor[i_var * J + ell]; 00688 } 00689 if( user_i == 0 ) 00690 user_state = user_arg; 00691 break; 00692 // ------------------------------------------------------------ 00693 00694 default: 00695 CPPAD_ASSERT_UNKNOWN(false); 00696 } 00697 } 00698 # if CPPAD_REVERSE_SWEEP_TRACE 00699 std::cout << std::endl; 00700 # endif 00701 // values corresponding to BeginOp 00702 CPPAD_ASSERT_UNKNOWN( i_op == 0 ); 00703 CPPAD_ASSERT_UNKNOWN( i_var == 0 ); 00704 } 00705 00706 } // END_CPPAD_NAMESPACE 00707 00708 // preprocessor symbols that are local to this file 00709 # undef CPPAD_REVERSE_SWEEP_TRACE 00710 # undef CPPAD_ATOMIC_CALL 00711 00712 # endif