CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_LOAD_OP_INCLUDED 00003 # define CPPAD_LOAD_OP_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 load_op.hpp 00020 Setting a variable so that it corresponds to current value of a VecAD element. 00021 */ 00022 00023 /*! 00024 Shared documentation for zero order forward mode implementation of 00025 op = LdpOp or LdvOp (not called). 00026 00027 The C++ source code corresponding to this operation is 00028 \verbatim 00029 z = v[x] 00030 \endverbatim 00031 where v is a VecAD<Base> vector and x is an AD<Base> index. 00032 We define the index corresponding to v[x] by 00033 \verbatim 00034 i_v_x = index_by_ind[ arg[0] + i_vec ] 00035 \endverbatim 00036 where i_vec is defined under the heading arg[1] below: 00037 00038 \tparam Base 00039 base type for the operator; i.e., this operation was recorded 00040 using AD<Base> and computations by this routine are done using type Base. 00041 00042 \param play 00043 is the tape that this operation appears in. 00044 This is for error detection and not used when NDEBUG is defined. 00045 00046 \param i_z 00047 is the AD variable index corresponding to the variable z. 00048 00049 \param arg 00050 \n 00051 arg[0] 00052 is the offset of this VecAD vector relative to the beginning 00053 of the isvar_by_ind and index)_by_ind arrays. 00054 \n 00055 \n 00056 arg[1] 00057 \n 00058 If this is the LdpOp operation (if x is a parameter), 00059 i_vec is defined by 00060 \verbatim 00061 i_vec = arg[1] 00062 \endverbatim 00063 If this is the LdvOp operation (if x is a variable), 00064 i_vec is defined by 00065 \verbatim 00066 i_vec = floor( taylor[ arg[1] * nc_taylor + 0 ] ) 00067 \endverbatim 00068 where floor(c) is the greatest integer less that or equal c. 00069 \n 00070 \n 00071 arg[2] 00072 Is the index of this vecad load instruction in the 00073 var_by_load_op array. 00074 00075 \param parameter 00076 If v[x] is a parameter, <code>parameter[ i_v_x ]</code> is its value. 00077 This vector has size play->num_par_rec(). 00078 00079 \param nc_taylor 00080 number of columns in the matrix containing the Taylor coefficients. 00081 00082 \param taylor 00083 \n 00084 Input 00085 \n 00086 In LdvOp case, <code>taylor[ arg[1] * nc_taylor + 0 ]</code> 00087 is used to compute the index in the definition of i_vec above. 00088 If v[x] is a variable, <code>taylor[ i_v_x * nc_taylor + 0 ]</code> 00089 is the zero order Taylor coefficient for v[x]. 00090 \n 00091 \n 00092 Output 00093 \n 00094 <code>taylor[ i_z * nc_taylor + 0 ]</code> 00095 is set to the zero order Taylor coefficient for the variable z. 00096 00097 \param isvar_by_ind 00098 If <code>isvar_by_ind[ arg[0] + i_vec ] </code> is true, 00099 v[x] is a variable. Otherwise it is a parameter. 00100 This vector has size play->num_vec_ind_rec(). 00101 00102 \param index_by_ind 00103 <code>index_by_ind[ arg[0] - 1 ]</code> 00104 is the number of elements in the user vector containing this element. 00105 <code>index_by_ind[ arg[0] + i_vec ]</code> is the variable or 00106 parameter index for this element, 00107 This array has size play->num_vec_ind_rec(). 00108 00109 \param var_by_load_op 00110 is a vector with size play->num_load_op_rec(). 00111 The input value of its elements does not matter. 00112 Upon return, it contains the variable index corresponding to each load 00113 instruction. 00114 In the case where the index is zero, 00115 the instruction corresponds to a parameter (not variable). 00116 This array has size play->num_load_op_rec(). 00117 00118 \par Check User Errors 00119 \li In the LdvOp case check that the index is with in range; i.e. 00120 <code>i_vec < index_by_ind[ arg[0] - 1 ]</code>. 00121 Note that, if x is a parameter, 00122 the corresponding vector index and it does not change. 00123 In this case, the error above should be detected during tape recording. 00124 */ 00125 template <class Base> 00126 inline void forward_load_op_0( 00127 player<Base>* play , 00128 size_t i_z , 00129 const addr_t* arg , 00130 const Base* parameter , 00131 size_t nc_taylor , 00132 Base* taylor , 00133 bool* isvar_by_ind , 00134 size_t* index_by_ind , 00135 addr_t* var_by_load_op ) 00136 { 00137 // This routine is only for documentaiton, it should not be used 00138 CPPAD_ASSERT_UNKNOWN( false ); 00139 } 00140 /*! 00141 Shared documentation for sparsity operations corresponding to 00142 op = LdpOp or LdvOp (not called). 00143 00144 <!-- define sparse_load_op --> 00145 The C++ source code corresponding to this operation is 00146 \verbatim 00147 z = v[x] 00148 \endverbatim 00149 where v is a VecAD<Base> vector and x is an AD<Base> index. 00150 00151 \tparam Vector_set 00152 is the type used for vectors of sets. It can be either 00153 \c sparse_pack, \c sparse_set, or \c sparse_list. 00154 00155 \param op 00156 is the code corresponding to this operator; i.e., LdpOp or LdvOp 00157 (only used for error checking). 00158 00159 \param i_z 00160 is the AD variable index corresponding to the variable z; i.e., 00161 the set with index \a i_z in \a var_sparsity is the sparsity pattern 00162 correpsonding to z. 00163 00164 \param arg 00165 \n 00166 \a arg[0] 00167 is the offset corresponding to this VecAD vector in the VecAD combined array. 00168 00169 \param num_combined 00170 is the total number of elements in the VecAD combinded array. 00171 00172 \param combined 00173 is the VecAD combined array. 00174 \n 00175 \n 00176 \a combined[ \a arg[0] - 1 ] 00177 is the index of the set corresponding to the vector v in \a vecad_sparsity. 00178 We use the notation i_v for this value; i.e., 00179 \verbatim 00180 i_v = combined[ \a arg[0] - 1 ] 00181 \endverbatim 00182 00183 \param var_sparsity 00184 The set with index \a i_z in \a var_sparsity is the sparsity pattern for z. 00185 This is an output for forward mode operations, 00186 and an input for reverse mode operations. 00187 00188 \param vecad_sparsity 00189 The set with index \a i_v is the sparsity pattern for the vector v. 00190 This is an input for forward mode operations. 00191 For reverse mode operations, 00192 the sparsity pattern for z is added to the sparsity pattern for v. 00193 00194 \par Checked Assertions 00195 \li NumArg(op) == 3 00196 \li NumRes(op) == 1 00197 \li 0 < \a arg[0] 00198 \li \a arg[0] < \a num_combined 00199 \li i_v < \a vecad_sparsity.n_set() 00200 <!-- end sparse_load_op --> 00201 */ 00202 template <class Vector_set> 00203 inline void sparse_load_op( 00204 OpCode op , 00205 size_t i_z , 00206 const addr_t* arg , 00207 size_t num_combined , 00208 const size_t* combined , 00209 Vector_set& var_sparsity , 00210 Vector_set& vecad_sparsity ) 00211 { 00212 // This routine is only for documentaiton, it should not be used 00213 CPPAD_ASSERT_UNKNOWN( false ); 00214 } 00215 00216 00217 /*! 00218 Zero order forward mode implementation of op = LdpOp. 00219 00220 \copydetails forward_load_op_0 00221 */ 00222 template <class Base> 00223 inline void forward_load_p_op_0( 00224 player<Base>* play , 00225 size_t i_z , 00226 const addr_t* arg , 00227 const Base* parameter , 00228 size_t nc_taylor , 00229 Base* taylor , 00230 bool* isvar_by_ind , 00231 size_t* index_by_ind , 00232 addr_t* var_by_load_op ) 00233 { CPPAD_ASSERT_UNKNOWN( NumArg(LdpOp) == 3 ); 00234 CPPAD_ASSERT_UNKNOWN( NumRes(LdpOp) == 1 ); 00235 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00236 CPPAD_ASSERT_UNKNOWN( arg[2] < play->num_load_op_rec() ); 00237 00238 // Because the index is a parameter, this indexing error should be 00239 // caught and reported to the user at an when the tape is recording. 00240 size_t i_vec = arg[1]; 00241 CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] ); 00242 CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() ); 00243 00244 size_t i_v_x = index_by_ind[ arg[0] + i_vec ]; 00245 Base* z = taylor + i_z * nc_taylor; 00246 if( isvar_by_ind[ arg[0] + i_vec ] ) 00247 { CPPAD_ASSERT_UNKNOWN( i_v_x < i_z ); 00248 var_by_load_op[ arg[2] ] = i_v_x; 00249 Base* v_x = taylor + i_v_x * nc_taylor; 00250 z[0] = v_x[0]; 00251 } 00252 else 00253 { CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() ); 00254 var_by_load_op[ arg[2] ] = 0; 00255 Base v_x = parameter[i_v_x]; 00256 z[0] = v_x; 00257 } 00258 } 00259 00260 /*! 00261 Zero order forward mode implementation of op = LdvOp. 00262 00263 \copydetails forward_load_op_0 00264 */ 00265 template <class Base> 00266 inline void forward_load_v_op_0( 00267 player<Base>* play , 00268 size_t i_z , 00269 const addr_t* arg , 00270 const Base* parameter , 00271 size_t nc_taylor , 00272 Base* taylor , 00273 bool* isvar_by_ind , 00274 size_t* index_by_ind , 00275 addr_t* var_by_load_op ) 00276 { CPPAD_ASSERT_UNKNOWN( NumArg(LdvOp) == 3 ); 00277 CPPAD_ASSERT_UNKNOWN( NumRes(LdvOp) == 1 ); 00278 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00279 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00280 CPPAD_ASSERT_UNKNOWN( arg[2] < play->num_load_op_rec() ); 00281 00282 size_t i_vec = Integer( taylor[ arg[1] * nc_taylor + 0 ] ); 00283 CPPAD_ASSERT_KNOWN( 00284 i_vec < index_by_ind[ arg[0] - 1 ] , 00285 "VecAD: index during zero order forward sweep is out of range" 00286 ); 00287 CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() ); 00288 00289 size_t i_v_x = index_by_ind[ arg[0] + i_vec ]; 00290 Base* z = taylor + i_z * nc_taylor; 00291 if( isvar_by_ind[ arg[0] + i_vec ] ) 00292 { CPPAD_ASSERT_UNKNOWN( i_v_x < i_z ); 00293 var_by_load_op[ arg[2] ] = i_v_x; 00294 Base* v_x = taylor + i_v_x * nc_taylor; 00295 z[0] = v_x[0]; 00296 } 00297 else 00298 { CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() ); 00299 var_by_load_op[ arg[2] ] = 0; 00300 Base v_x = parameter[i_v_x]; 00301 z[0] = v_x; 00302 } 00303 } 00304 00305 /*! 00306 Forward mode, except for zero order, for op = LdpOp or op = LdvOp 00307 00308 The C++ source code corresponding to this operation is 00309 \verbatim 00310 z = v[x] 00311 \endverbatim 00312 where v is a VecAD<Base> vector and x is an AD<Base> or Base index. 00313 00314 \tparam Base 00315 base type for the operator; i.e., this operation was recorded 00316 using AD<Base> and computations by this routine are done using type Base. 00317 00318 \param op 00319 is the code corresponding to this operator; i.e., LdpOp or LdvOp 00320 (only used for error checking). 00321 00322 \param p 00323 is the lowest order of the Taylor coefficient that we are computing. 00324 00325 \param q 00326 is the highest order of the Taylor coefficient that we are computing. 00327 00328 \param i_z 00329 is the AD variable index corresponding to the variable z. 00330 00331 \param arg 00332 arg[2] 00333 Is the index of this vecad load instruction in the 00334 var_by_load_op array. 00335 00336 \param nc_taylor 00337 number of columns in the matrix containing the Taylor coefficients. 00338 00339 \param taylor 00340 \n 00341 Input 00342 \n 00343 If v[x] is a variable, <code>taylor[ arg[2] * nc_taylor + k ]</code> 00344 for k = 0 , ... , q, 00345 is the k-order Taylor coefficient corresponding to v[x]. 00346 \n 00347 \n 00348 Output 00349 \n 00350 <code>taylor[ i_z * nc_taylor + d ]</code> 00351 for k = p , ... , q, 00352 is set to the k-order Taylor coefficient for the variable z. 00353 00354 \param var_by_load_op 00355 is a vector with size play->num_load_op_rec(). 00356 It contains the variable index corresponding to each load instruction. 00357 In the case where the index is zero, 00358 the instruction corresponds to a parameter (not variable). 00359 */ 00360 template <class Base> 00361 inline void forward_load_op( 00362 OpCode op , 00363 size_t p , 00364 size_t q , 00365 size_t i_z , 00366 const addr_t* arg , 00367 size_t nc_taylor , 00368 Base* taylor , 00369 const addr_t* var_by_load_op ) 00370 { size_t i_load = size_t( var_by_load_op[ arg[2] ] ); 00371 00372 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00373 CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); 00374 CPPAD_ASSERT_UNKNOWN( q < nc_taylor ); 00375 CPPAD_ASSERT_UNKNOWN( 0 < p && p <= q ); 00376 CPPAD_ASSERT_UNKNOWN( i_load < i_z ); 00377 00378 Base* z = taylor + i_z * nc_taylor; 00379 if( i_load > 0 ) 00380 { Base* v_x = taylor + i_load * nc_taylor; 00381 for(size_t d = p; d <= q; d++) 00382 z[d] = v_x[d]; 00383 } 00384 else 00385 { for(size_t d = p; d <= q; d++) 00386 z[d] = Base(0); 00387 } 00388 } 00389 00390 /*! 00391 Reverse mode for op = LdpOp or LdvOp. 00392 00393 The C++ source code corresponding to this operation is 00394 \verbatim 00395 z = y[x] 00396 \endverbatim 00397 where y is a VecAD<Base> vector and x is an AD<Base> or Base index. 00398 00399 This routine is given the partial derivatives of a function 00400 G(z , y[x] , w , u ... ) 00401 and it uses them to compute the partial derivatives of 00402 \verbatim 00403 H( y[x] , w , u , ... ) = G[ z( y[x] ) , y[x] , w , u , ... ] 00404 \endverbatim 00405 00406 \tparam Base 00407 base type for the operator; i.e., this operation was recorded 00408 using AD< \a Base > and computations by this routine are done using type 00409 \a Base. 00410 00411 \param op 00412 is the code corresponding to this operator; i.e., LdpOp or LdvOp 00413 (only used for error checking). 00414 00415 \param d 00416 highest order the Taylor coefficient that we are computing the partial 00417 derivative with respect to. 00418 00419 \param i_z 00420 is the AD variable index corresponding to the variable z. 00421 00422 \param arg 00423 \a arg[2] 00424 Is the index of this vecad load instruction in the 00425 var_by_load_op array. 00426 00427 \param nc_taylor 00428 number of columns in the matrix containing the Taylor coefficients 00429 (not used). 00430 00431 \param taylor 00432 matrix of Taylor coefficients (not used). 00433 00434 \param nc_partial 00435 number of colums in the matrix containing all the partial derivatives 00436 (not used if \a arg[2] is zero). 00437 00438 \param partial 00439 If \a arg[2] is zero, y[x] is a parameter 00440 and no values need to be modified; i.e., \a partial is not used. 00441 Otherwise, y[x] is a variable and: 00442 \n 00443 \n 00444 \a partial [ \a i_z * \a nc_partial + k ] 00445 for k = 0 , ... , \a d 00446 is the partial derivative of G 00447 with respect to the k-th order Taylor coefficient for z. 00448 \n 00449 \n 00450 If \a arg[2] is not zero, 00451 \a partial [ \a arg[2] * \a nc_partial + k ] 00452 for k = 0 , ... , \a d 00453 is the partial derivative with respect to 00454 the k-th order Taylor coefficient for x. 00455 On input, it corresponds to the function G, 00456 and on output it corresponds to the the function H. 00457 00458 \param var_by_load_op 00459 is a vector with size play->num_load_op_rec(). 00460 It contains the variable index corresponding to each load instruction. 00461 In the case where the index is zero, 00462 the instruction corresponds to a parameter (not variable). 00463 00464 \par Checked Assertions 00465 \li NumArg(op) == 3 00466 \li NumRes(op) == 1 00467 \li d < nc_taylor 00468 \li size_t(arg[2]) < i_z 00469 */ 00470 template <class Base> 00471 inline void reverse_load_op( 00472 OpCode op , 00473 size_t d , 00474 size_t i_z , 00475 const addr_t* arg , 00476 size_t nc_taylor , 00477 const Base* taylor , 00478 size_t nc_partial , 00479 Base* partial , 00480 const addr_t* var_by_load_op ) 00481 { size_t i_load = size_t( var_by_load_op[ arg[2] ] ); 00482 00483 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00484 CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); 00485 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00486 CPPAD_ASSERT_UNKNOWN( i_load < i_z ); 00487 00488 if( i_load > 0 ) 00489 { 00490 Base* pz = partial + i_z * nc_partial; 00491 Base* py_x = partial + i_load * nc_partial; 00492 size_t j = d + 1; 00493 while(j--) 00494 py_x[j] += pz[j]; 00495 } 00496 } 00497 00498 00499 /*! 00500 Forward mode sparsity operations for LdpOp and LdvOp 00501 00502 \copydetails sparse_load_op 00503 */ 00504 template <class Vector_set> 00505 inline void forward_sparse_load_op( 00506 OpCode op , 00507 size_t i_z , 00508 const addr_t* arg , 00509 size_t num_combined , 00510 const size_t* combined , 00511 Vector_set& var_sparsity , 00512 Vector_set& vecad_sparsity ) 00513 { 00514 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00515 CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); 00516 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00517 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); 00518 size_t i_v = combined[ arg[0] - 1 ]; 00519 CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); 00520 00521 var_sparsity.assignment(i_z, i_v, vecad_sparsity); 00522 00523 return; 00524 } 00525 00526 00527 /*! 00528 Reverse mode Jacobian sparsity operations for LdpOp and LdvOp 00529 00530 \copydetails sparse_load_op 00531 */ 00532 template <class Vector_set> 00533 inline void reverse_sparse_jacobian_load_op( 00534 OpCode op , 00535 size_t i_z , 00536 const addr_t* arg , 00537 size_t num_combined , 00538 const size_t* combined , 00539 Vector_set& var_sparsity , 00540 Vector_set& vecad_sparsity ) 00541 { 00542 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00543 CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); 00544 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00545 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); 00546 size_t i_v = combined[ arg[0] - 1 ]; 00547 CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); 00548 00549 vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity); 00550 00551 return; 00552 } 00553 00554 00555 /*! 00556 Reverse mode Hessian sparsity operations for LdpOp and LdvOp 00557 00558 This routine is given the sparsity patterns for 00559 G(z , v[x] , w , u ... ) 00560 and it uses them to compute the sparsity patterns for 00561 \verbatim 00562 H( v[x] , w , u , ... ) = G[ z( v[x] ) , v[x] , w , u , ... ] 00563 \endverbatim 00564 00565 <!-- replace sparse_load_op --> 00566 The C++ source code corresponding to this operation is 00567 \verbatim 00568 z = v[x] 00569 \endverbatim 00570 where v is a VecAD<Base> vector and x is an AD<Base> index. 00571 00572 \tparam Vector_set 00573 is the type used for vectors of sets. It can be either 00574 \c sparse_pack, \c sparse_set, or \c sparse_list. 00575 00576 \param op 00577 is the code corresponding to this operator; i.e., LdpOp or LdvOp 00578 (only used for error checking). 00579 00580 \param i_z 00581 is the AD variable index corresponding to the variable z; i.e., 00582 the set with index \a i_z in \a var_sparsity is the sparsity pattern 00583 correpsonding to z. 00584 00585 \param arg 00586 \n 00587 \a arg[0] 00588 is the offset corresponding to this VecAD vector in the VecAD combined array. 00589 00590 \param num_combined 00591 is the total number of elements in the VecAD combinded array. 00592 00593 \param combined 00594 is the VecAD combined array. 00595 \n 00596 \n 00597 \a combined[ \a arg[0] - 1 ] 00598 is the index of the set corresponding to the vector v in \a vecad_sparsity. 00599 We use the notation i_v for this value; i.e., 00600 \verbatim 00601 i_v = combined[ \a arg[0] - 1 ] 00602 \endverbatim 00603 00604 \param var_sparsity 00605 The set with index \a i_z in \a var_sparsity is the sparsity pattern for z. 00606 This is an output for forward mode operations, 00607 and an input for reverse mode operations. 00608 00609 \param vecad_sparsity 00610 The set with index \a i_v is the sparsity pattern for the vector v. 00611 This is an input for forward mode operations. 00612 For reverse mode operations, 00613 the sparsity pattern for z is added to the sparsity pattern for v. 00614 00615 \par Checked Assertions 00616 \li NumArg(op) == 3 00617 \li NumRes(op) == 1 00618 \li 0 < \a arg[0] 00619 \li \a arg[0] < \a num_combined 00620 \li i_v < \a vecad_sparsity.n_set() 00621 <!-- end sparse_load_op --> 00622 00623 \param var_jacobian 00624 \a var_jacobian[i_z] 00625 is false (true) if the Jacobian of G with respect to z is always zero 00626 (many be non-zero). 00627 00628 \param vecad_jacobian 00629 \a vecad_jacobian[i_v] 00630 is false (true) if the Jacobian with respect to x is always zero 00631 (may be non-zero). 00632 On input, it corresponds to the function G, 00633 and on output it corresponds to the function H. 00634 00635 */ 00636 template <class Vector_set> 00637 inline void reverse_sparse_hessian_load_op( 00638 OpCode op , 00639 size_t i_z , 00640 const addr_t* arg , 00641 size_t num_combined , 00642 const size_t* combined , 00643 Vector_set& var_sparsity , 00644 Vector_set& vecad_sparsity , 00645 bool* var_jacobian , 00646 bool* vecad_jacobian ) 00647 { 00648 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00649 CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 ); 00650 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00651 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined ); 00652 size_t i_v = combined[ arg[0] - 1 ]; 00653 CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() ); 00654 00655 vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity); 00656 00657 vecad_jacobian[i_v] |= var_jacobian[i_z]; 00658 00659 return; 00660 } 00661 00662 00663 } // END_CPPAD_NAMESPACE 00664 # endif