source: trunk/cppad/local/op_code.hpp @ 3495

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

Squashed commit of the following:

commit ea33674d009e14c6b8b8479fe08f5fd14efe15ce
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 17:32:52 2014 -0700

Change CPPAD_HAS_ERROR_FUNCTION -> CPPAD_COMPLIER_HAS_ERF.

commit c81badddaa95ce83d9d74ef5516955fb53be650f
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 16:31:03 2014 -0700

base_require.hpp: remove command that is not used.
base_adolc.hpp: define erf when it is required.
erf_op.hpp: fix derivative of zero order.
for_jac_sweep.hpp: remove trailing white space, add ErfOp?.
op_code.hpp: fix tracing of ErfOp?
rev_hes_sweep.hpp: add ErfOp?.
rev_jac_sweep.hpp: remove trailing white space, add ErfOp?.
erf.cpp: add more examples and tests.
erf.cpp: change x0 to not be multiply identity.

commit 213c2321cb527d6b913ac627ab631098e643be4f
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 07:14:56 2014 -0700

Add special routine for erf zero order forward mode.

commit 8cc6ca517ddbe213988e497a100a8ae6465a0a3e
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 06:54:33 2014 -0700

Implement and test atomic erf in reverse mode.

commit 8611fca3e9fea21ff5cc5d4e8742a01e1f29070f
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 05:31:47 2014 -0700

tan_reverse.omh: fix typo.

commit f582631d101fdbab721fb283e5284b59bc018015
Author: Brad Bell <bradbell@…>
Date: Tue Dec 23 04:53:39 2014 -0700

Test forward order zero, one, and two both with and without std::erf.

commit 7bba97a757252f279dfe7fc58209d8e55ce8e9f6
Author: Brad Bell <bradbell@…>
Date: Mon Dec 22 21:48:30 2014 -0700

  1. Ignore git_commit.sh (temporary file created by ~/bin/git_commit.sh).
  2. Add base requrements for erf function.
  3. Implement and test forward mode for erf(double).

erf_op.hpp: remove i_x (not used).
forward0sweep.hpp: add ErfOp? case.
undef.hpp: make CPPAD_HAS_ERROR_FUNCTION part of user api.
erf.cpp: comment out parts not yet being tested.

commit 967f6843f9c4133ed3f986371e01115504e20f68
Merge: 3a7a9ea 9edd70a
Author: Brad Bell <bradbell@…>
Date: Mon Dec 22 07:16:00 2014 -0700

Merge branch 'master' into erf

commit 3a7a9ea832d4ab90c80c5c9bbeea5a9f3c9839e7
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 18:51:58 2014 -0700

op_code.hpp: add ErfOp?.
undef.hpp: add CPPAD_HAS_ERROR_FUNCTION.
makefile.am: add erf_op.hpp.

commit d584798c43e7fe5c5c3d080328fee06ff7ba0fe1
Merge: 5f13ae6 58a292c
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 09:24:16 2014 -0700

Merge branch 'master' into erf

commit 5f13ae64b979e618188adabad4365ffa6c011215
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 09:12:11 2014 -0700

erf_op.hpp: only defined operators when compiler has erf.

commit acc16d2b5251250850ef3125a2bdcea11ec18cf8
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 08:41:35 2014 -0700

Implement erf general forward mode as plan for other changes (not hooked up).

commit 5522393a914a2117bdc149fe16b62c0afff0102e
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 06:40:27 2014 -0700

Add cppad_has_error_function (true if compiler has error function).

commit da4f1ba378f92e78b17ca1e85c417f86b6946dbf
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 06:13:52 2014 -0700

erf.hpp: Document planned change in this branch.
erf_forward.omh: fix sqrt{pi}, fix svn Id (messed up by git-svn).
erf_reverse.omh: fix svn Id.

commit 05eebb357f90818f2b4dec8a3e108820fb6c34b2
Merge: 2398fd6 7d9ed8a
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 05:33:05 2014 -0700

Merge branch 'master' into erf

commit 7d9ed8abddffba666f76f64e28e48766cbc28fb6
Author: Brad Bell <bradbell@…>
Date: Sun Dec 21 05:27:17 2014 -0700

  1. Change size_t_same_unsigned_int to size_t_not_unsigned_int. so that test result variable has same meaning as test.
  2. Fix svn Id property at top if files being commited.

package.sh: Remove check_svn_id.sh from list becuse git-svn messed up Id.

commit 2398fd6ad75d51c436ee1cf9b9cf2f606ef44828
Author: Brad Bell <bradbell@…>
Date: Sat Dec 20 09:02:02 2014 -0700

erf_reverse.omh: theory for for erf reverse mode calculation.

commit fc83d4fe0da0ecc09bbb5a8d0334379756e58c3e
Author: Brad Bell <bradbell@…>
Date: Sat Dec 20 07:43:50 2014 -0700

Start work on makeing erf an atomic operation (when supported by compiler).

erf_forward.omh: forward mode theory for erf.

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