source: branches/opt_cond_exp/cppad/local/op_code.hpp @ 2955

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

op_code.hpp: fix bug in printing atomic op codes.
optimize.hpp: improve comments about cummulative summation.

  • Property svn:keywords set to Id
File size: 19.0 KB
Line 
1/* $Id: op_code.hpp 2955 2013-10-16 14:56:16Z bradbell $ */
2# ifndef CPPAD_OP_CODE_INCLUDED
3# define CPPAD_OP_CODE_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell
7
8CppAD is distributed under multiple licenses. This distribution is under
9the terms of the
10                    Eclipse Public License Version 1.0.
11
12A copy of this license is included in the COPYING file of this distribution.
13Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14-------------------------------------------------------------------------- */
15# 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\defgroup op_code_hpp op_code.hpp
28\{
29\file op_code.hpp
30Defines the OpCode enum type and functions related to it.
31
32*/
33
34
35/*!
36Type used to distinguish different AD< \a Base > atomic operations.
37
38Each of the operators ends with the characters Op. Ignoring the Op at the end,
39the operators appear in alphabetical order. Binary operation where both
40operands have type AD< \a Base > use the following convention for thier endings:
41\verbatim
42    Ending  Left-Operand  Right-Operand
43      pvOp     parameter       variable 
44      vpOp      variable      parameter 
45      vvOp      variable       variable 
46\endverbatim
47For example, AddpvOp represents the addition operator where the left
48operand is a parameter and the right operand is a variable.
49*/
50enum OpCode {
51        AbsOp,    //  abs(variable)
52        AcosOp,   // asin(variable)
53        AddpvOp,  //      parameter  + variable
54        AddvvOp,  //      variable   + variable
55        AsinOp,   // asin(variable)
56        AtanOp,   // atan(variable)
57        BeginOp,  // used to mark the beginning of the tape
58        BskipOp,  // begin a conditional skip of operations
59        // arg[0] = index in cond_skip we will check for true
60        // arg[1] = number of operations that we will skip if true
61        CExpOp,   // CondExpRel(left, right, trueCase, falseCase)
62        // arg[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
63        // arg[1] & 1 = is left a variable
64        // arg[1] & 2 = is right a variable
65        // arg[1] & 4 = is trueCase a variable
66        // arg[1] & 8 = is falseCase a variable
67        // arg[2]     = index correspoding to left
68        // arg[3]     = index correspoding to right
69        // arg[4]     = index correspoding to trueCase
70        // arg[5]     = index correspoding to falseCase
71        ComOp,    // Compare(cop, result, left, right)
72        CosOp,    //  cos(variable)
73        CoshOp,   // cosh(variable)
74        CSumOp,   // Cummulative summation
75        // arg[0] = number of addition variables in summation
76        // arg[1] = number of subtraction variables in summation
77        // arg[2] = index of parameter that initializes summation
78        // arg[3] -> arg[2+arg[0]] = index for positive variables
79        // arg[3+arg[0]] -> arg[2+arg[0]+arg[1]] = index for minus variables
80        // arg[3+arg[0]+arg[1]] = arg[0] + arg[1]
81        DisOp,    //  discrete::eval(index, variable)
82        DivpvOp,  //      parameter  / variable
83        DivvpOp,  //      variable   / parameter
84        DivvvOp,  //      variable   / variable
85        EndOp,    //  used to mark the end of the tape
86        EskipOp,  // end a conditional skip of operations
87        // arg[0] = index in cond_skip we will check for true
88        // arg[1] = number of operations that we will skip if true
89        ExpOp,    //  exp(variable)
90        InvOp,    //                             independent variable
91        LdpOp,    //    z[parameter]
92        LdvOp,    //    z[variable]
93        LogOp,    //  log(variable)
94        MulpvOp,  //      parameter  * variable
95        MulvvOp,  //      variable   * variable
96        ParOp,    //      parameter
97        PowpvOp,  //  pow(parameter,   variable)
98        PowvpOp,  //  pow(variable,    parameter)
99        PowvvOp,  //  pow(variable,    variable)
100        PriOp,    //  PrintFor(text, parameter or variable, parameter or variable)
101        SignOp,   // sign(variable)
102        SinOp,    //  sin(variable)
103        SinhOp,   // sinh(variable)
104        SqrtOp,   // sqrt(variable)
105        SskipOp,  // set the next pair of conditional skip values
106        // arg[0]   = index in operation sequence of a CExpOp
107        // arg[1]   = index in cond_skip set to comparison result
108        // arg[1]+1 = index in cond_skip set to not comparison result
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        UsrapOp,  //  this user atomic argument is a parameter
121        UsravOp,  //  this user atomic argument is a variable
122        UsrrpOp,  //  this user atomic result is a parameter
123        UsrrvOp,  //  this user atomic result is a variable
124        NumberOp
125};
126// Note that bin/check_op_code.sh assumes the pattern '^\tNumberOp$' occurs
127// at the end of this list and only at the end of this list.
128
129/*!
130Table containing number of arguments for the corresponding operator.
131
132The i-th element in this table specifes the number of arguments stored for each
133occurance of the operator that is the i-th value in the OpCode enum type.
134For example, for the first three OpCode enum values we have
135\verbatim
136OpCode   j   NumArgTable[j]  Meaning
137AbsOp    0                1  index of variable we are taking absolute value of
138AcosOp   1                1  index of variable we are taking cosine of
139AddpvOp  1                2  indices of parameter and variable we are adding
140\endverbatim
141Note that the meaning of the arguments depends on the operator.
142*/
143const size_t NumArgTable[] = {
144        1, // AbsOp
145        1, // AcosOp
146        2, // AddpvOp
147        2, // AddvvOp
148        1, // AsinOp
149        1, // AtanOp
150        0, // BeginOp
151        2, // BskipOp
152        6, // CExpOp
153        4, // ComOp
154        1, // CosOp
155        1, // CoshOp
156        0, // CSumOp   (actually has a variable number of arguments, not zero)
157        2, // DisOp
158        2, // DivpvOp
159        2, // DivvpOp
160        2, // DivvvOp
161        0, // EndOp
162        2, // EskipOp
163        1, // ExpOp
164        0, // InvOp
165        3, // LdpOp
166        3, // LdvOp
167        1, // LogOp
168        2, // MulpvOp
169        2, // MulvvOp
170        1, // ParOp
171        2, // PowpvOp
172        2, // PowvpOp
173        2, // PowvvOp
174        5, // PriOp
175        1, // SignOp
176        1, // SinOp
177        1, // SinhOp
178        1, // SqrtOp
179        3, // SskipOp
180        3, // StppOp
181        3, // StpvOp
182        3, // StvpOp
183        3, // StvvOp
184        2, // SubpvOp
185        2, // SubvpOp
186        2, // SubvvOp
187        1, // TanOp
188        1, // TanhOp
189        4, // UserOp
190        1, // UsrapOp
191        1, // UsravOp
192        1, // UsrrpOp
193        0  // UsrrvOp
194};
195
196/*!
197Fetch the number of arguments for a specified operator.
198
199\return
200Number of arguments corresponding to the specified operator.
201
202\param op
203Operator for which we are fetching the number of arugments.
204
205- Check that argument taple size equal to NumberOp
206- Check that \c CPPAD_OP_CODE_TYPE can support all the operator codes.
207- Check that \c op is a valid operator value.
208*/
209inline size_t NumArg( OpCode op)
210{       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
211# ifndef NDEBUG
212        // only do these checks once to save time
213        static bool first = true;
214        if( first )
215        {       CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) ==
216                        sizeof(NumArgTable) / sizeof(NumArgTable[0])
217                );
218                CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) <=
219                        std::numeric_limits<CPPAD_OP_CODE_TYPE>::max()
220                );
221                first = false;
222        }
223        // do this check every time
224        CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
225# endif
226
227        return NumArgTable[(size_t) op];
228}
229
230/*!
231Number of variables resulting from the corresponding operation.
232
233The i-th element in this table specifes the number of varibles for each
234occurance of the operator that is the i-th value in the OpCode enum type.
235For example, for the first three OpCode enum values we have
236\verbatim
237OpCode   j   NumResTable[j]  Meaning
238AbsOp    0                1  variable that is the result of the absolute value
239AcosOp   1                2  acos(x) and sqrt(1-x*x) are required for this op
240AddpvOp  1                1  variable that is the result of the addition
241\endverbatim
242*/
243// alphabetical order (ignoring the Op at the end)
244const size_t NumResTable[] = {
245        1, // AbsOp
246        2, // AcosOp
247        1, // AddpvOp
248        1, // AddvvOp
249        2, // AsinOp
250        2, // AtanOp
251        1, // BeginOp  offsets first variable to have index one (not zero)
252        0, // BskipOp
253        1, // CExpOp
254        0, // ComOp
255        2, // CosOp
256        2, // CoshOp
257        1, // CSumOp
258        1, // DisOp
259        1, // DivpvOp
260        1, // DivvpOp
261        1, // DivvvOp
262        0, // EndOp
263        0, // EskipOp
264        1, // ExpOp
265        1, // InvOp
266        1, // LdpOp
267        1, // LdvOp
268        1, // LogOp
269        1, // MulpvOp
270        1, // MulvvOp
271        1, // ParOp
272        3, // PowpvOp
273        3, // PowvpOp
274        3, // PowvvOp
275        0, // PriOp
276        1, // SignOp
277        2, // SinOp
278        2, // SinhOp
279        1, // SqrtOp
280        0, // SskipOp
281        0, // StppOp
282        0, // StpvOp
283        0, // StvpOp
284        0, // StvvOp
285        1, // SubpvOp
286        1, // SubvpOp
287        1, // SubvvOp
288        2, // TanOp
289        2, // TanhOp
290        0, // UserOp
291        0, // UsrapOp
292        0, // UsravOp
293        0, // UsrrpOp
294        1, // UsrrvOp
295        0  // Last entry not used: avoids warning by g++ 4.3.2 when pycppad builds
296};
297
298/*!
299Fetch the number of variables resulting from the specified operation.
300
301\return
302number of variables resulting from the specified operator.
303
304\param op
305Operator for which we are fetching the number of result variables.
306*/
307inline size_t NumRes(OpCode op)
308{       // check ensuring conversion to size_t is as expected
309        CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) == 
310                sizeof(NumResTable) / sizeof(NumResTable[0]) - 1
311        );
312        // this test ensures that all indices are within the table
313        CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );
314
315        return NumResTable[(size_t) op];
316}
317
318/*!
319Prints a single field corresponding to an operator.
320
321A specified leader is printed in front of the value
322and then the value is left justified in the following width character.
323
324\tparam Type
325is the type of the value we are printing.
326
327\param os
328is the stream that we are printing to.
329
330\param leader
331are characters printed before the value.
332
333\param value
334is the value being printed.
335
336\param width
337is the number of character to print the value in.
338If the value does not fit in the width, the value is replace
339by width '*' characters.
340*/
341template <class Type>
342void printOpField(
343        std::ostream      &os , 
344        const char *   leader ,
345        const Type     &value , 
346        size_t          width )
347{
348        std::ostringstream buffer;
349        std::string        str;
350
351        // first print the leader
352        os << leader;
353
354        // print the value into an internal buffer
355        buffer << std::setw(width) << value;
356        str = buffer.str();
357
358        // length of the string
359        size_t len = str.size();
360        if( len > width )
361        {       size_t i;
362                for(i = 0; i < width-1; i++)
363                        os << str[i];
364                os << "*";
365                return;
366        }
367
368        // count number of spaces at begining
369        size_t nspace = 0; 
370        while(str[nspace] == ' ' && nspace < len)
371                nspace++;
372
373        // left justify the string
374        size_t i = nspace;
375        while( i < len )
376                os << str[i++];
377
378        i = width - len + nspace;
379        while(i--)
380                os << " "; 
381}
382
383/*!
384Prints a single operator, its operands, and the corresponding result values.
385
386\tparam Base
387Is the base type for these AD< \a Base > operations.
388
389\tparam Value
390Determines the type of the values that we are printing.
391
392\param os
393is the output stream that the information is printed on.
394
395\param Rec
396Is the entire recording for the tape that this operator is in.
397
398\param i_var
399is the index for the variable corresponding to the result of this operation
400(ignored if NumRes(op) == 0).
401
402\param op
403The operator code (OpCode) for this operation.
404
405\param ind
406is the vector of argument indices for this operation
407(must have NumArg(op) elements).
408
409\param nfz
410is the number of forward sweep calculated values of type Value
411that correspond to this operation
412(ignored if NumRes(op) == 0).
413
414\param fz
415points to the first forward calculated value
416that correspond to this operation
417(ignored if NumRes(op) == 0).
418
419\param nrz
420is the number of reverse sweep calculated values of type Value
421that correspond to this operation
422(ignored if NumRes(op) == 0).
423
424\param rz
425points to the first reverse calculated value
426that correspond to this operation
427(ignored if NumRes(op) == 0).
428*/
429template <class Base, class Value>
430void printOp(
431        std::ostream          &os     , 
432        const player<Base>   *Rec     ,
433        size_t                 i_var  , 
434        OpCode                 op     ,
435        const addr_t          *ind    ,
436        size_t                 nfz    ,
437        const  Value          *fz     ,
438        size_t                 nrz    ,
439        const  Value          *rz     )
440{       size_t i;
441       
442        CPPAD_ASSERT_KNOWN(
443                ! thread_alloc::in_parallel() ,
444                "cannot print trace of AD operations in parallel mode"
445        );
446        static const char *CompareOpName[] = 
447                { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" };
448        static const char *OpName[] = {
449                "Abs"   ,
450                "Acos"  ,
451                "Addpv" ,
452                "Addvv" ,
453                "Asin"  ,
454                "Atan"  ,
455                "Begin" ,
456                "Bskip" ,
457                "CExp"  ,
458                "Com"   ,
459                "Cos"   ,
460                "Cosh"  ,
461                "CSum"  ,
462                "Dis"   ,
463                "Divpv" ,
464                "Divvp" ,
465                "Divvv" ,
466                "End"   ,
467                "Eskip" ,
468                "Exp"   ,
469                "Inv"   ,
470                "Ldp"   ,
471                "Ldv"   ,
472                "Log"   ,
473                "Mulpv" ,
474                "Mulvv" ,
475                "Par"   ,
476                "Powpv" ,
477                "Powvp" ,
478                "Powvv" ,
479                "Pri"   ,
480                "Sign"  ,
481                "Sin"   ,
482                "Sinh"  ,
483                "Sqrt"  ,
484                "Sskip" ,
485                "Stpp"  ,
486                "Stpv"  ,
487                "Stvp"  ,
488                "Stvv"  ,
489                "Subpv" ,
490                "Subvp" ,
491                "Subvv" ,
492                "Tan"   ,
493                "Tanh"  ,
494                "User"  ,
495                "Usrap" ,
496                "Usrav" ,
497                "Usrrp" ,
498                "Usrrv"
499        };
500        CPPAD_ASSERT_UNKNOWN( 
501                size_t(NumberOp) == sizeof(OpName) / sizeof(OpName[0])
502        );
503
504        // print operator
505        printOpField(os,  "i=",      i_var, 5);
506        if( op == CExpOp )
507        {       printOpField(os, "op=", OpName[op], 4); 
508                printOpField(os, "", CompareOpName[ ind[0] ], 3);
509        }
510        else if( op == ComOp )
511        {       printOpField(os, "op=", OpName[op], 3); 
512                printOpField(os, "", CompareOpName[ ind[0] ], 4);
513        }
514        else    printOpField(os, "op=", OpName[op], 7); 
515
516        // print other fields
517        size_t ncol = 5;
518        switch( op )
519        {
520                case BskipOp:
521                case EskipOp:
522                /*
523                ind[0] = index in cond_skip we will check for true
524                ind[1] = number of operations that we will skip if true.
525                */
526                printOpField(os, "idx=", ind[0], ncol);
527                printOpField(os, "num=", ind[1], ncol);
528                break;
529
530                case SskipOp:
531                /*
532                arg[0]   = index in operation sequence of a CExpOp
533                arg[1]   = index in cond_skip set to comparison result
534                arg[1]+1 = index in cond_skip set to not comparison result
535                */
536                printOpField(os, "cdx=", ind[0], ncol);
537                printOpField(os, "sdx=", ind[1], ncol);
538                break;
539
540                case CSumOp:
541                /*
542                ind[0] = number of addition variables in summation
543                ind[1] = number of subtraction variables in summation
544                ind[2] = index of parameter that initializes summation
545                ind[3], ... , ind[2+ind[0]] = index for positive variables
546                ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables
547                ind[3+ind[0]+ind[1]] == ind[0] + ind[1]
548                */
549                CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] );
550                printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
551                for(i = 0; i < size_t(ind[0]); i++)
552                         printOpField(os, " +v=", ind[3+i], ncol);
553                for(i = 0; i < size_t(ind[1]); i++)
554                         printOpField(os, " -v=", ind[3+ind[0]+i], ncol);
555                break;
556
557                case LdpOp:
558                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
559                printOpField(os, "off=", ind[0], ncol);
560                printOpField(os, "idx=", ind[1], ncol);
561                break;
562
563                case LdvOp:
564                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
565                printOpField(os, "off=", ind[0], ncol);
566                printOpField(os, "  v=", ind[1], ncol);
567                break;
568
569                case StppOp:
570                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
571                printOpField(os, "off=", ind[0], ncol);
572                printOpField(os, "idx=", ind[1], ncol);
573                printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
574                break;
575
576                case StpvOp:
577                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
578                printOpField(os, "off=", ind[0], ncol);
579                printOpField(os, "idx=", ind[1], ncol);
580                printOpField(os, " vr=", ind[2], ncol);
581                break;
582
583                case StvpOp:
584                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
585                printOpField(os, "off=", ind[0], ncol);
586                printOpField(os, " vl=", ind[1], ncol);
587                printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
588                break;
589
590                case StvvOp:
591                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
592                printOpField(os, "off=", ind[0], ncol);
593                printOpField(os, " vl=", ind[1], ncol);
594                printOpField(os, " vr=", ind[2], ncol);
595                break;
596
597                case AddvvOp:
598                case DivvvOp:
599                case MulvvOp:
600                case PowvvOp:
601                case SubvvOp:
602                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
603                printOpField(os, " vl=", ind[0], ncol);
604                printOpField(os, " vr=", ind[1], ncol);
605                break;
606
607                case AddpvOp:
608                case SubpvOp:
609                case MulpvOp:
610                case PowpvOp:
611                case DivpvOp:
612                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
613                printOpField(os, " pl=", Rec->GetPar(ind[0]), ncol);
614                printOpField(os, " vr=", ind[1], ncol);
615                break;
616
617                case DivvpOp:
618                case PowvpOp:
619                case SubvpOp:
620                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
621                printOpField(os, " vl=", ind[0], ncol);
622                printOpField(os, " pr=", Rec->GetPar(ind[1]), ncol);
623                break;
624
625                case AbsOp:
626                case AcosOp:
627                case AsinOp:
628                case AtanOp:
629                case CosOp:
630                case CoshOp:
631                case ExpOp:
632                case LogOp:
633                case SignOp:
634                case SinOp:
635                case SinhOp:
636                case SqrtOp:
637                case UsravOp:
638                case TanOp:
639                case TanhOp:
640                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
641                printOpField(os, "  v=", ind[0], ncol);
642                break;
643
644                case ParOp:
645                case UsrapOp:
646                case UsrrpOp:
647                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
648                printOpField(os, "  p=", Rec->GetPar(ind[0]), ncol);
649                break;
650
651                case UserOp:
652                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
653                {       std::string name = atomic_base<Base>::class_name(ind[0]);
654                        printOpField(os, " f=",   name.c_str(), ncol);
655                        printOpField(os, " i=", ind[1], ncol);
656                        printOpField(os, " n=", ind[2], ncol);
657                        printOpField(os, " m=", ind[3], ncol);
658                }
659                break;
660
661                case PriOp:
662                CPPAD_ASSERT_NARG_NRES(op, 5, 0);
663                if( ind[0] & 1 )
664                        printOpField(os, " v=", ind[1], ncol);
665                else    printOpField(os, " p=", Rec->GetPar(ind[1]), ncol);
666                os << "before=\"" << Rec->GetTxt(ind[2]) << "\"";
667                if( ind[0] & 2 )
668                        printOpField(os, " v=", ind[3], ncol);
669                else    printOpField(os, " p=", Rec->GetPar(ind[3]), ncol);
670                os << "after=\"" << Rec->GetTxt(ind[4]) << "\"";
671                break;
672
673                case BeginOp:
674                case EndOp:
675                case InvOp:
676                case UsrrvOp:
677                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
678                break;
679
680                case DisOp:
681                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
682                {       const char* name = discrete<Base>::name(ind[0]);
683                        printOpField(os, " f=", name, ncol);
684                        printOpField(os, " x=", ind[1], ncol);
685                }
686                break;
687       
688
689                case CExpOp:
690                CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
691                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
692                if( ind[1] & 1 )
693                        printOpField(os, " vl=", ind[2], ncol);
694                else    printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol);
695                if( ind[1] & 2 )
696                        printOpField(os, " vr=", ind[3], ncol);
697                else    printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol);
698                if( ind[1] & 4 )
699                        printOpField(os, " vt=", ind[4], ncol);
700                else    printOpField(os, " pt=", Rec->GetPar(ind[4]), ncol);
701                if( ind[1] & 8 )
702                        printOpField(os, " vf=", ind[5], ncol);
703                else    printOpField(os, " pf=", Rec->GetPar(ind[5]), ncol);
704                break;
705
706                case ComOp:
707                CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
708                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
709                if( ind[1] & 1 )
710                        printOpField(os, "res=", 1, ncol);
711                else    printOpField(os, "res=", 0, ncol);
712                if( ind[1] & 2 )
713                        printOpField(os, " vl=", ind[2], ncol);
714                else    printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol);
715                if( ind[1] & 4 )
716                        printOpField(os, " vr=", ind[3], ncol);
717                else    printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol);
718                break;
719
720                default:
721                CPPAD_ASSERT_UNKNOWN(0);
722        }
723        size_t k;
724        if( NumRes(op) > 0 && (op != BeginOp) )
725        { 
726                for(k = 0; k < nfz; k++)
727                        std::cout << "| fz[" << k << "]=" << fz[k];
728                for(k = 0; k < nrz; k++)
729                        std::cout << "| rz[" << k << "]=" << rz[k];
730        }
731        std::cout << std::endl;
732}
733
734/*! \} */
735} // END_CPPAD_NAMESPACE
736# endif
Note: See TracBrowser for help on using the repository browser.