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

Last change on this file since 3607 was 3607, checked in by bradbell, 5 years ago

merge to branch: trunk
from repository: https://github.com/coin-or/CppAD
start hash code: f4baab0ea7c2679ba9351b0439b6efebfa77ba04
end hash code: 894d554a00ceec8a3545f05eca62708a7b5cb43d

commit 894d554a00ceec8a3545f05eca62708a7b5cb43d
Author: Brad Bell <bradbell@…>
Date: Tue Jan 20 09:06:10 2015 -0700

Fix copyright end date.


whats_new_15.omh: Add comment about date of deprecation.

commit 611e982000168db91aba22b763c14bb78d57da47
Author: Brad Bell <bradbell@…>
Date: Tue Jan 20 08:53:00 2015 -0700

Squashed commit from old/compare_op to master:


In addition, fix copyright end date for some files, and add note about
deprecated date in whats_new_15.omh.


commit 6e46df5c850ecd58d7a886db4043bc3f2d4579d1
Author: Brad Bell <bradbell@…>
Date: Tue Jan 20 08:16:57 2015 -0700


Always return f.compare_change_op_index() == 0 after f.optimize().


checkpoint.hpp: ignore comparison operators.
fun_construct.hpp: remove double initilaization of values.
compare_change.cpp: demonstrate more features of new interface.
whats_new_15.omh: prepare for merging this branch into master.
wish_list.omh: update wish list item to new compare_change interface.


commit 45315907c70e5b383d984fb9498b54a474001af0
Author: Brad Bell <bradbell@…>
Date: Tue Jan 20 05:04:37 2015 -0700


Use the new f.compare_change_count(0) option in speed tests.


commit bb6e72befd6d01f1fb62c43b9b19471ffaa7cc2c
Author: Brad Bell <bradbell@…>
Date: Tue Jan 20 04:51:16 2015 -0700


Move CompareChange? -> deprecated and plan -> compare_change.


forward0sweep.hpp: skip comparison operator when count is zero.
forward1sweep.hpp: skip comparison operator when count is zero.
compare_change.cpp: demonstrate count == 0 case.


commit 622a13c568c612d9dfe9ccd1a01f4ac5f74ba824
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 23:17:42 2015 -0700


Add example and test of new compare change user API.


ad_fun.hpp: fix f.compare_change_op_index.
compare_change.cpp: Change example to use new API.
compare_change.cpp: Move old example here (just test now).


commit ec4c1613eae8df56fbf31e7b8711ce69cc41df83
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 21:12:11 2015 -0700


Implement the compare change plan, still needs an example and test.
Also have the change from 'plan' to just plain documentation.


commit a81a46f27011bee08ba072551044dc9f4a99a906
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 17:49:05 2015 -0700


Change name of compare_change functions and partially implement this new plan.


commit 146faad48a700a56362e74f9c3a3c39144a79738
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 14:22:40 2015 -0700


Branch: compare_op
plan.omh: change name of count function.


commit 35d91d126765d1a0ab4bfe9e2b006bbf535cd648
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 13:19:07 2015 -0700


Add deprecation date for some more cases.


commit 5bb65a8c48fae4263b66fcd04520e10e66febc11
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 13:13:51 2015 -0700


Add date of deprecation for some more cases.


commit e95ee6b209601cd9a075d2e37c602e73c32fb6ab
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 12:58:44 2015 -0700


Add date of deprecation for some more cases.


commit 0ea84ccd87383edc62a6ae1711da104b12e8c444
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 12:47:01 2015 -0700


Add date of deprecation for some cases.


commit 17755e609ea8e03472b08dcc2fb5ad347eb723cb
Author: Brad Bell <bradbell@…>
Date: Mon Jan 19 08:20:45 2015 -0700


plan.omh: changs some names.


commit 29f369c06d4d0ee284c4c668d52d8461613066dc
Author: Brad Bell <bradbell@…>
Date: Fri Jan 16 06:39:45 2015 -0700


Document the plan for compare_change user API.


compare_change.omh: fix minor typo.
plan.txt: change to the omhelp file plan.omh.


commit a3a2f4dedd202a722812b6eb2714851b40726e6e
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 21:03:44 2015 -0700


new_branch.sh: remove unused variable.
push_git2svn.py: move repository from github/bradbell to coin-or/bradbell.


commit 3751a197ab2897e76616f9d9b0915148bd855356
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 20:56:17 2015 -0700


plan.txt: plan for this branches API will go here.


commit 76013ec2ad7baacdeab5e761812d542867910174
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 18:04:33 2015 -0700


Store the operator index for the first comparision change in the ADFun object.


commit 9caf25014079a60df5de17bcac76775daf8ee201
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 12:45:56 2015 -0700


Make compare_change a parameter (so will be easy to add compare_first).


commit 2246d22fe82b8909d432f82ab0d783ce3351a02f
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 09:12:40 2015 -0700


speed_branch.sh: fix directory (before cd).


commit b3910de86558a97749741bfb728e45c5a86d1c73
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 05:14:01 2015 -0700


search.sh: use git to get list of source files.
ad_fun.hpp: imporve doxygen doc for compare_change_.
ad_tape.hpp: remove RecordCompare? (no longer used).
atomic_base.hpp: minor edit to user documentation.


commit dd74f331386cadc9cc272c264296e575691aa3f8
Author: Brad Bell <bradbell@…>
Date: Thu Jan 15 04:12:34 2015 -0700


Change Leq..Op -> Le..Op and leq.._op -> le.._op.


commit ae729296323eb7f4f4a7c0e90a303a8d7f4ed42a
Author: Brad Bell <bradbell@…>
Date: Wed Jan 14 21:19:55 2015 -0700


comp_op.hpp: Add doxygen documentaiton for compare operators.
compare.hpp: avoid an extra branch.


commit b064d59a5ad01dff5c708cc8c02f628f58c863ec
Author: Brad Bell <bradbell@…>
Date: Wed Jan 14 16:11:25 2015 -0700


Remove ComOp?, replaced by specific cases Eq..Op, Ne..Op, Leq..Op, Lt..Op,
which should run faster.


forward0sweep.hpp: Remove out-dated comment about CompOp?.
forward1sweep.hpp: Remove out-dated comment about CompOp?.


commit 5bb0a70d1151e9086b88024050cea6cf11e83aa7
Author: Brad Bell <bradbell@…>
Date: Wed Jan 14 09:02:17 2015 -0700


Use Eq..Op, Ne..Op to implement == and !=.


commit 0ebeec61bc040a00c50db41ca5da31fb87194f93
Author: Brad Bell <bradbell@…>
Date: Wed Jan 14 07:19:26 2015 -0700


compare.hpp: Finish folding < <= > >= into Lt..Op and Leq..Op.


commit c949e5b72158b98cbab61c8aea98e76008e9c2f4
Author: Brad Bell <bradbell@…>
Date: Wed Jan 14 06:28:41 2015 -0700


  1. Change plan to fold all compare operations into Leq..Op and Lt..Op cases.
  2. Fix alphabetical order between Ld and Leq.


commit 6ffee88b68b682359d62bc75a8c2ba3e28d012ac
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 22:40:18 2015 -0700


Splite parameter <= variable and parameter > variable as separate compare
operators.


commit 0841014db4ead690d1c2358f5e09494030ae1e5f
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 21:12:57 2015 -0700


Attempting to recording and playback of compare operators faster:
Split variable <= variable and variable > variable out as separate cases.


compare.hpp: remove white space at end of lines.


commit cfd3afceebd4b3383b3042cbca98caf82ff77670
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 08:39:12 2015 -0700


speed_branch.sh: compare speed_cppad between two git branches.
speed_new.sh: correct list of options, remove unused variable.
wish_list.omh: correct discussion of effect of keeping compare operators.


commit 9ed03e1ee2c258ca38561ad083067e235d032e14
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 05:54:30 2015 -0700


Change test so it corresponds to optimization keeping compare operators.


commit 5c418d477d58984b094bba027ebb0794e759e557
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 05:12:50 2015 -0700


Include example and test of using CompareChange? with optimized tape.


commit c1b48edfa56ca096ce8c2db1dbadb2658cb13fe3
Author: Brad Bell <bradbell@…>
Date: Tue Jan 13 04:24:54 2015 -0700


Fix optimization so variables used in compare opertions are alwasy available.


commit 6fe607ca30db07b356fd3a9fe9779fa2dfd382d8
Author: Brad Bell <bradbell@…>
Date: Mon Jan 12 07:56:41 2015 -0700


Keep CompareChange? in optimized versions of tape and when NDEBUG is defined.

commit b4c0e51489cc0878499a331b4af4875b2781d8d8
Author: Brad Bell <bradbell@…>
Date: Sun Jan 11 17:01:59 2015 -0700

new_branch.sh: final procedure (only hand tested).

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