source: branches/opt_cond_exp/cppad/local/forward0sweep.hpp @ 2979

Last change on this file since 2979 was 2979, checked in by bradbell, 7 years ago
  1. Add operator index to trace output.
  2. Check that new operator values have been set and are valid.
  3. Reinitialize cskip_op_ after optimization.

optimize.hpp: Add test of entirely removing an atomic call.

  • Property svn:keywords set to Id
File size: 19.1 KB
Line 
1/* $Id: forward0sweep.hpp 2979 2013-10-20 18:00:28Z bradbell $ */
2# ifndef CPPAD_FORWARD0SWEEP_INCLUDED
3# define CPPAD_FORWARD0SWEEP_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
16namespace CppAD { // BEGIN_CPPAD_NAMESPACE
17/*!
18\defgroup forward0sweep_hpp forward0sweep.hpp
19\{
20\file forward0sweep.hpp
21Compute zero order forward mode Taylor coefficients.
22*/
23
24/*
25\def CPPAD_ATOMIC_CALL
26This avoids warnings when NDEBUG is defined and user_ok is not used.
27If \c NDEBUG is defined, this resolves to
28\code
29        user_atom->forward
30\endcode
31otherwise, it respolves to
32\code
33        user_ok = user_atom->forward
34\endcode
35This maco is undefined at the end of this file to facillitate is
36use with a different definition in other files.
37*/
38# ifdef NDEBUG
39# define CPPAD_ATOMIC_CALL user_atom->forward
40# else
41# define CPPAD_ATOMIC_CALL user_ok = user_atom->forward
42# endif
43
44/*!
45\def CPPAD_FORWARD0SWEEP_TRACE
46This value is either zero or one.
47Zero is the normal operational value.
48If it is one, a trace of every forward0sweep computation is printed.
49(Note that forward0sweep is not used if CPPAD_USE_FORWARD0SWEEP is zero).
50*/
51# define CPPAD_FORWARD0SWEEP_TRACE 0
52
53/*!
54Compute zero order forward mode Taylor coefficients.
55
56\tparam Base
57The type used during the forward mode computations; i.e., the corresponding
58recording of operations used the type \c AD<Base>.
59
60\param s_out
61Is the stream where output corresponding to \c PriOp operations will
62be written.
63
64\param print
65If \a print is false,
66suppress the output that is otherwise generated by the c PriOp instructions.
67
68\param n
69is the number of independent variables on the tape.
70
71\param numvar
72is the total number of variables on the tape.
73This is also equal to the number of rows in the matrix \a Taylor; i.e.,
74\a Rec->num_rec_var().
75
76\param Rec
772DO: change this name from Rec to play (becuase it is a player
78and not a recorder).
79The information stored in \a Rec
80is a recording of the operations corresponding to the function
81\f[
82        F : {\bf R}^n \rightarrow {\bf R}^m
83\f]
84where \f$ n \f$ is the number of independent variables and
85\f$ m \f$ is the number of dependent variables.
86\n
87\n
88The object \a Rec is effectly constant.
89There are two exceptions to this.
90The first exception is that while palying back the tape
91the object \a Rec holds information about the current location
92with in the tape and this changes during palyback.
93The second exception is the fact that the
94zero order ( \a d = 0 ) versions of the VecAD operators LdpOp and LdvOp
95modify the corresponding \a op_arg values returned by
96\ref player::next_forward and \ref player::next_reverse; see the
97\link load_op.hpp LdpOp and LdvOp \endlink operations.
98
99\param J
100Is the number of columns in the coefficient matrix \a Taylor.
101This must be greater than or equal one.
102
103\param Taylor
104\b Input: For j = 1 , ... , \a n,
105\a Taylor [ j * J + 0 ]
106variable with index i on the tape
107(independent variable with index (j-1) in the independent variable vector).
108\n
109\n
110\b Output: For i = \a n + 1, ... , \a numvar - 1,
111\a Taylor [ i * J + 0 ]
112is the zero order Taylor coefficient for the variable with
113index i on the tape.
114
115\param cskip_op
116Is a vector with size Rec->num_rec_op(),
117the input value of the elements does not matter.
118Upon return, if cskip_op[i] is true, the operator index i in the recording
119does not affect any of the dependent variable (given the value
120of the independent variables).
121
122\a return
123The return value is equal to the number of ComOp operations
124that have a different result from when the information in
125\a Rec was recorded.
126(Note that if NDEBUG is true, there are no ComOp operations
127in Rec and hence this return value is always zero.)
128*/
129
130template <class Base>
131size_t forward0sweep(
132        std::ostream&         s_out,
133        bool                  print,
134        size_t                n,
135        size_t                numvar,
136        player<Base>         *Rec,
137        size_t                J,
138        Base                 *Taylor,
139        CppAD::vector<bool>&  cskip_op
140)
141{       CPPAD_ASSERT_UNKNOWN( J >= 1 );
142
143        // op code for current instruction
144        OpCode           op;
145
146        // index for current instruction
147        size_t         i_op;
148
149        // next variables
150        size_t        i_var;
151
152        // constant and non-constant version of the operation argument indices
153        addr_t*         non_const_arg;
154        const addr_t*   arg = CPPAD_NULL;
155
156        // initialize the comparision operator (ComOp) counter
157        size_t compareCount = 0;
158
159        // This is an order zero calculation, initialize vector indices
160        pod_vector<size_t> VectorInd;  // address for each element
161        pod_vector<bool>   VectorVar;  // is element a variable
162        size_t  i = Rec->num_rec_vecad_ind();
163        if( i > 0 )
164        {       VectorInd.extend(i);
165                VectorVar.extend(i);
166                while(i--)
167                {       VectorInd[i] = Rec->GetVecInd(i);
168                        VectorVar[i] = false;
169                }
170        }
171
172        // zero order, so initialize conditional skip flags
173        for(i = 0; i < Rec->num_rec_op(); i++)
174                cskip_op[i] = false;
175
176        // work space used by UserOp.
177        const size_t user_q = 0;     // lowest order
178        const size_t user_p = 0;     // highest order
179        vector<bool> user_vx;        // empty vecotor
180        vector<bool> user_vy;        // empty vecotor
181        vector<Base> user_tx;        // argument vector Taylor coefficients
182        vector<Base> user_ty;        // result vector Taylor coefficients
183        size_t user_index = 0;       // indentifier for this atomic operation
184        size_t user_id    = 0;       // user identifier for this call to operator
185        size_t user_i     = 0;       // index in result vector
186        size_t user_j     = 0;       // index in argument vector
187        size_t user_m     = 0;       // size of result vector
188        size_t user_n     = 0;       // size of arugment vector
189        //
190        atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
191# ifndef NDEBUG
192        bool               user_ok   = false;      // atomic op return value
193# endif
194        //
195        // next expected operator in a UserOp sequence
196        enum { user_start, user_arg, user_ret, user_end } user_state = user_start;
197
198        // check numvar argument
199        CPPAD_ASSERT_UNKNOWN( Rec->num_rec_var() == numvar );
200
201        // length of the parameter vector (used by CppAD assert macros)
202        const size_t num_par = Rec->num_rec_par();
203
204        // length of the text vector (used by CppAD assert macros)
205        const size_t num_text = Rec->num_rec_text();
206
207        // pointer to the beginning of the parameter vector
208        const Base* parameter = CPPAD_NULL;
209        if( num_par > 0 )
210                parameter = Rec->GetPar();
211
212        // pointer to the beginning of the text vector
213        const char* text = CPPAD_NULL;
214        if( num_text > 0 )
215                text = Rec->GetTxt(0);
216
217        // skip the BeginOp at the beginning of the recording
218        Rec->start_forward(op, arg, i_op, i_var);
219        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
220# if CPPAD_FORWARD0SWEEP_TRACE
221        std::cout << std::endl;
222# endif
223        while(op != EndOp)
224        {
225                // this op
226                Rec->next_forward(op, arg, i_op, i_var);
227                CPPAD_ASSERT_UNKNOWN( (i_op > n)  | (op == InvOp) ); 
228                CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); 
229
230                // check if we are skipping this operation
231                while( cskip_op[i_op] )
232                {       if( op == CSumOp )
233                        {       // CSumOp has a variable number of arguments and
234                                Rec->forward_csum(op, arg, i_op, i_var);
235                        }
236                        Rec->next_forward(op, arg, i_op, i_var);
237                }
238
239                // action to take depends on the case
240                switch( op )
241                {
242                        case AbsOp:
243                        forward_abs_op_0(i_var, arg[0], J, Taylor);
244                        break;
245                        // -------------------------------------------------
246
247                        case AddvvOp:
248                        forward_addvv_op_0(i_var, arg, parameter, J, Taylor);
249                        break;
250                        // -------------------------------------------------
251
252                        case AddpvOp:
253                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
254                        forward_addpv_op_0(i_var, arg, parameter, J, Taylor);
255                        break;
256                        // -------------------------------------------------
257
258                        case AcosOp:
259                        // sqrt(1 - x * x), acos(x)
260                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
261                        forward_acos_op_0(i_var, arg[0], J, Taylor);
262                        break;
263                        // -------------------------------------------------
264
265                        case AsinOp:
266                        // sqrt(1 - x * x), asin(x)
267                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
268                        forward_asin_op_0(i_var, arg[0], J, Taylor);
269                        break;
270                        // -------------------------------------------------
271
272                        case AtanOp:
273                        // 1 + x * x, atan(x)
274                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
275                        forward_atan_op_0(i_var, arg[0], J, Taylor);
276                        break;
277                        // -------------------------------------------------
278
279                        case CExpOp:
280                        // Use the general case with d == 0
281                        // (could create an optimzied verison for this case)
282                        forward_cond_op_0(
283                                i_var, arg, num_par, parameter, J, Taylor
284                        );
285                        break;
286                        // ---------------------------------------------------
287                        case ComOp:
288                        forward_comp_op_0(
289                        compareCount, arg, num_par, parameter, J, Taylor
290                        );
291                        break;
292                        // ---------------------------------------------------
293
294                        case CosOp:
295                        // sin(x), cos(x)
296                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
297                        forward_cos_op_0(i_var, arg[0], J, Taylor);
298                        break;
299                        // ---------------------------------------------------
300
301                        case CoshOp:
302                        // sinh(x), cosh(x)
303                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
304                        forward_cosh_op_0(i_var, arg[0], J, Taylor);
305                        break;
306                        // -------------------------------------------------
307
308                        case CSkipOp:
309                        // CSumOp has a variable number of arguments and
310                        // next_forward thinks it one has one argument.
311                        // we must inform next_forward of this special case.
312                        Rec->forward_cskip(op, arg, i_op, i_var);
313                        forward_cskip_op_0(
314                                i_var, arg, num_par, parameter, J, Taylor, cskip_op
315                        );
316                        break;
317                        // -------------------------------------------------
318
319                        case CSumOp:
320                        // CSumOp has a variable number of arguments and
321                        // next_forward thinks it one has one argument.
322                        // we must inform next_forward of this special case.
323                        Rec->forward_csum(op, arg, i_op, i_var);
324                        forward_csum_op(
325                                0, 0, i_var, arg, num_par, parameter, J, Taylor
326                        );
327                        break;
328                        // -------------------------------------------------
329
330                        case DisOp:
331                        forward_dis_op_0(i_var, arg, J, Taylor);
332                        break;
333                        // -------------------------------------------------
334
335                        case DivvvOp:
336                        forward_divvv_op_0(i_var, arg, parameter, J, Taylor);
337                        break;
338                        // -------------------------------------------------
339
340                        case DivpvOp:
341                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
342                        forward_divpv_op_0(i_var, arg, parameter, J, Taylor);
343                        break;
344                        // -------------------------------------------------
345
346                        case DivvpOp:
347                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
348                        forward_divvp_op_0(i_var, arg, parameter, J, Taylor);
349                        break;
350                        // -------------------------------------------------
351
352                        case EndOp:
353                        CPPAD_ASSERT_NARG_NRES(op, 0, 0);
354                        break;
355                        // -------------------------------------------------
356
357                        case ExpOp:
358                        forward_exp_op_0(i_var, arg[0], J, Taylor);
359                        break;
360                        // -------------------------------------------------
361
362                        case InvOp:
363                        break;
364                        // -------------------------------------------------
365
366                        case LdpOp:
367                        CPPAD_ASSERT_UNKNOWN( VectorInd.size() != 0 );
368                        CPPAD_ASSERT_UNKNOWN( VectorVar.size() != 0 );
369                        non_const_arg = Rec->forward_non_const_arg();
370                        forward_load_p_op_0(
371                                i_var, 
372                                non_const_arg, 
373                                num_par, 
374                                parameter, 
375                                J, 
376                                Taylor,
377                                Rec->num_rec_vecad_ind(),
378                                VectorVar.data(),
379                                VectorInd.data()
380                        );
381                        break;
382                        // -------------------------------------------------
383
384                        case LdvOp:
385                        CPPAD_ASSERT_UNKNOWN( VectorInd.size() != 0 );
386                        CPPAD_ASSERT_UNKNOWN( VectorVar.size() != 0 );
387                        non_const_arg = Rec->forward_non_const_arg();
388                        forward_load_v_op_0(
389                                i_var, 
390                                non_const_arg, 
391                                num_par, 
392                                parameter, 
393                                J, 
394                                Taylor,
395                                Rec->num_rec_vecad_ind(),
396                                VectorVar.data(),
397                                VectorInd.data()
398                        );
399                        break;
400                        // -------------------------------------------------
401
402                        case LogOp:
403                        forward_log_op_0(i_var, arg[0], J, Taylor);
404                        break;
405                        // -------------------------------------------------
406
407                        case MulvvOp:
408                        forward_mulvv_op_0(i_var, arg, parameter, J, Taylor);
409                        break;
410                        // -------------------------------------------------
411
412                        case MulpvOp:
413                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
414                        forward_mulpv_op_0(i_var, arg, parameter, J, Taylor);
415                        break;
416                        // -------------------------------------------------
417
418                        case ParOp:
419                        forward_par_op_0(
420                                i_var, arg, num_par, parameter, J, Taylor
421                        );
422                        break;
423                        // -------------------------------------------------
424
425                        case PowvpOp:
426                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
427                        forward_powvp_op_0(i_var, arg, parameter, J, Taylor);
428                        break;
429                        // -------------------------------------------------
430
431                        case PowpvOp:
432                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
433                        forward_powpv_op_0(i_var, arg, parameter, J, Taylor);
434                        break;
435                        // -------------------------------------------------
436
437                        case PowvvOp:
438                        forward_powvv_op_0(i_var, arg, parameter, J, Taylor);
439                        break;
440                        // -------------------------------------------------
441
442                        case PriOp:
443                        if( print ) forward_pri_0(s_out,
444                                i_var, arg, num_text, text, num_par, parameter, J, Taylor
445                        );
446                        break;
447                        // -------------------------------------------------
448
449                        case SignOp:
450                        // cos(x), sin(x)
451                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
452                        forward_sign_op_0(i_var, arg[0], J, Taylor);
453                        break;
454                        // -------------------------------------------------
455
456                        case SinOp:
457                        // cos(x), sin(x)
458                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
459                        forward_sin_op_0(i_var, arg[0], J, Taylor);
460                        break;
461                        // -------------------------------------------------
462
463                        case SinhOp:
464                        // cosh(x), sinh(x)
465                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
466                        forward_sinh_op_0(i_var, arg[0], J, Taylor);
467                        break;
468                        // -------------------------------------------------
469
470                        case SqrtOp:
471                        forward_sqrt_op_0(i_var, arg[0], J, Taylor);
472                        break;
473                        // -------------------------------------------------
474
475                        case StppOp:
476                        forward_store_pp_op_0(
477                                i_var, 
478                                arg, 
479                                num_par, 
480                                J, 
481                                Taylor,
482                                Rec->num_rec_vecad_ind(),
483                                VectorVar.data(),
484                                VectorInd.data()
485                        );
486                        break;
487                        // -------------------------------------------------
488
489                        case StpvOp:
490                        forward_store_pv_op_0(
491                                i_var, 
492                                arg, 
493                                num_par, 
494                                J, 
495                                Taylor,
496                                Rec->num_rec_vecad_ind(),
497                                VectorVar.data(),
498                                VectorInd.data()
499                        );
500                        break;
501                        // -------------------------------------------------
502
503                        case StvpOp:
504                        forward_store_vp_op_0(
505                                i_var, 
506                                arg, 
507                                num_par, 
508                                J, 
509                                Taylor,
510                                Rec->num_rec_vecad_ind(),
511                                VectorVar.data(),
512                                VectorInd.data()
513                        );
514                        break;
515                        // -------------------------------------------------
516
517                        case StvvOp:
518                        forward_store_vv_op_0(
519                                i_var, 
520                                arg, 
521                                num_par, 
522                                J, 
523                                Taylor,
524                                Rec->num_rec_vecad_ind(),
525                                VectorVar.data(),
526                                VectorInd.data()
527                        );
528                        break;
529                        // -------------------------------------------------
530
531                        case SubvvOp:
532                        forward_subvv_op_0(i_var, arg, parameter, J, Taylor);
533                        break;
534                        // -------------------------------------------------
535
536                        case SubpvOp:
537                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
538                        forward_subpv_op_0(i_var, arg, parameter, J, Taylor);
539                        break;
540                        // -------------------------------------------------
541
542                        case SubvpOp:
543                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
544                        forward_subvp_op_0(i_var, arg, parameter, J, Taylor);
545                        break;
546                        // -------------------------------------------------
547
548                        case TanOp:
549                        // tan(x)^2, tan(x)
550                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
551                        forward_tan_op_0(i_var, arg[0], J, Taylor);
552                        break;
553                        // -------------------------------------------------
554
555                        case TanhOp:
556                        // tanh(x)^2, tanh(x)
557                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
558                        forward_tanh_op_0(i_var, arg[0], J, Taylor);
559                        break;
560                        // -------------------------------------------------
561
562                        case UserOp:
563                        // start or end an atomic operation sequence
564                        CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 );
565                        CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 );
566                        if( user_state == user_start )
567                        {       user_index = arg[0];
568                                user_id    = arg[1];
569                                user_n     = arg[2];
570                                user_m     = arg[3];
571                                user_atom  = atomic_base<Base>::class_object(user_index);
572# ifndef NDEBUG
573                                if( user_atom == CPPAD_NULL )
574                                {       std::string msg = 
575                                                atomic_base<Base>::class_name(user_index)
576                                                + ": atomic_base function has been deleted";
577                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
578                                }
579# endif
580                                if(user_tx.size() != user_n)
581                                        user_tx.resize(user_n);
582                                if(user_ty.size() != user_m)
583                                        user_ty.resize(user_m);
584                                user_j     = 0;
585                                user_i     = 0;
586                                user_state = user_arg;
587                        }
588                        else
589                        {       CPPAD_ASSERT_UNKNOWN( user_state == user_end );
590                                CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) );
591                                CPPAD_ASSERT_UNKNOWN( user_id    == size_t(arg[1]) );
592                                CPPAD_ASSERT_UNKNOWN( user_n     == size_t(arg[2]) );
593                                CPPAD_ASSERT_UNKNOWN( user_m     == size_t(arg[3]) );
594# ifndef NDEBUG
595                                if( ! user_ok )
596                                {       std::string msg = 
597                                                atomic_base<Base>::class_name(user_index)
598                                                + ": atomic_base.forward: returned false";
599                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
600                                }
601# endif
602                                user_state = user_start;
603                        }
604                        break;
605
606                        case UsrapOp:
607                        // parameter argument in an atomic operation sequence
608                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
609                        CPPAD_ASSERT_UNKNOWN( user_j < user_n );
610                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
611                        user_tx[user_j++] = parameter[ arg[0] ];
612                        if( user_j == user_n )
613                        {       // call users function for this operation
614                                user_atom->set_id(user_id);
615                                CPPAD_ATOMIC_CALL(user_q, user_p, 
616                                        user_vx, user_vy, user_tx, user_ty
617                                );
618                                user_state = user_ret;
619                        }
620                        break;
621
622                        case UsravOp:
623                        // variable argument in an atomic operation sequence
624                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
625                        CPPAD_ASSERT_UNKNOWN( user_j < user_n );
626                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
627                        user_tx[user_j++] = Taylor[ arg[0] * J + 0 ];
628                        if( user_j == user_n )
629                        {       // call users function for this operation
630                                user_atom->set_id(user_id);
631                                CPPAD_ATOMIC_CALL(user_q, user_p, 
632                                        user_vx, user_vy, user_tx, user_ty
633                                );
634                                user_state = user_ret;
635                        }
636                        break;
637
638                        case UsrrpOp:
639                        // parameter result in an atomic operation sequence
640                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
641                        CPPAD_ASSERT_UNKNOWN( user_i < user_m );
642                        user_i++;
643                        if( user_i == user_m )
644                                user_state = user_end;
645                        break;
646
647                        case UsrrvOp:
648                        // variable result in an atomic operation sequence
649                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
650                        CPPAD_ASSERT_UNKNOWN( user_i < user_m );
651                        Taylor[ i_var * J + 0 ] = user_ty[user_i++];
652                        if( user_i == user_m )
653                                user_state = user_end;
654                        break;
655                        // -------------------------------------------------
656
657                        default:
658                        CPPAD_ASSERT_UNKNOWN(false);
659                }
660# if CPPAD_FORWARD0SWEEP_TRACE
661                size_t       d      = 0;
662                size_t       i_tmp  = i_var;
663                Base*        Z_tmp  = Taylor + i_var * J;
664
665                printOp(
666                        std::cout, 
667                        Rec,
668                        i_op,
669                        i_tmp,
670                        op, 
671                        arg,
672                        d + 1, 
673                        Z_tmp, 
674                        0, 
675                        (Base *) CPPAD_NULL
676                );
677        }
678        std::cout << std::endl;
679# else
680        }
681# endif
682        CPPAD_ASSERT_UNKNOWN( user_state == user_start );
683        CPPAD_ASSERT_UNKNOWN( i_var + 1 == Rec->num_rec_var() );
684
685        return compareCount;
686}
687
688/*! \} */
689} // END_CPPAD_NAMESPACE
690
691// preprocessor symbols that are local to this file
692# undef CPPAD_FORWARD0SWEEP_TRACE
693# undef CPPAD_ATOMIC_CALL
694
695# endif
Note: See TracBrowser for help on using the repository browser.