source: trunk/cppad/local/atomic_base.hpp @ 2904

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

atomic_base.hpp: Add linkes for example use of atomic functions.

  • Property svn:keywords set to Id
File size: 38.1 KB
Line 
1/* $Id: atomic_base.hpp 2904 2013-09-19 16:05:20Z bradbell $ */
2# ifndef CPPAD_ATOMIC_BASE_INCLUDED
3# define CPPAD_ATOMIC_BASE_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell
7
8CppAD is distributed under multiple licenses. This distribution is under
9the terms of the
10                    Eclipse Public License Version 1.0.
11
12A copy of this license is included in the COPYING file of this distribution.
13Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14-------------------------------------------------------------------------- */
15
16# include <set>
17# include <cppad/local/cppad_assert.hpp>
18// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
19# include <cppad/thread_alloc.hpp>
20
21CPPAD_BEGIN_NAMESPACE
22/*!
23\defgroup atomic_base.hpp atomic_base.hpp
24\{
25\file atomic_base.hpp
26Base class for atomic user operations.
27*/
28
29template <class Base>
30class atomic_base {
31// ===================================================================
32public:
33        enum option_enum { bool_sparsity_enum, set_sparsity_enum};
34private:
35        // ------------------------------------------------------
36        // constants
37        //
38        /// index of this object in class_object
39        const size_t index_;
40
41        // -----------------------------------------------------
42        // variables
43        //
44        /// sparsity pattern this object is currently using
45        /// (set by constructor and option member functions)
46        option_enum sparsity_;
47
48        /// temporary work space used afun, declared here to avoid memory
49        /// allocation/deallocation for each call to afun
50        vector<bool>  afun_vx_[CPPAD_MAX_NUM_THREADS];
51        vector<bool>  afun_vy_[CPPAD_MAX_NUM_THREADS];
52        vector<Base>  afun_tx_[CPPAD_MAX_NUM_THREADS];
53        vector<Base>  afun_ty_[CPPAD_MAX_NUM_THREADS];
54
55        // -----------------------------------------------------
56        // static member functions
57        //
58        /// List of all the object in this class
59        static std::vector<atomic_base *>& class_object(void)
60        {       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
61                static std::vector<atomic_base *> list_;
62                return list_;
63        }
64        /// List of names for each object in this class
65        static std::vector<std::string>& class_name(void)
66        {       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
67                static std::vector<std::string> list_;
68                return list_;
69        }
70        // =====================================================================
71public:
72        // -----------------------------------------------------
73        // member functions not in user API
74        //
75        /// current sparsity setting
76        option_enum sparsity(void) const
77        {       return sparsity_; }
78
79        /// Name corresponding to a base_atomic object
80        const std::string& afun_name(void) const
81        {       return class_name()[index_]; }
82/*
83$begin atomic_ctor$$
84$spell
85        std
86        afun
87        arg
88        CppAD
89        bool
90        ctor
91        const
92        matrix_mul.hpp
93$$
94
95$section Atomic Function Constructor$$
96$index constructor, atomic function$$
97$index atomic, function constructor$$
98$index function, atomic constructor$$
99
100$head Syntax$$
101$icode%atomic_user afun%(%ctor_arg_list%)
102%$$
103$codei%atomic_base<%Base%>(%name%)
104%$$
105
106$head atomic_user$$
107
108$subhead ctor_arg_list$$
109Is a list of arguments for the $icode atomic_user$$ constructor.
110
111$subhead afun$$
112The object $icode afun$$ must stay in scope for as long
113as the corresponding atomic function is used.
114This includes use by any $cref/ADFun<Base>/ADFun/$$ that
115has this $icode atomic_user$$ operation in its
116$cref/operation sequence/glossary/Operation/Sequence/$$.
117
118$subhead Implementation$$
119The user defined $icode atomic_user$$ class is a publicly derived class of
120$codei%atomic_base<%Base%>%$$.
121It should be declared as follows:
122$codei%
123        class %atomic_user% : public CppAD::atomic_base<%Base%> {
124        public:
125                %atomic_user%(%ctor_arg_list%) : atomic_base<%Base%>(%name%)
126        %...%
127        };
128%$$
129where $icode ...$$ 
130denotes the rest of the implementation of the derived class.
131This includes completing the constructor and
132all the virtual functions that have their
133$code atomic_base$$ implementations replaced by
134$icode atomic_user$$ implementations.
135
136$head atomic_base$$
137
138$subhead Restrictions$$
139The $code atomic_base$$ constructor cannot be called in
140$cref/parallel/ta_in_parallel/$$ mode.
141
142$subhead Base$$
143The template parameter determines the
144$icode Base$$ type for this $codei%AD<%Base%>%$$ atomic operation.
145
146$subhead name$$
147This $icode atomic_base$$ constructor argument has either of the
148following prototypes
149$codei%
150        const char*        %name%
151        const std::string& %name%
152%$$
153It is the name for this atomic function and is used for error reporting.
154The suggested value for $icode name$$ is $icode afun$$ or $icode atomic_user$$,
155i.e., the name of the corresponding atomic object or class.
156
157$head Examples$$
158The following files contain example user atomic function constructors:
159$cref%get_started.cpp%atomic_get_started.cpp%Constructor%$$,
160$cref%reciprocal.cpp%atomic_reciprocal.cpp%Constructor%$$,
161$cref%tangent.cpp%atomic_tangent.cpp%Constructor%$$,
162$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%Constructor%$$.
163
164
165$end
166*/
167/*!
168Base class for atomic_user functions.
169
170\tparam Base
171This class is used for defining an AD<Base> atomic operation y = f(x).
172*/
173/// make sure user does not invoke the default constructor
174atomic_base(void)
175{       CPPAD_ASSERT_KNOWN(false,
176                "Attempt to use the atomic_base default constructor"
177        );
178}
179/*!
180Constructor
181
182\param name
183name used for error reporting
184*/
185atomic_base( const std::string&  name) :
186index_( class_object().size() )     ,
187sparsity_( set_sparsity_enum )
188{       CPPAD_ASSERT_KNOWN(
189                ! thread_alloc::in_parallel() ,
190                "atomic_base: constructor cannot be called in parallel mode."
191        );
192        class_object().push_back(this);
193        class_name().push_back(name);
194        CPPAD_ASSERT_UNKNOWN( class_object().size() == class_name().size() );
195}
196/// destructor informs CppAD that this atomic function with this index
197/// has dropped out of scope by setting its pointer to null
198virtual ~atomic_base(void)
199{       CPPAD_ASSERT_UNKNOWN( class_object().size() > index_ );
200        // change object pointer to null, but leave name for error reporting
201        class_object()[index_] = CPPAD_NULL;
202}
203/// atomic_base function object corresponding to a certain index
204static atomic_base* class_object(size_t index)
205{       CPPAD_ASSERT_UNKNOWN( class_object().size() > index );
206        return class_object()[index];
207}
208/// atomic_base function name corresponding to a certain index
209static const std::string& class_name(size_t index)
210{       CPPAD_ASSERT_UNKNOWN( class_name().size() > index );
211        return class_name()[index];
212}
213/*
214$begin atomic_option$$
215$spell
216        enum
217        afun
218        bool
219        CppAD
220        std
221        typedef
222$$
223
224$section Set Atomic Function Options$$
225$index atomic, options$$
226$index options, atomic$$
227
228$head Syntax$$
229$icode%afun%.option(%option_value%)%$$
230
231$head atomic_sparsity$$
232$index atomic_sparsity$$
233$index sparsity, atomic$$
234You can used this option to set to type used for
235$icode afun$$ sparsity patterns.
236This does not apply individual calls to $icode afun$$,
237but rather all its uses between when the sparsity pattern is set and when
238it is changed.
239If neither the $code set_sparsity_enum$$ or
240$code bool_sparsity_enum$$ option is set,
241the type for $icode atomic_sparsity$$ is one of the two choices below
242(and otherwise unspecified).
243
244$subhead bool_sparsity_enum$$
245$index bool_sparsity_enum$$
246If $icode option_value$$ is $code atomic_base::bool_sparsity_enum$$,
247then the type used by $icode afun$$ for
248$cref/sparsity patterns/glossary/Sparsity Pattern/$$,
249(after the option is set) will be
250$codei%
251        typedef CppAD::vector<bool> %atomic_sparsity%
252%$$
253If $icode r$$ is a sparsity pattern
254for a matrix $latex R \in B^{p \times q}$$:
255$icode%r%.size() == %p% * %q%$$.
256
257$subhead set_sparsity_enum$$
258$index set_sparsity_enum$$
259If $icode option_value$$ is $code atomic_base::set_sparsity_enum$$,
260then the type used by $icode afun$$ for
261$cref/sparsity patterns/glossary/Sparsity Pattern/$$,
262(after the option is set) will be
263$codei%
264        typedef CppAD::vector< std::set<size_t> > %atomic_sparsity%
265%$$
266If $icode r$$ is a sparsity pattern
267for a matrix $code R \in B^{p \times q}$$:
268$icode%r%.size() == %p%$$, and for $latex i = 0 , \ldots , p-1$$,
269the elements of $icode%r%[%i%]%$$ are between zero and $latex q-1$$ inclusive.
270
271$end
272*/
273void option(enum option_enum option_value)
274{       switch( option_value )
275        {       case bool_sparsity_enum:
276                case set_sparsity_enum:
277                sparsity_ = option_value;
278                break;
279
280                default:
281                CPPAD_ASSERT_KNOWN(
282                        false,
283                        "atoic_base::option: option_value is not valid"
284                );
285        }
286        return;
287}
288/*
289-----------------------------------------------------------------------------
290$begin atomic_afun$$
291
292$spell
293        mul
294        afun
295        const
296        CppAD
297$$
298
299$section Using an Atomic Function$$
300$index atomic, use function$$
301
302$head Syntax$$
303$icode%afun%(%ax%, %ay%)%$$
304
305$head Purpose$$
306Given $icode ax$$,
307this call computes the corresponding value of $icode ay$$.
308If $codei%AD<%Base%>%$$ operations are being recorded,
309it enters the computation as an atomic operation in the recording;
310see $cref/start recording/Independent/Start Recording/$$.
311
312$head ADVector$$
313The type $icode ADVector$$ must be a
314$cref/simple vector class/SimpleVector/$$ with elements of type
315$codei%AD<%Base%>%$$; see $cref/Base/atomic_ctor/atomic_base/Base/$$.
316
317$head afun$$
318is a $cref/atomic_user/atomic_ctor/atomic_user/$$ object
319and this $icode afun$$ function call is implemented by the
320$cref/atomic_base/atomic_ctor/atomic_base/$$ class.
321
322$head ax$$
323This argument has prototype
324$codei%
325        const %ADVector%& %ax%
326%$$
327and size must be equal to $icode n$$.
328It specifies vector $latex x \in B^n$$
329at which an $codei%AD<%Base%>%$$ version of
330$latex y = f(x)$$ is to be evaluated; see
331$cref/Base/atomic_ctor/atomic_base/Base/$$.
332
333$head ay$$
334This argument has prototype
335$codei%
336        %ADVector%& %ay%
337%$$
338and size must be equal to $icode m$$.
339The input values of its elements
340are not specified (must not matter).
341Upon return, it is an $codei%AD<%Base%>%$$ version of
342$latex y = f(x)$$.
343
344$head Examples$$
345The following files contain example uses of atomic functions:
346$cref%get_started.cpp%atomic_get_started.cpp%Use Atomic Function%$$,
347$cref%reciprocal.cpp%atomic_reciprocal.cpp%Use Atomic Function%$$,
348$cref%tangent.cpp%atomic_tangent.cpp%Use Atomic Function%$$,
349$cref%matrix_mul.cpp%atomic_mat_mul.cpp%Use Atomic Function%$$.
350
351$end
352-----------------------------------------------------------------------------
353*/
354/*!
355Implement the user call to <tt>afun(ax, ay)</tt> and old_atomic call to
356<tt>afun(ax, ay, id)</tt>.
357
358\tparam ADVector
359A simple vector class with elements of type <code>AD<Base></code>.
360
361\param id
362optional extra information vector that is just passed through by CppAD,
363and used by old_atomic derived class (not other derived classes).
364This is an extra parameter to the virtual callbacks for old_atomic;
365see the set_id member function.
366
367\param ax
368is the argument vector for this call,
369<tt>ax.size()</tt> determines the number of arguments.
370
371\param ay
372is the result vector for this call,
373<tt>ay.size()</tt> determines the number of results.
374*/
375template <class ADVector>
376void operator()(
377        const ADVector&  ax     ,
378              ADVector&  ay     ,
379        size_t           id = 0 )
380{       size_t i, j;
381        size_t n = ax.size();
382        size_t m = ay.size();
383# ifndef NDEBUG
384        bool ok;
385        std::string msg = "atomic_base: " + afun_name() + ".eval: ";
386        if( (n == 0) | (m == 0) )
387        {       msg += "ax.size() or ay.size() is zero";
388                CPPAD_ASSERT_KNOWN(false, msg.c_str() );
389        }
390# endif
391        size_t thread = thread_alloc::thread_num();
392        vector <Base>& tx  = afun_tx_[thread];
393        vector <Base>& ty  = afun_ty_[thread];
394        vector <bool>& vx  = afun_vx_[thread];
395        vector <bool>& vy  = afun_vy_[thread];
396        //
397        if( vx.size() != n )
398        {       vx.resize(n);
399                tx.resize(n);
400        }
401        if( vy.size() != m )
402        {       vy.resize(m);
403                ty.resize(m);
404        }
405        //
406        // Determine tape corresponding to variables in ax
407        tape_id_t     tape_id  = 0;
408        ADTape<Base>* tape     = CPPAD_NULL;
409        for(j = 0; j < n; j++)
410        {       tx[j]  = ax[j].value_;
411                vx[j]  = Variable( ax[j] );
412                if( vx[j] )
413                {
414                        if( tape_id == 0 )
415                        {       tape    = ax[j].tape_this();
416                                tape_id = ax[j].tape_id_;
417                                CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL );
418                        }
419# ifndef NDEBUG
420                        if( tape_id != ax[j].tape_id_ )
421                        {       msg += afun_name() + 
422                                ": ax contains variables from different threads.";
423                                CPPAD_ASSERT_KNOWN(false, msg.c_str());
424                        }
425# endif
426                }
427        }
428        // Use zero order forward mode to compute values
429        size_t q = 0, p = 0;
430        set_id(id);
431# ifdef NDEBUG
432        forward(q, p, vx, vy, tx, ty); 
433# else
434        ok = forward(q, p, vx, vy, tx, ty); 
435        if( ! ok )
436        {       msg += afun_name() + ": ok is false for "
437                        "zero order forward mode calculation.";
438                CPPAD_ASSERT_KNOWN(false, msg.c_str());
439        }
440# endif
441        bool record_operation = false;
442        for(i = 0; i < m; i++)
443        {
444                // pass back values
445                ay[i].value_ = ty[i];
446
447                // initialize entire vector parameters (not in tape)
448                ay[i].tape_id_ = 0;
449                ay[i].taddr_   = 0;
450
451                // we need to record this operation if
452                // any of the eleemnts of ay are variables,
453                record_operation |= vy[i];
454        }
455# ifndef NDEBUG
456        if( record_operation & (tape == CPPAD_NULL) )
457        {       msg += 
458                "all elements of vx are false but vy contains a true element";
459                CPPAD_ASSERT_KNOWN(false, msg.c_str() );
460        }
461# endif
462        // if tape is not null, ay is on the tape
463        if( record_operation )
464        {
465                // Operator that marks beginning of this atomic operation
466                CPPAD_ASSERT_UNKNOWN( NumRes(UserOp) == 0 );
467                CPPAD_ASSERT_UNKNOWN( NumArg(UserOp) == 4 );
468                tape->Rec_.PutArg(index_, id, n, m);
469                tape->Rec_.PutOp(UserOp);
470
471                // Now put n operators, one for each element of arugment vector
472                CPPAD_ASSERT_UNKNOWN( NumRes(UsravOp) == 0 );
473                CPPAD_ASSERT_UNKNOWN( NumRes(UsrapOp) == 0 );
474                CPPAD_ASSERT_UNKNOWN( NumArg(UsravOp) == 1 );
475                CPPAD_ASSERT_UNKNOWN( NumArg(UsrapOp) == 1 );
476                for(j = 0; j < n; j++)
477                {       if( vx[j] )
478                        {       // information for an argument that is a variable
479                                tape->Rec_.PutArg(ax[j].taddr_);
480                                tape->Rec_.PutOp(UsravOp);
481                        }
482                        else
483                        {       // information for an arugment that is parameter
484                                addr_t par = tape->Rec_.PutPar(ax[j].value_);
485                                tape->Rec_.PutArg(par);
486                                tape->Rec_.PutOp(UsrapOp);
487                        }
488                }
489
490                // Now put m operators, one for each element of result vector
491                CPPAD_ASSERT_UNKNOWN( NumArg(UsrrpOp) == 1 );
492                CPPAD_ASSERT_UNKNOWN( NumRes(UsrrpOp) == 0 );
493                CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 );
494                CPPAD_ASSERT_UNKNOWN( NumRes(UsrrvOp) == 1 );
495                for(i = 0; i < m; i++)
496                {       if( vy[i] )
497                        {       ay[i].taddr_    = tape->Rec_.PutOp(UsrrvOp);
498                                ay[i].tape_id_  = tape_id;
499                        }
500                        else
501                        {       addr_t par = tape->Rec_.PutPar(ay[i].value_);
502                                tape->Rec_.PutArg(par);
503                                tape->Rec_.PutOp(UsrrpOp);
504                        }
505                }
506
507                // Put a duplicate UserOp at end of UserOp sequence
508                tape->Rec_.PutArg(index_, id, n, m);
509                tape->Rec_.PutOp(UserOp);
510        } 
511        return;
512}
513/*
514-----------------------------------------------------------------------------
515$begin atomic_forward$$
516$spell
517        mul.hpp
518        hes
519        afun
520        vx
521        vy
522        ty
523        Taylor
524        const
525        CppAD
526        bool
527$$
528
529$section Atomic Forward Mode$$
530$index atomic, forward callback$$
531$index forward, atomic callback$$
532$index forward, atomic virtual$$
533
534
535$head Syntax$$
536$icode%ok% = %afun%.forward(%q%, %p%, %vx%, %vy%, %tx%, %ty%)%$$
537
538$head Purpose$$
539This virtual function is used by $cref atomic_afun$$
540to evaluate function values.
541It is also used buy $cref/forward/Forward/$$
542to compute function vales and derivatives.
543
544$head Implementation$$
545This virtual function must be defined by the
546$cref/atomic_user/atomic_ctor/atomic_user/$$ class.
547It can just return $icode%ok% == false%$$
548(and not compute anything) for values
549of $icode%p% > 0%$$ that are greater than those used by your
550$cref/forward/Forward/$$ mode calculations.
551
552$head q$$
553The argument $icode q$$ has prototype
554$codei%
555        size_t %q%
556%$$
557It specifies the lowest order Taylor coefficient that we are evaluating.
558During calls to $cref atomic_afun$$, $icode%q% == 0%$$.
559
560$head p$$
561The argument $icode p$$ has prototype
562$codei%
563        size_t %p%
564%$$
565It specifies the highest order Taylor coefficient that we are evaluating.
566During calls to $cref atomic_afun$$, $icode%p% == 0%$$.
567
568$head vx$$
569The $code forward$$ argument $icode vx$$ has prototype
570$codei%
571        const CppAD::vector<bool>& %vx%
572%$$
573The case $icode%vx%.size() > 0%$$ only occurs while evaluating a call to
574$cref atomic_afun$$.
575In this case,
576$icode%q% == %p% == 0%$$,
577$icode%vx%.size() == %n%$$, and
578for $latex j = 0 , \ldots , n-1$$,
579$icode%vx%[%j%]%$$ is true if and only if
580$icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$
581in the corresponding call to
582$codei%
583        %afun%(%ax%, %ay%, %id%)
584%$$
585If $icode%vx%.size() == 0%$$,
586then $icode%vy%.size() == 0%$$ and neither of these vectors
587should be used.
588
589$head vy$$
590The $code forward$$ argument $icode vy$$ has prototype
591$codei%
592        CppAD::vector<bool>& %vy%
593%$$
594If $icode%vy%.size() == 0%$$, it should not be used.
595Otherwise,
596$icode%p% == 0%$$ and $icode%vy%.size() == %m%$$.
597The input values of the elements of $icode vy$$
598are not specified (must not matter).
599Upon return, for $latex j = 0 , \ldots , m-1$$,
600$icode%vy%[%i%]%$$ is true if and only if
601$icode%ay%[%i%]%$$ is a variable
602(CppAD uses $icode vy$$ to reduce the necessary computations).
603
604$head tx$$
605The argument $icode tx$$ has prototype
606$codei%
607        const CppAD::vector<%Base%>& %tx%
608%$$
609and $icode%tx%.size() == (%p%+1)*%n%$$.
610For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , p$$,
611we use the Taylor coefficient notation
612$latex \[
613\begin{array}{rcl}
614        x_j^k    & = & tx [ j * ( p + 1 ) + k ]
615        \\
616        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^p t^p
617\end{array}
618\] $$
619Note that superscripts represent an index for $latex x_j^k$$
620and an exponent for $latex t^k$$.
621Also note that the Taylor coefficients for $latex X(t)$$ correspond
622to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
623$latex \[
624        x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
625\] $$
626
627$head ty$$
628The argument $icode ty$$ has prototype
629$codei%
630        CppAD::vector<%Base%>& %ty%
631%$$
632and $icode%tx%.size() == (%p%+1)*%m%$$.
633Upon return,
634For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , p$$,
635$latex \[
636\begin{array}{rcl}
637        Y_i (t)  & = & f_i [ X(t) ]
638        \\
639        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^p t^p + o ( t^p )
640        \\
641        ty [ i * ( p + 1 ) + k ] & = & y_i^k
642\end{array}
643\] $$
644where $latex o( t^p ) / t^p \rightarrow 0$$ as $latex t \rightarrow 0$$.
645Note that superscripts represent an index for $latex y_j^k$$
646and an exponent for $latex t^k$$.
647Also note that the Taylor coefficients for $latex Y(t)$$ correspond
648to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
649$latex \[
650        y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
651\] $$
652If $latex q > 0$$,
653for $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q-1$$,
654the input of $icode ty$$ satisfies
655$latex \[
656        ty [ i * ( p + 1 ) + k ] = y_i^k
657\]$$
658and hence the corresponding elements need not be recalculated.
659
660$head ok$$
661If the required results are calculated, $icode ok$$ should be true.
662Otherwise, it should be false.
663
664$head Discussion$$
665For example, suppose that $icode%p% == 2%$$,
666and you know how to compute the function $latex f(x)$$,
667its first derivative $latex f^{(1)} (x)$$,
668and it component wise Hessian $latex f_i^{(2)} (x)$$.
669Then you can compute $icode ty$$ using the following formulas:
670$latex \[
671\begin{array}{rcl}
672y_i^0 & = & Y(0)
673        = f_i ( x^0 )
674\\
675y_i^1 & = & Y^{(1)} ( 0 )
676        = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 )
677        = f_i^{(1)} ( x^0 ) x^1
678\\
679y_i^2
680& = & \frac{1}{2 !} Y^{(2)} (0)
681\\
682& = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 )
683  +   \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 )
684\\
685& = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1
686  +    f_i^{(1)} ( x^0 ) x^2
687\end{array}
688\] $$
689For $latex i = 0 , \ldots , m-1$$, and $latex k = 0 , 1 , 2$$,
690$latex \[
691        ty [ i * (p + 1) + k ] = y_i^k
692\] $$
693
694$head Examples$$
695The following files contain example atomic $code forward$$ functions:
696$cref%get_started.cpp%atomic_get_started.cpp%forward%$$,
697$cref%reciprocal.cpp%atomic_reciprocal.cpp%forward%$$,
698$cref%tangent.cpp%atomic_tangent.cpp%forward%$$,
699$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%forward%$$.
700
701 
702$end
703-----------------------------------------------------------------------------
704*/
705/*!
706Link from atomic_base to forward mode
707
708\param q [in]
709lowerest order for this forward mode calculation.
710
711\param p [in]
712highest order for this forward mode calculation.
713
714\param vx [in]
715if size not zero, which components of \c x are variables
716
717\param vy [out]
718if size not zero, which components of \c y are variables
719
720\param tx [in]
721Taylor coefficients corresponding to \c x for this calculation.
722
723\param ty [out]
724Taylor coefficient corresponding to \c y for this calculation
725
726See the forward mode in user's documentation for base_atomic
727*/
728virtual bool forward(
729        size_t                    q  ,
730        size_t                    p  ,
731        const vector<bool>&       vx ,
732              vector<bool>&       vy ,
733        const vector<Base>&       tx ,
734              vector<Base>&       ty )
735{       return false; }
736/*
737-----------------------------------------------------------------------------
738$begin atomic_reverse$$
739$spell
740        mul.hpp
741        afun
742        ty
743        px
744        py
745        Taylor
746        const
747        CppAD
748$$
749
750$section Atomic Reverse Mode$$
751$index atomic, reverse callback$$
752$index reverse, atomic callback$$
753$index reverse, atomic virtual$$
754$spell
755        bool
756$$
757
758$head Syntax$$
759$icode%ok% = %afun%.reverse(%p%, %tx%, %ty%, %px%, %py%)%$$
760
761$head Purpose$$
762This function is used by $cref/reverse/Reverse/$$
763to compute derivatives.
764
765$head Implementation$$
766If you are using
767$cref/reverse/Reverse/$$ mode,
768this virtual function must be defined by the
769$cref/atomic_user/atomic_ctor/atomic_user/$$ class.
770It can just return $icode%ok% == false%$$
771(and not compute anything) for values
772of $icode p$$ that are greater than those used by your
773$cref/reverse/Reverse/$$ mode calculations.
774
775$head p$$
776The argument $icode p$$ has prototype
777$codei%
778        size_t %p%
779%$$
780It specifies the highest order Taylor coefficient that
781computing the derivative of.
782
783$head tx$$
784The argument $icode tx$$ has prototype
785$codei%
786        const CppAD::vector<%Base%>& %tx%
787%$$
788and $icode%tx%.size() == (%p%+1)*%n%$$.
789For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , p$$,
790we use the Taylor coefficient notation
791$latex \[
792\begin{array}{rcl}
793        x_j^k    & = & tx [ j * ( p + 1 ) + k ]
794        \\
795        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^p t^p
796\end{array}
797\] $$
798Note that superscripts represent an index for $latex x_j^k$$
799and an exponent for $latex t^k$$.
800Also note that the Taylor coefficients for $latex X(t)$$ correspond
801to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
802$latex \[
803        x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
804\] $$
805
806$head ty$$
807The argument $icode ty$$ has prototype
808$codei%
809        const CppAD::vector<%Base%>& %ty%
810%$$
811and $icode%tx%.size() == (%p%+1)*%m%$$.
812For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , p$$,
813we use the Taylor coefficient notation
814$latex \[
815\begin{array}{rcl}
816        Y_i (t)  & = & f_i [ X(t) ]
817        \\
818        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^p t^p + o ( t^p )
819        \\
820        y_i^k    & = & ty [ i * ( p + 1 ) + k ]
821\end{array}
822\] $$
823where $latex o( t^p ) / t^p \rightarrow 0$$ as $latex t \rightarrow 0$$.
824Note that superscripts represent an index for $latex y_j^k$$
825and an exponent for $latex t^k$$.
826Also note that the Taylor coefficients for $latex Y(t)$$ correspond
827to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
828$latex \[
829        y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
830\] $$
831
832
833$head F, G, H$$
834We use the notation $latex \{ x_j^k \} \in B^{n \times (p+1)}$$ for
835$latex \[
836        \{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , p \}
837\]$$
838We use the notation $latex \{ y_i^k \} \in B^{m \times (p+1)}$$ for
839$latex \[
840        \{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , p \}
841\]$$
842We define the function
843$latex F : B^{n \times (p+1)} \rightarrow B^{m \times (p+1)}$$ by
844$latex \[
845        y_i^k = F_i^k [ \{ x_j^k \} ]
846\] $$
847We use $latex G : B^{m \times (p+1)} \rightarrow B$$
848to denote an arbitrary scalar valued function of $latex \{ y_i^k \}$$.
849We use $latex H : B^{n \times (p+1)} \rightarrow B$$
850defined by
851$latex \[
852        H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ]
853\] $$
854
855$head py$$
856The argument $icode py$$ has prototype
857$codei%
858        const CppAD::vector<%Base%>& %py%
859%$$
860and $icode%py%.size() == m * (%p%+1)%$$.
861For $latex i = 0 , \ldots , m-1$$, $latex k = 0 , \ldots , p$$,
862$latex \[
863        py[ i * (p + 1 ) + k ] = \partial G / \partial y_i^k
864\] $$
865
866$subhead px$$
867The $icode px$$ has prototype
868$codei%
869        CppAD::vector<%Base%>& %px%
870%$$
871and $icode%px%.size() == n * (%p%+1)%$$.
872The input values of the elements of $icode px$$
873are not specified (must not matter).
874Upon return,
875for $latex j = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , p$$,
876$latex \[
877\begin{array}{rcl}
878px [ j * (p + 1) + \ell ] & = & \partial H / \partial x_j^\ell
879\\
880& = &
881( \partial G / \partial \{ y_i^k \} )
882        ( \partial \{ y_i^k \} / \partial x_j^\ell )
883\\
884& = &
885\sum_{i=0}^{m-1} \sum_{k=0}^p
886( \partial G / \partial y_i^k ) ( \partial y_i^k / \partial x_j^\ell )
887\\
888& = &
889\sum_{i=0}^{m-1} \sum_{k=\ell}^p
890py[ i * (p + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell )
891\end{array}
892\] $$
893Note that we have used the fact that for $latex k < \ell$$,
894$latex \partial F_i^k / \partial x_j^\ell = 0$$.
895
896$head ok$$
897The return value $icode ok$$ has prototype
898$codei%
899        bool %ok%
900%$$
901If it is $code true$$, the corresponding evaluation succeeded,
902otherwise it failed.
903
904$head Examples$$
905The following files contain example atomic $code reverse$$ functions:
906$cref%reciprocal.cpp%atomic_reciprocal.cpp%reverse%$$,
907$cref%tangent.cpp%atomic_tangent.cpp%reverse%$$,
908$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%reverse%$$.
909
910
911$end
912-----------------------------------------------------------------------------
913*/
914/*!
915Link from reverse mode sweep to users routine.
916
917\param p [in]
918highest order for this reverse mode calculation.
919
920\param tx [in]
921Taylor coefficients corresponding to \c x for this calculation.
922
923\param ty [in]
924Taylor coefficient corresponding to \c y for this calculation
925
926\param px [out]
927Partials w.r.t. the \c x Taylor coefficients.
928
929\param py [in]
930Partials w.r.t. the \c y Taylor coefficients.
931
932See atomic_reverse mode use documentation
933*/
934virtual bool reverse(
935        size_t                    p  ,
936        const vector<Base>&       tx ,
937        const vector<Base>&       ty ,
938              vector<Base>&       px ,
939        const vector<Base>&       py )
940{       return false; }
941/*
942-------------------------------------- ---------------------------------------
943$begin atomic_for_sparse_jac$$
944$spell
945        mul.hpp
946        afun
947        Jacobian
948        jac
949        const
950        CppAD
951        std
952        bool
953        std
954$$
955
956$section Atomic Forward Jacobian Sparsity Patterns$$
957$index atomic, for_sparse_jac callback$$
958$index for_sparse_jac, atomic callback$$
959$index for_sparse_jac, atomic virtual$$
960
961$head Syntax$$
962$icode%ok% = %afun%.for_sparse_jac(%q%, %r%, %s%)%$$
963
964$head Purpose$$
965This function is used by $cref ForSparseJac$$ to compute
966Jacobian sparsity patterns.
967For a fixed matrix $latex R \in B^{n \times q}$$,
968the Jacobian of $latex f( x + R * u)$$ with respect to $latex u \in B^q$$ is
969$latex \[
970        S(x) = f^{(1)} (x) * R
971\] $$
972Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
973$code for_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$.
974
975$head Implementation$$
976If you are using $cref ForSparseJac$$,
977this virtual function must be defined by the
978$cref/atomic_user/atomic_ctor/atomic_user/$$ class.
979
980$subhead q$$
981The argument $icode q$$ has prototype
982$codei%
983     size_t %q%
984%$$
985It specifies the number of columns in
986$latex R \in B^{n \times q}$$ and the Jacobian
987$latex S(x) \in B^{m \times q}$$.
988
989$subhead r$$
990This argument has prototype
991$codei%
992     const %atomic_sparsity%& %r%
993%$$
994and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
995$latex R \in B^{n \times q}$$.
996
997$subhead s$$
998This argument has prototype
999$codei%
1000        %atomic_sparsity%& %s%
1001%$$
1002The input values of its elements
1003are not specified (must not matter).
1004Upon return, $icode s$$ is a
1005$cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1006$latex S(x) \in B^{m \times q}$$.
1007
1008$head ok$$
1009The return value $icode ok$$ has prototype
1010$codei%
1011        bool %ok%
1012%$$
1013If it is $code true$$, the corresponding evaluation succeeded,
1014otherwise it failed.
1015
1016$head Examples$$
1017The following files contain example atomic $code for_sparse_jac$$ functions:
1018$cref%reciprocal.cpp%atomic_reciprocal.cpp%for_sparse_jac%$$,
1019$cref%tangent.cpp%atomic_tangent.cpp%for_sparse_jac%$$,
1020$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%for_sparse_jac%$$.
1021
1022$end
1023-----------------------------------------------------------------------------
1024*/
1025/*!
1026Link from forward Jacobian sparsity sweep to atomic_base
1027
1028\param q
1029is the column dimension for the Jacobian sparsity partterns.
1030
1031\param r
1032is the Jacobian sparsity pattern for the argument vector x
1033
1034\param s
1035is the Jacobian sparsity pattern for the result vector y
1036*/
1037virtual bool for_sparse_jac(
1038        size_t                                  q  ,
1039        const vector< std::set<size_t> >&       r  ,
1040              vector< std::set<size_t> >&       s  )
1041{       return false; }
1042virtual bool for_sparse_jac(
1043        size_t                                  q  ,
1044        const vector<bool>&                     r  ,
1045              vector<bool>&                     s  )
1046{       return false; }
1047/*
1048-------------------------------------- ---------------------------------------
1049$begin atomic_rev_sparse_jac$$
1050$spell
1051        mul.hpp
1052        rt
1053        afun
1054        Jacobian
1055        jac
1056        CppAD
1057        std
1058        bool
1059        const
1060        hes
1061$$
1062
1063$section Atomic Reverse Jacobian Sparsity Patterns$$
1064$index atomic, rev_sparse_jac callback$$
1065$index rev_sparse_jac, atomic callback$$
1066$index rev_sparse_jac, atomic virtual$$
1067
1068$head Syntax$$
1069$icode%ok% = %afun%.rev_sparse_jac(%q%, %rt%, %st%)%$$
1070
1071$head Purpose$$
1072This function is used by $cref RevSparseJac$$ to compute
1073Jacobian sparsity patterns.
1074For a fixed matrix $latex R \in B^{q \times m}$$,
1075the Jacobian of $latex R * f( x )$$ with respect to $latex x \in B^q$$ is
1076$latex \[
1077        S(x) = R * f^{(1)} (x)
1078\] $$
1079Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
1080$code rev_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$.
1081
1082$head Implementation$$
1083If you are using $cref RevSparseJac$$,
1084this virtual function must be defined by the
1085$cref/atomic_user/atomic_ctor/atomic_user/$$ class.
1086
1087$subhead q$$
1088The argument $icode q$$ has prototype
1089$codei%
1090     size_t %q%
1091%$$
1092It specifies the number of rows in
1093$latex R \in B^{q \times m}$$ and the Jacobian
1094$latex S(x) \in B^{q \times n}$$.
1095
1096$subhead rt$$
1097This argument has prototype
1098$codei%
1099     const %atomic_sparsity%& %rt%
1100%$$
1101and is a
1102$cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1103$latex R^\R{T} \in B^{m \times q}$$.
1104
1105$subhead st$$
1106This argument has prototype
1107$codei%
1108        %atomic_sparsity%& %st%
1109%$$
1110The input value of its elements
1111are not specified (must not matter).
1112Upon return, $icode s$$ is a
1113$cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1114$latex S(x)^\R{T} \in B^{n \times q}$$.
1115
1116$head ok$$
1117The return value $icode ok$$ has prototype
1118$codei%
1119        bool %ok%
1120%$$
1121If it is $code true$$, the corresponding evaluation succeeded,
1122otherwise it failed.
1123
1124$head Examples$$
1125The following files contain example atomic $code rev_sparse_jac$$ functions:
1126$cref%reciprocal.cpp%atomic_reciprocal.cpp%rev_sparse_jac%$$,
1127$cref%tangent.cpp%atomic_tangent.cpp%rev_sparse_jac%$$,
1128$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%rev_sparse_jac%$$.
1129
1130$end
1131-----------------------------------------------------------------------------
1132*/
1133/*!
1134Link from reverse Jacobian sparsity sweep to atomic_base
1135
1136\param q [in]
1137is the row dimension for the Jacobian sparsity partterns
1138
1139\param rt [out]
1140is the tansposed Jacobian sparsity pattern w.r.t to range variables y
1141
1142\param st [in]
1143is the tansposed Jacobian sparsity pattern for the argument variables x
1144*/
1145virtual bool rev_sparse_jac(
1146        size_t                                  q  ,
1147        const vector< std::set<size_t> >&       rt ,
1148              vector< std::set<size_t> >&       st )
1149{       return false; }
1150virtual bool rev_sparse_jac(
1151        size_t                                  q  ,
1152        const vector<bool>&                     rt ,
1153              vector<bool>&                     st )
1154{       return false; }
1155/*
1156-------------------------------------- ---------------------------------------
1157$begin atomic_rev_sparse_hes$$
1158$spell
1159        mul.hpp
1160        vx
1161        afun
1162        Jacobian
1163        jac
1164        CppAD
1165        std
1166        bool
1167        hes
1168        const
1169$$
1170
1171$section Atomic Reverse Hessian Sparsity Patterns$$
1172$index atomic, rev_sparse_hes callback$$
1173$index rev_sparse_hes, atomic callback$$
1174$index rev_sparse_hes, atomic virtual$$
1175
1176$head Syntax$$
1177$icode%ok% = %afun%.rev_sparse_hes(%vx%, %s%, %t%, %q%, %r%, %u%, %v%)%$$
1178
1179$head Purpose$$
1180This function is used by $cref RevSparseHes$$ to compute
1181Hessian sparsity patterns.
1182There is an unspecified scalar valued function
1183$latex g : B^m \rightarrow B$$.
1184Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for
1185$latex R \in B^{n \times q}$$,
1186and information about the function $latex z = g(y)$$,
1187this routine computes the sparsity pattern for
1188$latex \[
1189        V(x) = (g \circ f)^{(2)}( x ) R
1190\] $$
1191
1192$head Implementation$$
1193If you are using and $cref RevSparseHes$$,
1194this virtual function must be defined by the
1195$cref/atomic_user/atomic_ctor/atomic_user/$$ class.
1196
1197$subhead vx$$
1198The argument $icode vx$$ has prototype
1199$codei%
1200     const CppAD:vector<bool>& %vx%
1201%$$
1202$icode%vx%.size() == %n%$$, and
1203for $latex j = 0 , \ldots , n-1$$,
1204$icode%vx%[%j%]%$$ is true if and only if
1205$icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$
1206in the corresponding call to
1207$codei%
1208        %afun%(%ax%, %ay%, %id%)
1209%$$
1210
1211$subhead s$$
1212The argument $icode s$$ has prototype
1213$codei%
1214     const CppAD:vector<bool>& %s%
1215%$$
1216and its size is $icode m$$.
1217It is a sparsity pattern for
1218$latex S(x) = g^{(1)} (y) \in B^{1 \times m}$$.
1219
1220$subhead t$$
1221This argument has prototype
1222$codei%
1223     CppAD:vector<bool>& %t%
1224%$$
1225and its size is $icode m$$.
1226The input values of its elements
1227are not specified (must not matter).
1228Upon return, $icode t$$ is a
1229sparsity pattern for
1230$latex T(x) \in B^{1 \times n}$$ where
1231$latex \[
1232        T(x) = (g \circ f)^{(1)} (x) = S(x) * f^{(1)} (x)
1233\]$$
1234
1235$subhead q$$
1236The argument $icode q$$ has prototype
1237$codei%
1238     size_t %q%
1239%$$
1240It specifies the number of columns in
1241$latex R \in B^{n \times q}$$,
1242$latex U(x) \in B^{m \times q}$$, and
1243$latex V(x) \in B^{n \times q}$$.
1244
1245$subhead r$$
1246This argument has prototype
1247$codei%
1248     const %atomic_sparsity%& %r%
1249%$$
1250and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1251$latex R \in B^{n \times q}$$.
1252
1253$head u$$
1254This argument has prototype
1255$codei%
1256     const %atomic_sparsity%& %u%
1257%$$
1258and is a $cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1259$latex U(x) \in B^{m \times q}$$ which is defined by
1260$latex \[
1261\begin{array}{rcl}
1262U(x)
1263& = &
1264\partial_u \{ \partial_y g[ y + f^{(1)} (x) R u ] \}_{u=0}
1265\\
1266& = &
1267\partial_u \{ g^{(1)} [ y + f^{(1)} (x) R u ] \}_{u=0}
1268\\
1269& = &
1270g^{(2)} (y) f^{(1)} (x) R
1271\end{array}
1272\] $$
1273
1274$subhead v$$
1275This argument has prototype
1276$codei%
1277     %atomic_sparsity%& %v%
1278%$$
1279The input value of its elements
1280are not specified (must not matter).
1281Upon return, $icode v$$ is a
1282$cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ pattern for
1283$latex V(x) \in B^{n \times q}$$ which is defined by
1284$latex \[
1285\begin{array}{rcl}
1286V(x)
1287& = &
1288\partial_u [ \partial_x (g \circ f) ( x + R u )  ]_{u=0}
1289\\
1290& = &
1291\partial_u [ (g \circ f)^{(1)}( x + R u )  ]_{u=0}
1292\\
1293& = &
1294(g \circ f)^{(2)}( x ) R
1295\\
1296& = &
1297f^{(1)} (x)^\R{T} g^{(2)} ( y ) f^{(1)} (x)  R
1298+
1299\sum_{i=1}^m g_i^{(1)} (y) \; f_i^{(2)} (x) R
1300\\
1301& = &
1302f^{(1)} (x)^\R{T} U(x)
1303+
1304\sum_{i=1}^m S_i (x) \; f_i^{(2)} (x) R
1305\end{array}
1306\] $$
1307
1308$head Examples$$
1309The following files contain example atomic $code rev_sparse_hes$$ functions:
1310$cref%reciprocal.cpp%atomic_reciprocal.cpp%rev_sparse_hes%$$,
1311$cref%tangent.cpp%atomic_tangent.cpp%rev_sparse_hes%$$,
1312$cref%matrix_mul.hpp%atomic_matrix_mul.hpp%rev_sparse_hes%$$.
1313
1314$end
1315-----------------------------------------------------------------------------
1316*/
1317/*!
1318Link from reverse Hessian sparsity sweep to base_atomic
1319
1320\param vx [in]
1321which componens of x are variables.
1322
1323\param s [in]
1324is the reverse Jacobian sparsity pattern w.r.t the result vector y.
1325
1326\param t [out]
1327is the reverse Jacobian sparsity pattern w.r.t the argument vector x.
1328
1329\param q [in]
1330is the column dimension for the sparsity partterns.
1331
1332\param r [in]
1333is the forward Jacobian sparsity pattern w.r.t the argument vector x
1334
1335\param u [in]
1336is the Hessian sparsity pattern w.r.t the result vector y.
1337
1338\param v [out]
1339is the Hessian sparsity pattern w.r.t the argument vector x.
1340*/
1341virtual bool rev_sparse_hes(
1342        const vector<bool>&                     vx ,
1343        const vector<bool>&                     s  ,
1344              vector<bool>&                     t  ,
1345        size_t                                  q  ,
1346        const vector< std::set<size_t> >&       r  ,
1347        const vector< std::set<size_t> >&       u  ,
1348              vector< std::set<size_t> >&       v  )
1349{       return false; }
1350virtual bool rev_sparse_hes(
1351        const vector<bool>&                     vx ,
1352        const vector<bool>&                     s  ,
1353              vector<bool>&                     t  ,
1354        size_t                                  q  ,
1355        const vector<bool>&                     r  ,
1356        const vector<bool>&                     u  ,
1357              vector<bool>&                     v  )
1358{       return false; }
1359/*
1360------------------------------------------------------------------------------
1361$begin atomic_base_clear$$
1362
1363$section Free Static Variables$$
1364$index free, atomic static$$
1365$index atomic, free static$$
1366$index static, free atomic$$
1367$index clear, atomic static$$
1368
1369$head Syntax$$
1370$codei%atomic_base<%Base%>::clear()%$$
1371
1372$head Purpose$$
1373The $code atomic_base$$ class holds onto static work space in order to
1374increase speed by avoiding system memory allocation calls.
1375This call makes to work space $cref/available/ta_available/$$ to
1376for other uses by the same thread.
1377This should be called when you are done using the
1378user atomic functions for a specific value of $icode Base$$.
1379
1380$head Restriction$$
1381This routine cannot be called
1382while in $cref/parallel/ta_in_parallel/$$ execution mode.
1383
1384$end
1385------------------------------------------------------------------------------
1386*/
1387/*!
1388Free all thread_alloc static memory held by atomic_base (avoids reallocations).
1389(This does not include class_object() which is an std::vector.)
1390*/
1391/// Free vector memory used by this class (work space)
1392static void clear(void)
1393{       CPPAD_ASSERT_KNOWN(
1394                ! thread_alloc::in_parallel() ,
1395                "cannot use atomic_base clear during parallel execution"
1396        );
1397        size_t i = class_object().size();
1398        while(i--)
1399        {       size_t thread = CPPAD_MAX_NUM_THREADS;
1400                while(thread--)
1401                {
1402                        atomic_base* op = class_object()[i];
1403                        if( op != CPPAD_NULL )
1404                        {       op->afun_vx_[thread].clear();
1405                                op->afun_vy_[thread].clear();
1406                                op->afun_tx_[thread].clear();
1407                                op->afun_ty_[thread].clear();
1408                        }
1409                }
1410        }
1411        return;
1412}
1413// -------------------------------------------------------------------------
1414/*!
1415Set value of id (used by deprecated old_atomic class)
1416
1417This function is called just before calling any of the virtual funcitons
1418and has the corresponding id of the corresponding virtual call.
1419*/
1420virtual void set_id(size_t id) 
1421{ }
1422// ---------------------------------------------------------------------------
1423};
1424/*! \} */
1425CPPAD_END_NAMESPACE
1426# endif
Note: See TracBrowser for help on using the repository browser.