source: trunk/cppad/local/op_code.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: 25.7 KB
Line 
1/* $Id: op_code.hpp 3607 2015-01-20 16:20:41Z bradbell $ */
2# ifndef CPPAD_OP_CODE_INCLUDED
3# define CPPAD_OP_CODE_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# include <string>
16# include <sstream>
17# include <iomanip>
18
19# include <cppad/local/define.hpp>
20# include <cppad/local/cppad_assert.hpp>
21
22// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
23# include <cppad/thread_alloc.hpp>
24
25namespace CppAD { // BEGIN_CPPAD_NAMESPACE
26/*!
27\file op_code.hpp
28Defines the OpCode enum type and functions related to it.
29
30*/
31
32
33/*!
34Type used to distinguish different AD< \a Base > atomic operations.
35
36Each of the operators ends with the characters Op. Ignoring the Op at the end,
37the operators appear in alphabetical order. Binary operation where both
38operands have type AD< \a Base > use the following convention for thier endings:
39\verbatim
40    Ending  Left-Operand  Right-Operand
41      pvOp     parameter       variable 
42      vpOp      variable      parameter 
43      vvOp      variable       variable 
44\endverbatim
45For example, AddpvOp represents the addition operator where the left
46operand is a parameter and the right operand is a variable.
47*/
48// alphabetical order is checked by bin/check_op_code.sh
49enum OpCode {
50        AbsOp,    //  abs(variable)
51        AcosOp,   // asin(variable)
52        AddpvOp,  //      parameter  + variable
53        AddvvOp,  //      variable   + variable
54        AsinOp,   // asin(variable)
55        AtanOp,   // atan(variable)
56        BeginOp,  // used to mark the beginning of the tape
57        CExpOp,   // CondExpRel(left, right, trueCase, falseCase)
58        // arg[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
59        // arg[1] & 1 = is left a variable
60        // arg[1] & 2 = is right a variable
61        // arg[1] & 4 = is trueCase a variable
62        // arg[1] & 8 = is falseCase a variable
63        // arg[2]     = index correspoding to left
64        // arg[3]     = index correspoding to right
65        // arg[4]     = index correspoding to trueCase
66        // arg[5]     = index correspoding to falseCase
67        CosOp,    //  cos(variable)
68        CoshOp,   // cosh(variable)
69        CSkipOp,  // Conditional skip
70        // arg[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
71        // arg[1] & 1 = is left a variable
72        // arg[1] & 2 = is right a variable
73        // arg[2]     = index correspoding to left
74        // arg[3]     = index correspoding to right
75        // arg[4] = number of operations to skip if CExpOp comparision is true
76        // arg[5] = number of operations to skip if CExpOp comparision is false
77        // arg[6] -> arg[5+arg[4]]               = skip operations if true
78        // arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false
79        // arg[6+arg[4]+arg[5]] = arg[4] + arg[5]
80        CSumOp,   // Cummulative summation
81        // arg[0] = number of addition variables in summation
82        // arg[1] = number of subtraction variables in summation
83        // arg[2] = index of parameter that initializes summation
84        // arg[3] -> arg[2+arg[0]] = index for positive variables
85        // arg[3+arg[0]] -> arg[2+arg[0]+arg[1]] = index for minus variables
86        // arg[3+arg[0]+arg[1]] = arg[0] + arg[1]
87        DisOp,    //  discrete::eval(index, variable)
88        DivpvOp,  //      parameter  / variable
89        DivvpOp,  //      variable   / parameter
90        DivvvOp,  //      variable   / variable
91        EndOp,    //  used to mark the end of the tape
92        EqpvOp,   //  parameter  == variable
93        EqvvOp,   //  variable   == variable
94        ErfOp,    //  erf(variable)
95        ExpOp,    //  exp(variable)
96        InvOp,    //                             independent variable
97        LdpOp,    //    z[parameter]
98        LdvOp,    //    z[variable]
99        LepvOp,   //  parameter <= variable
100        LevpOp,   //  variable  <= parameter
101        LevvOp,   //  variable  <= variable
102        LogOp,    //  log(variable)
103        LtpvOp,   //  parameter < variable
104        LtvpOp,   //  variable  < parameter
105        LtvvOp,   //  variable  < variable
106        MulpvOp,  //      parameter  * variable
107        MulvvOp,  //      variable   * variable
108        NepvOp,   //  parameter  != variable
109        NevvOp,   //  variable   != variable
110        ParOp,    //      parameter
111        PowpvOp,  //  pow(parameter,   variable)
112        PowvpOp,  //  pow(variable,    parameter)
113        PowvvOp,  //  pow(variable,    variable)
114        PriOp,    //  PrintFor(text, parameter or variable, parameter or variable)
115        SignOp,   // sign(variable)
116        SinOp,    //  sin(variable)
117        SinhOp,   // sinh(variable)
118        SqrtOp,   // sqrt(variable)
119        StppOp,   //    z[parameter] = parameter
120        StpvOp,   //    z[parameter] = variable
121        StvpOp,   //    z[variable]  = parameter
122        StvvOp,   //    z[variable]  = variable
123        SubpvOp,  //      parameter  - variable
124        SubvpOp,  //      variable   - parameter
125        SubvvOp,  //      variable   - variable
126        TanOp,    //  tan(variable)
127        TanhOp,   //  tan(variable)
128        // user atomic operation codes
129        UserOp,   //  start of a user atomic operaiton
130        // arg[0] = index of the operation if atomic_base<Base> class
131        // arg[1] = extra information passed trough by deprecated old atomic class
132        // arg[2] = number of arguments to this atomic function
133        // arg[3] = number of results for this atomic function
134        UsrapOp,  //  this user atomic argument is a parameter
135        UsravOp,  //  this user atomic argument is a variable
136        UsrrpOp,  //  this user atomic result is a parameter
137        UsrrvOp,  //  this user atomic result is a variable
138        NumberOp
139};
140// Note that bin/check_op_code.sh assumes the pattern '^\tNumberOp$' occurs
141// at the end of this list and only at the end of this list.
142
143/*!
144Number of arguments for a specified operator.
145
146\return
147Number of arguments corresponding to the specified operator.
148
149\param op
150Operator for which we are fetching the number of arugments.
151
152\par NumArgTable
153this table specifes the number of arguments stored for each
154occurance of the operator that is the i-th value in the OpCode enum type.
155For example, for the first three OpCode enum values we have
156\verbatim
157OpCode   j   NumArgTable[j]  Meaning
158AbsOp    0                1  index of variable we are taking absolute value of
159AcosOp   1                1  index of variable we are taking cosine of
160AddpvOp  1                2  indices of parameter and variable we are adding
161\endverbatim
162Note that the meaning of the arguments depends on the operator.
163*/
164inline size_t NumArg( OpCode op)
165{       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
166
167        // agreement with OpCode is checked by bin/check_op_code.sh
168        static const size_t NumArgTable[] = {
169                1, // AbsOp
170                1, // AcosOp
171                2, // AddpvOp
172                2, // AddvvOp
173                1, // AsinOp
174                1, // AtanOp
175                1, // BeginOp  offset first real argument to have index 1
176                6, // CExpOp
177                1, // CosOp
178                1, // CoshOp
179                0, // CSkipOp  (actually has a variable number of arguments, not zero)
180                0, // CSumOp   (actually has a variable number of arguments, not zero)
181                2, // DisOp
182                2, // DivpvOp
183                2, // DivvpOp
184                2, // DivvvOp
185                0, // EndOp
186                2, // EqpvOp
187                2, // EqvvOp
188                3, // ErfOp
189                1, // ExpOp
190                0, // InvOp
191                3, // LdpOp
192                3, // LdvOp
193                2, // LepvOp
194                2, // LevpOp
195                2, // LevvOp
196                1, // LogOp
197                2, // LtpvOp
198                2, // LtvpOp
199                2, // LtvvOp
200                2, // MulpvOp
201                2, // MulvvOp
202                2, // NepvOp
203                2, // NevvOp
204                1, // ParOp
205                2, // PowpvOp
206                2, // PowvpOp
207                2, // PowvvOp
208                5, // PriOp
209                1, // SignOp
210                1, // SinOp
211                1, // SinhOp
212                1, // SqrtOp
213                3, // StppOp
214                3, // StpvOp
215                3, // StvpOp
216                3, // StvvOp
217                2, // SubpvOp
218                2, // SubvpOp
219                2, // SubvvOp
220                1, // TanOp
221                1, // TanhOp
222                4, // UserOp
223                1, // UsrapOp
224                1, // UsravOp
225                1, // UsrrpOp
226                0  // UsrrvOp
227        };
228# ifndef NDEBUG
229        // only do these checks once to save time
230        static bool first = true;
231        if( first )
232        {       CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) ==
233                        sizeof(NumArgTable) / sizeof(NumArgTable[0])
234                );
235                CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) <=
236                        std::numeric_limits<CPPAD_OP_CODE_TYPE>::max()
237                );
238                first = false;
239        }
240        // do this check every time
241        CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
242# endif
243
244        return NumArgTable[op];
245}
246
247/*!
248Number of variables resulting from the specified operation.
249
250\param op
251Operator for which we are fecching the number of results.
252
253\par NumResTable
254table specifes the number of varibles that result for each
255occurance of the operator that is the i-th value in the OpCode enum type.
256For example, for the first three OpCode enum values we have
257\verbatim
258OpCode   j   NumResTable[j]  Meaning
259AbsOp    0                1  variable that is the result of the absolute value
260AcosOp   1                2  acos(x) and sqrt(1-x*x) are required for this op
261AddpvOp  1                1  variable that is the result of the addition
262\endverbatim
263*/
264inline size_t NumRes(OpCode op)
265{       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
266
267        // agreement with OpCode is checked by bin/check_op_code.sh
268        static const size_t NumResTable[] = {
269                1, // AbsOp
270                2, // AcosOp
271                1, // AddpvOp
272                1, // AddvvOp
273                2, // AsinOp
274                2, // AtanOp
275                1, // BeginOp  offsets first variable to have index one (not zero)
276                1, // CExpOp
277                2, // CosOp
278                2, // CoshOp
279                0, // CSkipOp
280                1, // CSumOp
281                1, // DisOp
282                1, // DivpvOp
283                1, // DivvpOp
284                1, // DivvvOp
285                0, // EndOp
286                0, // EqpvOp
287                0, // EqvvOp
288                5, // ErfOp
289                1, // ExpOp
290                1, // InvOp
291                1, // LdpOp
292                1, // LdvOp
293                0, // LepvOp
294                0, // LevpOp
295                0, // LevvOp
296                1, // LogOp
297                0, // LtpvOp
298                0, // LtvpOp
299                0, // LtvvOp
300                1, // MulpvOp
301                1, // MulvvOp
302                0, // NepvOp
303                0, // NevvOp
304                1, // ParOp
305                3, // PowpvOp
306                3, // PowvpOp
307                3, // PowvvOp
308                0, // PriOp
309                1, // SignOp
310                2, // SinOp
311                2, // SinhOp
312                1, // SqrtOp
313                0, // StppOp
314                0, // StpvOp
315                0, // StvpOp
316                0, // StvvOp
317                1, // SubpvOp
318                1, // SubvpOp
319                1, // SubvvOp
320                2, // TanOp
321                2, // TanhOp
322                0, // UserOp
323                0, // UsrapOp
324                0, // UsravOp
325                0, // UsrrpOp
326                1, // UsrrvOp
327                0  // Last entry not used: avoids g++ 4.3.2 warn when pycppad builds
328        };
329        // check ensuring conversion to size_t is as expected
330        CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == 
331                sizeof(NumResTable) / sizeof(NumResTable[0]) - 1
332        );
333        // this test ensures that all indices are within the table
334        CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
335
336        return NumResTable[op];
337}
338
339
340/*!
341Fetch the name for a specified operation.
342
343\return
344name of the specified operation.
345
346\param op
347Operator for which we are fetching the name
348*/
349inline const char* OpName(OpCode op)
350{       // agreement with OpCode is checked by bin/check_op_code.sh
351        static const char *OpNameTable[] = {
352                "Abs"   ,
353                "Acos"  ,
354                "Addpv" ,
355                "Addvv" ,
356                "Asin"  ,
357                "Atan"  ,
358                "Begin" ,
359                "CExp"  ,
360                "Cos"   ,
361                "Cosh"  ,
362                "CSkip" ,
363                "CSum"  ,
364                "Dis"   ,
365                "Divpv" ,
366                "Divvp" ,
367                "Divvv" ,
368                "End"   ,
369                "Eqpv"  ,
370                "Eqvv"  ,
371                "Erf"   ,
372                "Exp"   ,
373                "Inv"   ,
374                "Ldp"   ,
375                "Ldv"   ,
376                "Lepv"  ,
377                "Levp"  ,
378                "Levv"  ,
379                "Log"   ,
380                "Ltpv"  ,
381                "Ltvp"  ,
382                "Ltvv"  ,
383                "Mulpv" ,
384                "Mulvv" ,
385                "Nepv"  ,
386                "Nevv"  ,
387                "Par"   ,
388                "Powpv" ,
389                "Powvp" ,
390                "Powvv" ,
391                "Pri"   ,
392                "Sign"  ,
393                "Sin"   ,
394                "Sinh"  ,
395                "Sqrt"  ,
396                "Stpp"  ,
397                "Stpv"  ,
398                "Stvp"  ,
399                "Stvv"  ,
400                "Subpv" ,
401                "Subvp" ,
402                "Subvv" ,
403                "Tan"   ,
404                "Tanh"  ,
405                "User"  ,
406                "Usrap" ,
407                "Usrav" ,
408                "Usrrp" ,
409                "Usrrv" 
410        };
411        // check ensuring conversion to size_t is as expected
412        CPPAD_ASSERT_UNKNOWN( 
413                size_t(NumberOp) == sizeof(OpNameTable)/sizeof(OpNameTable[0]) 
414        );
415        // this test ensures that all indices are within the table
416        CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
417
418        return OpNameTable[op];
419}
420
421/*!
422Prints a single field corresponding to an operator.
423
424A specified leader is printed in front of the value
425and then the value is left justified in the following width character.
426
427\tparam Type
428is the type of the value we are printing.
429
430\param os
431is the stream that we are printing to.
432
433\param leader
434are characters printed before the value.
435
436\param value
437is the value being printed.
438
439\param width
440is the number of character to print the value in.
441If the value does not fit in the width, the value is replace
442by width '*' characters.
443*/
444template <class Type>
445void printOpField(
446        std::ostream      &os , 
447        const char *   leader ,
448        const Type     &value , 
449        size_t          width )
450{
451        std::ostringstream buffer;
452        std::string        str;
453
454        // first print the leader
455        os << leader;
456
457        // print the value into an internal buffer
458        buffer << std::setw(width) << value;
459        str = buffer.str();
460
461        // length of the string
462        size_t len = str.size();
463        if( len > width )
464        {       size_t i;
465                for(i = 0; i < width-1; i++)
466                        os << str[i];
467                os << "*";
468                return;
469        }
470
471        // count number of spaces at begining
472        size_t nspace = 0; 
473        while(str[nspace] == ' ' && nspace < len)
474                nspace++;
475
476        // left justify the string
477        size_t i = nspace;
478        while( i < len )
479                os << str[i++];
480
481        i = width - len + nspace;
482        while(i--)
483                os << " "; 
484}
485
486/*!
487Prints a single operator and its operands
488
489\tparam Base
490Is the base type for these AD< \a Base > operations.
491
492\param os
493is the output stream that the information is printed on.
494
495\param play
496Is the entire recording for the tape that this operator is in.
497
498\param i_op
499is the index for the operator corresponding to this operation.
500
501\param i_var
502is the index for the variable corresponding to the result of this operation
503(if NumRes(op) > 0).
504
505\param op
506The operator code (OpCode) for this operation.
507
508\param ind
509is the vector of argument indices for this operation
510(must have NumArg(op) elements).
511*/
512template <class Base>
513void printOp(
514        std::ostream&          os     , 
515        const player<Base>*    play   ,
516        size_t                 i_op   , 
517        size_t                 i_var  , 
518        OpCode                 op     ,
519        const addr_t*          ind    )
520{       size_t i;
521        CPPAD_ASSERT_KNOWN(
522                ! thread_alloc::in_parallel() ,
523                "cannot print trace of AD operations in parallel mode"
524        );
525        static const char *CompareOpName[] = 
526                { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" };
527
528        // print operator
529        printOpField(os,  "o=",      i_op,  5);
530        if( NumRes(op) > 0 && op != BeginOp )
531                printOpField(os,  "v=",      i_var, 5);
532        else    printOpField(os,  "v=",      "",    5);
533        if( op == CExpOp || op == CSkipOp )
534        {       printOpField(os, "", OpName(op), 5); 
535                printOpField(os, "", CompareOpName[ ind[0] ], 3);
536        }
537        else    printOpField(os, "", OpName(op), 8); 
538
539        // print other fields
540        size_t ncol = 5;
541        switch( op )
542        {
543                case CSkipOp:
544                /*
545                ind[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
546                ind[1] & 1 = is left a variable
547                ind[1] & 2 = is right a variable
548                ind[2]     = index correspoding to left
549                ind[3]     = index correspoding to right
550                ind[4] = number of operations to skip if CExpOp comparision is true
551                ind[5] = number of operations to skip if CExpOp comparision is false
552                ind[6] -> ind[5+ind[4]]               = skip operations if true
553                ind[6+ind[4]] -> ind[5+ind[4]+ind[5]] = skip operations if false
554                ind[6+ind[4]+ind[5]] = ind[4] + ind[5]
555                */
556                CPPAD_ASSERT_UNKNOWN( ind[6+ind[4]+ind[5]] == ind[4]+ind[5] );
557                CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
558                if( ind[1] & 1 )
559                        printOpField(os, " vl=", ind[2], ncol);
560                else    printOpField(os, " pl=", play->GetPar(ind[2]), ncol);
561                if( ind[1] & 2 )
562                        printOpField(os, " vr=", ind[3], ncol);
563                else    printOpField(os, " pr=", play->GetPar(ind[3]), ncol);
564                if( size_t(ind[4]) < 3 )
565                {       for(i = 0; i < size_t(ind[4]); i++)
566                                printOpField(os, " ot=", ind[6+i], ncol);
567                }
568                else
569                {       printOpField(os, "\n\tot=", ind[6+0], ncol);
570                        for(i = 1; i < size_t(ind[4]); i++)
571                                printOpField(os, " ot=", ind[6+i], ncol);
572                }
573                if( size_t(ind[5]) < 3 )
574                {       for(i = 0; i < size_t(ind[5]); i++)
575                                printOpField(os, " of=", ind[6+ind[4]+i], ncol);
576                }
577                else
578                {       printOpField(os, "\n\tof=", ind[6+ind[4]+0], ncol);
579                        {       for(i = 1; i < size_t(ind[5]); i++)
580                                        printOpField(os, " of=", ind[6+ind[4]+i], ncol);
581                        }
582                }
583                break;
584
585                case CSumOp:
586                /*
587                ind[0] = number of addition variables in summation
588                ind[1] = number of subtraction variables in summation
589                ind[2] = index of parameter that initializes summation
590                ind[3], ... , ind[2+ind[0]] = index for positive variables
591                ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables
592                ind[3+ind[0]+ind[1]] == ind[0] + ind[1]
593                */
594                CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] );
595                printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
596                for(i = 0; i < size_t(ind[0]); i++)
597                         printOpField(os, " +v=", ind[3+i], ncol);
598                for(i = 0; i < size_t(ind[1]); i++)
599                         printOpField(os, " -v=", ind[3+ind[0]+i], ncol);
600                break;
601
602                case LdpOp:
603                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
604                printOpField(os, "off=", ind[0], ncol);
605                printOpField(os, "idx=", ind[1], ncol);
606                break;
607
608                case LdvOp:
609                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
610                printOpField(os, "off=", ind[0], ncol);
611                printOpField(os, "  v=", ind[1], ncol);
612                break;
613
614                case StppOp:
615                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
616                printOpField(os, "off=", ind[0], ncol);
617                printOpField(os, "idx=", ind[1], ncol);
618                printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
619                break;
620
621                case StpvOp:
622                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
623                printOpField(os, "off=", ind[0], ncol);
624                printOpField(os, "idx=", ind[1], ncol);
625                printOpField(os, " vr=", ind[2], ncol);
626                break;
627
628                case StvpOp:
629                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
630                printOpField(os, "off=", ind[0], ncol);
631                printOpField(os, " vl=", ind[1], ncol);
632                printOpField(os, " pr=", play->GetPar(ind[2]), ncol);
633                break;
634
635                case StvvOp:
636                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
637                printOpField(os, "off=", ind[0], ncol);
638                printOpField(os, " vl=", ind[1], ncol);
639                printOpField(os, " vr=", ind[2], ncol);
640                break;
641
642                case AddvvOp:
643                case DivvvOp:
644                case LevvOp:
645                case LtvvOp:
646                case EqvvOp:
647                case NevvOp:
648                case MulvvOp:
649                case PowvvOp:
650                case SubvvOp:
651                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
652                printOpField(os, " vl=", ind[0], ncol);
653                printOpField(os, " vr=", ind[1], ncol);
654                break;
655
656                case AddpvOp:
657                case LepvOp:
658                case LtpvOp:
659                case EqpvOp:
660                case NepvOp:
661                case SubpvOp:
662                case MulpvOp:
663                case PowpvOp:
664                case DivpvOp:
665                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
666                printOpField(os, " pl=", play->GetPar(ind[0]), ncol);
667                printOpField(os, " vr=", ind[1], ncol);
668                break;
669
670                case DivvpOp:
671                case LevpOp:
672                case LtvpOp:
673                case PowvpOp:
674                case SubvpOp:
675                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
676                printOpField(os, " vl=", ind[0], ncol);
677                printOpField(os, " pr=", play->GetPar(ind[1]), ncol);
678                break;
679
680                case AbsOp:
681                case AcosOp:
682                case AsinOp:
683                case AtanOp:
684                case CosOp:
685                case CoshOp:
686                case ExpOp:
687                case LogOp:
688                case SignOp:
689                case SinOp:
690                case SinhOp:
691                case SqrtOp:
692                case UsravOp:
693                case TanOp:
694                case TanhOp:
695                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
696                printOpField(os, "  v=", ind[0], ncol);
697                break;
698
699                case ErfOp:
700                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
701                // ind[2] points to the parameter 0
702                // ind[3] points to the parameter 2 / sqrt(pi)
703                printOpField(os, "  v=", ind[0], ncol);
704                break;
705
706                case ParOp:
707                case UsrapOp:
708                case UsrrpOp:
709                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
710                printOpField(os, "  p=", play->GetPar(ind[0]), ncol);
711                break;
712
713                case UserOp:
714                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
715                {       std::string name =  atomic_base<Base>::class_name(ind[0]);
716                        printOpField(os, " f=",   name.c_str(), ncol);
717                        printOpField(os, " i=", ind[1], ncol);
718                        printOpField(os, " n=", ind[2], ncol);
719                        printOpField(os, " m=", ind[3], ncol);
720                }
721                break;
722
723                case PriOp:
724                CPPAD_ASSERT_NARG_NRES(op, 5, 0);
725                if( ind[0] & 1 )
726                        printOpField(os, " v=", ind[1], ncol);
727                else    printOpField(os, " p=", play->GetPar(ind[1]), ncol);
728                os << "before=\"" << play->GetTxt(ind[2]) << "\"";
729                if( ind[0] & 2 )
730                        printOpField(os, " v=", ind[3], ncol);
731                else    printOpField(os, " p=", play->GetPar(ind[3]), ncol);
732                os << "after=\"" << play->GetTxt(ind[4]) << "\"";
733                break;
734
735                case BeginOp:
736                // argument not used (created by independent)
737                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
738                break;
739
740                case EndOp:
741                case InvOp:
742                case UsrrvOp:
743                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
744                break;
745
746                case DisOp:
747                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
748                {       const char* name = discrete<Base>::name(ind[0]);
749                        printOpField(os, " f=", name, ncol);
750                        printOpField(os, " x=", ind[1], ncol);
751                }
752                break;
753       
754
755                case CExpOp:
756                CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
757                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
758                if( ind[1] & 1 )
759                        printOpField(os, " vl=", ind[2], ncol);
760                else    printOpField(os, " pl=", play->GetPar(ind[2]), ncol);
761                if( ind[1] & 2 )
762                        printOpField(os, " vr=", ind[3], ncol);
763                else    printOpField(os, " pr=", play->GetPar(ind[3]), ncol);
764                if( ind[1] & 4 )
765                        printOpField(os, " vt=", ind[4], ncol);
766                else    printOpField(os, " pt=", play->GetPar(ind[4]), ncol);
767                if( ind[1] & 8 )
768                        printOpField(os, " vf=", ind[5], ncol);
769                else    printOpField(os, " pf=", play->GetPar(ind[5]), ncol);
770                break;
771
772                default:
773                CPPAD_ASSERT_UNKNOWN(0);
774        }
775}
776
777/*!
778Prints the result values correspnding to an operator.
779
780\tparam Base
781Is the base type for these AD< \a Base > operations.
782
783\tparam Value
784Determines the type of the values that we are printing.
785
786\param os
787is the output stream that the information is printed on.
788
789\param nfz
790is the number of forward sweep calculated values of type Value
791that correspond to this operation
792(ignored if NumRes(op) == 0).
793
794\param fz
795points to the first forward calculated value
796that correspond to this operation
797(ignored if NumRes(op) == 0).
798
799\param nrz
800is the number of reverse sweep calculated values of type Value
801that correspond to this operation
802(ignored if NumRes(op) == 0).
803
804\param rz
805points to the first reverse calculated value
806that correspond to this operation
807(ignored if NumRes(op) == 0).
808*/
809template <class Value>
810void printOpResult(
811        std::ostream          &os     , 
812        size_t                 nfz    ,
813        const  Value          *fz     ,
814        size_t                 nrz    ,
815        const  Value          *rz     )
816{
817        size_t k;
818        for(k = 0; k < nfz; k++)
819                os << "| fz[" << k << "]=" << fz[k];
820        for(k = 0; k < nrz; k++)
821                os << "| rz[" << k << "]=" << rz[k];
822}
823
824/*!
825If NDEBUG is not defined, assert that arguments come before result.
826
827\param op
828Operator for which we are checking order.
829All the operators are checked except for those of the form UserOp or Usr..Op.
830
831\param result
832is the variable index for the result.
833
834\param arg
835is a vector of lenght NumArg(op) pointing to the arguments
836for this operation.
837*/
838inline void assert_arg_before_result(
839        OpCode op, const addr_t* arg, size_t result
840)
841{
842        switch( op )
843        {
844
845                // These cases are not included below
846                case UserOp:
847                case UsrapOp:
848                case UsravOp:
849                case UsrrpOp:
850                case UsrrvOp:
851                break;
852                // ------------------------------------------------------------------
853
854                // 0 arguments
855                case CSkipOp:
856                case CSumOp:
857                case EndOp:
858                case InvOp:
859                break;
860                // ------------------------------------------------------------------
861
862                // 1 argument, but is not used
863                case BeginOp:
864                break;
865
866                // 1 argument , 1 result
867                case AbsOp:
868                case ExpOp:
869                case LogOp:
870                case ParOp:
871                case SignOp:
872                case SqrtOp:
873                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result );
874                break;
875
876                // 1 argument, 2 results
877                case AcosOp:
878                case AsinOp:
879                case AtanOp:
880                case CosOp:
881                case CoshOp:
882                case SinOp:
883                case SinhOp:
884                case TanOp:
885                case TanhOp:
886                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 1 < result );
887                break;
888
889                // 1 argument, 5 results
890                case ErfOp:
891                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 4 < result );
892                break;
893                // ------------------------------------------------------------------
894                // 2 arguments, no results
895                case LepvOp:
896                case LtpvOp:
897                case EqpvOp:
898                case NepvOp:
899                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result );
900                break;
901                //
902                case LevpOp:
903                case LtvpOp:
904                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= result );
905                break;
906                //
907                case LevvOp:
908                case LtvvOp:
909                case EqvvOp:
910                case NevvOp:
911                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= result );
912                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result );
913                break;
914
915                // 2 arguments (both variables), 1 results
916                case AddvvOp:
917                case DivvvOp:
918                case MulvvOp:
919                case SubvvOp:
920                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result );
921                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result );
922                break;
923
924                // 2 arguments (first variables), 1 results
925                case DivvpOp:
926                case SubvpOp:
927                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < result );
928                break;
929
930                // 2 arguments (second variables), 1 results
931                case AddpvOp:
932                case DisOp:
933                case DivpvOp:
934                case MulpvOp:
935                case SubpvOp:
936                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result );
937                break;
938
939                // 2 arguments (both variables), 3 results
940                case PowvvOp:
941                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 2 < result );
942                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) + 2 < result );
943                break;
944
945                // 2 arguments (first variable), 3 results
946                case PowvpOp:
947                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) + 2 < result );
948                break;
949
950                // 2 arguments (second variable), 3 results
951                case PowpvOp:
952                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) + 2 < result );
953                break;
954                // ------------------------------------------------------------------
955
956                // 3 arguments, none variables
957                case LdpOp:
958                case StppOp:
959                break;
960
961                // 3 arguments, second variable, 1 result
962                case LdvOp:
963                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < result );
964                break;
965               
966                // 3 arguments, third variable, no result
967                case StpvOp:
968                CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= result );
969                break;
970
971                // 3 arguments, second variable, no result
972                case StvpOp:
973                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result );
974                break;
975
976                // 3 arguments, second and third variable, no result
977                case StvvOp:
978                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result );
979                CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= result );
980                break;
981                // ------------------------------------------------------------------
982
983                // 5 arguments, no result
984                case PriOp:
985                if( arg[0] & 1 )
986                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) <= result );
987                }
988                if( arg[0] & 2 )
989                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) <= result );
990                }
991                break;
992                // ------------------------------------------------------------------
993
994                // 6 arguments, 1 result
995                case CExpOp:
996                if( arg[1] & 1 )
997                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < result );
998                }
999                if( arg[1] & 2 )
1000                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < result );
1001                }
1002                if( arg[1] & 4 )
1003                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < result );
1004                }
1005                if( arg[1] & 8 )
1006                {       CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < result );
1007                }
1008                break;
1009                // ------------------------------------------------------------------
1010
1011                default:
1012                CPPAD_ASSERT_UNKNOWN(false);
1013                break;
1014
1015        }
1016        return;
1017}
1018
1019} // END_CPPAD_NAMESPACE
1020# endif
Note: See TracBrowser for help on using the repository browser.