CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
op_code.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_OP_CODE_HPP
2 # define CPPAD_LOCAL_OP_CODE_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 # include <string>
15 # include <sstream>
16 # include <iomanip>
17 
18 # include <cppad/core/define.hpp>
21 
22 // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
24 
25 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
26 /*!
27 \file op_code.hpp
28 Defines the OpCode enum type and functions related to it.
29 
30 */
31 
32 
33 /*!
34 Type used to distinguish different AD< \a Base > atomic operations.
35 
36 Each of the operators ends with the characters Op. Ignoring the Op at the end,
37 the operators appear in alphabetical order. Binary operation where both
38 operands have type AD< \a Base > use the following convention for thier endings:
39 \verbatim
40  Ending Left-Operand Right-Operand
41  pvOp parameter variable
42  vpOp variable parameter
43  vvOp variable variable
44 \endverbatim
45 For example, AddpvOp represents the addition operator where the left
46 operand is a parameter and the right operand is a variable.
47 */
48 // alphabetical order is checked by bin/check_op_code.sh
49 enum OpCode {
50  AbsOp, // fabs(variable)
51  AcosOp, // acos(variable)
52  AcoshOp, // acosh(variable)
53  AddpvOp, // parameter + variable
54  AddvvOp, // variable + variable
55  AsinOp, // asin(variable)
56  AsinhOp, // asinh(variable)
57  AtanOp, // atan(variable)
58  AtanhOp, // atanh(variable)
59  BeginOp, // used to mark the beginning of the tape
60  CExpOp, // CondExpRel(left, right, trueCase, falseCase)
61  // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
62  // arg[1] & 1 = is left a variable
63  // arg[1] & 2 = is right a variable
64  // arg[1] & 4 = is trueCase a variable
65  // arg[1] & 8 = is falseCase a variable
66  // arg[2] = index correspoding to left
67  // arg[3] = index correspoding to right
68  // arg[4] = index correspoding to trueCase
69  // arg[5] = index correspoding to falseCase
70  CosOp, // cos(variable)
71  CoshOp, // cosh(variable)
72  CSkipOp, // Conditional skip
73  // arg[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
74  // arg[1] & 1 = is left a variable
75  // arg[1] & 2 = is right a variable
76  // arg[2] = index correspoding to left
77  // arg[3] = index correspoding to right
78  // arg[4] = number of operations to skip if CExpOp comparision is true
79  // arg[5] = number of operations to skip if CExpOp comparision is false
80  // arg[6] -> arg[5+arg[4]] = skip operations if true
81  // arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false
82  // arg[6+arg[4]+arg[5]] = arg[4] + arg[5]
83  CSumOp, // Cummulative summation
84  // arg[0] = number of addition variables in summation
85  // arg[1] = number of subtraction variables in summation
86  // arg[2] = index of parameter that initializes summation
87  // arg[3] -> arg[2+arg[0]] = index for positive variables
88  // arg[3+arg[0]] -> arg[2+arg[0]+arg[1]] = index for minus variables
89  // arg[3+arg[0]+arg[1]] = arg[0] + arg[1]
90  DisOp, // discrete::eval(index, variable)
91  DivpvOp, // parameter / variable
92  DivvpOp, // variable / parameter
93  DivvvOp, // variable / variable
94  EndOp, // used to mark the end of the tape
95  EqpvOp, // parameter == variable
96  EqvvOp, // variable == variable
97  ErfOp, // erf(variable)
98  ExpOp, // exp(variable)
99  Expm1Op, // expm1(variable)
100  InvOp, // independent variable
101  LdpOp, // z[parameter] (parameter converted to index)
102  LdvOp, // z[variable]
103  LepvOp, // parameter <= variable
104  LevpOp, // variable <= parameter
105  LevvOp, // variable <= variable
106  LogOp, // log(variable)
107  Log1pOp, // log1p(variable)
108  LtpvOp, // parameter < variable
109  LtvpOp, // variable < parameter
110  LtvvOp, // variable < variable
111  MulpvOp, // parameter * variable
112  MulvvOp, // variable * variable
113  NepvOp, // parameter != variable
114  NevvOp, // variable != variable
115  ParOp, // parameter
116  PowpvOp, // pow(parameter, variable)
117  PowvpOp, // pow(variable, parameter)
118  PowvvOp, // pow(variable, variable)
119  PriOp, // PrintFor(text, parameter or variable, parameter or variable)
120  SignOp, // sign(variable)
121  SinOp, // sin(variable)
122  SinhOp, // sinh(variable)
123  SqrtOp, // sqrt(variable)
124  StppOp, // z[parameter] = parameter (first parameter converted to index)
125  StpvOp, // z[parameter] = variable (parameter converted to index)
126  StvpOp, // z[variable] = parameter
127  StvvOp, // z[variable] = variable
128  SubpvOp, // parameter - variable
129  SubvpOp, // variable - parameter
130  SubvvOp, // variable - variable
131  TanOp, // tan(variable)
132  TanhOp, // tan(variable)
133  // user atomic operation codes
134  UserOp, // start of a user atomic operaiton
135  // arg[0] = index of the operation if atomic_base<Base> class
136  // arg[1] = extra information passed through by deprecated old atomic class
137  // arg[2] = number of arguments to this atomic function
138  // arg[3] = number of results for this atomic function
139  UsrapOp, // this user atomic argument is a parameter
140  UsravOp, // this user atomic argument is a variable
141  UsrrpOp, // this user atomic result is a parameter
142  UsrrvOp, // this user atomic result is a variable
143  ZmulpvOp, // azmul(parameter, variable)
144  ZmulvpOp, // azmul(variabe, parameter)
145  ZmulvvOp, // azmul(variable, variable)
146  NumberOp // number of operator codes (not an operator)
147 };
148 // Note that bin/check_op_code.sh assumes the pattern '^\tNumberOp$' occurs
149 // at the end of this list and only at the end of this list.
150 
151 /// specialize is_pod<OpCode> to be true
152 template <> inline bool is_pod<OpCode>(void) { return true; }
153 
154 /*!
155 Number of arguments for a specified operator.
156 
157 \return
158 Number of arguments corresponding to the specified operator.
159 
160 \param op
161 Operator for which we are fetching the number of arugments.
162 
163 \par NumArgTable
164 this table specifes the number of arguments stored for each
165 occurance of the operator that is the i-th value in the OpCode enum type.
166 For example, for the first three OpCode enum values we have
167 \verbatim
168 OpCode j NumArgTable[j] Meaning
169 AbsOp 0 1 index of variable we are taking absolute value of
170 AcosOp 1 1 index of variable we are taking acos of
171 AcoshOp 2 1 index of variable we are taking acosh of
172 \endverbatim
173 Note that the meaning of the arguments depends on the operator.
174 */
175 inline size_t NumArg( OpCode op)
177 
178  // agreement with OpCode is checked by bin/check_op_code.sh
179  static const size_t NumArgTable[] = {
180  1, // AbsOp
181  1, // AcosOp
182  1, // AcoshOp
183  2, // AddpvOp
184  2, // AddvvOp
185  1, // AsinOp
186  1, // AsinhOp
187  1, // AtanOp
188  1, // AtanhOp
189  1, // BeginOp offset first real argument to have index 1
190  6, // CExpOp
191  1, // CosOp
192  1, // CoshOp
193  0, // CSkipOp (actually has a variable number of arguments, not zero)
194  0, // CSumOp (actually has a variable number of arguments, not zero)
195  2, // DisOp
196  2, // DivpvOp
197  2, // DivvpOp
198  2, // DivvvOp
199  0, // EndOp
200  2, // EqpvOp
201  2, // EqvvOp
202  3, // ErfOp
203  1, // ExpOp
204  1, // Expm1Op
205  0, // InvOp
206  3, // LdpOp
207  3, // LdvOp
208  2, // LepvOp
209  2, // LevpOp
210  2, // LevvOp
211  1, // LogOp
212  1, // Log1pOp
213  2, // LtpvOp
214  2, // LtvpOp
215  2, // LtvvOp
216  2, // MulpvOp
217  2, // MulvvOp
218  2, // NepvOp
219  2, // NevvOp
220  1, // ParOp
221  2, // PowpvOp
222  2, // PowvpOp
223  2, // PowvvOp
224  5, // PriOp
225  1, // SignOp
226  1, // SinOp
227  1, // SinhOp
228  1, // SqrtOp
229  3, // StppOp
230  3, // StpvOp
231  3, // StvpOp
232  3, // StvvOp
233  2, // SubpvOp
234  2, // SubvpOp
235  2, // SubvvOp
236  1, // TanOp
237  1, // TanhOp
238  4, // UserOp
239  1, // UsrapOp
240  1, // UsravOp
241  1, // UsrrpOp
242  0, // UsrrvOp
243  2, // ZmulpvOp
244  2, // ZmulvpOp
245  2, // ZmulvvOp
246  0 // NumberOp not used
247  };
248 # ifndef NDEBUG
249  // only do these checks once to save time
250  static bool first = true;
251  if( first )
252  { CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) + 1 ==
253  sizeof(NumArgTable) / sizeof(NumArgTable[0])
254  );
255  first = false;
256  }
257  // do this check every time
258  CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
259 # endif
260 
261  return NumArgTable[op];
262 }
263 
264 /*!
265 Number of variables resulting from the specified operation.
266 
267 \param op
268 Operator for which we are fecching the number of results.
269 
270 \par NumResTable
271 table specifes the number of varibles that result for each
272 occurance of the operator that is the i-th value in the OpCode enum type.
273 For example, for the first three OpCode enum values we have
274 \verbatim
275 OpCode j NumResTable[j] Meaning
276 AbsOp 0 1 variable that is the result of the absolute value
277 AcosOp 1 2 acos(x) and sqrt(1-x*x) are required for this op
278 AcoshOp 2 2 acosh(x) and sqrt(x*x-1) are required for this op
279 \endverbatim
280 */
281 inline size_t NumRes(OpCode op)
283 
284  // agreement with OpCode is checked by bin/check_op_code.sh
285  static const size_t NumResTable[] = {
286  1, // AbsOp
287  2, // AcosOp
288  2, // AcoshOp
289  1, // AddpvOp
290  1, // AddvvOp
291  2, // AsinOp
292  2, // AsinhOp
293  2, // AtanOp
294  2, // AtanhOp
295  1, // BeginOp offsets first variable to have index one (not zero)
296  1, // CExpOp
297  2, // CosOp
298  2, // CoshOp
299  0, // CSkipOp
300  1, // CSumOp
301  1, // DisOp
302  1, // DivpvOp
303  1, // DivvpOp
304  1, // DivvvOp
305  0, // EndOp
306  0, // EqpvOp
307  0, // EqvvOp
308  5, // ErfOp
309  1, // ExpOp
310  1, // Expm1Op
311  1, // InvOp
312  1, // LdpOp
313  1, // LdvOp
314  0, // LepvOp
315  0, // LevpOp
316  0, // LevvOp
317  1, // LogOp
318  1, // Log1pOp
319  0, // LtpvOp
320  0, // LtvpOp
321  0, // LtvvOp
322  1, // MulpvOp
323  1, // MulvvOp
324  0, // NepvOp
325  0, // NevvOp
326  1, // ParOp
327  3, // PowpvOp
328  3, // PowvpOp
329  3, // PowvvOp
330  0, // PriOp
331  1, // SignOp
332  2, // SinOp
333  2, // SinhOp
334  1, // SqrtOp
335  0, // StppOp
336  0, // StpvOp
337  0, // StvpOp
338  0, // StvvOp
339  1, // SubpvOp
340  1, // SubvpOp
341  1, // SubvvOp
342  2, // TanOp
343  2, // TanhOp
344  0, // UserOp
345  0, // UsrapOp
346  0, // UsravOp
347  0, // UsrrpOp
348  1, // UsrrvOp
349  1, // ZmulpvOp
350  1, // ZmulvpOp
351  1, // ZmulvvOp
352  0 // NumberOp not used and avoids g++ 4.3.2 warn when pycppad builds
353  };
354  // check ensuring conversion to size_t is as expected
355  CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) + 1 ==
356  sizeof(NumResTable) / sizeof(NumResTable[0])
357  );
358  // this test ensures that all indices are within the table
359  CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
360 
361  return NumResTable[op];
362 }
363 
364 
365 /*!
366 Fetch the name for a specified operation.
367 
368 \return
369 name of the specified operation.
370 
371 \param op
372 Operator for which we are fetching the name
373 */
374 inline const char* OpName(OpCode op)
375 { // agreement with OpCode is checked by bin/check_op_code.sh
376  static const char *OpNameTable[] = {
377  "Abs" ,
378  "Acos" ,
379  "Acosh" ,
380  "Addpv" ,
381  "Addvv" ,
382  "Asin" ,
383  "Asinh" ,
384  "Atan" ,
385  "Atanh" ,
386  "Begin" ,
387  "CExp" ,
388  "Cos" ,
389  "Cosh" ,
390  "CSkip" ,
391  "CSum" ,
392  "Dis" ,
393  "Divpv" ,
394  "Divvp" ,
395  "Divvv" ,
396  "End" ,
397  "Eqpv" ,
398  "Eqvv" ,
399  "Erf" ,
400  "Exp" ,
401  "Expm1" ,
402  "Inv" ,
403  "Ldp" ,
404  "Ldv" ,
405  "Lepv" ,
406  "Levp" ,
407  "Levv" ,
408  "Log" ,
409  "Log1p" ,
410  "Ltpv" ,
411  "Ltvp" ,
412  "Ltvv" ,
413  "Mulpv" ,
414  "Mulvv" ,
415  "Nepv" ,
416  "Nevv" ,
417  "Par" ,
418  "Powpv" ,
419  "Powvp" ,
420  "Powvv" ,
421  "Pri" ,
422  "Sign" ,
423  "Sin" ,
424  "Sinh" ,
425  "Sqrt" ,
426  "Stpp" ,
427  "Stpv" ,
428  "Stvp" ,
429  "Stvv" ,
430  "Subpv" ,
431  "Subvp" ,
432  "Subvv" ,
433  "Tan" ,
434  "Tanh" ,
435  "User" ,
436  "Usrap" ,
437  "Usrav" ,
438  "Usrrp" ,
439  "Usrrv" ,
440  "Zmulpv",
441  "Zmulvp",
442  "Zmulvv",
443  "Number" // not used
444  };
445  // check ensuring conversion to size_t is as expected
447  size_t(NumberOp) + 1 == sizeof(OpNameTable)/sizeof(OpNameTable[0])
448  );
449  // this test ensures that all indices are within the table
450  CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
451 
452  return OpNameTable[op];
453 }
454 
455 /*!
456 Prints a single field corresponding to an operator.
457 
458 A specified leader is printed in front of the value
459 and then the value is left justified in the following width character.
460 
461 \tparam Type
462 is the type of the value we are printing.
463 
464 \param os
465 is the stream that we are printing to.
466 
467 \param leader
468 are characters printed before the value.
469 
470 \param value
471 is the value being printed.
472 
473 \param width
474 is the number of character to print the value in.
475 If the value does not fit in the width, the value is replace
476 by width '*' characters.
477 */
478 template <class Type>
480  std::ostream &os ,
481  const char * leader ,
482  const Type &value ,
483  size_t width )
484 {
485  std::ostringstream buffer;
486  std::string str;
487 
488  // first print the leader
489  os << leader;
490 
491  // print the value into an internal buffer
492  buffer << std::setw( int(width) ) << value;
493  str = buffer.str();
494 
495  // length of the string
496  size_t len = str.size();
497  if( len > width )
498  { size_t i;
499  for(i = 0; i < width-1; i++)
500  os << str[i];
501  os << "*";
502  return;
503  }
504 
505  // count number of spaces at begining
506  size_t nspace = 0;
507  while(str[nspace] == ' ' && nspace < len)
508  nspace++;
509 
510  // left justify the string
511  size_t i = nspace;
512  while( i < len )
513  os << str[i++];
514 
515  i = width - len + nspace;
516  while(i--)
517  os << " ";
518 }
519 
520 /*!
521 Prints a single operator and its operands
522 
523 \tparam Base
524 Is the base type for these AD< \a Base > operations.
525 
526 \param os
527 is the output stream that the information is printed on.
528 
529 \param play
530 Is the entire recording for the tape that this operator is in.
531 
532 \param i_op
533 is the index for the operator corresponding to this operation.
534 
535 \param i_var
536 is the index for the variable corresponding to the result of this operation
537 (if NumRes(op) > 0).
538 
539 \param op
540 The operator code (OpCode) for this operation.
541 
542 \param ind
543 is the vector of argument indices for this operation
544 (must have NumArg(op) elements).
545 */
546 template <class Base>
547 void printOp(
548  std::ostream& os ,
549  const local::player<Base>* play,
550  size_t i_op ,
551  size_t i_var ,
552  OpCode op ,
553  const addr_t* ind )
554 { size_t i;
557  "cannot print trace of AD operations in parallel mode"
558  );
559  static const char *CompareOpName[] =
560  { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" };
561 
562  // print operator
563  printOpField(os, "o=", i_op, 5);
564  if( NumRes(op) > 0 && op != BeginOp )
565  printOpField(os, "v=", i_var, 5);
566  else printOpField(os, "v=", "", 5);
567  if( op == CExpOp || op == CSkipOp )
568  { printOpField(os, "", OpName(op), 5);
569  printOpField(os, "", CompareOpName[ ind[0] ], 3);
570  }
571  else printOpField(os, "", OpName(op), 8);
572 
573  // print other fields
574  size_t ncol = 5;
575  switch( op )
576  {
577  case CSkipOp:
578  /*
579  ind[0] = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
580  ind[1] & 1 = is left a variable
581  ind[1] & 2 = is right a variable
582  ind[2] = index correspoding to left
583  ind[3] = index correspoding to right
584  ind[4] = number of operations to skip if CExpOp comparision is true
585  ind[5] = number of operations to skip if CExpOp comparision is false
586  ind[6] -> ind[5+ind[4]] = skip operations if true
587  ind[6+ind[4]] -> ind[5+ind[4]+ind[5]] = skip operations if false
588  ind[6+ind[4]+ind[5]] = ind[4] + ind[5]
589  */
590  CPPAD_ASSERT_UNKNOWN( ind[6+ind[4]+ind[5]] == ind[4]+ind[5] );
591  CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
592  if( ind[1] & 1 )
593  printOpField(os, " vl=", ind[2], ncol);
594  else printOpField(os, " pl=", play->GetPar(ind[2]), ncol);
595  if( ind[1] & 2 )
596  printOpField(os, " vr=", ind[3], ncol);
597  else printOpField(os, " pr=", play->GetPar(ind[3]), ncol);
598  if( size_t(ind[4]) < 3 )
599  { for(i = 0; i < size_t(ind[4]); i++)
600  printOpField(os, " ot=", ind[6+i], ncol);
601  }
602  else
603  { printOpField(os, "\n\tot=", ind[6+0], ncol);
604  for(i = 1; i < size_t(ind[4]); i++)
605  printOpField(os, " ot=", ind[6+i], ncol);
606  }
607  if( size_t(ind[5]) < 3 )
608  { for(i = 0; i < size_t(ind[5]); i++)
609  printOpField(os, " of=", ind[6+ind[4]+i], ncol);
610  }
611  else
612  { printOpField(os, "\n\tof=", ind[6+ind[4]+0], ncol);
613  { for(i = 1; i < size_t(ind[5]); i++)
614  printOpField(os, " of=", ind[6+ind[4]+i], ncol);
615  }
616  }
617  break;
618 
619  case CSumOp:
620  /*
621  ind[0] = number of addition variables in summation
622  ind[1] = number of subtraction variables in summation
623  ind[2] = index of parameter that initializes summation
624  ind[3], ... , ind[2+ind[0]] = index for positive variables
625  ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables
626  ind[3+ind[0]+ind[1]] == ind[0] + ind[1]
627  */
628  CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] );
629  printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
630  for(i = 0; i < size_t(ind[0]); i++)
631  printOpField(os, " +v=", ind[3+i], ncol);
632  for(i = 0; i < size_t(ind[1]); i++)
633  printOpField(os, " -v=", ind[3+ind[0]+i], ncol);
634  break;
635 
636  case LdpOp:
637  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
638  printOpField(os, "off=", ind[0], ncol);
639  printOpField(os, "idx=", ind[1], ncol);
640  break;
641 
642  case LdvOp:
643  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
644  printOpField(os, "off=", ind[0], ncol);
645  printOpField(os, " v=", ind[1], ncol);
646  break;
647 
648  case StppOp:
649  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
650  printOpField(os, "off=", ind[0], ncol);
651  printOpField(os, "idx=", ind[1], ncol);
652  printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
653  break;
654 
655  case StpvOp:
656  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
657  printOpField(os, "off=", ind[0], ncol);
658  printOpField(os, "idx=", ind[1], ncol);
659  printOpField(os, " vr=", ind[2], ncol);
660  break;
661 
662  case StvpOp:
663  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
664  printOpField(os, "off=", ind[0], ncol);
665  printOpField(os, " vl=", ind[1], ncol);
666  printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
667  break;
668 
669  case StvvOp:
670  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
671  printOpField(os, "off=", ind[0], ncol);
672  printOpField(os, " vl=", ind[1], ncol);
673  printOpField(os, " vr=", ind[2], ncol);
674  break;
675 
676  case AddvvOp:
677  case DivvvOp:
678  case EqvvOp:
679  case LevvOp:
680  case LtvvOp:
681  case NevvOp:
682  case MulvvOp:
683  case PowvvOp:
684  case SubvvOp:
685  case ZmulvvOp:
686  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
687  printOpField(os, " vl=", ind[0], ncol);
688  printOpField(os, " vr=", ind[1], ncol);
689  break;
690 
691  case AddpvOp:
692  case EqpvOp:
693  case DivpvOp:
694  case LepvOp:
695  case LtpvOp:
696  case NepvOp:
697  case SubpvOp:
698  case MulpvOp:
699  case PowpvOp:
700  case ZmulpvOp:
701  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
702  printOpField(os, " pl=", play->GetPar(ind[0]), ncol);
703  printOpField(os, " vr=", ind[1], ncol);
704  break;
705 
706  case DivvpOp:
707  case LevpOp:
708  case LtvpOp:
709  case PowvpOp:
710  case SubvpOp:
711  case ZmulvpOp:
712  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
713  printOpField(os, " vl=", ind[0], ncol);
714  printOpField(os, " pr=", play->GetPar(ind[1]), ncol);
715  break;
716 
717  case AbsOp:
718  case AcosOp:
719  case AcoshOp:
720  case AsinOp:
721  case AsinhOp:
722  case AtanOp:
723  case AtanhOp:
724  case CosOp:
725  case CoshOp:
726  case ExpOp:
727  case Expm1Op:
728  case LogOp:
729  case Log1pOp:
730  case SignOp:
731  case SinOp:
732  case SinhOp:
733  case SqrtOp:
734  case UsravOp:
735  case TanOp:
736  case TanhOp:
737  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
738  printOpField(os, " v=", ind[0], ncol);
739  break;
740 
741  case ErfOp:
742  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
743  // ind[1] points to the parameter 0
744  // ind[2] points to the parameter 2 / sqrt(pi)
745  printOpField(os, " v=", ind[0], ncol);
746  break;
747 
748  case ParOp:
749  case UsrapOp:
750  case UsrrpOp:
751  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
752  printOpField(os, " p=", play->GetPar(ind[0]), ncol);
753  break;
754 
755  case UserOp:
756  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
757  { std::string name = atomic_base<Base>::class_name(ind[0]);
758  printOpField(os, " f=", name.c_str(), ncol);
759  printOpField(os, " i=", ind[1], ncol);
760  printOpField(os, " n=", ind[2], ncol);
761  printOpField(os, " m=", ind[3], ncol);
762  }
763  break;
764 
765  case PriOp:
766  CPPAD_ASSERT_NARG_NRES(op, 5, 0);
767  if( ind[0] & 1 )
768  printOpField(os, " v=", ind[1], ncol);
769  else printOpField(os, " p=", play->GetPar(ind[1]), ncol);
770  os << "before=\"" << play->GetTxt(ind[2]) << "\"";
771  if( ind[0] & 2 )
772  printOpField(os, " v=", ind[3], ncol);
773  else printOpField(os, " p=", play->GetPar(ind[3]), ncol);
774  os << "after=\"" << play->GetTxt(ind[4]) << "\"";
775  break;
776 
777  case BeginOp:
778  // argument not used (created by independent)
779  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
780  break;
781 
782  case EndOp:
783  case InvOp:
784  case UsrrvOp:
785  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
786  break;
787 
788  case DisOp:
789  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
790  { const char* name = discrete<Base>::name(ind[0]);
791  printOpField(os, " f=", name, ncol);
792  printOpField(os, " x=", ind[1], ncol);
793  }
794  break;
795 
796 
797  case CExpOp:
798  CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
799  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
800  if( ind[1] & 1 )
801  printOpField(os, " vl=", ind[2], ncol);
802  else printOpField(os, " pl=", play->GetPar(ind[2]), ncol);
803  if( ind[1] & 2 )
804  printOpField(os, " vr=", ind[3], ncol);
805  else printOpField(os, " pr=", play->GetPar(ind[3]), ncol);
806  if( ind[1] & 4 )
807  printOpField(os, " vt=", ind[4], ncol);
808  else printOpField(os, " pt=", play->GetPar(ind[4]), ncol);
809  if( ind[1] & 8 )
810  printOpField(os, " vf=", ind[5], ncol);
811  else printOpField(os, " pf=", play->GetPar(ind[5]), ncol);
812  break;
813 
814  default:
816  }
817 }
818 
819 /*!
820 Prints the result values correspnding to an operator.
821 
822 \tparam Base
823 Is the base type for these AD< \a Base > operations.
824 
825 \tparam Value
826 Determines the type of the values that we are printing.
827 
828 \param os
829 is the output stream that the information is printed on.
830 
831 \param nfz
832 is the number of forward sweep calculated values of type Value
833 that correspond to this operation
834 (ignored if NumRes(op) == 0).
835 
836 \param fz
837 points to the first forward calculated value
838 that correspond to this operation
839 (ignored if NumRes(op) == 0).
840 
841 \param nrz
842 is the number of reverse sweep calculated values of type Value
843 that correspond to this operation
844 (ignored if NumRes(op) == 0).
845 
846 \param rz
847 points to the first reverse calculated value
848 that correspond to this operation
849 (ignored if NumRes(op) == 0).
850 */
851 template <class Value>
853  std::ostream &os ,
854  size_t nfz ,
855  const Value *fz ,
856  size_t nrz ,
857  const Value *rz )
858 {
859  size_t k;
860  for(k = 0; k < nfz; k++)
861  os << "| fz[" << k << "]=" << fz[k];
862  for(k = 0; k < nrz; k++)
863  os << "| rz[" << k << "]=" << rz[k];
864 }
865 
866 /*!
867 Determines which arguments are variaibles for an operator.
868 
869 \param op
870 is the operator. Note that CSkipOp and CSumOp are special cases
871 because the true number of arguments is not equal to NumArg(op)
872 and the true number of arguments num_arg can be large.
873 It may be more efficient to handle these cases separately
874 (see below).
875 
876 \param arg
877 is the argument vector for this operator.
878 
879 \param is_variable
880 If the input value of the elements in this vector do not matter.
881 Upon return, for j < NumArg(op), the j-th argument for this operator is a
882 variable index if and only if is_variable[j] is true. Note that the variable
883 index 0, for the BeginOp, does not correspond to a real variable and false
884 is returned for this case.
885 
886 \return
887 The return value is the true number of arguments num_arg.
888 If op is CSkipOp or CSumOp, see below.
889 Otherwise the true number of arguments num_arg = NumArg(op).
890 If the input size of is_variable is less than num_arg,
891 is_variable.extend is used to increase its size to be num_arg.
892 
893 \par CSkipOp
894 In the case of CSkipOp,
895 \code
896  num_arg = 7 + arg[4] + arg[5];
897  is_variable[2] = (arg[1] & 1) != 0;
898  is_variable[3] = (arg[1] & 2) != 0;
899 \endcode
900 and all the other is_variable values are false.
901 
902 \par CSumOp
903 In the case of CSumOp,
904 \code
905  num_arg = 4 + arg[0] + arg[1];
906  for(size_t i = 3; i < num_arg - 1; ++i)
907  is_variable[i] = true;
908 \endcode
909 and all the other is_variable values are false.
910 */
911 inline size_t arg_is_variable(
912  OpCode op ,
913  const addr_t* arg ,
914  pod_vector<bool>& is_variable )
915 { size_t num_arg = NumArg(op);
916  if( is_variable.size() < num_arg )
917  is_variable.extend( num_arg - is_variable.size() );
918  //
919  switch(op)
920  {
921  // -------------------------------------------------------------------
922  // cases where true number of arugments = NumArg(op) == 0
923 
924  case EndOp:
925  case InvOp:
926  case UsrrvOp:
927  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
928  break;
929 
930  // -------------------------------------------------------------------
931  // cases where NumArg(op) == 1
932  case AbsOp:
933  case AcoshOp:
934  case AcosOp:
935  case AsinhOp:
936  case AsinOp:
937  case AtanhOp:
938  case AtanOp:
939  case CoshOp:
940  case CosOp:
941  case Expm1Op:
942  case ExpOp:
943  case Log1pOp:
944  case LogOp:
945  case SignOp:
946  case SinhOp:
947  case SinOp:
948  case SqrtOp:
949  case TanhOp:
950  case TanOp:
951  case UsravOp:
952  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
953  is_variable[0] = true;
954  break;
955 
956  case BeginOp:
957  case ParOp:
958  case UsrapOp:
959  case UsrrpOp:
960  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
961  is_variable[0] = false;
962  break;
963 
964 
965  // -------------------------------------------------------------------
966  // cases where NumArg(op) == 2
967 
968  case AddpvOp:
969  case DisOp:
970  case DivpvOp:
971  case EqpvOp:
972  case LepvOp:
973  case LtpvOp:
974  case MulpvOp:
975  case NepvOp:
976  case PowpvOp:
977  case SubpvOp:
978  case ZmulpvOp:
979  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
980  is_variable[0] = false;
981  is_variable[1] = true;
982  break;
983 
984  case DivvpOp:
985  case LevpOp:
986  case LtvpOp:
987  case PowvpOp:
988  case SubvpOp:
989  case ZmulvpOp:
990  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
991  is_variable[0] = true;
992  is_variable[1] = false;
993  break;
994 
995  case AddvvOp:
996  case DivvvOp:
997  case EqvvOp:
998  case LevvOp:
999  case LtvvOp:
1000  case MulvvOp:
1001  case NevvOp:
1002  case PowvvOp:
1003  case SubvvOp:
1004  case ZmulvvOp:
1005  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
1006  is_variable[0] = true;
1007  is_variable[1] = true;
1008  break;
1009 
1010  case ErfOp:
1011  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
1012  is_variable[0] = false; // parameter index corresponding to zero
1013  is_variable[1] = false; // parameter index corresponding to one
1014  is_variable[2] = true;
1015  break;
1016 
1017  // --------------------------------------------------------------------
1018  // cases where NumArg(op) == 3
1019 
1020  case LdpOp:
1021  case StppOp:
1022  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
1023  is_variable[0] = false;
1024  is_variable[1] = false;
1025  is_variable[2] = false;
1026  break;
1027 
1028  case LdvOp:
1029  case StvpOp:
1030  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
1031  is_variable[0] = false;
1032  is_variable[1] = true;
1033  is_variable[2] = false;
1034  break;
1035 
1036  case StpvOp:
1037  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
1038  is_variable[0] = false;
1039  is_variable[1] = false;
1040  is_variable[2] = true;
1041  break;
1042 
1043  case StvvOp:
1044  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
1045  is_variable[0] = false;
1046  is_variable[1] = true;
1047  is_variable[2] = true;
1048  break;
1049 
1050  // --------------------------------------------------------------------
1051  // case where NumArg(op) == 4
1052  case UserOp:
1053  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
1054  for(size_t i = 0; i < 4; i++)
1055  is_variable[i] = false;
1056  break;
1057 
1058  // --------------------------------------------------------------------
1059  // case where NumArg(op) == 5
1060  case PriOp:
1061  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 5 );
1062  is_variable[0] = false;
1063  is_variable[1] = (arg[0] & 1) != 0;
1064  is_variable[2] = false;
1065  is_variable[3] = (arg[0] & 2) != 0;
1066  is_variable[4] = false;
1067  break;
1068 
1069  // --------------------------------------------------------------------
1070  // case where NumArg(op) == 6
1071  case CExpOp:
1072  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
1073  is_variable[0] = false;
1074  is_variable[1] = false;
1075  is_variable[2] = (arg[0] & 1) != 0;
1076  is_variable[3] = (arg[0] & 2) != 0;
1077  is_variable[4] = (arg[0] & 4) != 0;
1078  is_variable[5] = (arg[0] & 8) != 0;
1079  break;
1080 
1081  // -------------------------------------------------------------------
1082  // CSkipOp:
1083  case CSkipOp:
1084  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 )
1085  //
1086  // true number of arguments
1087  num_arg = 7 + arg[4] + arg[5];
1088  if( is_variable.size() < num_arg )
1089  is_variable.extend( num_arg - is_variable.size() );
1090  is_variable[0] = false;
1091  is_variable[1] = false;
1092  is_variable[2] = (arg[1] & 1) != 0;
1093  is_variable[3] = (arg[1] & 2) != 0;
1094  for(size_t i = 4; i < num_arg; ++i)
1095  is_variable[i] = false;
1096  break;
1097 
1098  // -------------------------------------------------------------------
1099  // CSumOp:
1100  case CSumOp:
1101  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 )
1102  //
1103  // true number of arguments
1104  num_arg = 4 + arg[0] + arg[1];
1105  if( is_variable.size() < num_arg )
1106  is_variable.extend( num_arg - is_variable.size() );
1107  is_variable[0] = false;
1108  is_variable[1] = false;
1109  is_variable[2] = false;
1110  for(size_t i = 3; i < num_arg - 1; ++i)
1111  is_variable[i] = true;
1112  is_variable[num_arg - 1] = false;
1113  break;
1114 
1115  // --------------------------------------------------------------------
1116  default:
1117  CPPAD_ASSERT_UNKNOWN(false);
1118  break;
1119  }
1120  return num_arg;
1121 }
1122 
1123 } } // END_CPPAD_LOCAL_NAMESPACE
1124 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
Define processor symbols and macros that are used by CppAD.
size_t extend(size_t n)
Increase the number of elements the end of this vector (existing elements are always preserved)...
Definition: pod_vector.hpp:115
size_t arg_is_variable(OpCode op, const addr_t *arg, pod_vector< bool > &is_variable)
Determines which arguments are variaibles for an operator.
Definition: op_code.hpp:911
void printOpResult(std::ostream &os, size_t nfz, const Value *fz, size_t nrz, const Value *rz)
Prints the result values correspnding to an operator.
Definition: op_code.hpp:852
CPPAD_TAPE_ADDR_TYPE addr_t
Definition: declare_ad.hpp:44
static bool in_parallel(void)
Are we in a parallel execution state; i.e., is it possible that other threads are currently executing...
static const char * name(size_t index)
Name corresponding to a discrete object.
Definition: discrete.hpp:285
const char * GetTxt(size_t i) const
Fetch a &#39;\0&#39; terminated string from the recording.
Definition: player.hpp:608
size_t NumArg(OpCode op)
Number of arguments for a specified operator.
Definition: op_code.hpp:175
Class used to store and play back an operation sequence recording.
Definition: declare_ad.hpp:27
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
const char * OpName(OpCode op)
Fetch the name for a specified operation.
Definition: op_code.hpp:374
#define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
Check that the first call to a routine is not during parallel execution mode.
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION Base Value(const AD< Base > &x)
Definition: value.hpp:82
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
File used to define pod_vector class.
static std::vector< std::string > & class_name(void)
List of names for each object in this class.
Definition: atomic_base.hpp:89
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
bool is_pod< OpCode >(void)
specialize is_pod&lt;OpCode&gt; to be true
Definition: op_code.hpp:152
void printOp(std::ostream &os, const local::player< Base > *play, size_t i_op, size_t i_var, OpCode op, const addr_t *ind)
Prints a single operator and its operands.
Definition: op_code.hpp:547
#define CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res)
Check that operator op has the specified number of of arguments and results.
File used to define the CppAD multi-threading allocator class.
void printOpField(std::ostream &os, const char *leader, const Type &value, size_t width)
Prints a single field corresponding to an operator.
Definition: op_code.hpp:479
Base GetPar(size_t i) const
Fetch a parameter from the recording.
Definition: player.hpp:584