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

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

Convert forward_sweep to handel CSkip operators.

forward0sweep.hpp: minor clean up of doxygen, alphabetic order ops.

  • Property svn:keywords set to Id
File size: 19.1 KB
Line 
1/* $Id: forward0sweep.hpp 2970 2013-10-19 02:16:02Z 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\param cskip_var
114Is a vector with size \c numvar,
115the input value of the elements does not matter.
116Upon return, if cskip_var[i] is true, the value of variable with index i
117does not affect any of the dependent variable (given the value
118of the independent variables).
119
120\a return
121The return value is equal to the number of ComOp operations
122that have a different result from when the information in
123\a Rec was recorded.
124(Note that if NDEBUG is true, there are no ComOp operations
125in Rec and hence this return value is always zero.)
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                CPPAD_ASSERT_UNKNOWN( (i_op > n)  | (op == InvOp) ); 
226                CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); 
227
228                // check if we are skipping this operation
229                CPPAD_ASSERT_UNKNOWN( NumRes(CSkipOp) == 0 );
230                CPPAD_ASSERT_UNKNOWN( NumRes(EndOp)  == 0 );
231                while( cskip_var[i_var] && NumRes(op) > 0 )
232                {       Rec->next_forward(op, arg, i_op, i_var);
233                        if( op == CSumOp )
234                        {       // CSumOp has a variable number of arguments and
235                                Rec->forward_csum(op, arg, i_op, i_var);
236                        }
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_var
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_tmp,
669                        op, 
670                        arg,
671                        d + 1, 
672                        Z_tmp, 
673                        0, 
674                        (Base *) CPPAD_NULL
675                );
676        }
677        std::cout << std::endl;
678# else
679        }
680# endif
681        CPPAD_ASSERT_UNKNOWN( user_state == user_start );
682        CPPAD_ASSERT_UNKNOWN( i_var + 1 == Rec->num_rec_var() );
683
684        return compareCount;
685}
686
687/*! \} */
688} // END_CPPAD_NAMESPACE
689
690// preprocessor symbols that are local to this file
691# undef CPPAD_FORWARD0SWEEP_TRACE
692# undef CPPAD_ATOMIC_CALL
693
694# endif
Note: See TracBrowser for help on using the repository browser.