CppAD: A C++ Algorithmic Differentiation Package  20130918
rev_jac_sweep.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_REV_JAC_SWEEP_INCLUDED
00003 # define CPPAD_REV_JAC_SWEEP_INCLUDED
00004 
00005 /* --------------------------------------------------------------------------
00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Eclipse Public License Version 1.0.
00011 
00012 A copy of this license is included in the COPYING file of this distribution.
00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00014 -------------------------------------------------------------------------- */
00015 
00016 namespace CppAD { // BEGIN_CPPAD_NAMESPACE
00017 /*!
00018 \file rev_jac_sweep.hpp
00019 Compute Reverse mode Jacobian sparsity patterns.
00020 */
00021 
00022 /*!
00023 \def CPPAD_REV_JAC_SWEEP_TRACE
00024 This value is either zero or one. 
00025 Zero is the normal operational value.
00026 If it is one, a trace of every rev_jac_sweep computation is printed.
00027 */
00028 # define CPPAD_REV_JAC_SWEEP_TRACE 0
00029 
00030 /*
00031 \def CPPAD_ATOMIC_CALL
00032 This avoids warnings when NDEBUG is defined and user_ok is not used.
00033 If \c NDEBUG is defined, this resolves to
00034 \code
00035      user_atom->rev_sparse_jac
00036 \endcode
00037 otherwise, it respolves to
00038 \code
00039      user_ok = user_atom->rev_sparse_jac
00040 \endcode
00041 This maco is undefined at the end of this file to facillitate is 
00042 use with a different definition in other files.
00043 */
00044 # ifdef NDEBUG
00045 # define CPPAD_ATOMIC_CALL user_atom->rev_sparse_jac
00046 # else
00047 # define CPPAD_ATOMIC_CALL user_ok = user_atom->rev_sparse_jac
00048 # endif
00049 
00050 /*!
00051 Given the sparsity pattern for the dependent variables,
00052 RevJacSweep computes the sparsity pattern for all the independent variables.
00053 
00054 \tparam Base
00055 base type for the operator; i.e., this operation sequence was recorded
00056 using AD< \a Base > and computations by this routine are done using type 
00057 \a Base.
00058 
00059 \tparam Vector_set
00060 is the type used for vectors of sets. It can be either
00061 \c sparse_pack, \c sparse_set, or \c sparse_list.
00062 
00063 \param nz_compare
00064 Are the derivatives with respect to left and right of the expression below
00065 considered to be non-zero:
00066 \code
00067      CondExpRel(left, right, if_true, if_false)
00068 \endcode
00069 This is used by the optimizer to obtain the correct dependency relations.
00070 
00071 \param n
00072 is the number of independent variables on the tape.
00073 
00074 \param numvar
00075 is the total number of variables on the tape; i.e.,
00076 \a play->num_var_rec().
00077 This is also the number of rows in the entire sparsity pattern \a RevJac.
00078 
00079 \param play
00080 The information stored in \a play
00081 is a recording of the operations corresponding to a function
00082 \f[
00083      F : {\bf R}^n \rightarrow {\bf R}^m
00084 \f]
00085 where \f$ n \f$ is the number of independent variables
00086 and \f$ m \f$ is the number of dependent variables.
00087 The object \a play is effectly constant.
00088 It is not declared const because while playing back the tape
00089 the object \a play holds information about the currentl location
00090 with in the tape and this changes during playback.
00091 
00092 \param var_sparsity
00093 For i = 0 , ... , \a numvar - 1,
00094 (all the variables on the tape)
00095 the forward Jacobian sparsity pattern for variable i
00096 corresponds to the set with index i in \a var_sparsity.
00097 \b
00098 \b
00099 \b Input: 
00100 For i = 0 , ... , \a numvar - 1,
00101 the forward Jacobian sparsity pattern for variable i is an input
00102 if i corresponds to a dependent variable.
00103 Otherwise the sparsity patten is empty. 
00104 \n
00105 \n
00106 \b Output: For j = 1 , ... , \a n,
00107 the sparsity pattern for the dependent variable with index (j-1) 
00108 is given by the set with index index j in \a var_sparsity.
00109 */
00110 
00111 template <class Base, class Vector_set>
00112 void RevJacSweep(
00113      bool                  nz_compare,
00114      size_t                n,
00115      size_t                numvar,
00116      player<Base>         *play,
00117      Vector_set&           var_sparsity
00118 )
00119 {
00120      OpCode           op;
00121      size_t         i_op;
00122      size_t        i_var;
00123 
00124      const addr_t*   arg = CPPAD_NULL;
00125 
00126      size_t            i, j, k;
00127 
00128      // length of the parameter vector (used by CppAD assert macros)
00129      const size_t num_par = play->num_par_rec();
00130 
00131      // check numvar argument
00132      CPPAD_ASSERT_UNKNOWN( numvar > 0 );
00133      CPPAD_ASSERT_UNKNOWN( play->num_var_rec()   == numvar );
00134      CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar );
00135 
00136      // upper limit (exclusive) for elements in the set
00137      size_t limit = var_sparsity.end();
00138 
00139      // vecad_sparsity contains a sparsity pattern for each VecAD object.
00140      // vecad_ind maps a VecAD index (beginning of the VecAD object) 
00141      // to the index of the corresponding set in vecad_sparsity. 
00142      size_t num_vecad_ind   = play->num_vec_ind_rec();
00143      size_t num_vecad_vec   = play->num_vecad_vec_rec();
00144      Vector_set  vecad_sparsity;
00145      vecad_sparsity.resize(num_vecad_vec, limit);
00146      pod_vector<size_t> vecad_ind;
00147      if( num_vecad_vec > 0 )
00148      {    size_t length;
00149           vecad_ind.extend(num_vecad_ind);
00150           j             = 0;
00151           for(i = 0; i < num_vecad_vec; i++)
00152           {    // length of this VecAD
00153                length   = play->GetVecInd(j);
00154                // set to proper index for this VecAD
00155                vecad_ind[j] = i; 
00156                for(k = 1; k <= length; k++)
00157                     vecad_ind[j+k] = num_vecad_vec; // invalid index
00158                // start of next VecAD
00159                j       += length + 1;
00160           }
00161           CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() );
00162      }
00163 
00164      // work space used by UserOp.
00165      typedef std::set<size_t> size_set;
00166      size_set::iterator set_itr;  // iterator for a standard set
00167      size_set::iterator set_end;  // end of iterator sequence
00168      vector< size_set > set_r;   // set sparsity pattern for the argument x
00169      vector< size_set > set_s;   // set sparisty pattern for the result y
00170      //
00171      vector<bool>       bool_r;   // bool sparsity pattern for the argument x
00172      vector<bool>       bool_s;   // bool sparisty pattern for the result y
00173      //
00174      const size_t user_q = limit; // maximum element plus one
00175      size_t user_index = 0;       // indentifier for this atomic operation
00176      size_t user_id    = 0;       // user identifier for this call to operator
00177      size_t user_i     = 0;       // index in result vector
00178      size_t user_j     = 0;       // index in argument vector
00179      size_t user_m     = 0;       // size of result vector
00180      size_t user_n     = 0;       // size of arugment vector
00181      //
00182      atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
00183      bool               user_bool = false;      // use bool or set sparsity ?
00184 # ifndef NDEBUG
00185      bool               user_ok   = false;      // atomic op return value
00186 # endif
00187      // next expected operator in a UserOp sequence
00188      enum { user_start, user_arg, user_ret, user_end } user_state = user_end;
00189 
00190      // Initialize
00191      play->reverse_start(op, arg, i_op, i_var);
00192      CPPAD_ASSERT_UNKNOWN( op == EndOp );
00193 # if CPPAD_REV_JAC_SWEEP_TRACE
00194      std::cout << std::endl;
00195      CppAD::vector<bool> z_value(limit);
00196 # endif
00197      bool more_operators = true;
00198      while(more_operators)
00199      {
00200           // next op
00201           play->reverse_next(op, arg, i_op, i_var);
00202 # ifndef NDEBUG
00203           if( i_op <= n )
00204           {    CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
00205           }
00206           else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
00207 # endif
00208 
00209           // rest of information depends on the case
00210           switch( op )
00211           {
00212                case AbsOp:
00213                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00214                reverse_sparse_jacobian_unary_op(
00215                     i_var, arg[0], var_sparsity
00216                );
00217                break;
00218                // -------------------------------------------------
00219 
00220                case AddvvOp:
00221                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00222                reverse_sparse_jacobian_binary_op(
00223                     i_var, arg, var_sparsity
00224                );
00225                break;
00226                // -------------------------------------------------
00227 
00228                case AddpvOp:
00229                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00230                reverse_sparse_jacobian_unary_op(
00231                     i_var, arg[1], var_sparsity
00232                );
00233                break;
00234                // -------------------------------------------------
00235 
00236                case AcosOp:
00237                // sqrt(1 - x * x), acos(x)
00238                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00239                reverse_sparse_jacobian_unary_op(
00240                     i_var, arg[0], var_sparsity
00241                );
00242                break;
00243                // -------------------------------------------------
00244 
00245                case AsinOp:
00246                // sqrt(1 - x * x), asin(x)
00247                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00248                reverse_sparse_jacobian_unary_op(
00249                     i_var, arg[0], var_sparsity
00250                );
00251                break;
00252                // -------------------------------------------------
00253 
00254                case AtanOp:
00255                // 1 + x * x, atan(x)
00256                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00257                reverse_sparse_jacobian_unary_op(
00258                     i_var, arg[0], var_sparsity
00259                );
00260                break;
00261                // -------------------------------------------------
00262 
00263                case BeginOp:
00264                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00265                more_operators = false;
00266                break;
00267                // -------------------------------------------------
00268 
00269                case CSkipOp:
00270                // CSkipOp has a variable number of arguments and
00271                // reverse_next thinks it one has one argument.
00272                // We must inform reverse_next of this special case.
00273                play->reverse_cskip(op, arg, i_op, i_var);
00274                break;
00275                // -------------------------------------------------
00276 
00277                case CSumOp:
00278                // CSumOp has a variable number of arguments and
00279                // reverse_next thinks it one has one argument.
00280                // We must inform reverse_next of this special case.
00281                play->reverse_csum(op, arg, i_op, i_var);
00282                reverse_sparse_jacobian_csum_op(
00283                     i_var, arg, var_sparsity
00284                );
00285                break;
00286                // -------------------------------------------------
00287 
00288                case CExpOp:
00289                reverse_sparse_jacobian_cond_op(
00290                     nz_compare, i_var, arg, num_par, var_sparsity
00291                );
00292                break;
00293                // ---------------------------------------------------
00294 
00295                case ComOp:
00296                CPPAD_ASSERT_NARG_NRES(op, 4, 0);
00297                CPPAD_ASSERT_UNKNOWN( arg[1] > 1 );
00298                break;
00299                // --------------------------------------------------
00300 
00301                case CosOp:
00302                // sin(x), cos(x)
00303                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00304                reverse_sparse_jacobian_unary_op(
00305                     i_var, arg[0], var_sparsity
00306                );
00307                break;
00308                // ---------------------------------------------------
00309 
00310                case CoshOp:
00311                // sinh(x), cosh(x)
00312                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00313                reverse_sparse_jacobian_unary_op(
00314                     i_var, arg[0], var_sparsity
00315                );
00316                break;
00317                // -------------------------------------------------
00318 
00319                case DisOp:
00320                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00321                // derivative is identically zero
00322                break;
00323                // -------------------------------------------------
00324 
00325                case DivvvOp:
00326                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00327                reverse_sparse_jacobian_binary_op(
00328                     i_var, arg, var_sparsity
00329                );
00330                break;
00331                // -------------------------------------------------
00332 
00333                case DivpvOp:
00334                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00335                reverse_sparse_jacobian_unary_op(
00336                     i_var, arg[1], var_sparsity
00337                );
00338                break;
00339                // -------------------------------------------------
00340 
00341                case DivvpOp:
00342                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00343                reverse_sparse_jacobian_unary_op(
00344                     i_var, arg[0], var_sparsity
00345                );
00346                break;
00347                // -------------------------------------------------
00348 
00349                case ExpOp:
00350                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00351                reverse_sparse_jacobian_unary_op(
00352                     i_var, arg[0], var_sparsity
00353                );
00354                break;
00355                // -------------------------------------------------
00356 
00357                case InvOp:
00358                CPPAD_ASSERT_NARG_NRES(op, 0, 1);
00359                break;
00360                // -------------------------------------------------
00361 
00362                case LdpOp:
00363                reverse_sparse_jacobian_load_op(
00364                     op,
00365                     i_var,
00366                     arg,
00367                     num_vecad_ind,
00368                     vecad_ind.data(),
00369                     var_sparsity,
00370                     vecad_sparsity
00371                );
00372                break;
00373                // -------------------------------------------------
00374 
00375                case LdvOp:
00376                reverse_sparse_jacobian_load_op(
00377                     op,
00378                     i_var,
00379                     arg,
00380                     num_vecad_ind,
00381                     vecad_ind.data(),
00382                     var_sparsity,
00383                     vecad_sparsity
00384                );
00385                break;
00386                // -------------------------------------------------
00387 
00388                case LogOp:
00389                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00390                reverse_sparse_jacobian_unary_op(
00391                     i_var, arg[0], var_sparsity
00392                );
00393                break;
00394                // -------------------------------------------------
00395 
00396                case MulvvOp:
00397                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00398                reverse_sparse_jacobian_binary_op(
00399                     i_var, arg, var_sparsity
00400                );
00401                break;
00402                // -------------------------------------------------
00403 
00404                case MulpvOp:
00405                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00406                reverse_sparse_jacobian_unary_op(
00407                     i_var, arg[1], var_sparsity
00408                );
00409                break;
00410                // -------------------------------------------------
00411 
00412                case ParOp:
00413                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00414 
00415                break;
00416                // -------------------------------------------------
00417 
00418                case PowvpOp:
00419                reverse_sparse_jacobian_unary_op(
00420                     i_var, arg[0], var_sparsity
00421                );
00422                break;
00423                // -------------------------------------------------
00424 
00425                case PowpvOp:
00426                CPPAD_ASSERT_NARG_NRES(op, 2, 3);
00427                reverse_sparse_jacobian_unary_op(
00428                     i_var, arg[1], var_sparsity
00429                );
00430                break;
00431                // -------------------------------------------------
00432 
00433                case PowvvOp:
00434                CPPAD_ASSERT_NARG_NRES(op, 2, 3);
00435                reverse_sparse_jacobian_binary_op(
00436                     i_var, arg, var_sparsity
00437                );
00438                break;
00439                // -------------------------------------------------
00440 
00441                case PriOp:
00442                CPPAD_ASSERT_NARG_NRES(op, 5, 0);
00443                break;
00444                // -------------------------------------------------
00445 
00446                case SignOp:
00447                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00448                // derivative is identically zero
00449                break;
00450                // -------------------------------------------------
00451 
00452                case SinOp:
00453                // cos(x), sin(x)
00454                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00455                reverse_sparse_jacobian_unary_op(
00456                     i_var, arg[0], var_sparsity
00457                );
00458                break;
00459                // -------------------------------------------------
00460 
00461                case SinhOp:
00462                // cosh(x), sinh(x)
00463                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00464                reverse_sparse_jacobian_unary_op(
00465                     i_var, arg[0], var_sparsity
00466                );
00467                break;
00468                // -------------------------------------------------
00469 
00470                case SqrtOp:
00471                CPPAD_ASSERT_NARG_NRES(op, 1, 1);
00472                reverse_sparse_jacobian_unary_op(
00473                     i_var, arg[0], var_sparsity
00474                );
00475                break;
00476                // -------------------------------------------------
00477 
00478                case StppOp:
00479                // sparsity cannot proagate through a parameter
00480                CPPAD_ASSERT_NARG_NRES(op, 3, 0);
00481                break;
00482                // -------------------------------------------------
00483 
00484                case StpvOp:
00485                reverse_sparse_jacobian_store_op(
00486                     op,
00487                     arg,
00488                     num_vecad_ind,
00489                     vecad_ind.data(),
00490                     var_sparsity,
00491                     vecad_sparsity
00492                );
00493                break;
00494                // -------------------------------------------------
00495 
00496                case StvpOp:
00497                CPPAD_ASSERT_NARG_NRES(op, 3, 0);
00498                break;
00499                // -------------------------------------------------
00500 
00501                case StvvOp:
00502                reverse_sparse_jacobian_store_op(
00503                     op,
00504                     arg,
00505                     num_vecad_ind,
00506                     vecad_ind.data(),
00507                     var_sparsity,
00508                     vecad_sparsity
00509                );
00510                break;
00511                // -------------------------------------------------
00512 
00513                case SubvvOp:
00514                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00515                reverse_sparse_jacobian_binary_op(
00516                     i_var, arg, var_sparsity
00517                );
00518                break;
00519                // -------------------------------------------------
00520 
00521                case SubpvOp:
00522                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00523                reverse_sparse_jacobian_unary_op(
00524                     i_var, arg[1], var_sparsity
00525                );
00526                break;
00527                // -------------------------------------------------
00528 
00529                case SubvpOp:
00530                CPPAD_ASSERT_NARG_NRES(op, 2, 1);
00531                reverse_sparse_jacobian_unary_op(
00532                     i_var, arg[0], var_sparsity
00533                );
00534                break;
00535                // -------------------------------------------------
00536 
00537                case TanOp:
00538                // tan(x)^2, tan(x)
00539                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00540                reverse_sparse_jacobian_unary_op(
00541                     i_var, arg[0], var_sparsity
00542                );
00543                break;
00544                // -------------------------------------------------
00545 
00546                case TanhOp:
00547                // tanh(x)^2, tanh(x)
00548                CPPAD_ASSERT_NARG_NRES(op, 1, 2);
00549                reverse_sparse_jacobian_unary_op(
00550                     i_var, arg[0], var_sparsity
00551                );
00552                break;
00553                // -------------------------------------------------
00554 
00555                case UserOp:
00556                // start or end atomic operation sequence
00557                CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 );
00558                CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 );
00559                if( user_state == user_end )
00560                {    user_index = arg[0];
00561                     user_id    = arg[1];
00562                     user_n     = arg[2];
00563                     user_m     = arg[3];
00564                     user_atom  = atomic_base<Base>::class_object(user_index);
00565 # ifndef NDEBUG
00566                     if( user_atom == CPPAD_NULL )
00567                     {    std::string msg = 
00568                               atomic_base<Base>::class_name(user_index)
00569                               + ": atomic_base function has been deleted";
00570                          CPPAD_ASSERT_KNOWN(false, msg.c_str() );
00571                     }
00572 # endif
00573                     user_bool  = user_atom->sparsity() ==
00574                                    atomic_base<Base>::bool_sparsity_enum;
00575                     if( user_bool )
00576                     {    if( bool_r.size() != user_m * user_q )
00577                               bool_r.resize( user_m * user_q );
00578                          if( bool_s.size() != user_n * user_q )
00579                               bool_s.resize( user_n * user_q );
00580                          for(i = 0; i < user_m; i++)
00581                               for(j = 0; j < user_q; j++)
00582                                    bool_r[ i * user_q + j] = false;
00583                     }
00584                     else
00585                     {    if(set_r.size() != user_m )
00586                               set_r.resize(user_m);
00587                          if(set_s.size() != user_n )
00588                               set_s.resize(user_n);
00589                          for(i = 0; i < user_m; i++)
00590                               set_r[i].clear();
00591                     }
00592                     user_j     = user_n;
00593                     user_i     = user_m;
00594                     user_state = user_ret;
00595                }
00596                else
00597                {    CPPAD_ASSERT_UNKNOWN( user_state == user_start );
00598                     CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) );
00599                     CPPAD_ASSERT_UNKNOWN( user_id    == size_t(arg[1]) );
00600                     CPPAD_ASSERT_UNKNOWN( user_n     == size_t(arg[2]) );
00601                     CPPAD_ASSERT_UNKNOWN( user_m     == size_t(arg[3]) );
00602 # ifndef NDEBUG
00603                     if( ! user_ok )
00604                     {    std::string msg = 
00605                               atomic_base<Base>::class_name(user_index)
00606                               + ": atomic_base.rev_sparse_jac: returned false";
00607                          CPPAD_ASSERT_KNOWN(false, msg.c_str() );
00608                     }
00609 # endif
00610                     user_state = user_end;
00611                }
00612                break;
00613 
00614                case UsrapOp:
00615                // parameter argument in an atomic operation sequence
00616                CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
00617                CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n );
00618                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
00619                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
00620                --user_j;
00621                if( user_j == 0 )
00622                     user_state = user_start;
00623                break;
00624 
00625                case UsravOp:
00626                // variable argument in an atomic operation sequence
00627                CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
00628                CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n );
00629                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
00630                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
00631                CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
00632                --user_j;
00633                // It might be faster if we add set union to var_sparsity
00634                // where one of the sets is not in var_sparsity.
00635                if( user_bool )
00636                {    for(j = 0; j < user_q; j++)
00637                          if( bool_s[ user_j * user_q + j ] )     
00638                               var_sparsity.add_element(arg[0], j);    
00639                }
00640                else
00641                {    set_itr = set_s[user_j].begin();
00642                     set_end = set_s[user_j].end();
00643                     while( set_itr != set_end )
00644                          var_sparsity.add_element(arg[0], *set_itr++);     
00645                }
00646                if( user_j == 0 )
00647                     user_state = user_start;
00648                break;
00649 
00650                case UsrrpOp:
00651                // parameter result in an atomic operation sequence
00652                CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
00653                CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m );
00654                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
00655                CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
00656                --user_i;
00657                if( user_i == 0 )
00658                {    // call users function for this operation
00659                     user_atom->set_id(user_id);
00660                     if( user_bool) 
00661                          CPPAD_ATOMIC_CALL(
00662                               user_q, bool_r, bool_s
00663                     );
00664                     else
00665                          CPPAD_ATOMIC_CALL(
00666                               user_q, set_r, set_s
00667                     );
00668                     user_state = user_arg;
00669                }
00670                break;
00671 
00672                case UsrrvOp:
00673                // variable result in an atomic operation sequence
00674                CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
00675                CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m );
00676                --user_i;
00677                var_sparsity.begin(i_var);
00678                i = var_sparsity.next_element();
00679                while( i < user_q )
00680                {    if( user_bool )
00681                          bool_r[ user_i * user_q + i ] = true;
00682                          else
00683                               set_r[user_i].insert(i);
00684                     i = var_sparsity.next_element();
00685                }
00686                if( user_i == 0 )
00687                {    // call users function for this operation
00688                     user_atom->set_id(user_id);
00689                     if( user_bool) 
00690                          CPPAD_ATOMIC_CALL(
00691                               user_q, bool_r, bool_s
00692                     );
00693                     else
00694                          CPPAD_ATOMIC_CALL(
00695                               user_q, set_r, set_s
00696                     );
00697                     user_state = user_arg;
00698                }
00699                break;
00700                // -------------------------------------------------
00701 
00702                default:
00703                CPPAD_ASSERT_UNKNOWN(0);
00704           }
00705 # if CPPAD_REV_JAC_SWEEP_TRACE
00706           for(j = 0; j < limit; j++)
00707                z_value[j] = false;
00708           var_sparsity.begin(i_var);
00709           j = var_sparsity.next_element();
00710           while( j < limit )
00711           {    z_value[j] = true;
00712                j          = var_sparsity.next_element();
00713           }
00714           printOp(
00715                std::cout, 
00716                play,
00717                i_op,
00718                i_var,
00719                op, 
00720                arg,
00721                0, 
00722                (CppAD::vector<bool> *) CPPAD_NULL,
00723                1, 
00724                &z_value
00725           );
00726 # endif
00727      }
00728      // values corresponding to BeginOp
00729      CPPAD_ASSERT_UNKNOWN( i_op == 0 );
00730      CPPAD_ASSERT_UNKNOWN( i_var == 0 );
00731 
00732      return;
00733 }
00734 } // END_CPPAD_NAMESPACE
00735 
00736 // preprocessor symbols that are local to this file
00737 # undef CPPAD_REV_JAC_SWEEP_TRACE
00738 # undef CPPAD_ATOMIC_CALL
00739 
00740 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines