CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_OP_CODE_INCLUDED 00003 # define CPPAD_OP_CODE_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 # include <string> 00016 # include <sstream> 00017 # include <iomanip> 00018 00019 # include <cppad/local/define.hpp> 00020 # include <cppad/local/cppad_assert.hpp> 00021 00022 // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL 00023 # include <cppad/thread_alloc.hpp> 00024 00025 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00026 /*! 00027 \file op_code.hpp 00028 Defines the OpCode enum type and functions related to it. 00029 00030 */ 00031 00032 00033 /*! 00034 Type used to distinguish different AD< \a Base > atomic operations. 00035 00036 Each of the operators ends with the characters Op. Ignoring the Op at the end, 00037 the operators appear in alphabetical order. Binary operation where both 00038 operands have type AD< \a Base > use the following convention for thier endings: 00039 \verbatim 00040 Ending Left-Operand Right-Operand 00041 pvOp parameter variable 00042 vpOp variable parameter 00043 vvOp variable variable 00044 \endverbatim 00045 For example, AddpvOp represents the addition operator where the left 00046 operand is a parameter and the right operand is a variable. 00047 */ 00048 // alphabetical order is checked by bin/check_op_code.sh 00049 enum OpCode { 00050 AbsOp, // abs(variable) 00051 AcosOp, // asin(variable) 00052 AddpvOp, // parameter + variable 00053 AddvvOp, // variable + variable 00054 AsinOp, // asin(variable) 00055 AtanOp, // atan(variable) 00056 BeginOp, // used to mark the beginning of the tape 00057 CExpOp, // CondExpRel(left, right, trueCase, falseCase) 00058 // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne 00059 // arg[1] & 1 = is left a variable 00060 // arg[1] & 2 = is right a variable 00061 // arg[1] & 4 = is trueCase a variable 00062 // arg[1] & 8 = is falseCase a variable 00063 // arg[2] = index correspoding to left 00064 // arg[3] = index correspoding to right 00065 // arg[4] = index correspoding to trueCase 00066 // arg[5] = index correspoding to falseCase 00067 ComOp, // Compare(cop, result, left, right) 00068 CosOp, // cos(variable) 00069 CoshOp, // cosh(variable) 00070 CSkipOp, // Conditional skip 00071 // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne 00072 // arg[1] & 1 = is left a variable 00073 // arg[1] & 2 = is right a variable 00074 // arg[2] = index correspoding to left 00075 // arg[3] = index correspoding to right 00076 // arg[4] = number of operations to skip if CExpOp comparision is true 00077 // arg[5] = number of operations to skip if CExpOp comparision is false 00078 // arg[6] -> arg[5+arg[4]] = skip operations if true 00079 // arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false 00080 // arg[6+arg[4]+arg[5]] = arg[4] + arg[5] 00081 CSumOp, // Cummulative summation 00082 // arg[0] = number of addition variables in summation 00083 // arg[1] = number of subtraction variables in summation 00084 // arg[2] = index of parameter that initializes summation 00085 // arg[3] -> arg[2+arg[0]] = index for positive variables 00086 // arg[3+arg[0]] -> arg[2+arg[0]+arg[1]] = index for minus variables 00087 // arg[3+arg[0]+arg[1]] = arg[0] + arg[1] 00088 DisOp, // discrete::eval(index, variable) 00089 DivpvOp, // parameter / variable 00090 DivvpOp, // variable / parameter 00091 DivvvOp, // variable / variable 00092 EndOp, // used to mark the end of the tape 00093 ExpOp, // exp(variable) 00094 InvOp, // independent variable 00095 LdpOp, // z[parameter] 00096 LdvOp, // z[variable] 00097 LogOp, // log(variable) 00098 MulpvOp, // parameter * variable 00099 MulvvOp, // variable * variable 00100 ParOp, // parameter 00101 PowpvOp, // pow(parameter, variable) 00102 PowvpOp, // pow(variable, parameter) 00103 PowvvOp, // pow(variable, variable) 00104 PriOp, // PrintFor(text, parameter or variable, parameter or variable) 00105 SignOp, // sign(variable) 00106 SinOp, // sin(variable) 00107 SinhOp, // sinh(variable) 00108 SqrtOp, // sqrt(variable) 00109 StppOp, // z[parameter] = parameter 00110 StpvOp, // z[parameter] = variable 00111 StvpOp, // z[variable] = parameter 00112 StvvOp, // z[variable] = variable 00113 SubpvOp, // parameter - variable 00114 SubvpOp, // variable - parameter 00115 SubvvOp, // variable - variable 00116 TanOp, // tan(variable) 00117 TanhOp, // tan(variable) 00118 // user atomic operation codes 00119 UserOp, // start of a user atomic operaiton 00120 // arg[0] = index of the operation if atomic_base<Base> class 00121 // arg[1] = extra information passed trough by deprecated old atomic class 00122 // arg[2] = number of arguments to this atomic function 00123 // arg[3] = number of results for this atomic function 00124 UsrapOp, // this user atomic argument is a parameter 00125 UsravOp, // this user atomic argument is a variable 00126 UsrrpOp, // this user atomic result is a parameter 00127 UsrrvOp, // this user atomic result is a variable 00128 NumberOp 00129 }; 00130 // Note that bin/check_op_code.sh assumes the pattern '^\tNumberOp$' occurs 00131 // at the end of this list and only at the end of this list. 00132 00133 /*! 00134 Number of arguments for a specified operator. 00135 00136 \return 00137 Number of arguments corresponding to the specified operator. 00138 00139 \param op 00140 Operator for which we are fetching the number of arugments. 00141 00142 \par NumArgTable 00143 this table specifes the number of arguments stored for each 00144 occurance of the operator that is the i-th value in the OpCode enum type. 00145 For example, for the first three OpCode enum values we have 00146 \verbatim 00147 OpCode j NumArgTable[j] Meaning 00148 AbsOp 0 1 index of variable we are taking absolute value of 00149 AcosOp 1 1 index of variable we are taking cosine of 00150 AddpvOp 1 2 indices of parameter and variable we are adding 00151 \endverbatim 00152 Note that the meaning of the arguments depends on the operator. 00153 */ 00154 inline size_t NumArg( OpCode op) 00155 { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; 00156 00157 // agreement with OpCode is checked by bin/check_op_code.sh 00158 static const size_t NumArgTable[] = { 00159 1, // AbsOp 00160 1, // AcosOp 00161 2, // AddpvOp 00162 2, // AddvvOp 00163 1, // AsinOp 00164 1, // AtanOp 00165 1, // BeginOp offset first real argument to have index 1 00166 6, // CExpOp 00167 4, // ComOp 00168 1, // CosOp 00169 1, // CoshOp 00170 0, // CSkipOp (actually has a variable number of arguments, not zero) 00171 0, // CSumOp (actually has a variable number of arguments, not zero) 00172 2, // DisOp 00173 2, // DivpvOp 00174 2, // DivvpOp 00175 2, // DivvvOp 00176 0, // EndOp 00177 1, // ExpOp 00178 0, // InvOp 00179 3, // LdpOp 00180 3, // LdvOp 00181 1, // LogOp 00182 2, // MulpvOp 00183 2, // MulvvOp 00184 1, // ParOp 00185 2, // PowpvOp 00186 2, // PowvpOp 00187 2, // PowvvOp 00188 5, // PriOp 00189 1, // SignOp 00190 1, // SinOp 00191 1, // SinhOp 00192 1, // SqrtOp 00193 3, // StppOp 00194 3, // StpvOp 00195 3, // StvpOp 00196 3, // StvvOp 00197 2, // SubpvOp 00198 2, // SubvpOp 00199 2, // SubvvOp 00200 1, // TanOp 00201 1, // TanhOp 00202 4, // UserOp 00203 1, // UsrapOp 00204 1, // UsravOp 00205 1, // UsrrpOp 00206 0 // UsrrvOp 00207 }; 00208 # ifndef NDEBUG 00209 // only do these checks once to save time 00210 static bool first = true; 00211 if( first ) 00212 { CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == 00213 sizeof(NumArgTable) / sizeof(NumArgTable[0]) 00214 ); 00215 CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) <= 00216 std::numeric_limits<CPPAD_OP_CODE_TYPE>::max() 00217 ); 00218 first = false; 00219 } 00220 // do this check every time 00221 CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); 00222 # endif 00223 00224 return NumArgTable[op]; 00225 } 00226 00227 /*! 00228 Number of variables resulting from the specified operation. 00229 00230 \param op 00231 Operator for which we are fecching the number of results. 00232 00233 \par NumResTable 00234 table specifes the number of varibles that result for each 00235 occurance of the operator that is the i-th value in the OpCode enum type. 00236 For example, for the first three OpCode enum values we have 00237 \verbatim 00238 OpCode j NumResTable[j] Meaning 00239 AbsOp 0 1 variable that is the result of the absolute value 00240 AcosOp 1 2 acos(x) and sqrt(1-x*x) are required for this op 00241 AddpvOp 1 1 variable that is the result of the addition 00242 \endverbatim 00243 */ 00244 inline size_t NumRes(OpCode op) 00245 { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; 00246 00247 // agreement with OpCode is checked by bin/check_op_code.sh 00248 static const size_t NumResTable[] = { 00249 1, // AbsOp 00250 2, // AcosOp 00251 1, // AddpvOp 00252 1, // AddvvOp 00253 2, // AsinOp 00254 2, // AtanOp 00255 1, // BeginOp offsets first variable to have index one (not zero) 00256 1, // CExpOp 00257 0, // ComOp 00258 2, // CosOp 00259 2, // CoshOp 00260 0, // CSkipOp 00261 1, // CSumOp 00262 1, // DisOp 00263 1, // DivpvOp 00264 1, // DivvpOp 00265 1, // DivvvOp 00266 0, // EndOp 00267 1, // ExpOp 00268 1, // InvOp 00269 1, // LdpOp 00270 1, // LdvOp 00271 1, // LogOp 00272 1, // MulpvOp 00273 1, // MulvvOp 00274 1, // ParOp 00275 3, // PowpvOp 00276 3, // PowvpOp 00277 3, // PowvvOp 00278 0, // PriOp 00279 1, // SignOp 00280 2, // SinOp 00281 2, // SinhOp 00282 1, // SqrtOp 00283 0, // StppOp 00284 0, // StpvOp 00285 0, // StvpOp 00286 0, // StvvOp 00287 1, // SubpvOp 00288 1, // SubvpOp 00289 1, // SubvvOp 00290 2, // TanOp 00291 2, // TanhOp 00292 0, // UserOp 00293 0, // UsrapOp 00294 0, // UsravOp 00295 0, // UsrrpOp 00296 1, // UsrrvOp 00297 0 // Last entry not used: avoids g++ 4.3.2 warn when pycppad builds 00298 }; 00299 // check ensuring conversion to size_t is as expected 00300 CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == 00301 sizeof(NumResTable) / sizeof(NumResTable[0]) - 1 00302 ); 00303 // this test ensures that all indices are within the table 00304 CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); 00305 00306 return NumResTable[op]; 00307 } 00308 00309 00310 /*! 00311 Fetch the name for a specified operation. 00312 00313 \return 00314 name of the specified operation. 00315 00316 \param op 00317 Operator for which we are fetching the name 00318 */ 00319 inline const char* OpName(OpCode op) 00320 { // agreement with OpCode is checked by bin/check_op_code.sh 00321 static const char *OpNameTable[] = { 00322 "Abs" , 00323 "Acos" , 00324 "Addpv" , 00325 "Addvv" , 00326 "Asin" , 00327 "Atan" , 00328 "Begin" , 00329 "CExp" , 00330 "Com" , 00331 "Cos" , 00332 "Cosh" , 00333 "CSkip" , 00334 "CSum" , 00335 "Dis" , 00336 "Divpv" , 00337 "Divvp" , 00338 "Divvv" , 00339 "End" , 00340 "Exp" , 00341 "Inv" , 00342 "Ldp" , 00343 "Ldv" , 00344 "Log" , 00345 "Mulpv" , 00346 "Mulvv" , 00347 "Par" , 00348 "Powpv" , 00349 "Powvp" , 00350 "Powvv" , 00351 "Pri" , 00352 "Sign" , 00353 "Sin" , 00354 "Sinh" , 00355 "Sqrt" , 00356 "Stpp" , 00357 "Stpv" , 00358 "Stvp" , 00359 "Stvv" , 00360 "Subpv" , 00361 "Subvp" , 00362 "Subvv" , 00363 "Tan" , 00364 "Tanh" , 00365 "User" , 00366 "Usrap" , 00367 "Usrav" , 00368 "Usrrp" , 00369 "Usrrv" 00370 }; 00371 // check ensuring conversion to size_t is as expected 00372 CPPAD_ASSERT_UNKNOWN( 00373 size_t(NumberOp) == sizeof(OpNameTable)/sizeof(OpNameTable[0]) 00374 ); 00375 // this test ensures that all indices are within the table 00376 CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) ); 00377 00378 return OpNameTable[op]; 00379 } 00380 00381 /*! 00382 Prints a single field corresponding to an operator. 00383 00384 A specified leader is printed in front of the value 00385 and then the value is left justified in the following width character. 00386 00387 \tparam Type 00388 is the type of the value we are printing. 00389 00390 \param os 00391 is the stream that we are printing to. 00392 00393 \param leader 00394 are characters printed before the value. 00395 00396 \param value 00397 is the value being printed. 00398 00399 \param width 00400 is the number of character to print the value in. 00401 If the value does not fit in the width, the value is replace 00402 by width '*' characters. 00403 */ 00404 template <class Type> 00405 void printOpField( 00406 std::ostream &os , 00407 const char * leader , 00408 const Type &value , 00409 size_t width ) 00410 { 00411 std::ostringstream buffer; 00412 std::string str; 00413 00414 // first print the leader 00415 os << leader; 00416 00417 // print the value into an internal buffer 00418 buffer << std::setw(width) << value; 00419 str = buffer.str(); 00420 00421 // length of the string 00422 size_t len = str.size(); 00423 if( len > width ) 00424 { size_t i; 00425 for(i = 0; i < width-1; i++) 00426 os << str[i]; 00427 os << "*"; 00428 return; 00429 } 00430 00431 // count number of spaces at begining 00432 size_t nspace = 0; 00433 while(str[nspace] == ' ' && nspace < len) 00434 nspace++; 00435 00436 // left justify the string 00437 size_t i = nspace; 00438 while( i < len ) 00439 os << str[i++]; 00440 00441 i = width - len + nspace; 00442 while(i--) 00443 os << " "; 00444 } 00445 00446 /*! 00447 Prints a single operator, its operands, and the corresponding result values. 00448 00449 \tparam Base 00450 Is the base type for these AD< \a Base > operations. 00451 00452 \tparam Value 00453 Determines the type of the values that we are printing. 00454 00455 \param os 00456 is the output stream that the information is printed on. 00457 00458 \param Rec 00459 2DO: change this name from Rec to play (becuase it is a player 00460 and not a recorder). 00461 Is the entire recording for the tape that this operator is in. 00462 00463 \param i_op 00464 is the index for the operator corresponding to this operation. 00465 00466 \param i_var 00467 is the index for the variable corresponding to the result of this operation 00468 (ignored if NumRes(op) == 0). 00469 00470 \param op 00471 The operator code (OpCode) for this operation. 00472 00473 \param ind 00474 is the vector of argument indices for this operation 00475 (must have NumArg(op) elements). 00476 00477 \param nfz 00478 is the number of forward sweep calculated values of type Value 00479 that correspond to this operation 00480 (ignored if NumRes(op) == 0). 00481 00482 \param fz 00483 points to the first forward calculated value 00484 that correspond to this operation 00485 (ignored if NumRes(op) == 0). 00486 00487 \param nrz 00488 is the number of reverse sweep calculated values of type Value 00489 that correspond to this operation 00490 (ignored if NumRes(op) == 0). 00491 00492 \param rz 00493 points to the first reverse calculated value 00494 that correspond to this operation 00495 (ignored if NumRes(op) == 0). 00496 00497 \par 2DO 00498 print the operator index (in addition to the variables index). 00499 */ 00500 template <class Base, class Value> 00501 void printOp( 00502 std::ostream &os , 00503 const player<Base> *Rec , 00504 size_t i_op , 00505 size_t i_var , 00506 OpCode op , 00507 const addr_t *ind , 00508 size_t nfz , 00509 const Value *fz , 00510 size_t nrz , 00511 const Value *rz ) 00512 { size_t i; 00513 CPPAD_ASSERT_KNOWN( 00514 ! thread_alloc::in_parallel() , 00515 "cannot print trace of AD operations in parallel mode" 00516 ); 00517 static const char *CompareOpName[] = 00518 { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" }; 00519 00520 // print operator 00521 printOpField(os, "o=", i_op, 5); 00522 printOpField(os, "v=", i_var, 5); 00523 if( op == CExpOp || op == CSkipOp || op == ComOp ) 00524 { printOpField(os, "", OpName(op), 5); 00525 printOpField(os, "", CompareOpName[ ind[0] ], 3); 00526 } 00527 else printOpField(os, "", OpName(op), 8); 00528 00529 // print other fields 00530 size_t ncol = 5; 00531 switch( op ) 00532 { 00533 case CSkipOp: 00534 /* 00535 ind[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne 00536 ind[1] & 1 = is left a variable 00537 ind[1] & 2 = is right a variable 00538 ind[2] = index correspoding to left 00539 ind[3] = index correspoding to right 00540 ind[4] = number of operations to skip if CExpOp comparision is true 00541 ind[5] = number of operations to skip if CExpOp comparision is false 00542 ind[6] -> ind[5+ind[4]] = skip operations if true 00543 ind[6+ind[4]] -> ind[5+ind[4]+ind[5]] = skip operations if false 00544 ind[6+ind[4]+ind[5]] = ind[4] + ind[5] 00545 */ 00546 CPPAD_ASSERT_UNKNOWN( ind[6+ind[4]+ind[5]] == ind[4]+ind[5] ); 00547 CPPAD_ASSERT_UNKNOWN(ind[1] != 0); 00548 if( ind[1] & 1 ) 00549 printOpField(os, " vl=", ind[2], ncol); 00550 else printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol); 00551 if( ind[1] & 2 ) 00552 printOpField(os, " vr=", ind[3], ncol); 00553 else printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol); 00554 if( size_t(ind[4]) < 3 ) 00555 { for(i = 0; i < size_t(ind[4]); i++) 00556 printOpField(os, " ot=", ind[6+i], ncol); 00557 } 00558 else 00559 { printOpField(os, "\n\tot=", ind[6+0], ncol); 00560 for(i = 1; i < size_t(ind[4]); i++) 00561 printOpField(os, " ot=", ind[6+i], ncol); 00562 } 00563 if( size_t(ind[5]) < 3 ) 00564 { for(i = 0; i < size_t(ind[5]); i++) 00565 printOpField(os, " of=", ind[6+ind[4]+i], ncol); 00566 } 00567 else 00568 { printOpField(os, "\n\tof=", ind[6+ind[4]+0], ncol); 00569 { for(i = 1; i < size_t(ind[5]); i++) 00570 printOpField(os, " of=", ind[6+ind[4]+i], ncol); 00571 } 00572 } 00573 break; 00574 00575 case CSumOp: 00576 /* 00577 ind[0] = number of addition variables in summation 00578 ind[1] = number of subtraction variables in summation 00579 ind[2] = index of parameter that initializes summation 00580 ind[3], ... , ind[2+ind[0]] = index for positive variables 00581 ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables 00582 ind[3+ind[0]+ind[1]] == ind[0] + ind[1] 00583 */ 00584 CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] ); 00585 printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol); 00586 for(i = 0; i < size_t(ind[0]); i++) 00587 printOpField(os, " +v=", ind[3+i], ncol); 00588 for(i = 0; i < size_t(ind[1]); i++) 00589 printOpField(os, " -v=", ind[3+ind[0]+i], ncol); 00590 break; 00591 00592 case LdpOp: 00593 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00594 printOpField(os, "off=", ind[0], ncol); 00595 printOpField(os, "idx=", ind[1], ncol); 00596 break; 00597 00598 case LdvOp: 00599 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00600 printOpField(os, "off=", ind[0], ncol); 00601 printOpField(os, " v=", ind[1], ncol); 00602 break; 00603 00604 case StppOp: 00605 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00606 printOpField(os, "off=", ind[0], ncol); 00607 printOpField(os, "idx=", ind[1], ncol); 00608 printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol); 00609 break; 00610 00611 case StpvOp: 00612 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00613 printOpField(os, "off=", ind[0], ncol); 00614 printOpField(os, "idx=", ind[1], ncol); 00615 printOpField(os, " vr=", ind[2], ncol); 00616 break; 00617 00618 case StvpOp: 00619 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00620 printOpField(os, "off=", ind[0], ncol); 00621 printOpField(os, " vl=", ind[1], ncol); 00622 printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol); 00623 break; 00624 00625 case StvvOp: 00626 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 ); 00627 printOpField(os, "off=", ind[0], ncol); 00628 printOpField(os, " vl=", ind[1], ncol); 00629 printOpField(os, " vr=", ind[2], ncol); 00630 break; 00631 00632 case AddvvOp: 00633 case DivvvOp: 00634 case MulvvOp: 00635 case PowvvOp: 00636 case SubvvOp: 00637 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); 00638 printOpField(os, " vl=", ind[0], ncol); 00639 printOpField(os, " vr=", ind[1], ncol); 00640 break; 00641 00642 case AddpvOp: 00643 case SubpvOp: 00644 case MulpvOp: 00645 case PowpvOp: 00646 case DivpvOp: 00647 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); 00648 printOpField(os, " pl=", Rec->GetPar(ind[0]), ncol); 00649 printOpField(os, " vr=", ind[1], ncol); 00650 break; 00651 00652 case DivvpOp: 00653 case PowvpOp: 00654 case SubvpOp: 00655 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); 00656 printOpField(os, " vl=", ind[0], ncol); 00657 printOpField(os, " pr=", Rec->GetPar(ind[1]), ncol); 00658 break; 00659 00660 case AbsOp: 00661 case AcosOp: 00662 case AsinOp: 00663 case AtanOp: 00664 case CosOp: 00665 case CoshOp: 00666 case ExpOp: 00667 case LogOp: 00668 case SignOp: 00669 case SinOp: 00670 case SinhOp: 00671 case SqrtOp: 00672 case UsravOp: 00673 case TanOp: 00674 case TanhOp: 00675 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00676 printOpField(os, " v=", ind[0], ncol); 00677 break; 00678 00679 case ParOp: 00680 case UsrapOp: 00681 case UsrrpOp: 00682 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00683 printOpField(os, " p=", Rec->GetPar(ind[0]), ncol); 00684 break; 00685 00686 case UserOp: 00687 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 ); 00688 { std::string name = atomic_base<Base>::class_name(ind[0]); 00689 printOpField(os, " f=", name.c_str(), ncol); 00690 printOpField(os, " i=", ind[1], ncol); 00691 printOpField(os, " n=", ind[2], ncol); 00692 printOpField(os, " m=", ind[3], ncol); 00693 } 00694 break; 00695 00696 case PriOp: 00697 CPPAD_ASSERT_NARG_NRES(op, 5, 0); 00698 if( ind[0] & 1 ) 00699 printOpField(os, " v=", ind[1], ncol); 00700 else printOpField(os, " p=", Rec->GetPar(ind[1]), ncol); 00701 os << "before=\"" << Rec->GetTxt(ind[2]) << "\""; 00702 if( ind[0] & 2 ) 00703 printOpField(os, " v=", ind[3], ncol); 00704 else printOpField(os, " p=", Rec->GetPar(ind[3]), ncol); 00705 os << "after=\"" << Rec->GetTxt(ind[4]) << "\""; 00706 break; 00707 00708 case BeginOp: 00709 // argument not used (created by independent) 00710 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00711 break; 00712 00713 case EndOp: 00714 case InvOp: 00715 case UsrrvOp: 00716 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); 00717 break; 00718 00719 case DisOp: 00720 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); 00721 { const char* name = discrete<Base>::name(ind[0]); 00722 printOpField(os, " f=", name, ncol); 00723 printOpField(os, " x=", ind[1], ncol); 00724 } 00725 break; 00726 00727 00728 case CExpOp: 00729 CPPAD_ASSERT_UNKNOWN(ind[1] != 0); 00730 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 ); 00731 if( ind[1] & 1 ) 00732 printOpField(os, " vl=", ind[2], ncol); 00733 else printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol); 00734 if( ind[1] & 2 ) 00735 printOpField(os, " vr=", ind[3], ncol); 00736 else printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol); 00737 if( ind[1] & 4 ) 00738 printOpField(os, " vt=", ind[4], ncol); 00739 else printOpField(os, " pt=", Rec->GetPar(ind[4]), ncol); 00740 if( ind[1] & 8 ) 00741 printOpField(os, " vf=", ind[5], ncol); 00742 else printOpField(os, " pf=", Rec->GetPar(ind[5]), ncol); 00743 break; 00744 00745 case ComOp: 00746 CPPAD_ASSERT_UNKNOWN(ind[1] != 0); 00747 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 ); 00748 if( ind[1] & 1 ) 00749 printOpField(os, "res=", 1, ncol); 00750 else printOpField(os, "res=", 0, ncol); 00751 if( ind[1] & 2 ) 00752 printOpField(os, " vl=", ind[2], ncol); 00753 else printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol); 00754 if( ind[1] & 4 ) 00755 printOpField(os, " vr=", ind[3], ncol); 00756 else printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol); 00757 break; 00758 00759 default: 00760 CPPAD_ASSERT_UNKNOWN(0); 00761 } 00762 size_t k; 00763 if( NumRes(op) > 0 && (op != BeginOp) ) 00764 { 00765 for(k = 0; k < nfz; k++) 00766 std::cout << "| fz[" << k << "]=" << fz[k]; 00767 for(k = 0; k < nrz; k++) 00768 std::cout << "| rz[" << k << "]=" << rz[k]; 00769 } 00770 std::cout << std::endl; 00771 } 00772 00773 } // END_CPPAD_NAMESPACE 00774 # endif