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

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

First versiont that actually skips operations (forward0sweep only).

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