CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
reverse_sweep.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_REVERSE_SWEEP_HPP
2 # define CPPAD_LOCAL_REVERSE_SWEEP_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 
15 
16 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
17 /*!
18 \file reverse_sweep.hpp
19 Compute derivatives of arbitrary order Taylor coefficients.
20 */
21 
22 /*
23 \def CPPAD_ATOMIC_CALL
24 This avoids warnings when NDEBUG is defined and user_ok is not used.
25 If \c NDEBUG is defined, this resolves to
26 \code
27  user_atom->reverse
28 \endcode
29 otherwise, it respolves to
30 \code
31  user_ok = user_atom->reverse
32 \endcode
33 This maco is undefined at the end of this file to facillitate is
34 use with a different definition in other files.
35 */
36 # ifdef NDEBUG
37 # define CPPAD_ATOMIC_CALL user_atom->reverse
38 # else
39 # define CPPAD_ATOMIC_CALL user_ok = user_atom->reverse
40 # endif
41 
42 /*!
43 \def CPPAD_REVERSE_SWEEP_TRACE
44 This value is either zero or one.
45 Zero is the normal operational value.
46 If it is one, a trace of every reverse_sweep computation is printed.
47 */
48 # define CPPAD_REVERSE_SWEEP_TRACE 0
49 
50 /*!
51 Compute derivative of arbitrary order forward mode Taylor coefficients.
52 
53 \tparam Base
54 this operation sequence was recorded using AD<Base>
55 and computations by this routine are done using type Base.
56 
57 \param d
58 is the highest order Taylor coefficients that
59 we are computing the derivative of.
60 
61 \param n
62 is the number of independent variables on the tape.
63 
64 \param numvar
65 is the total number of variables on the tape.
66 This is also equal to the number of rows in the matrix \a Taylor; i.e.,
67 play->num_var_rec().
68 
69 \param play
70 The information stored in \a play
71 is a recording of the operations corresponding to the function
72 \f[
73  F : {\bf R}^n \rightarrow {\bf R}^m
74 \f]
75 where \f$ n \f$ is the number of independent variables and
76 \f$ m \f$ is the number of dependent variables.
77 We define \f$ u^{(k)} \f$ as the value of <code>x_k</code> in the previous call
78 of the form
79 <code>
80  f.Forward(k, x_k)
81 </code>
82 We define
83 \f$ X : {\bf R}^{n \times d} \rightarrow {\bf R}^n \f$ by
84 \f[
85  X(t, u) = u^{(0)} + u^{(1)} t + \cdots + u^{(d)} t^d
86 \f]
87 We define
88 \f$ Y : {\bf R}^{n \times d} \rightarrow {\bf R}^m \f$ by
89 \f[
90  Y(t, u) = F[ X(t, u) ]
91 \f]
92 We define the function
93 \f$ W : {\bf R}^{n \times d} \rightarrow {\bf R} \f$ by
94 \f[
95 W(u)
96 =
97 \sum_{k=0}^{d} ( w^{(k)} )^{\rm T}
98  \frac{1}{k !} \frac{\partial^k}{\partial t^k} Y(0, u)
99 \f]
100 (The matrix \f$ w \in {\bf R}^m \f$,
101 is defined below under the heading Partial.)
102 Note that the scale factor 1 / k converts
103 the k-th partial derivative to the k-th order Taylor coefficient.
104 This routine computes the derivative of \f$ W(u) \f$
105 with respect to all the Taylor coefficients
106 \f$ u^{(k)} \f$ for \f$ k = 0 , ... , d \f$.
107 
108 \param J
109 Is the number of columns in the coefficient matrix \a Taylor.
110 This must be greater than or equal \a d + 1.
111 
112 \param Taylor
113 For i = 1 , ... , \a numvar, and for k = 0 , ... , \a d,
114 \a Taylor [ i * J + k ]
115 is the k-th order Taylor coefficient corresponding to
116 variable with index i on the tape.
117 The value \f$ u \in {\bf R}^{n \times d} \f$,
118 at which the derivative is computed,
119 is defined by
120 \f$ u_j^{(k)} \f$ = \a Taylor [ j * J + k ]
121 for j = 1 , ... , \a n, and for k = 0 , ... , \a d.
122 
123 \param K
124 Is the number of columns in the partial derivative matrix \a Partial.
125 It must be greater than or equal \a d + 1.
126 
127 \param Partial
128 \b Input:
129 The last \f$ m \f$ rows of \a Partial are inputs.
130 The matrix \f$ w \f$, used to define \f$ W(u) \f$,
131 is specified by these rows.
132 For i = 0 , ... , m - 1,
133 for k = 0 , ... , d,
134 <code>Partial [ (numvar - m + i ) * K + k ] = w[i,k]</code>.
135 \n
136 \n
137 \b Temporary:
138 For i = n+1 , ... , \a numvar - 1 and for k = 0 , ... , d,
139 the value of \a Partial [ i * K + k ] is used for temporary work space
140 and its output value is not defined.
141 \n
142 \n
143 \b Output:
144 For j = 1 , ... , n and for k = 0 , ... , d,
145 \a Partial [ j * K + k ]
146 is the partial derivative of \f$ W( u ) \f$ with
147 respect to \f$ u_j^{(k)} \f$.
148 
149 \param cskip_op
150 Is a vector with size play->num_op_rec().
151 If cskip_op[i] is true, the operator index i in the recording
152 does not affect any of the dependent variable (given the value
153 of the independent variables).
154 Note that all the operators in an atomic function call are skipped as a block,
155 so only the last UserOp fore each call needs to have cskip_op[i] true.
156 
157 \param var_by_load_op
158 is a vector with size play->num_load_op_rec().
159 It contains the variable index corresponding to each load instruction.
160 In the case where the index is zero,
161 the instruction corresponds to a parameter (not variable).
162 
163 \param subgraph
164 is the set of operators over which the reverse mode calculations
165 will be preformed. For k = 0, ... , subgraph.size() - 1,
166 subgraph[k] is an operator index and
167 \code
168  play->num_op_rec() > subgraph[k] > subgraph[k-1]
169 \endcode
170 If i_var is a variable index, and play->var2op(i_var) is not in the subgraph,
171 then the partials with respect to i_var are not modified and need to be
172 initialized as zero. Note that this means the partial for the independent
173 varaibles, that are not in the subgraph are not calculated.
174 If part of an atomic function call is in the subgraph,
175 the entire atomic function call must be in the subgraph.
176 
177 \par Assumptions
178 The first operator on the tape is a BeginOp,
179 and the next \a n operators are InvOp operations for the
180 corresponding independent variables; see play->check_inv_op(n_ind).
181 */
182 template <class Base>
184  size_t d,
185  size_t n,
186  size_t numvar,
187  const local::player<Base>* play,
188  size_t J,
189  const Base* Taylor,
190  size_t K,
191  Base* Partial,
192  bool* cskip_op,
193  const pod_vector<addr_t>& var_by_load_op,
194  const pod_vector<addr_t>& subgraph
195 )
196 {
197  // check numvar argument
198  CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
199  CPPAD_ASSERT_UNKNOWN( numvar > 0 );
200 
201  // length of the parameter vector (used by CppAD assert macros)
202  const size_t num_par = play->num_par_rec();
203 
204  // pointer to the beginning of the parameter vector
205  const Base* parameter = CPPAD_NULL;
206  if( num_par > 0 )
207  parameter = play->GetPar();
208 
209  // work space used by UserOp.
210  const size_t user_k = d; // highest order we are differentiating
211  const size_t user_k1 = d+1; // number of orders for this calculation
212  vector<size_t> user_ix; // variable indices for argument vector
213  vector<Base> user_tx; // argument vector Taylor coefficients
214  vector<Base> user_ty; // result vector Taylor coefficients
215  vector<Base> user_px; // partials w.r.t argument vector
216  vector<Base> user_py; // partials w.r.t. result vector
217  //
218  atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
219 # ifndef NDEBUG
220  bool user_ok = false; // atomic op return value
221 # endif
222  //
223  // information defined by forward_user
224  size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
225  enum_user_state user_state = end_user; // proper initialization
226 
227  // temporary indices
228  size_t j, ell;
229 
230  // Initialize
231 # if CPPAD_REVERSE_SWEEP_TRACE
232  std::cout << std::endl;
233 # endif
234  size_t subgraph_index = subgraph.size();
235  while(subgraph_index > 0)
236  { bool flag; // temporary for use in switch cases
237  //
238  // next op
239  size_t i_op = subgraph[--subgraph_index];
240  OpCode op;
241  const addr_t* arg;
242  size_t i_var;
243  play->get_op_info(i_op, op, arg, i_var);
244  CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
245 
246  // check if we are skipping this operation
247  while( cskip_op[i_op] )
248  { switch(op)
249  {
250  case UserOp:
251  { // get information for this user atomic call
252  CPPAD_ASSERT_UNKNOWN( user_state == end_user );
253  play->get_user_info(op, arg, user_old, user_m, user_n);
254  //
255  // skip to the first UserOp
256  CPPAD_ASSERT_UNKNOWN(subgraph_index > user_m + user_n);
257  subgraph_index -= user_m + user_n;
258  i_op = subgraph[--subgraph_index];
259  CPPAD_ASSERT_UNKNOWN( play->GetOp(i_op) == UserOp );
260  }
261  break;
262 
263  default:
264  break;
265  }
266  CPPAD_ASSERT_UNKNOWN( 0 < i_op );
267  CPPAD_ASSERT_UNKNOWN( subgraph_index > 0 );
268  i_op = subgraph[--subgraph_index];
269  play->get_op_info(i_op, op, arg, i_var);
270  }
271 # if CPPAD_REVERSE_SWEEP_TRACE
272  size_t i_tmp = i_var;
273  const Base* Z_tmp = Taylor + i_var * J;
274  const Base* pZ_tmp = Partial + i_var * K;
275  printOp(
276  std::cout,
277  play,
278  i_op,
279  i_tmp,
280  op,
281  arg
282  );
283  if( NumRes(op) > 0 && op != BeginOp ) printOpResult(
284  std::cout,
285  d + 1,
286  Z_tmp,
287  d + 1,
288  pZ_tmp
289  );
290  std::cout << std::endl;
291 # endif
292  switch( op )
293  {
294  case AbsOp:
296  d, i_var, arg[0], J, Taylor, K, Partial
297  );
298  break;
299  // --------------------------------------------------
300 
301  case AcosOp:
302  // sqrt(1 - x * x), acos(x)
303  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
305  d, i_var, arg[0], J, Taylor, K, Partial
306  );
307  break;
308  // --------------------------------------------------
309 
310 # if CPPAD_USE_CPLUSPLUS_2011
311  case AcoshOp:
312  // sqrt(x * x - 1), acosh(x)
313  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
315  d, i_var, arg[0], J, Taylor, K, Partial
316  );
317  break;
318 # endif
319  // --------------------------------------------------
320 
321  case AddvvOp:
323  d, i_var, arg, parameter, J, Taylor, K, Partial
324  );
325  break;
326  // --------------------------------------------------
327 
328  case AddpvOp:
329  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
331  d, i_var, arg, parameter, J, Taylor, K, Partial
332  );
333  break;
334  // --------------------------------------------------
335 
336  case AsinOp:
337  // sqrt(1 - x * x), asin(x)
338  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
340  d, i_var, arg[0], J, Taylor, K, Partial
341  );
342  break;
343  // --------------------------------------------------
344 
345 # if CPPAD_USE_CPLUSPLUS_2011
346  case AsinhOp:
347  // sqrt(1 + x * x), asinh(x)
348  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
350  d, i_var, arg[0], J, Taylor, K, Partial
351  );
352  break;
353 # endif
354  // --------------------------------------------------
355 
356  case AtanOp:
357  // 1 + x * x, atan(x)
358  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
360  d, i_var, arg[0], J, Taylor, K, Partial
361  );
362  break;
363  // -------------------------------------------------
364 
365 # if CPPAD_USE_CPLUSPLUS_2011
366  case AtanhOp:
367  // 1 - x * x, atanh(x)
368  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
370  d, i_var, arg[0], J, Taylor, K, Partial
371  );
372  break;
373 # endif
374  // -------------------------------------------------
375 
376  case BeginOp:
377  CPPAD_ASSERT_NARG_NRES(op, 1, 1);
378  CPPAD_ASSERT_UNKNOWN( i_op == 0 );
379  break;
380  // --------------------------------------------------
381 
382  case CSkipOp:
383  // CSkipOp has a zero order forward action.
384  break;
385  // -------------------------------------------------
386 
387  case CSumOp:
389  d, i_var, arg, K, Partial
390  );
391  // end of a cummulative summation
392  break;
393  // -------------------------------------------------
394 
395  case CExpOp:
397  d,
398  i_var,
399  arg,
400  num_par,
401  parameter,
402  J,
403  Taylor,
404  K,
405  Partial
406  );
407  break;
408  // --------------------------------------------------
409 
410  case CosOp:
411  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
413  d, i_var, arg[0], J, Taylor, K, Partial
414  );
415  break;
416  // --------------------------------------------------
417 
418  case CoshOp:
419  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
421  d, i_var, arg[0], J, Taylor, K, Partial
422  );
423  break;
424  // --------------------------------------------------
425 
426  case DisOp:
427  // Derivative of discrete operation is zero so no
428  // contribution passes through this operation.
429  break;
430  // --------------------------------------------------
431 
432  case DivvvOp:
434  d, i_var, arg, parameter, J, Taylor, K, Partial
435  );
436  break;
437  // --------------------------------------------------
438 
439  case DivpvOp:
440  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
442  d, i_var, arg, parameter, J, Taylor, K, Partial
443  );
444  break;
445  // --------------------------------------------------
446 
447  case DivvpOp:
448  CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
450  d, i_var, arg, parameter, J, Taylor, K, Partial
451  );
452  break;
453  // --------------------------------------------------
454  case EndOp:
456  i_op == play->num_op_rec() - 1
457  );
458  break;
459 
460  // --------------------------------------------------
461 
462 # if CPPAD_USE_CPLUSPLUS_2011
463  case ErfOp:
465  d, i_var, arg, parameter, J, Taylor, K, Partial
466  );
467  break;
468 # endif
469  // --------------------------------------------------
470 
471  case ExpOp:
473  d, i_var, arg[0], J, Taylor, K, Partial
474  );
475  break;
476  // --------------------------------------------------
477 
478 # if CPPAD_USE_CPLUSPLUS_2011
479  case Expm1Op:
481  d, i_var, arg[0], J, Taylor, K, Partial
482  );
483  break;
484 # endif
485  // --------------------------------------------------
486 
487  case InvOp:
488  break;
489  // --------------------------------------------------
490 
491  case LdpOp:
493  op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
494  );
495  break;
496  // -------------------------------------------------
497 
498  case LdvOp:
500  op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
501  );
502  break;
503  // --------------------------------------------------
504 
505  case EqpvOp:
506  case EqvvOp:
507  case LtpvOp:
508  case LtvpOp:
509  case LtvvOp:
510  case LepvOp:
511  case LevpOp:
512  case LevvOp:
513  case NepvOp:
514  case NevvOp:
515  break;
516  // -------------------------------------------------
517 
518  case LogOp:
520  d, i_var, arg[0], J, Taylor, K, Partial
521  );
522  break;
523  // --------------------------------------------------
524 
525 # if CPPAD_USE_CPLUSPLUS_2011
526  case Log1pOp:
528  d, i_var, arg[0], J, Taylor, K, Partial
529  );
530  break;
531 # endif
532  // --------------------------------------------------
533 
534  case MulpvOp:
535  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
537  d, i_var, arg, parameter, J, Taylor, K, Partial
538  );
539  break;
540  // --------------------------------------------------
541 
542  case MulvvOp:
544  d, i_var, arg, parameter, J, Taylor, K, Partial
545  );
546  break;
547  // --------------------------------------------------
548 
549  case ParOp:
550  break;
551  // --------------------------------------------------
552 
553  case PowvpOp:
554  CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
556  d, i_var, arg, parameter, J, Taylor, K, Partial
557  );
558  break;
559  // -------------------------------------------------
560 
561  case PowpvOp:
562  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
564  d, i_var, arg, parameter, J, Taylor, K, Partial
565  );
566  break;
567  // -------------------------------------------------
568 
569  case PowvvOp:
571  d, i_var, arg, parameter, J, Taylor, K, Partial
572  );
573  break;
574  // --------------------------------------------------
575 
576  case PriOp:
577  // no result so nothing to do
578  break;
579  // --------------------------------------------------
580 
581  case SignOp:
582  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
584  d, i_var, arg[0], J, Taylor, K, Partial
585  );
586  break;
587  // -------------------------------------------------
588 
589  case SinOp:
590  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
592  d, i_var, arg[0], J, Taylor, K, Partial
593  );
594  break;
595  // -------------------------------------------------
596 
597  case SinhOp:
598  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
600  d, i_var, arg[0], J, Taylor, K, Partial
601  );
602  break;
603  // --------------------------------------------------
604 
605  case SqrtOp:
607  d, i_var, arg[0], J, Taylor, K, Partial
608  );
609  break;
610  // --------------------------------------------------
611 
612  case StppOp:
613  break;
614  // --------------------------------------------------
615 
616  case StpvOp:
617  break;
618  // -------------------------------------------------
619 
620  case StvpOp:
621  break;
622  // -------------------------------------------------
623 
624  case StvvOp:
625  break;
626  // --------------------------------------------------
627 
628  case SubvvOp:
630  d, i_var, arg, parameter, J, Taylor, K, Partial
631  );
632  break;
633  // --------------------------------------------------
634 
635  case SubpvOp:
636  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
638  d, i_var, arg, parameter, J, Taylor, K, Partial
639  );
640  break;
641  // --------------------------------------------------
642 
643  case SubvpOp:
644  CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
646  d, i_var, arg, parameter, J, Taylor, K, Partial
647  );
648  break;
649  // -------------------------------------------------
650 
651  case TanOp:
652  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
654  d, i_var, arg[0], J, Taylor, K, Partial
655  );
656  break;
657  // -------------------------------------------------
658 
659  case TanhOp:
660  CPPAD_ASSERT_UNKNOWN( i_var < numvar );
662  d, i_var, arg[0], J, Taylor, K, Partial
663  );
664  break;
665  // --------------------------------------------------
666 
667  case UserOp:
668  // start or end an atomic function call
669  flag = user_state == end_user;
670  user_atom = play->get_user_info(op, arg, user_old, user_m, user_n);
671  if( flag )
672  { user_state = ret_user;
673  user_i = user_m;
674  user_j = user_n;
675  //
676  user_ix.resize(user_n);
677  if(user_tx.size() != user_n * user_k1)
678  { user_tx.resize(user_n * user_k1);
679  user_px.resize(user_n * user_k1);
680  }
681  if(user_ty.size() != user_m * user_k1)
682  { user_ty.resize(user_m * user_k1);
683  user_py.resize(user_m * user_k1);
684  }
685  }
686  else
687  { user_state = end_user;
688  //
689  // call users function for this operation
690  user_atom->set_old(user_old);
692  user_k, user_tx, user_ty, user_px, user_py
693  );
694 # ifndef NDEBUG
695  if( ! user_ok )
696  { std::string msg =
697  user_atom->afun_name()
698  + ": atomic_base.reverse: returned false";
699  CPPAD_ASSERT_KNOWN(false, msg.c_str() );
700  }
701 # endif
702  for(j = 0; j < user_n; j++) if( user_ix[j] > 0 )
703  { for(ell = 0; ell < user_k1; ell++)
704  Partial[user_ix[j] * K + ell] +=
705  user_px[j * user_k1 + ell];
706  }
707  }
708  break;
709 
710  case UsrapOp:
711  // parameter argument in an atomic operation sequence
712  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
713  CPPAD_ASSERT_UNKNOWN( user_state == arg_user );
714  CPPAD_ASSERT_UNKNOWN( user_i == 0 );
715  CPPAD_ASSERT_UNKNOWN( user_j <= user_n );
716  CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par );
717  //
718  --user_j;
719  user_ix[user_j] = 0;
720  user_tx[user_j * user_k1 + 0] = parameter[ arg[0]];
721  for(ell = 1; ell < user_k1; ell++)
722  user_tx[user_j * user_k1 + ell] = Base(0.);
723  //
724  if( user_j == 0 )
725  user_state = start_user;
726  break;
727 
728  case UsravOp:
729  // variable argument in an atomic operation sequence
730  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
731  CPPAD_ASSERT_UNKNOWN( user_state == arg_user );
732  CPPAD_ASSERT_UNKNOWN( user_i == 0 );
733  CPPAD_ASSERT_UNKNOWN( user_j <= user_n );
734  //
735  --user_j;
736  user_ix[user_j] = arg[0];
737  for(ell = 0; ell < user_k1; ell++)
738  user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell];
739  //
740  if( user_j == 0 )
741  user_state = start_user;
742  break;
743 
744  case UsrrpOp:
745  // parameter result for a user atomic function
746  CPPAD_ASSERT_NARG_NRES(op, 1, 0);
747  CPPAD_ASSERT_UNKNOWN( user_state == ret_user );
748  CPPAD_ASSERT_UNKNOWN( user_i <= user_m );
749  CPPAD_ASSERT_UNKNOWN( user_j == user_n );
750  CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par );
751  //
752  --user_i;
753  for(ell = 0; ell < user_k1; ell++)
754  { user_py[user_i * user_k1 + ell] = Base(0.);
755  user_ty[user_i * user_k1 + ell] = Base(0.);
756  }
757  user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ];
758  //
759  if( user_i == 0 )
760  user_state = arg_user;
761  break;
762 
763  case UsrrvOp:
764  // variable result for a user atomic function
765  CPPAD_ASSERT_NARG_NRES(op, 0, 1);
766  CPPAD_ASSERT_UNKNOWN( user_state == ret_user );
767  CPPAD_ASSERT_UNKNOWN( user_i <= user_m );
768  CPPAD_ASSERT_UNKNOWN( user_j == user_n );
769  //
770  --user_i;
771  for(ell = 0; ell < user_k1; ell++)
772  { user_py[user_i * user_k1 + ell] =
773  Partial[i_var * K + ell];
774  user_ty[user_i * user_k1 + ell] =
775  Taylor[i_var * J + ell];
776  }
777  if( user_i == 0 )
778  user_state = arg_user;
779  break;
780  // ------------------------------------------------------------
781 
782  case ZmulpvOp:
783  CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
785  d, i_var, arg, parameter, J, Taylor, K, Partial
786  );
787  break;
788  // --------------------------------------------------
789 
790  case ZmulvpOp:
791  CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
793  d, i_var, arg, parameter, J, Taylor, K, Partial
794  );
795  break;
796  // --------------------------------------------------
797 
798  case ZmulvvOp:
800  d, i_var, arg, parameter, J, Taylor, K, Partial
801  );
802  break;
803  // --------------------------------------------------
804 
805  default:
806  CPPAD_ASSERT_UNKNOWN(false);
807  }
808  }
809 # if CPPAD_REVERSE_SWEEP_TRACE
810  std::cout << std::endl;
811 # endif
812 }
813 
814 } } // END_CPPAD_LOCAL_NAMESPACE
815 
816 // preprocessor symbols that are local to this file
817 # undef CPPAD_REVERSE_SWEEP_TRACE
818 # undef CPPAD_ATOMIC_CALL
819 
820 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
void reverse_subvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = SubvvOp.
Definition: sub_op.hpp:151
void reverse_sin_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = SinOp.
Definition: sin_op.hpp:188
void reverse_atan_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Reverse mode partial derivatives for result of op = AtanOp.
Definition: atan_op.hpp:180
void reverse_mulvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = MulvvOp.
Definition: mul_op.hpp:158
size_t num_par_rec(void) const
Fetch number of parameters in the recording.
Definition: player.hpp:638
void reverse_asin_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AsinOp.
Definition: asin_op.hpp:193
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
next UsrrpOp (UsrrvOp) is a parameter (variable) result
Definition: user_state.hpp:25
size_t NumArg(OpCode op)
Number of arguments for a specified operator.
Definition: op_code.hpp:175
void reverse_powvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = PowvvOp.
Definition: pow_op.hpp:177
#define CPPAD_ATOMIC_CALL
Class used to store and play back an operation sequence recording.
Definition: declare_ad.hpp:27
void reverse_sign_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = SignOp.
Definition: sign_op.hpp:134
void reverse_mulpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = MulpvOp.
Definition: mul_op.hpp:326
void reverse_exp_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Reverse mode partial derivatives for result of op = ExpOp.
Definition: exp_op.hpp:146
void resize(size_t n)
change the number of elements in this vector.
Definition: vector.hpp:399
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
void reverse_erf_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = ErfOp.
Definition: erf_op.hpp:479
void reverse_powpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = PowpvOp.
Definition: pow_op.hpp:412
void reverse_divpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = DivpvOp.
Definition: div_op.hpp:357
next UserOp marks end of a user atomic call
Definition: user_state.hpp:28
void reverse_addpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = AddpvOp.
Definition: add_op.hpp:309
atomic_base< Base > * get_user_info(const OpCode op, const addr_t *op_arg, size_t &user_old, size_t &user_m, size_t &user_n) const
unpack extra information corresponding to a UserOp
Definition: player.hpp:517
void reverse_tanh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = TanOp.
Definition: tanh_op.hpp:182
virtual void set_old(size_t id)
Set value of id (used by deprecated old_atomic class)
void reverse_expm1_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Reverse mode partial derivatives for result of op = Expm1Op.
Definition: expm1_op.hpp:149
size_t size(void) const
number of elements currently in this vector.
Definition: vector.hpp:387
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
void reverse_divvp_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = DivvpOp.
Definition: div_op.hpp:538
void reverse_zmulpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = ZmulpvOp.
Definition: zmul_op.hpp:325
next UserOp marks beginning of a user atomic call
Definition: user_state.hpp:19
void get_op_info(size_t op_index, OpCode &op, const addr_t *&op_arg, size_t &var_index) const
fetch the information corresponding to an operator
Definition: player.hpp:485
void reverse_load_op(OpCode op, size_t d, size_t i_z, const addr_t *arg, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial, const addr_t *var_by_load_op)
Reverse mode for op = LdpOp or LdvOp.
Definition: load_op.hpp:547
void reverse_asinh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AsinhOp.
Definition: asinh_op.hpp:194
void reverse_powvp_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = PowvpOp.
Definition: pow_op.hpp:619
void reverse_acos_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AcosOp.
Definition: acos_op.hpp:193
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
Type * data(void)
current data pointer is no longer valid after any of the following: extend, erase, operator=, and ~pod_vector. Take extreem care when using this function.
Definition: pod_vector.hpp:89
next UsrapOp (UsravOp) is a parameter (variable) argument
Definition: user_state.hpp:22
void reverse_log1p_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = Log1pOp.
Definition: log1p_op.hpp:156
void reverse_zmulvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = ZmulvvOp.
Definition: zmul_op.hpp:158
void reverse_subpv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = SubpvOp.
Definition: sub_op.hpp:312
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
void reverse_csum_op(size_t d, size_t i_z, const addr_t *arg, size_t nc_partial, Base *partial)
Compute reverse mode Taylor coefficients for result of op = CsumOp.
Definition: csum_op.hpp:332
void reverse_sqrt_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = SqrtOp.
Definition: sqrt_op.hpp:149
size_t num_op_rec(void) const
Fetch number of operators in the recording.
Definition: player.hpp:622
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.
void reverse_cos_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = CosOp.
Definition: cos_op.hpp:186
void reverse_acosh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AcoshOp.
Definition: acosh_op.hpp:194
void reverse_sweep(size_t d, size_t n, size_t numvar, const local::player< Base > *play, size_t J, const Base *Taylor, size_t K, Base *Partial, bool *cskip_op, const pod_vector< addr_t > &var_by_load_op, const pod_vector< addr_t > &subgraph)
Compute derivative of arbitrary order forward mode Taylor coefficients.
const std::string & afun_name(void) const
Name corresponding to a base_atomic object.
void reverse_abs_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AbsOp.
Definition: abs_op.hpp:131
void reverse_cosh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = CoshOp.
Definition: cosh_op.hpp:186
void reverse_addvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = AddvvOp.
Definition: add_op.hpp:151
void reverse_log_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = LogOp.
Definition: log_op.hpp:155
Base GetPar(size_t i) const
Fetch a parameter from the recording.
Definition: player.hpp:584
void reverse_subvp_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = SubvpOp.
Definition: sub_op.hpp:472
void reverse_atanh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Reverse mode partial derivatives for result of op = AtanhOp.
Definition: atanh_op.hpp:181
OpCode GetOp(size_t i) const
fetch an operator from the recording.
Definition: player.hpp:558
void reverse_zmulvp_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivative for result of op = ZmulvpOp.
Definition: zmul_op.hpp:485
void reverse_tan_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = TanOp.
Definition: tan_op.hpp:183
void reverse_cond_op(size_t d, size_t i_z, const addr_t *arg, size_t num_par, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode Taylor coefficients for op = CExpOp.
Definition: cond_op.hpp:814
void reverse_divvv_op(size_t d, size_t i_z, const addr_t *arg, const Base *parameter, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = DivvvOp.
Definition: div_op.hpp:166
size_t num_var_rec(void) const
Fetch number of variables in the recording.
Definition: player.hpp:614
void reverse_sinh_op(size_t d, size_t i_z, size_t i_x, size_t cap_order, const Base *taylor, size_t nc_partial, Base *partial)
Compute reverse mode partial derivatives for result of op = SinhOp.
Definition: sinh_op.hpp:187