CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_REV_JAC_SWEEP_INCLUDED 00003 # define CPPAD_REV_JAC_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 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00017 /*! 00018 \file rev_jac_sweep.hpp 00019 Compute Reverse mode Jacobian sparsity patterns. 00020 */ 00021 00022 /*! 00023 \def CPPAD_REV_JAC_SWEEP_TRACE 00024 This value is either zero or one. 00025 Zero is the normal operational value. 00026 If it is one, a trace of every rev_jac_sweep computation is printed. 00027 */ 00028 # define CPPAD_REV_JAC_SWEEP_TRACE 0 00029 00030 /* 00031 \def CPPAD_ATOMIC_CALL 00032 This avoids warnings when NDEBUG is defined and user_ok is not used. 00033 If \c NDEBUG is defined, this resolves to 00034 \code 00035 user_atom->rev_sparse_jac 00036 \endcode 00037 otherwise, it respolves to 00038 \code 00039 user_ok = user_atom->rev_sparse_jac 00040 \endcode 00041 This maco is undefined at the end of this file to facillitate is 00042 use with a different definition in other files. 00043 */ 00044 # ifdef NDEBUG 00045 # define CPPAD_ATOMIC_CALL user_atom->rev_sparse_jac 00046 # else 00047 # define CPPAD_ATOMIC_CALL user_ok = user_atom->rev_sparse_jac 00048 # endif 00049 00050 /*! 00051 Given the sparsity pattern for the dependent variables, 00052 RevJacSweep computes the sparsity pattern for all the independent variables. 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 \tparam Vector_set 00060 is the type used for vectors of sets. It can be either 00061 \c sparse_pack, \c sparse_set, or \c sparse_list. 00062 00063 \param nz_compare 00064 Are the derivatives with respect to left and right of the expression below 00065 considered to be non-zero: 00066 \code 00067 CondExpRel(left, right, if_true, if_false) 00068 \endcode 00069 This is used by the optimizer to obtain the correct dependency relations. 00070 00071 \param n 00072 is the number of independent variables on the tape. 00073 00074 \param numvar 00075 is the total number of variables on the tape; i.e., 00076 \a play->num_var_rec(). 00077 This is also the number of rows in the entire sparsity pattern \a RevJac. 00078 00079 \param play 00080 The information stored in \a play 00081 is a recording of the operations corresponding to a function 00082 \f[ 00083 F : {\bf R}^n \rightarrow {\bf R}^m 00084 \f] 00085 where \f$ n \f$ is the number of independent variables 00086 and \f$ m \f$ is the number of dependent variables. 00087 The object \a play is effectly constant. 00088 It is not declared const because while playing back the tape 00089 the object \a play holds information about the currentl location 00090 with in the tape and this changes during playback. 00091 00092 \param var_sparsity 00093 For i = 0 , ... , \a numvar - 1, 00094 (all the variables on the tape) 00095 the forward Jacobian sparsity pattern for variable i 00096 corresponds to the set with index i in \a var_sparsity. 00097 \b 00098 \b 00099 \b Input: 00100 For i = 0 , ... , \a numvar - 1, 00101 the forward Jacobian sparsity pattern for variable i is an input 00102 if i corresponds to a dependent variable. 00103 Otherwise the sparsity patten is empty. 00104 \n 00105 \n 00106 \b Output: For j = 1 , ... , \a n, 00107 the sparsity pattern for the dependent variable with index (j-1) 00108 is given by the set with index index j in \a var_sparsity. 00109 */ 00110 00111 template <class Base, class Vector_set> 00112 void RevJacSweep( 00113 bool nz_compare, 00114 size_t n, 00115 size_t numvar, 00116 player<Base> *play, 00117 Vector_set& var_sparsity 00118 ) 00119 { 00120 OpCode op; 00121 size_t i_op; 00122 size_t i_var; 00123 00124 const addr_t* arg = CPPAD_NULL; 00125 00126 size_t i, j, k; 00127 00128 // length of the parameter vector (used by CppAD assert macros) 00129 const size_t num_par = play->num_par_rec(); 00130 00131 // check numvar argument 00132 CPPAD_ASSERT_UNKNOWN( numvar > 0 ); 00133 CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); 00134 CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); 00135 00136 // upper limit (exclusive) for elements in the set 00137 size_t limit = var_sparsity.end(); 00138 00139 // vecad_sparsity contains a sparsity pattern for each VecAD object. 00140 // vecad_ind maps a VecAD index (beginning of the VecAD object) 00141 // to the index of the corresponding set in vecad_sparsity. 00142 size_t num_vecad_ind = play->num_vec_ind_rec(); 00143 size_t num_vecad_vec = play->num_vecad_vec_rec(); 00144 Vector_set vecad_sparsity; 00145 vecad_sparsity.resize(num_vecad_vec, limit); 00146 pod_vector<size_t> vecad_ind; 00147 if( num_vecad_vec > 0 ) 00148 { size_t length; 00149 vecad_ind.extend(num_vecad_ind); 00150 j = 0; 00151 for(i = 0; i < num_vecad_vec; i++) 00152 { // length of this VecAD 00153 length = play->GetVecInd(j); 00154 // set to proper index for this VecAD 00155 vecad_ind[j] = i; 00156 for(k = 1; k <= length; k++) 00157 vecad_ind[j+k] = num_vecad_vec; // invalid index 00158 // start of next VecAD 00159 j += length + 1; 00160 } 00161 CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); 00162 } 00163 00164 // work space used by UserOp. 00165 typedef std::set<size_t> size_set; 00166 size_set::iterator set_itr; // iterator for a standard set 00167 size_set::iterator set_end; // end of iterator sequence 00168 vector< size_set > set_r; // set sparsity pattern for the argument x 00169 vector< size_set > set_s; // set sparisty pattern for the result y 00170 // 00171 vector<bool> bool_r; // bool sparsity pattern for the argument x 00172 vector<bool> bool_s; // bool sparisty pattern for the result y 00173 // 00174 const size_t user_q = limit; // maximum element plus one 00175 size_t user_index = 0; // indentifier for this atomic operation 00176 size_t user_id = 0; // user identifier for this call to operator 00177 size_t user_i = 0; // index in result vector 00178 size_t user_j = 0; // index in argument vector 00179 size_t user_m = 0; // size of result vector 00180 size_t user_n = 0; // size of arugment vector 00181 // 00182 atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator 00183 bool user_bool = false; // use bool or set sparsity ? 00184 # ifndef NDEBUG 00185 bool user_ok = false; // atomic op return value 00186 # endif 00187 // next expected operator in a UserOp sequence 00188 enum { user_start, user_arg, user_ret, user_end } user_state = user_end; 00189 00190 // Initialize 00191 play->reverse_start(op, arg, i_op, i_var); 00192 CPPAD_ASSERT_UNKNOWN( op == EndOp ); 00193 # if CPPAD_REV_JAC_SWEEP_TRACE 00194 std::cout << std::endl; 00195 CppAD::vector<bool> z_value(limit); 00196 # endif 00197 bool more_operators = true; 00198 while(more_operators) 00199 { 00200 // next op 00201 play->reverse_next(op, arg, i_op, i_var); 00202 # ifndef NDEBUG 00203 if( i_op <= n ) 00204 { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); 00205 } 00206 else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); 00207 # endif 00208 00209 // rest of information depends on the case 00210 switch( op ) 00211 { 00212 case AbsOp: 00213 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00214 reverse_sparse_jacobian_unary_op( 00215 i_var, arg[0], var_sparsity 00216 ); 00217 break; 00218 // ------------------------------------------------- 00219 00220 case AddvvOp: 00221 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00222 reverse_sparse_jacobian_binary_op( 00223 i_var, arg, var_sparsity 00224 ); 00225 break; 00226 // ------------------------------------------------- 00227 00228 case AddpvOp: 00229 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00230 reverse_sparse_jacobian_unary_op( 00231 i_var, arg[1], var_sparsity 00232 ); 00233 break; 00234 // ------------------------------------------------- 00235 00236 case AcosOp: 00237 // sqrt(1 - x * x), acos(x) 00238 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00239 reverse_sparse_jacobian_unary_op( 00240 i_var, arg[0], var_sparsity 00241 ); 00242 break; 00243 // ------------------------------------------------- 00244 00245 case AsinOp: 00246 // sqrt(1 - x * x), asin(x) 00247 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00248 reverse_sparse_jacobian_unary_op( 00249 i_var, arg[0], var_sparsity 00250 ); 00251 break; 00252 // ------------------------------------------------- 00253 00254 case AtanOp: 00255 // 1 + x * x, atan(x) 00256 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00257 reverse_sparse_jacobian_unary_op( 00258 i_var, arg[0], var_sparsity 00259 ); 00260 break; 00261 // ------------------------------------------------- 00262 00263 case BeginOp: 00264 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00265 more_operators = false; 00266 break; 00267 // ------------------------------------------------- 00268 00269 case CSkipOp: 00270 // CSkipOp has a variable number of arguments and 00271 // reverse_next thinks it one has one argument. 00272 // We must inform reverse_next of this special case. 00273 play->reverse_cskip(op, arg, i_op, i_var); 00274 break; 00275 // ------------------------------------------------- 00276 00277 case CSumOp: 00278 // CSumOp has a variable number of arguments and 00279 // reverse_next thinks it one has one argument. 00280 // We must inform reverse_next of this special case. 00281 play->reverse_csum(op, arg, i_op, i_var); 00282 reverse_sparse_jacobian_csum_op( 00283 i_var, arg, var_sparsity 00284 ); 00285 break; 00286 // ------------------------------------------------- 00287 00288 case CExpOp: 00289 reverse_sparse_jacobian_cond_op( 00290 nz_compare, i_var, arg, num_par, var_sparsity 00291 ); 00292 break; 00293 // --------------------------------------------------- 00294 00295 case ComOp: 00296 CPPAD_ASSERT_NARG_NRES(op, 4, 0); 00297 CPPAD_ASSERT_UNKNOWN( arg[1] > 1 ); 00298 break; 00299 // -------------------------------------------------- 00300 00301 case CosOp: 00302 // sin(x), cos(x) 00303 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00304 reverse_sparse_jacobian_unary_op( 00305 i_var, arg[0], var_sparsity 00306 ); 00307 break; 00308 // --------------------------------------------------- 00309 00310 case CoshOp: 00311 // sinh(x), cosh(x) 00312 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00313 reverse_sparse_jacobian_unary_op( 00314 i_var, arg[0], var_sparsity 00315 ); 00316 break; 00317 // ------------------------------------------------- 00318 00319 case DisOp: 00320 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00321 // derivative is identically zero 00322 break; 00323 // ------------------------------------------------- 00324 00325 case DivvvOp: 00326 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00327 reverse_sparse_jacobian_binary_op( 00328 i_var, arg, var_sparsity 00329 ); 00330 break; 00331 // ------------------------------------------------- 00332 00333 case DivpvOp: 00334 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00335 reverse_sparse_jacobian_unary_op( 00336 i_var, arg[1], var_sparsity 00337 ); 00338 break; 00339 // ------------------------------------------------- 00340 00341 case DivvpOp: 00342 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00343 reverse_sparse_jacobian_unary_op( 00344 i_var, arg[0], var_sparsity 00345 ); 00346 break; 00347 // ------------------------------------------------- 00348 00349 case ExpOp: 00350 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00351 reverse_sparse_jacobian_unary_op( 00352 i_var, arg[0], var_sparsity 00353 ); 00354 break; 00355 // ------------------------------------------------- 00356 00357 case InvOp: 00358 CPPAD_ASSERT_NARG_NRES(op, 0, 1); 00359 break; 00360 // ------------------------------------------------- 00361 00362 case LdpOp: 00363 reverse_sparse_jacobian_load_op( 00364 op, 00365 i_var, 00366 arg, 00367 num_vecad_ind, 00368 vecad_ind.data(), 00369 var_sparsity, 00370 vecad_sparsity 00371 ); 00372 break; 00373 // ------------------------------------------------- 00374 00375 case LdvOp: 00376 reverse_sparse_jacobian_load_op( 00377 op, 00378 i_var, 00379 arg, 00380 num_vecad_ind, 00381 vecad_ind.data(), 00382 var_sparsity, 00383 vecad_sparsity 00384 ); 00385 break; 00386 // ------------------------------------------------- 00387 00388 case LogOp: 00389 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00390 reverse_sparse_jacobian_unary_op( 00391 i_var, arg[0], var_sparsity 00392 ); 00393 break; 00394 // ------------------------------------------------- 00395 00396 case MulvvOp: 00397 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00398 reverse_sparse_jacobian_binary_op( 00399 i_var, arg, var_sparsity 00400 ); 00401 break; 00402 // ------------------------------------------------- 00403 00404 case MulpvOp: 00405 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00406 reverse_sparse_jacobian_unary_op( 00407 i_var, arg[1], var_sparsity 00408 ); 00409 break; 00410 // ------------------------------------------------- 00411 00412 case ParOp: 00413 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00414 00415 break; 00416 // ------------------------------------------------- 00417 00418 case PowvpOp: 00419 reverse_sparse_jacobian_unary_op( 00420 i_var, arg[0], var_sparsity 00421 ); 00422 break; 00423 // ------------------------------------------------- 00424 00425 case PowpvOp: 00426 CPPAD_ASSERT_NARG_NRES(op, 2, 3); 00427 reverse_sparse_jacobian_unary_op( 00428 i_var, arg[1], var_sparsity 00429 ); 00430 break; 00431 // ------------------------------------------------- 00432 00433 case PowvvOp: 00434 CPPAD_ASSERT_NARG_NRES(op, 2, 3); 00435 reverse_sparse_jacobian_binary_op( 00436 i_var, arg, var_sparsity 00437 ); 00438 break; 00439 // ------------------------------------------------- 00440 00441 case PriOp: 00442 CPPAD_ASSERT_NARG_NRES(op, 5, 0); 00443 break; 00444 // ------------------------------------------------- 00445 00446 case SignOp: 00447 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00448 // derivative is identically zero 00449 break; 00450 // ------------------------------------------------- 00451 00452 case SinOp: 00453 // cos(x), sin(x) 00454 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00455 reverse_sparse_jacobian_unary_op( 00456 i_var, arg[0], var_sparsity 00457 ); 00458 break; 00459 // ------------------------------------------------- 00460 00461 case SinhOp: 00462 // cosh(x), sinh(x) 00463 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00464 reverse_sparse_jacobian_unary_op( 00465 i_var, arg[0], var_sparsity 00466 ); 00467 break; 00468 // ------------------------------------------------- 00469 00470 case SqrtOp: 00471 CPPAD_ASSERT_NARG_NRES(op, 1, 1); 00472 reverse_sparse_jacobian_unary_op( 00473 i_var, arg[0], var_sparsity 00474 ); 00475 break; 00476 // ------------------------------------------------- 00477 00478 case StppOp: 00479 // sparsity cannot proagate through a parameter 00480 CPPAD_ASSERT_NARG_NRES(op, 3, 0); 00481 break; 00482 // ------------------------------------------------- 00483 00484 case StpvOp: 00485 reverse_sparse_jacobian_store_op( 00486 op, 00487 arg, 00488 num_vecad_ind, 00489 vecad_ind.data(), 00490 var_sparsity, 00491 vecad_sparsity 00492 ); 00493 break; 00494 // ------------------------------------------------- 00495 00496 case StvpOp: 00497 CPPAD_ASSERT_NARG_NRES(op, 3, 0); 00498 break; 00499 // ------------------------------------------------- 00500 00501 case StvvOp: 00502 reverse_sparse_jacobian_store_op( 00503 op, 00504 arg, 00505 num_vecad_ind, 00506 vecad_ind.data(), 00507 var_sparsity, 00508 vecad_sparsity 00509 ); 00510 break; 00511 // ------------------------------------------------- 00512 00513 case SubvvOp: 00514 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00515 reverse_sparse_jacobian_binary_op( 00516 i_var, arg, var_sparsity 00517 ); 00518 break; 00519 // ------------------------------------------------- 00520 00521 case SubpvOp: 00522 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00523 reverse_sparse_jacobian_unary_op( 00524 i_var, arg[1], var_sparsity 00525 ); 00526 break; 00527 // ------------------------------------------------- 00528 00529 case SubvpOp: 00530 CPPAD_ASSERT_NARG_NRES(op, 2, 1); 00531 reverse_sparse_jacobian_unary_op( 00532 i_var, arg[0], var_sparsity 00533 ); 00534 break; 00535 // ------------------------------------------------- 00536 00537 case TanOp: 00538 // tan(x)^2, tan(x) 00539 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00540 reverse_sparse_jacobian_unary_op( 00541 i_var, arg[0], var_sparsity 00542 ); 00543 break; 00544 // ------------------------------------------------- 00545 00546 case TanhOp: 00547 // tanh(x)^2, tanh(x) 00548 CPPAD_ASSERT_NARG_NRES(op, 1, 2); 00549 reverse_sparse_jacobian_unary_op( 00550 i_var, arg[0], var_sparsity 00551 ); 00552 break; 00553 // ------------------------------------------------- 00554 00555 case UserOp: 00556 // start or end atomic operation sequence 00557 CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); 00558 CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); 00559 if( user_state == user_end ) 00560 { user_index = arg[0]; 00561 user_id = arg[1]; 00562 user_n = arg[2]; 00563 user_m = arg[3]; 00564 user_atom = atomic_base<Base>::class_object(user_index); 00565 # ifndef NDEBUG 00566 if( user_atom == CPPAD_NULL ) 00567 { std::string msg = 00568 atomic_base<Base>::class_name(user_index) 00569 + ": atomic_base function has been deleted"; 00570 CPPAD_ASSERT_KNOWN(false, msg.c_str() ); 00571 } 00572 # endif 00573 user_bool = user_atom->sparsity() == 00574 atomic_base<Base>::bool_sparsity_enum; 00575 if( user_bool ) 00576 { if( bool_r.size() != user_m * user_q ) 00577 bool_r.resize( user_m * user_q ); 00578 if( bool_s.size() != user_n * user_q ) 00579 bool_s.resize( user_n * user_q ); 00580 for(i = 0; i < user_m; i++) 00581 for(j = 0; j < user_q; j++) 00582 bool_r[ i * user_q + j] = false; 00583 } 00584 else 00585 { if(set_r.size() != user_m ) 00586 set_r.resize(user_m); 00587 if(set_s.size() != user_n ) 00588 set_s.resize(user_n); 00589 for(i = 0; i < user_m; i++) 00590 set_r[i].clear(); 00591 } 00592 user_j = user_n; 00593 user_i = user_m; 00594 user_state = user_ret; 00595 } 00596 else 00597 { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); 00598 CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); 00599 CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); 00600 CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); 00601 CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); 00602 # ifndef NDEBUG 00603 if( ! user_ok ) 00604 { std::string msg = 00605 atomic_base<Base>::class_name(user_index) 00606 + ": atomic_base.rev_sparse_jac: returned false"; 00607 CPPAD_ASSERT_KNOWN(false, msg.c_str() ); 00608 } 00609 # endif 00610 user_state = user_end; 00611 } 00612 break; 00613 00614 case UsrapOp: 00615 // parameter argument in an atomic operation sequence 00616 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00617 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00618 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00619 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00620 --user_j; 00621 if( user_j == 0 ) 00622 user_state = user_start; 00623 break; 00624 00625 case UsravOp: 00626 // variable argument in an atomic operation sequence 00627 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00628 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00629 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00630 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); 00631 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00632 --user_j; 00633 // It might be faster if we add set union to var_sparsity 00634 // where one of the sets is not in var_sparsity. 00635 if( user_bool ) 00636 { for(j = 0; j < user_q; j++) 00637 if( bool_s[ user_j * user_q + j ] ) 00638 var_sparsity.add_element(arg[0], j); 00639 } 00640 else 00641 { set_itr = set_s[user_j].begin(); 00642 set_end = set_s[user_j].end(); 00643 while( set_itr != set_end ) 00644 var_sparsity.add_element(arg[0], *set_itr++); 00645 } 00646 if( user_j == 0 ) 00647 user_state = user_start; 00648 break; 00649 00650 case UsrrpOp: 00651 // parameter result in an atomic operation sequence 00652 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00653 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00654 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00655 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); 00656 --user_i; 00657 if( user_i == 0 ) 00658 { // call users function for this operation 00659 user_atom->set_id(user_id); 00660 if( user_bool) 00661 CPPAD_ATOMIC_CALL( 00662 user_q, bool_r, bool_s 00663 ); 00664 else 00665 CPPAD_ATOMIC_CALL( 00666 user_q, set_r, set_s 00667 ); 00668 user_state = user_arg; 00669 } 00670 break; 00671 00672 case UsrrvOp: 00673 // variable result in an atomic operation sequence 00674 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00675 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00676 --user_i; 00677 var_sparsity.begin(i_var); 00678 i = var_sparsity.next_element(); 00679 while( i < user_q ) 00680 { if( user_bool ) 00681 bool_r[ user_i * user_q + i ] = true; 00682 else 00683 set_r[user_i].insert(i); 00684 i = var_sparsity.next_element(); 00685 } 00686 if( user_i == 0 ) 00687 { // call users function for this operation 00688 user_atom->set_id(user_id); 00689 if( user_bool) 00690 CPPAD_ATOMIC_CALL( 00691 user_q, bool_r, bool_s 00692 ); 00693 else 00694 CPPAD_ATOMIC_CALL( 00695 user_q, set_r, set_s 00696 ); 00697 user_state = user_arg; 00698 } 00699 break; 00700 // ------------------------------------------------- 00701 00702 default: 00703 CPPAD_ASSERT_UNKNOWN(0); 00704 } 00705 # if CPPAD_REV_JAC_SWEEP_TRACE 00706 for(j = 0; j < limit; j++) 00707 z_value[j] = false; 00708 var_sparsity.begin(i_var); 00709 j = var_sparsity.next_element(); 00710 while( j < limit ) 00711 { z_value[j] = true; 00712 j = var_sparsity.next_element(); 00713 } 00714 printOp( 00715 std::cout, 00716 play, 00717 i_op, 00718 i_var, 00719 op, 00720 arg, 00721 0, 00722 (CppAD::vector<bool> *) CPPAD_NULL, 00723 1, 00724 &z_value 00725 ); 00726 # endif 00727 } 00728 // values corresponding to BeginOp 00729 CPPAD_ASSERT_UNKNOWN( i_op == 0 ); 00730 CPPAD_ASSERT_UNKNOWN( i_var == 0 ); 00731 00732 return; 00733 } 00734 } // END_CPPAD_NAMESPACE 00735 00736 // preprocessor symbols that are local to this file 00737 # undef CPPAD_REV_JAC_SWEEP_TRACE 00738 # undef CPPAD_ATOMIC_CALL 00739 00740 # endif