source: trunk/cppad/local/reverse_sweep.hpp @ 3680

Last change on this file since 3680 was 3680, checked in by bradbell, 5 years ago

merge to branch: trunk
from repository: https://github.com/coin-or/CppAD
start hash code: 071875a4beba3363e5fa9752426aec4762cd1caa
end hash code: 0bef506513a519e1073c6279d5c4cba9e5c3b180

commit 0bef506513a519e1073c6279d5c4cba9e5c3b180
Author: Brad Bell <bradbell@…>
Date: Thu May 7 12:14:32 2015 -0700

Add the acosh function (as an atomic operation when defined by compiler).

commit b3264fa17b2f65b65800423a0e243c9c3ccfe06a
Author: Brad Bell <bradbell@…>
Date: Wed May 6 20:25:38 2015 -0700

CMakeLists.txt: Change so test only check for compliation.

commit dcbac4d4f20cc383f2bd9edb02036659df40b791
Author: Brad Bell <bradbell@…>
Date: Wed May 6 15:06:28 2015 -0700

asinh.cpp: check higher orders, relax accuracy on test.

commit 5f8881993fedd18cccc3c74831133a8f8a9d17b0
Author: Brad Bell <bradbell@…>
Date: Wed May 6 14:36:18 2015 -0700

Change Acos to acos.
acos.cpp: remove trailing white space.

commit e828fa1f7c4c3848c727f14b1b7a8030071ee705
Author: Brad Bell <bradbell@…>
Date: Wed May 6 12:07:35 2015 -0700

Change Acos to acos.
acos.cpp: remove redundant index commands, remove trailing with space.

commit 3d16e5b9fe1bdafa4ad01d1d466bb72b792650fa
Author: Brad Bell <bradbell@…>
Date: Wed May 6 11:30:49 2015 -0700

op_code.hpp: Minor edits to AcosOp? commnets.

commit 58beaaad149b4ac29fae44589d7f8900bf8f4c40
Author: Brad Bell <bradbell@…>
Date: Wed May 6 10:51:43 2015 -0700

for_jac_sweep.hpp: Add missing AsinhOp? case.

commit 623c134870c522ae5e80bcf0f89d230902594c80
Author: Brad Bell <bradbell@…>
Date: Wed May 6 10:27:39 2015 -0700

Fix comment about AsinhOp? operator.

commit 226b14f6f4810f5abf1ca247aae541963efaf4d6
Author: Brad Bell <bradbell@…>
Date: Wed May 6 10:14:08 2015 -0700

Add derivative of F to make order zero case clearer.
acos_reverse.omh: Fix some sign errors.
asin_reverse.omh: Fix typo.
acos_forward.omh: Simplify by distributing minus sign.

commit 4682f4ee73e33b600b180086576e986f636a24dc
Author: Brad Bell <bradbell@…>
Date: Wed May 6 08:15:50 2015 -0700

acos_forward.omh: fix sign that depends on acos versus acosh.

commit 906ae10adf019ddda7f57dd165aab08fc55289c4
Author: Brad Bell <bradbell@…>
Date: Wed May 6 07:09:47 2015 -0700

  1. Fix inclusion of some temporary files in package (e.g., git_commit.sh).
  2. Simplify and improve using git ls-files and ls bin/check_*.
  3. Remove trailing white space.

commit 5096f4706a547bd76caa3766aa2c62802ef7f0bf
Author: Brad Bell <bradbell@…>
Date: Wed May 6 06:41:20 2015 -0700

Combine base type documentation for erf, asinh
(will add more functions to this list list).

commit b3535db5ad95bee90672abcaa686032d23bce2fc
Author: Brad Bell <bradbell@…>
Date: Tue May 5 18:01:11 2015 -0700

  1. Change Arc Cosine/Sine? to Inverse Cosine/Sine?.
  2. Change arcsin-> asin and arccos->acos.
  3. Remove index commands that are duplicates of words in titles.


acos_reverse.omh: Add acosh case to this page.

  • Property svn:keywords set to Id
File size: 21.2 KB
Line 
1/* $Id: reverse_sweep.hpp 3680 2015-05-07 19:17:37Z bradbell $ */
2# ifndef CPPAD_REVERSE_SWEEP_INCLUDED
3# define CPPAD_REVERSE_SWEEP_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell
7
8CppAD is distributed under multiple licenses. This distribution is under
9the terms of the
10                    Eclipse Public License Version 1.0.
11
12A copy of this license is included in the COPYING file of this distribution.
13Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14-------------------------------------------------------------------------- */
15
16
17namespace CppAD { // BEGIN_CPPAD_NAMESPACE
18/*!
19\file reverse_sweep.hpp
20Compute derivatives of arbitrary order Taylor coefficients.
21*/
22
23/*
24\def CPPAD_ATOMIC_CALL
25This avoids warnings when NDEBUG is defined and user_ok is not used.
26If \c NDEBUG is defined, this resolves to
27\code
28        user_atom->reverse
29\endcode
30otherwise, it respolves to
31\code
32        user_ok = user_atom->reverse
33\endcode
34This maco is undefined at the end of this file to facillitate is
35use with a different definition in other files.
36*/
37# ifdef NDEBUG
38# define CPPAD_ATOMIC_CALL user_atom->reverse
39# else
40# define CPPAD_ATOMIC_CALL user_ok = user_atom->reverse
41# endif
42
43/*!
44\def CPPAD_REVERSE_SWEEP_TRACE
45This value is either zero or one.
46Zero is the normal operational value.
47If it is one, a trace of every reverse_sweep computation is printed.
48*/
49# define CPPAD_REVERSE_SWEEP_TRACE 0
50
51/*!
52Compute derivative of arbitrary order forward mode Taylor coefficients.
53
54\tparam Base
55base type for the operator; i.e., this operation sequence was recorded
56using AD< \a Base > and computations by this routine are done using type
57\a Base.
58
59\param d
60is the highest order Taylor coefficients that
61we are computing the derivative of.
62
63\param n
64is the number of independent variables on the tape.
65
66\param numvar
67is the total number of variables on the tape.
68This is also equal to the number of rows in the matrix \a Taylor; i.e.,
69play->num_var_rec().
70
71\param play
72The information stored in \a play
73is a recording of the operations corresponding to the function
74\f[
75        F : {\bf R}^n \rightarrow {\bf R}^m
76\f]
77where \f$ n \f$ is the number of independent variables and
78\f$ m \f$ is the number of dependent variables.
79We define \f$ u^{(k)} \f$ as the value of <code>x_k</code> in the previous call
80of the form
81<code>
82        f.Forward(k, x_k)
83</code>
84We define
85\f$ X : {\bf R}^{n \times d} \rightarrow {\bf R}^n \f$ by
86\f[
87        X(t, u) =  u^{(0)} + u^{(1)} t + \cdots + u^{(d)} t^d
88\f]
89We define
90\f$ Y : {\bf R}^{n \times d} \rightarrow {\bf R}^m \f$ by
91\f[
92        Y(t, u) =  F[ X(t, u) ]
93\f]
94We define the function
95\f$ W : {\bf R}^{n \times d} \rightarrow {\bf R} \f$ by
96\f[
97W(u)
98=
99\sum_{k=0}^{d} ( w^{(k)} )^{\rm T}
100        \frac{1}{k !} \frac{\partial^k}{\partial t^k} Y(0, u)
101\f]
102(The matrix \f$ w \in {\bf R}^m \f$,
103is defined below under the heading Partial.)
104Note that the scale factor  1 / k  converts
105the k-th partial derivative to the k-th order Taylor coefficient.
106This routine computes the derivative of \f$ W(u) \f$
107with respect to all the Taylor coefficients
108\f$ u^{(k)} \f$ for \f$ k = 0 , ... , d \f$.
109\n
110\n
111The object \a play is effectly constant.
112There is an exception to this,
113while palying back the tape
114the object \a play holds information about the current location
115with in the tape and this changes during palyback.
116
117\param J
118Is the number of columns in the coefficient matrix \a Taylor.
119This must be greater than or equal \a d + 1.
120
121\param Taylor
122For i = 1 , ... , \a numvar, and for k = 0 , ... , \a d,
123\a Taylor [ i * J + k ]
124is the k-th order Taylor coefficient corresponding to
125variable with index i on the tape.
126The value \f$ u \in {\bf R}^{n \times d} \f$,
127at which the derivative is computed,
128is defined by
129\f$ u_j^{(k)} \f$ = \a Taylor [ j * J + k ]
130for j = 1 , ... , \a n, and for k = 0 , ... , \a d.
131
132\param K
133Is the number of columns in the partial derivative matrix \a Partial.
134It must be greater than or equal \a d + 1.
135
136\param Partial
137\b Input:
138The last \f$ m \f$ rows of \a Partial are inputs.
139The matrix \f$ w \f$, used to define \f$ W(u) \f$,
140is specified by these rows.
141For i = 0 , ... , m - 1,
142for k = 0 , ... , d,
143<code>Partial [ (numvar - m + i ) * K + k ] = w[i,k]</code>.
144\n
145\n
146\b Temporary:
147For i = n+1 , ... , \a numvar - 1 and for k = 0 , ... , d,
148the value of \a Partial [ i * K + k ] is used for temporary work space
149and its output value is not defined.
150\n
151\n
152\b Output:
153For j = 1 , ... , n and for k = 0 , ... , d,
154\a Partial [ j * K + k ]
155is the partial derivative of \f$ W( u ) \f$ with
156respect to \f$ u_j^{(k)} \f$.
157
158\param cskip_op
159Is a vector with size play->num_op_rec().
160If cskip_op[i] is true, the operator index i in the recording
161does not affect any of the dependent variable (given the value
162of the independent variables).
163
164\param var_by_load_op
165is a vector with size play->num_load_op_rec().
166Is the variable index corresponding to each load instruction.
167In the case where the index is zero,
168the instruction corresponds to a parameter (not variable).
169
170\par Assumptions
171The first operator on the tape is a BeginOp,
172and the next \a n operators are InvOp operations for the
173corresponding independent variables.
174*/
175template <class Base>
176void ReverseSweep(
177        size_t                      d,
178        size_t                      n,
179        size_t                      numvar,
180        player<Base>*               play,
181        size_t                      J,
182        const Base*                 Taylor,
183        size_t                      K,
184        Base*                       Partial,
185        bool*                       cskip_op,
186        const pod_vector<addr_t>&   var_by_load_op
187)
188{
189        OpCode           op;
190        size_t         i_op;
191        size_t        i_var;
192
193        const addr_t*   arg = CPPAD_NULL;
194
195        // check numvar argument
196        CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
197        CPPAD_ASSERT_UNKNOWN( numvar > 0 );
198
199        // length of the parameter vector (used by CppAD assert macros)
200        const size_t num_par = play->num_par_rec();
201
202        // pointer to the beginning of the parameter vector
203        const Base* parameter = CPPAD_NULL;
204        if( num_par > 0 )
205                parameter = play->GetPar();
206
207        // work space used by UserOp.
208        const size_t user_k  = d;    // highest order we are differentiating
209        const size_t user_k1 = d+1;  // number of orders for this calculation
210        vector<size_t> user_ix;      // variable indices for argument vector
211        vector<Base> user_tx;        // argument vector Taylor coefficients
212        vector<Base> user_ty;        // result vector Taylor coefficients
213        vector<Base> user_px;        // partials w.r.t argument vector
214        vector<Base> user_py;        // partials w.r.t. result vector
215        size_t user_index = 0;       // indentifier for this atomic operation
216        size_t user_id    = 0;       // user identifier for this call to operator
217        size_t user_i     = 0;       // index in result vector
218        size_t user_j     = 0;       // index in argument vector
219        size_t user_m     = 0;       // size of result vector
220        size_t user_n     = 0;       // size of arugment vector
221        //
222        atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
223# ifndef NDEBUG
224        bool               user_ok   = false;      // atomic op return value
225# endif
226        //
227        // next expected operator in a UserOp sequence
228        enum { user_start, user_arg, user_ret, user_end } user_state = user_end;
229
230        // temporary indices
231        size_t j, ell;
232
233        // Initialize
234        play->reverse_start(op, arg, i_op, i_var);
235        CPPAD_ASSERT_UNKNOWN( op == EndOp );
236# if CPPAD_REVERSE_SWEEP_TRACE
237        std::cout << std::endl;
238# endif
239        bool more_operators = true;
240        while(more_operators)
241        {       // next op
242                play->reverse_next(op, arg, i_op, i_var);
243                CPPAD_ASSERT_UNKNOWN((i_op >  n) | (op == InvOp) | (op == BeginOp));
244                CPPAD_ASSERT_UNKNOWN((i_op <= n) | (op != InvOp) | (op != BeginOp));
245                CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
246
247                // check if we are skipping this operation
248                while( cskip_op[i_op] )
249                {       if( op == CSumOp )
250                        {       // CSumOp has a variable number of arguments
251                                play->reverse_csum(op, arg, i_op, i_var);
252                        }
253                        CPPAD_ASSERT_UNKNOWN( op != CSkipOp );
254                        // if( op == CSkipOp )
255                        // {    // CSkip has a variable number of arguments
256                        //      play->reverse_cskip(op, arg, i_op, i_var);
257                        // }
258                        CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
259                        play->reverse_next(op, arg, i_op, i_var);
260                }
261
262                // rest of informaiton depends on the case
263# if CPPAD_REVERSE_SWEEP_TRACE
264                if( op == CSumOp )
265                {       // CSumOp has a variable number of arguments
266                        play->reverse_csum(op, arg, i_op, i_var);
267                }
268                if( op == CSkipOp )
269                {       // CSkip has a variable number of arguments
270                        play->reverse_cskip(op, arg, i_op, i_var);
271                }
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
295                        case AbsOp:
296                        reverse_abs_op(
297                                d, i_var, arg[0], J, Taylor, K, Partial
298                        );
299                        break;
300                        // --------------------------------------------------
301
302                        case AcosOp:
303                        // sqrt(1 - x * x), acos(x)
304                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
305                        reverse_acos_op(
306                                d, i_var, arg[0], J, Taylor, K, Partial
307                        );
308                        break;
309                        // --------------------------------------------------
310
311# if CPPAD_COMPILER_HAS_ACOSH
312                        case AcoshOp:
313                        // sqrt(x * x - 1), acosh(x)
314                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
315                        reverse_acosh_op(
316                                d, i_var, arg[0], J, Taylor, K, Partial
317                        );
318                        break;
319# endif
320                        // --------------------------------------------------
321
322                        case AddvvOp:
323                        reverse_addvv_op(
324                                d, i_var, arg, parameter, J, Taylor, K, Partial
325                        );
326                        break;
327                        // --------------------------------------------------
328
329                        case AddpvOp:
330                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
331                        reverse_addpv_op(
332                                d, i_var, arg, parameter, J, Taylor, K, Partial
333                        );
334                        break;
335                        // --------------------------------------------------
336
337                        case AsinOp:
338                        // sqrt(1 - x * x), asin(x)
339                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
340                        reverse_asin_op(
341                                d, i_var, arg[0], J, Taylor, K, Partial
342                        );
343                        break;
344                        // --------------------------------------------------
345
346# if CPPAD_COMPILER_HAS_ASINH
347                        case AsinhOp:
348                        // sqrt(1 + x * x), asinh(x)
349                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
350                        reverse_asinh_op(
351                                d, i_var, arg[0], J, Taylor, K, Partial
352                        );
353                        break;
354# endif
355                        // --------------------------------------------------
356
357                        case AtanOp:
358                        // 1 + x * x, atan(x)
359                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
360                        reverse_atan_op(
361                                d, i_var, arg[0], J, Taylor, K, Partial
362                        );
363                        break;
364                        // -------------------------------------------------
365
366                        case BeginOp:
367                        CPPAD_ASSERT_NARG_NRES(op, 1, 1);
368                        more_operators = false;
369                        break;
370                        // --------------------------------------------------
371
372                        case CSkipOp:
373                        // CSkipOp has a variable number of arguments and
374                        // forward_next thinks it one has one argument.
375                        // we must inform reverse_next of this special case.
376# if ! CPPAD_REVERSE_SWEEP_TRACE
377                        play->reverse_cskip(op, arg, i_op, i_var);
378# endif
379                        break;
380                        // -------------------------------------------------
381
382                        case CSumOp:
383                        // CSumOp has a variable number of arguments and
384                        // reverse_next thinks it one has one argument.
385                        // We must inform reverse_next of this special case.
386# if ! CPPAD_REVERSE_SWEEP_TRACE
387                        play->reverse_csum(op, arg, i_op, i_var);
388# endif
389                        reverse_csum_op(
390                                d, i_var, arg, K, Partial
391                        );
392                        // end of a cummulative summation
393                        break;
394                        // -------------------------------------------------
395
396                        case CExpOp:
397                        reverse_cond_op(
398                                d,
399                                i_var,
400                                arg,
401                                num_par,
402                                parameter,
403                                J,
404                                Taylor,
405                                K,
406                                Partial
407                        );
408                        break;
409                        // --------------------------------------------------
410
411                        case CosOp:
412                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
413                        reverse_cos_op(
414                                d, i_var, arg[0], J, Taylor, K, Partial
415                        );
416                        break;
417                        // --------------------------------------------------
418
419                        case CoshOp:
420                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
421                        reverse_cosh_op(
422                                d, i_var, arg[0], J, Taylor, K, Partial
423                        );
424                        break;
425                        // --------------------------------------------------
426
427                        case DisOp:
428                        // Derivative of discrete operation is zero so no
429                        // contribution passes through this operation.
430                        break;
431                        // --------------------------------------------------
432
433                        case DivvvOp:
434                        reverse_divvv_op(
435                                d, i_var, arg, parameter, J, Taylor, K, Partial
436                        );
437                        break;
438                        // --------------------------------------------------
439
440                        case DivpvOp:
441                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
442                        reverse_divpv_op(
443                                d, i_var, arg, parameter, J, Taylor, K, Partial
444                        );
445                        break;
446                        // --------------------------------------------------
447
448                        case DivvpOp:
449                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
450                        reverse_divvp_op(
451                                d, i_var, arg, parameter, J, Taylor, K, Partial
452                        );
453                        break;
454                        // --------------------------------------------------
455
456# if CPPAD_COMPILER_HAS_ERF
457                        case ErfOp:
458                        reverse_erf_op(
459                                d, i_var, arg, parameter, J, Taylor, K, Partial
460                        );
461                        break;
462# endif
463                        // --------------------------------------------------
464
465                        case ExpOp:
466                        reverse_exp_op(
467                                d, i_var, arg[0], J, Taylor, K, Partial
468                        );
469                        break;
470                        // --------------------------------------------------
471
472                        case InvOp:
473                        break;
474                        // --------------------------------------------------
475
476                        case LdpOp:
477                        reverse_load_op(
478                        op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
479                        );
480                        break;
481                        // -------------------------------------------------
482
483                        case LdvOp:
484                        reverse_load_op(
485                        op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
486                        );
487                        break;
488                        // --------------------------------------------------
489
490                        case EqpvOp:
491                        case EqvvOp:
492                        case LtpvOp:
493                        case LtvpOp:
494                        case LtvvOp:
495                        case LepvOp:
496                        case LevpOp:
497                        case LevvOp:
498                        case NepvOp:
499                        case NevvOp:
500                        break;
501                        // -------------------------------------------------
502
503                        case LogOp:
504                        reverse_log_op(
505                                d, i_var, arg[0], J, Taylor, K, Partial
506                        );
507                        break;
508                        // --------------------------------------------------
509
510                        case MulvvOp:
511                        reverse_mulvv_op(
512                                d, i_var, arg, parameter, J, Taylor, K, Partial
513                        );
514                        break;
515                        // --------------------------------------------------
516
517                        case MulpvOp:
518                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
519                        reverse_mulpv_op(
520                                d, i_var, arg, parameter, J, Taylor, K, Partial
521                        );
522                        break;
523                        // --------------------------------------------------
524
525                        case ParOp:
526                        break;
527                        // --------------------------------------------------
528
529                        case PowvpOp:
530                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
531                        reverse_powvp_op(
532                                d, i_var, arg, parameter, J, Taylor, K, Partial
533                        );
534                        break;
535                        // -------------------------------------------------
536
537                        case PowpvOp:
538                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
539                        reverse_powpv_op(
540                                d, i_var, arg, parameter, J, Taylor, K, Partial
541                        );
542                        break;
543                        // -------------------------------------------------
544
545                        case PowvvOp:
546                        reverse_powvv_op(
547                                d, i_var, arg, parameter, J, Taylor, K, Partial
548                        );
549                        break;
550                        // --------------------------------------------------
551
552                        case PriOp:
553                        // no result so nothing to do
554                        break;
555                        // --------------------------------------------------
556
557                        case SignOp:
558                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
559                        reverse_sign_op(
560                                d, i_var, arg[0], J, Taylor, K, Partial
561                        );
562                        break;
563                        // -------------------------------------------------
564
565                        case SinOp:
566                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
567                        reverse_sin_op(
568                                d, i_var, arg[0], J, Taylor, K, Partial
569                        );
570                        break;
571                        // -------------------------------------------------
572
573                        case SinhOp:
574                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
575                        reverse_sinh_op(
576                                d, i_var, arg[0], J, Taylor, K, Partial
577                        );
578                        break;
579                        // --------------------------------------------------
580
581                        case SqrtOp:
582                        reverse_sqrt_op(
583                                d, i_var, arg[0], J, Taylor, K, Partial
584                        );
585                        break;
586                        // --------------------------------------------------
587
588                        case StppOp:
589                        break;
590                        // --------------------------------------------------
591
592                        case StpvOp:
593                        break;
594                        // -------------------------------------------------
595
596                        case StvpOp:
597                        break;
598                        // -------------------------------------------------
599
600                        case StvvOp:
601                        break;
602                        // --------------------------------------------------
603
604                        case SubvvOp:
605                        reverse_subvv_op(
606                                d, i_var, arg, parameter, J, Taylor, K, Partial
607                        );
608                        break;
609                        // --------------------------------------------------
610
611                        case SubpvOp:
612                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
613                        reverse_subpv_op(
614                                d, i_var, arg, parameter, J, Taylor, K, Partial
615                        );
616                        break;
617                        // --------------------------------------------------
618
619                        case SubvpOp:
620                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
621                        reverse_subvp_op(
622                                d, i_var, arg, parameter, J, Taylor, K, Partial
623                        );
624                        break;
625                        // -------------------------------------------------
626
627                        case TanOp:
628                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
629                        reverse_tan_op(
630                                d, i_var, arg[0], J, Taylor, K, Partial
631                        );
632                        break;
633                        // -------------------------------------------------
634
635                        case TanhOp:
636                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
637                        reverse_tanh_op(
638                                d, i_var, arg[0], J, Taylor, K, Partial
639                        );
640                        break;
641                        // --------------------------------------------------
642
643                        case UserOp:
644                        // start or end an atomic operation sequence
645                        CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 );
646                        CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 );
647                        if( user_state == user_end )
648                        {       user_index = arg[0];
649                                user_id    = arg[1];
650                                user_n     = arg[2];
651                                user_m     = arg[3];
652                                user_atom  = atomic_base<Base>::class_object(user_index);
653# ifndef NDEBUG
654                                if( user_atom == CPPAD_NULL )
655                                {       std::string msg =
656                                                atomic_base<Base>::class_name(user_index)
657                                                + ": atomic_base function has been deleted";
658                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
659                                }
660# endif
661                                if(user_ix.size() != user_n)
662                                        user_ix.resize(user_n);
663                                if(user_tx.size() != user_n * user_k1)
664                                {       user_tx.resize(user_n * user_k1);
665                                        user_px.resize(user_n * user_k1);
666                                }
667                                if(user_ty.size() != user_m * user_k1)
668                                {       user_ty.resize(user_m * user_k1);
669                                        user_py.resize(user_m * user_k1);
670                                }
671                                user_j     = user_n;
672                                user_i     = user_m;
673                                user_state = user_ret;
674                        }
675                        else
676                        {       CPPAD_ASSERT_UNKNOWN( user_state == user_start );
677                                CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) );
678                                CPPAD_ASSERT_UNKNOWN( user_id    == size_t(arg[1]) );
679                                CPPAD_ASSERT_UNKNOWN( user_n     == size_t(arg[2]) );
680                                CPPAD_ASSERT_UNKNOWN( user_m     == size_t(arg[3]) );
681
682                                // call users function for this operation
683                                user_atom->set_id(user_id);
684                                CPPAD_ATOMIC_CALL(
685                                        user_k, user_tx, user_ty, user_px, user_py
686                                );
687# ifndef NDEBUG
688                                if( ! user_ok )
689                                {       std::string msg =
690                                                atomic_base<Base>::class_name(user_index)
691                                                + ": atomic_base.reverse: returned false";
692                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
693                                }
694# endif
695                                for(j = 0; j < user_n; j++) if( user_ix[j] > 0 )
696                                {       for(ell = 0; ell < user_k1; ell++)
697                                                Partial[user_ix[j] * K + ell] +=
698                                                        user_px[j * user_k1 + ell];
699                                }
700                                user_state = user_end;
701                        }
702                        break;
703
704                        case UsrapOp:
705                        // parameter argument in an atomic operation sequence
706                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
707                        CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n );
708                        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
709                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
710                        --user_j;
711                        user_ix[user_j] = 0;
712                        user_tx[user_j * user_k1 + 0] = parameter[ arg[0]];
713                        for(ell = 1; ell < user_k1; ell++)
714                                user_tx[user_j * user_k1 + ell] = Base(0.);
715
716                        if( user_j == 0 )
717                                user_state = user_start;
718                        break;
719
720                        case UsravOp:
721                        // variable argument in an atomic operation sequence
722                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
723                        CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n );
724                        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
725                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
726                        CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
727                        --user_j;
728                        user_ix[user_j] = arg[0];
729                        for(ell = 0; ell < user_k1; ell++)
730                                user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell];
731                        if( user_j == 0 )
732                                user_state = user_start;
733                        break;
734
735                        case UsrrpOp:
736                        // parameter result in an atomic operation sequence
737                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
738                        CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m );
739                        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
740                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
741                        --user_i;
742                        for(ell = 0; ell < user_k1; ell++)
743                        {       user_py[user_i * user_k1 + ell] = Base(0.);
744                                user_ty[user_i * user_k1 + ell] = Base(0.);
745                        }
746                        user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ];
747                        if( user_i == 0 )
748                                user_state = user_arg;
749                        break;
750
751                        case UsrrvOp:
752                        // variable result in an atomic operation sequence
753                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
754                        CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m );
755                        --user_i;
756                        for(ell = 0; ell < user_k1; ell++)
757                        {       user_py[user_i * user_k1 + ell] =
758                                                Partial[i_var * K + ell];
759                                user_ty[user_i * user_k1 + ell] =
760                                                Taylor[i_var * J + ell];
761                        }
762                        if( user_i == 0 )
763                                user_state = user_arg;
764                        break;
765                        // ------------------------------------------------------------
766
767                        default:
768                        CPPAD_ASSERT_UNKNOWN(false);
769                }
770        }
771# if CPPAD_REVERSE_SWEEP_TRACE
772        std::cout << std::endl;
773# endif
774        // values corresponding to BeginOp
775        CPPAD_ASSERT_UNKNOWN( i_op == 0 );
776        CPPAD_ASSERT_UNKNOWN( i_var == 0 );
777}
778
779} // END_CPPAD_NAMESPACE
780
781// preprocessor symbols that are local to this file
782# undef CPPAD_REVERSE_SWEEP_TRACE
783# undef CPPAD_ATOMIC_CALL
784
785# endif
Note: See TracBrowser for help on using the repository browser.