source: branches/cache/cppad/local/op_code.hpp @ 3341

Last change on this file since 3341 was 3341, checked in by bradbell, 6 years ago
  1. Add num_var and cache2var to cppad_assert_arg_before_result.
  2. In sweeps, change numvar to num_var.

forward2sweep.hpp: remove extra asserts (arg_before_result cases).

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