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

Last change on this file since 2910 was 2910, checked in by bradbell, 7 years ago

Remove CPPAD_BEGIN_NAMESPACE, CPPAD_END_NAMESPACE, and instead use

namespace CppAD { BEGIN_CPPAD_NAMESPACE
}
END_CPPAD_NAMESPACE

becasue doxygen 1.8.3 gets confused when using a macro for this purpose
(begining and ending the CppAD namespace without indenting code).

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