bool ASTPrintVisitor::visit_augassign(AST_AugAssign* node) { node->target->accept(this); printOp(node->op_type); stream << '='; node->value->accept(this); return true; }
bool ASTPrintVisitor::visit_augbinop(AST_AugBinOp* node) { node->left->accept(this); stream << '='; printOp(node->op_type); node->right->accept(this); return true; }
void NodeUnaryOp::printPostfix(File * fp) { if(m_node) m_node->printPostfix(fp); else fp->write("<NULL>"); printOp(fp); //operators last } //printPostfix
void printTP(tape_point tp){ Base dummy[1000]; OpCode op=tp.op; const addr_t* arg=tp.op_arg; const Base* Z_tmp =dummy;//= Taylor + i_var * J; const Base* pZ_tmp =dummy;// Partial + i_var * K; printOp( std::cout, &play_, tp.op_index, tp.var_index, op, arg); std::cout << "\n"; }
void NodeControl::printPostfix(File * fp) { if(m_nodeCondition) m_nodeCondition->printPostfix(fp); else fp->write("<NULLCONDITION>"); fp->write(" cond"); if(m_nodeBody) m_nodeBody->printPostfix(fp); else fp->write("<NULLTRUE>"); printOp(fp); //operators last } //printPostfix
void forward2sweep( const size_t q, const size_t r, const size_t n, const size_t numvar, player<Base>* play, const size_t J, Base* taylor, const bool* cskip_op, const pod_vector<addr_t>& var_by_load_op ) { CPPAD_ASSERT_UNKNOWN( q > 0 ); CPPAD_ASSERT_UNKNOWN( J >= q + 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); // used to avoid compiler errors until all operators are implemented size_t p = q; // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // work space used by UserOp. vector<bool> user_vx; // empty vecotor vector<bool> user_vy; // empty vecotor vector<Base> user_tx_one; // argument vector Taylor coefficients vector<Base> user_tx_all; vector<Base> user_ty_one; // result vector Taylor coefficients vector<Base> user_ty_all; size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end, user_trace } user_state = user_start; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // temporary indices size_t i, j, k, ell; // number of orders for this user calculation // (not needed for order zero) const size_t user_q1 = q+1; // variable indices for results vector // (done differently for order zero). vector<size_t> user_iy; // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD2SWEEP_TRACE std::cout << std::endl; CppAD::vector<Base> Z_vec(q+1); # endif bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->forward_cskip(op, arg, i_op, i_var); // } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action depends on the operator switch( op ) { case AbsOp: forward_abs_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acosh_op_dir(q, r, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asinh_op_dir(q, r, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atanh_op_dir(q, r, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case CExpOp: forward_cond_op_dir( q, r, i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op_dir(q, r, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op_dir( q, r, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: // needed for sparse_jacobian test CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ExpOp: forward_exp_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: forward_expm1_op_dir(q, r, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: case LdvOp: forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // --------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_UNKNOWN(q > 0 ); break; // ------------------------------------------------- case LogOp: forward_log_op_dir(q, r, i_var, arg[0], J, taylor); break; // --------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: forward_log1p_op_dir(q, r, i_var, arg[0], J, taylor); break; # endif // --------------------------------------------------- case MulvvOp: forward_mulvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case ParOp: k = i_var*(J-1)*r + i_var + (q-1)*r + 1; for(ell = 0; ell < r; ell++) taylor[k + ell] = Base(0); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_UNKNOWN(q > 0); break; // ------------------------------------------------- case SignOp: // sign(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: case StpvOp: case StvpOp: case StvvOp: CPPAD_ASSERT_UNKNOWN(q > 0 ); break; // ------------------------------------------------- case SubvvOp: forward_subvv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op_dir(q, r, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op_dir(q, r, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx_one.size() != user_n * user_q1) user_tx_one.resize(user_n * user_q1); if( user_tx_all.size() != user_n * (q * r + 1) ) user_tx_all.resize(user_n * (q * r + 1)); // if(user_ty_one.size() != user_m * user_q1) user_ty_one.resize(user_m * user_q1); if( user_ty_all.size() != user_m * (q * r + 1) ) user_ty_all.resize(user_m * (q * r + 1)); // if(user_iy.size() != user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); for(ell = 0; ell < r; ell++) { // set user_tx for(j = 0; j < user_n; j++) { size_t j_all = j * (q * r + 1); size_t j_one = j * user_q1; user_tx_one[j_one+0] = user_tx_all[j_all+0]; for(k = 1; k < user_q1; k++) { size_t k_all = j_all + (k-1)*r+1+ell; size_t k_one = j_one + k; user_tx_one[k_one] = user_tx_all[k_all]; } } // set user_ty for(i = 0; i < user_m; i++) { size_t i_all = i * (q * r + 1); size_t i_one = i * user_q1; user_ty_one[i_one+0] = user_ty_all[i_all+0]; for(k = 1; k < q; k++) { size_t k_all = i_all + (k-1)*r+1+ell; size_t k_one = i_one + k; user_ty_one[k_one] = user_ty_all[k_all]; } } CPPAD_ATOMIC_CALL( q, q, user_vx, user_vy, user_tx_one, user_ty_one ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_m; i++) { if( user_iy[i] > 0 ) { size_t i_taylor = user_iy[i]*((J-1)*r+1); size_t q_taylor = i_taylor + (q-1)*r+1+ell; size_t q_one = i * user_q1 + q; taylor[q_taylor] = user_ty_one[q_one]; } } } # if CPPAD_FORWARD2SWEEP_TRACE user_state = user_trace; # else user_state = user_start; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx_all[user_j*(q*r+1) + 0] = parameter[ arg[0]]; for(ell = 0; ell < r; ell++) for(k = 1; k < user_q1; k++) user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); user_tx_all[user_j*(q*r+1)+0] = taylor[arg[0]*((J-1)*r+1)+0]; for(ell = 0; ell < r; ell++) { for(k = 1; k < user_q1; k++) { user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = taylor[arg[0]*((J-1)*r+1) + (k-1)*r+1+ell]; } } ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty_all[user_i*(q*r+1) + 0] = parameter[ arg[0]]; for(ell = 0; ell < r; ell++) for(k = 1; k < user_q1; k++) user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; user_ty_all[user_i*(q*r+1)+0] = taylor[i_var*((J-1)*r+1)+0]; for(ell = 0; ell < r; ell++) { for(k = 1; k < user_q1; k++) { user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = taylor[i_var*((J-1)*r+1) + (k-1)*r+1+ell]; } } user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD2SWEEP_TRACE if( user_state == user_trace ) { user_state = user_start; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; printOp( std::cout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i]*((J-1) * r + 1); { Z_vec[0] = Z_tmp[0]; for(ell = 0; ell < r; ell++) { std::cout << std::endl << " "; for(size_t p_tmp = 1; p_tmp <= q; p_tmp++) Z_vec[p_tmp] = Z_tmp[(p_tmp-1)*r+ell+1]; printOpResult( std::cout, q + 1, Z_vec.data(), 0, (Base *) CPPAD_NULL ); } } std::cout << std::endl; } } const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { printOp( std::cout, play, i_op, i_var, op, arg_tmp ); Base* Z_tmp = CPPAD_NULL; if( op == UsravOp ) Z_tmp = taylor + arg[0]*((J-1) * r + 1); else if( NumRes(op) > 0 ) Z_tmp = taylor + i_var*((J-1)*r + 1); if( Z_tmp != CPPAD_NULL ) { Z_vec[0] = Z_tmp[0]; for(ell = 0; ell < r; ell++) { std::cout << std::endl << " "; for(size_t p_tmp = 1; p_tmp <= q; p_tmp++) Z_vec[p_tmp] = Z_tmp[ (p_tmp-1)*r + ell + 1]; printOpResult( std::cout, q + 1, Z_vec.data(), 0, (Base *) CPPAD_NULL ); } } std::cout << std::endl; } } std::cout << std::endl; # else }
size_t forward_sweep( bool print, size_t d, size_t n, size_t numvar, player<Base> *Rec, size_t J, Base *Taylor ) { CPPAD_ASSERT_UNKNOWN( J >= d + 1 ); // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; # if CPPAD_USE_FORWARD0SWEEP CPPAD_ASSERT_UNKNOWN( d > 0 ); # else size_t* non_const_arg; # endif const size_t *arg = 0; size_t i; // initialize the comparision operator (ComOp) counter size_t compareCount = 0; // if this is an order zero calculation, initialize vector indices size_t *VectorInd = CPPAD_NULL; // address for each element bool *VectorVar = CPPAD_NULL; // is element a variable i = Rec->num_rec_vecad_ind(); if( i > 0 ) { VectorInd = CPPAD_TRACK_NEW_VEC(i, VectorInd); VectorVar = CPPAD_TRACK_NEW_VEC(i, VectorVar); while(i--) { VectorInd[i] = Rec->GetVecInd(i); VectorVar[i] = false; } } // check numvar argument CPPAD_ASSERT_UNKNOWN( Rec->num_rec_var() == numvar ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = Rec->num_rec_par(); // length of the text vector (used by CppAD assert macros) const size_t num_text = Rec->num_rec_text(); // pointer to the beginning of the parameter vector const Base* parameter = 0; if( num_par > 0 ) parameter = Rec->GetPar(); // pointer to the beginning of the text vector const char* text = 0; if( num_text > 0 ) text = Rec->GetTxt(0); // skip the BeginOp at the beginning of the recording Rec->start_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD_SWEEP_TRACE std::cout << std::endl; # endif while(op != EndOp) { // this op Rec->next_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); // action depends on the operator switch( op ) { case AbsOp: forward_abs_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); forward_addpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AcosOp: // variables: sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AsinOp: // results: sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AtanOp: // results: 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_forward thinks it one has one argument. // we must inform next_forward of this special case. Rec->forward_csum(op, arg, i_op, i_var); forward_csum_op( d, i_var, arg, num_par, parameter, J, Taylor ); break; // ------------------------------------------------- case CExpOp: forward_cond_op( d, i_var, arg, num_par, parameter, J, Taylor ); break; // --------------------------------------------------- case ComOp: # if ! USE_FORWARD0SWEEP if( d == 0 ) forward_comp_op_0( compareCount, arg, num_par, parameter, J, Taylor ); # endif break; // --------------------------------------------------- case CosOp: // variables: sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op(d, i_var, arg[0], J, Taylor); break; // --------------------------------------------------- case CoshOp: // variables: sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case DisOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) forward_dis_op_0(i_var, arg, J, Taylor); else # endif { Taylor[ i_var * J + d] = Base(0); } break; // ------------------------------------------------- case DivvvOp: forward_divvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); forward_divpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( arg[1] < num_par ); forward_divvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); break; // ------------------------------------------------- case ExpOp: forward_exp_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); break; // ------------------------------------------------- case LdpOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_p_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } else # endif { forward_load_op( op, d, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LdvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_v_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } else # endif { forward_load_op( op, d, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LogOp: forward_log_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); forward_mulpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case ParOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) forward_par_op_0( i_var, arg, num_par, parameter, J, Taylor ); else # endif { Taylor[ i_var * J + d] = Base(0); } break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( arg[1] < num_par ); forward_powvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); forward_powpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PripOp: # if ! CPPAD_USE_FORWARD0SWEEP if( print && ( d == 0 ) ) forward_prip_0( arg, num_text, text, num_par, parameter ); # endif break; // ------------------------------------------------- case PrivOp: # if ! CPPAD_USE_FORWARD0SWEEP if( print && ( d == 0 ) ) forward_priv_0( i_var, arg, num_text, text, J, Taylor ); # endif break; // ------------------------------------------------- case SinOp: // variables: cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SinhOp: // variables: cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case StppOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_pp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } # endif break; // ------------------------------------------------- case StpvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_pv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } # endif break; // ------------------------------------------------- case StvpOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_vp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } # endif break; // ------------------------------------------------- case StvvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_vv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar, VectorInd ); } # endif break; // ------------------------------------------------- case SubvvOp: forward_subvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); forward_subpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( arg[1] < num_par ); forward_subvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD_SWEEP_TRACE size_t i_tmp = i_var; Base* Z_tmp = Taylor + J * i_var; printOp( std::cout, Rec, i_tmp, op, arg, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); } std::cout << std::endl; # else }
int main() { int f1,f2,s1,s2,lf1,lf2,ls1,ls2,os,of,N,l1,l2; char ch; scanf("%d\n",&N); while(N--) { f1=f2=s1=s2=lf1=lf2=ls1=ls2=os=of=l1=l2=0; // printf("\nf1=%d,f2=%d,s1=%d,s2=%d,lf1=%d,lf2=%d,ls1=%d,ls2=%d,os=%d,of=%d\n ",f1,f2,s1,s2,lf1,lf2,ls1,ls2,os,of); while((ch=fgetc(stdin))!=10) { if(ch<'4') { lf1++; } else if(ch<'7'&&ch>'4') { ls1++; } if(ch=='7') { s1++; } else if(ch=='4') { f1++; } l1++; } l2=l1; while((ch=fgetc(stdin))!=10) { if(ch<'4') { lf2++; } else if(ch<'7'&&ch>'4') { ls2++; } if(ch=='7') { s2++; } else if(ch=='4') { f2++; } } #ifdef debug printf("\nf1=%d,f2=%d,s1=%d,s2=%d,lf1=%d,lf2=%d,ls1=%d,ls2=%d,os=%d,of=%d\n ",f1,f2,s1,s2,lf1,lf2,ls1,ls2,os,of); #endif //update the characteristics to reflect that a character has been //taken //7 taken while(s1&&ls2&&l2&&l1) { s1--; ls2--; os++; l2--; l1--; } while(s1&&lf2&&l2&&l1) { s1--; lf2--; os++; l2--; l1--; } while(s2&&ls1&&l2&&l1) { s2--; ls1--; os++; l1--; l2--; } #ifdef debug printf("\nf1=%d,f2=%d,s1=%d,s2=%d,lf1=%d,lf2=%d,ls1=%d,ls2=%d,os=%d,of=%d\n ",f1,f2,s1,s2,lf1,lf2,ls1,ls2,os,of); #endif while(s2&&lf1&&l2&&l1) { s2--; lf1--; os++; l1--; l2--; } while(f1&&lf2&&l2&&l1) { f1--; lf2--; of++; l2--; l1--; } while(f2&&lf1&&l2&&l1) { f2--; lf1--; of++; l1--; l2--; } //now adjust the 7s and 4s //take 7s of 1 with 4s of 2 while(l1&&s1&&f2&&l2) { l1--; os++; s1--; f2--; l2--; } //take 7s of 2 with 4s of 1 while(l2&&s2&&f1&&l1) { l1--; os++; s2--; f1--; l2--; } //take 7s of 1 with 7s of 2 while(l1&&l2&&s1&&s2) { l1--; l2--; s1--; s2--; os++; } //take 4s of 1 with 4s of 2 while(l1&&f1&&f2&&l2) { of++; f1--; f2--; l2--; l1--; } //printf("\n%d os=%d of=%d",N,os,of); printOp(os,of); } return 0; }
void ForHesSweep( size_t n, size_t numvar, player<Base> *play, Vector_set& for_jac_sparse, // should be const Vector_set& rev_jac_sparse, // should be const Vector_set& for_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument size_t limit = n+1; CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.n_set() == limit ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == limit ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; pod_vector<bool> vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // work space used by UserOp. vector<size_t> user_ix; // variable indices for argument vector x vector<Base> user_x; // parameters in x as integers // // typedef std::set<size_t> size_set; vector< size_set > set_h; // forward Hessian sparsity vector<bool> bool_h; // forward Hessian sparsity vectorBool pack_h; // forward Hessian sparstiy // vector<bool> user_vx; // which components of x are variables vector<bool> user_r; // forward Jacobian sparsity for x vector<bool> user_s; // reverse Jacobian sparsity for y // size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_pack = false; // sparsity pattern type is pack bool user_bool = false; // sparsity pattern type is bool bool user_set = false; // sparsity pattern type is set bool user_ok = false; // atomic op return value // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_start; // // pointer to the beginning of the parameter vector // (used by user atomic functions) const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // Initialize play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); bool more_operators = true; # if CPPAD_FOR_HES_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit * limit); # endif while(more_operators) { // next op play->forward_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // does the Hessian in question have a non-zero derivative // with respect to this variable bool include = rev_jac_sparse.is_element(i_var, 0); // // operators to include even if derivative is zero include |= op == EndOp; include |= op == CSkipOp; include |= op == UserOp; include |= op == UsrapOp; include |= op == UsravOp; include |= op == UsrrpOp; include |= op == UsrrvOp; // if( include ) switch( op ) { // operators that should not occurr // case BeginOp // ------------------------------------------------- // operators that do not affect hessian case AbsOp: case AddvvOp: case AddpvOp: case CExpOp: case DisOp: case DivvpOp: case InvOp: case LdpOp: case LdvOp: case MulpvOp: case ParOp: case PriOp: case SignOp: case StppOp: case StpvOp: case StvpOp: case StvvOp: case SubvvOp: case SubpvOp: case SubvpOp: case ZmulpvOp: case ZmulvpOp: break; // ------------------------------------------------- // nonlinear unary operators case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ExpOp: case LogOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: case AsinhOp: case AtanhOp: case Expm1Op: case Log1pOp: # endif CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ) forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_div_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_nonlinear_unary_op( arg[1], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[2] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- // ------------------------------------------------- // logical comparision operators case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( arg[1], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_pow_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_x.resize( user_n ); // user_pack = user_atom->sparsity() == atomic_base<Base>::pack_sparsity_enum; user_bool = user_atom->sparsity() == atomic_base<Base>::bool_sparsity_enum; user_set = user_atom->sparsity() == atomic_base<Base>::set_sparsity_enum; CPPAD_ASSERT_UNKNOWN( user_pack || user_bool || user_set ); user_ix.resize(user_n); user_vx.resize(user_n); user_r.resize(user_n); user_s.resize(user_m); // simpler to initialize sparsity patterns as empty for(i = 0; i < user_m; i++) user_s[i] = false; for(i = 0; i < user_n; i++) user_r[i] = false; if( user_pack ) { pack_h.resize(user_n * user_n); for(i = 0; i < user_n; i++) { for(j = 0; j < user_n; j++) pack_h[ i * user_n + j] = false; } } if( user_bool ) { bool_h.resize(user_n * user_n); for(i = 0; i < user_n; i++) { for(j = 0; j < user_n; j++) bool_h[ i * user_n + j] = false; } } if( user_set ) { set_h.resize(user_n); for(i = 0; i < user_n; i++) set_h[i].clear(); } user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); if( user_pack ) { user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, pack_h, user_x ); if( ! user_ok ) user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, pack_h ); } if( user_bool ) { user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, bool_h, user_x ); if( ! user_ok ) user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, bool_h ); } if( user_set ) { user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, set_h, user_x ); if( ! user_ok ) user_ok = user_atom->for_sparse_hes( user_vx, user_r, user_s, set_h ); } if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.for_sparse_hes: returned false\n"; if( user_pack ) msg += "sparsity = pack_sparsity_enum"; if( user_bool ) msg += "sparsity = bool_sparsity_enum"; if( user_set ) msg += "sparsity = set_sparsity_enum"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } for(i = 0; i < user_n; i++) for(j = 0; j < user_n; j++) { if( user_ix[i] > 0 && user_ix[j] > 0 ) { bool flag = false; if( user_pack ) flag = pack_h[i * user_n + j]; if( user_bool ) flag = bool_h[i * user_n + j]; if( user_set ) flag = set_h[i].find(j) != set_h[i].end(); if( flag ) { size_t i_x = user_ix[i]; size_t j_x = user_ix[j]; for_hes_sparse.binary_union( i_x, i_x, j_x, for_jac_sparse ); for_hes_sparse.binary_union( j_x, j_x, i_x, for_jac_sparse ); } } } // user_state = user_start; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_ix[user_j] = 0; user_vx[user_j] = false; // // parameters as integers user_x[user_j] = parameter[arg[0]]; // ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); user_ix[user_j] = arg[0]; user_vx[user_j] = true; // variables as integers user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN(); // for_jac_sparse.begin(arg[0]); i = for_jac_sparse.next_element(); if( i < for_jac_sparse.end() ) user_r[user_j] = true; ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); ++user_i; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); if( rev_jac_sparse.is_element(i_var, 0) ) user_s[user_i] = true; ++user_i; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FOR_HES_SWEEP_TRACE if( include ) { for(i = 0; i < limit; i++) { zf_value[i] = false; for(j = 0; j < limit; j++) zh_value[i * limit + j] = false; } for_jac_sparse.begin(i_var);; j = for_jac_sparse.next_element();; while( j < limit ) { zf_value[j] = true; j = for_jac_sparse.next_element(); } for(i = 0; i < limit; i++) { for_hes_sparse.begin(i);; j = for_hes_sparse.next_element();; while( j < limit ) { zh_value[i * limit + j] = true; j = for_hes_sparse.next_element(); } } printOp( std::cout, play, i_op, i_var, op, arg ); // should also print RevJac[i_var], but printOpResult does not // yet allow for this if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, 1, &zf_value, 1, &zh_value ); std::cout << std::endl; } } std::cout << std::endl; # else }
void RevHesSweep( size_t n, size_t numvar, player<Base> *play, Vector_set& for_jac_sparse, // should be const bool* RevJac, Vector_set& rev_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const size_t *arg = 0; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_rec_par(); size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_rec_var() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements size_t limit = rev_hes_sparse.end(); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.end() == limit ); // check number of sets match CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == rev_hes_sparse.n_set() ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_rec_vecad_ind(); size_t num_vecad_vec = play->num_rec_vecad_vec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); size_t* vecad_ind = CPPAD_NULL; bool* vecad_jac = CPPAD_NULL; if( num_vecad_vec > 0 ) { size_t length; vecad_ind = CPPAD_TRACK_NEW_VEC(num_vecad_ind, vecad_ind); vecad_jac = CPPAD_TRACK_NEW_VEC(num_vecad_vec, vecad_jac); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_rec_vecad_ind() ); } // Initialize play->start_reverse(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_HES_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit); # endif while(op != BeginOp) { // next op play->next_reverse(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AcosOp: // acos(x) and sqrt(1 - x * x) are computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AsinOp: // asin(x) and sqrt(1 - x * x) are computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AtanOp: // atan(x) and 1 + x * x must be computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_reverse thinks it one has one argument. // We must inform next_reverse of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_hessian_csum_op( i_var, arg, RevJac, rev_hes_sparse ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_hessian_cond_op( i_var, arg, num_par, RevJac, rev_hes_sparse ); break; // --------------------------------------------------- case ComOp: CPPAD_ASSERT_NARG_NRES(op, 4, 0) CPPAD_ASSERT_UNKNOWN( arg[1] > 1 ); break; // -------------------------------------------------- case CosOp: // cosine and sine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // --------------------------------------------------- case CoshOp: // hyperbolic cosine and sine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_div_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) // Z is already defined break; // ------------------------------------------------- case LdpOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_pow_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PripOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case PrivOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case SinOp: // sine and cosine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SinhOp: // sine and cosine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case StppOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StpvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case StvpOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StvvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_HES_SWEEP_TRACE for(j = 0; j < limit; j++) { zf_value[j] = false; zh_value[j] = false; } for_jac_sparse.begin(i_var);; j = for_jac_sparse.next_element();; while( j < limit ) { zf_value[j] = true; j = for_jac_sparse.next_element(); } rev_hes_sparse.begin(i_var);; j = rev_hes_sparse.next_element();; while( j < limit ) { zh_value[j] = true; j = rev_hes_sparse.next_element(); } // should also print RevJac[i_var], but printOp does not // yet allow for this. printOp( std::cout, play, i_var, op, arg, 1, &zf_value, 1, &zh_value ); # endif } // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); if( vecad_jac != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(vecad_jac); if( vecad_ind != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(vecad_ind); return; }
void forward1sweep( std::ostream& s_out, const bool print, const size_t p, const size_t q, const size_t n, const size_t numvar, player<Base>* play, const size_t J, Base* taylor, bool* cskip_op, pod_vector<addr_t>& var_by_load_op, size_t compare_change_count, size_t& compare_change_number, size_t& compare_change_op_index ) { // number of directions const size_t r = 1; CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( J >= q + 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); /* <!-- replace forward0sweep_code_define --> */ // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // initialize the comparision operator counter if( p == 0 ) { compare_change_number = 0; compare_change_op_index = 0; } // If this includes a zero calculation, initialize this information pod_vector<bool> isvar_by_ind; pod_vector<size_t> index_by_ind; if( p == 0 ) { size_t i; // this includes order zero calculation, initialize vector indices size_t num = play->num_vec_ind_rec(); if( num > 0 ) { isvar_by_ind.extend(num); index_by_ind.extend(num); for(i = 0; i < num; i++) { index_by_ind[i] = play->GetVecInd(i); isvar_by_ind[i] = false; } } // includes zero order, so initialize conditional skip flags num = play->num_op_rec(); for(i = 0; i < num; i++) cskip_op[i] = false; } // work space used by UserOp. vector<bool> user_vx; // empty vecotor vector<bool> user_vy; // empty vecotor vector<Base> user_tx; // argument vector Taylor coefficients vector<Base> user_ty; // result vector Taylor coefficients size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end, user_trace } user_state = user_start; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // length of the text vector (used by CppAD assert macros) const size_t num_text = play->num_text_rec(); // pointer to the beginning of the text vector const char* text = CPPAD_NULL; if( num_text > 0 ) text = play->GetTxt(0); /* <!-- end forward0sweep_code_define --> */ // temporary indices size_t i, k; // number of orders for this user calculation // (not needed for order zero) const size_t user_q1 = q+1; // variable indices for results vector // (done differently for order zero). vector<size_t> user_iy; // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD1SWEEP_TRACE std::cout << std::endl; # endif bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->forward_cskip(op, arg, i_op, i_var); // } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action depends on the operator switch( op ) { case AbsOp: forward_abs_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acosh_op(p, q, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asinh_op(p, q, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atanh_op(p, q, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case CExpOp: forward_cond_op( p, q, i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op(p, q, i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. if( p == 0 ) { forward_cskip_op_0( i_var, arg, num_par, parameter, J, taylor, cskip_op ); } play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op( p, q, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case EqpvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_eqpv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case EqvvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_eqvv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case ErfOp: CPPAD_ASSERT_UNKNOWN( CPPAD_USE_CPLUSPLUS_2011 ); // 2DO: implement zero order version of this function forward_erf_op(p, q, i_var, arg, parameter, J, taylor); break; # endif // ------------------------------------------------- case ExpOp: forward_exp_op(p, q, i_var, arg[0], J, taylor); break; // --------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: forward_expm1_op(p, q, i_var, arg[0], J, taylor); break; # endif // --------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: if( p == 0 ) { forward_load_p_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); if( p < q ) forward_load_op( play, op, p+1, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); } else forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // ------------------------------------------------- case LdvOp: if( p == 0 ) { forward_load_v_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); if( p < q ) forward_load_op( play, op, p+1, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); } else forward_load_op( play, op, p, q, r, J, i_var, arg, var_by_load_op.data(), taylor ); break; // ------------------------------------------------- case LepvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_lepv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; case LevpOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_levp_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LevvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_levv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LogOp: forward_log_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: forward_log1p_op(p, q, i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case LtpvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltpv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; case LtvpOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltvp_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case LtvvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_ltvv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case NepvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_nepv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case NevvOp: if( ( p == 0 ) & ( compare_change_count > 0 ) ) { forward_nevv_op_0( compare_change_number, arg, parameter, J, taylor ); if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } break; // ------------------------------------------------- case ParOp: i = p; if( i == 0 ) { forward_par_op_0( i_var, arg, num_par, parameter, J, taylor ); i++; } while(i <= q) { taylor[ i_var * J + i] = Base(0); i++; } break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: if( (p == 0) & print ) forward_pri_0(s_out, arg, num_text, text, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case SignOp: // sign(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: if( p == 0 ) { forward_store_pp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StpvOp: if( p == 0 ) { forward_store_pv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StvpOp: if( p == 0 ) { forward_store_vp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case StvvOp: if( p == 0 ) { forward_store_vv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); } break; // ------------------------------------------------- case SubvvOp: forward_subvv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op(p, q, i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op(p, q, i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx.size() != user_n * user_q1) user_tx.resize(user_n * user_q1); if(user_ty.size() != user_m * user_q1) user_ty.resize(user_m * user_q1); if(user_iy.size() != user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( p, q, user_vx, user_vy, user_tx, user_ty ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) for(k = p; k <= q; k++) taylor[ user_iy[i] * J + k ] = user_ty[ i * user_q1 + k ]; # if CPPAD_FORWARD1SWEEP_TRACE user_state = user_trace; # else user_state = user_start; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx[user_j * user_q1 + 0] = parameter[ arg[0]]; for(k = 1; k < user_q1; k++) user_tx[user_j * user_q1 + k] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); for(k = 0; k < user_q1; k++) user_tx[user_j * user_q1 + k] = taylor[ arg[0] * J + k]; ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty[user_i * user_q1 + 0] = parameter[ arg[0]]; for(k = 1; k < p; k++) user_ty[user_i * user_q1 + k] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; for(k = 0; k < p; k++) user_ty[user_i * user_q1 + k] = taylor[ i_var * J + k]; user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD1SWEEP_TRACE if( user_state == user_trace ) { user_state = user_start; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; printOp( std::cout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i] * J; printOpResult( std::cout, q + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); std::cout << std::endl; } } Base* Z_tmp = taylor + J * i_var; const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { printOp( std::cout, play, i_op, i_var, op, arg_tmp ); if( NumRes(op) > 0 ) printOpResult( std::cout, q + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); std::cout << std::endl; } } std::cout << std::endl; # else }
void ReverseSweep( size_t d, size_t n, size_t numvar, player<Base>* play, size_t J, const Base* Taylor, size_t K, Base* Partial, bool* cskip_op, const pod_vector<addr_t>& var_by_load_op ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // work space used by UserOp. const size_t user_k = d; // highest order we are differentiating const size_t user_k1 = d+1; // number of orders for this calculation vector<size_t> user_ix; // variable indices for argument vector vector<Base> user_tx; // argument vector Taylor coefficients vector<Base> user_ty; // result vector Taylor coefficients vector<Base> user_px; // partials w.r.t argument vector vector<Base> user_py; // partials w.r.t. result vector size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // temporary indices size_t j, ell; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REVERSE_SWEEP_TRACE std::cout << std::endl; # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN((i_op > n) | (op == InvOp) | (op == BeginOp)); CPPAD_ASSERT_UNKNOWN((i_op <= n) | (op != InvOp) | (op != BeginOp)); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments play->reverse_csum(op, arg, i_op, i_var); } CPPAD_ASSERT_UNKNOWN( op != CSkipOp ); // if( op == CSkipOp ) // { // CSkip has a variable number of arguments // play->reverse_cskip(op, arg, i_op, i_var); // } CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); play->reverse_next(op, arg, i_op, i_var); } // rest of informaiton depends on the case # if CPPAD_REVERSE_SWEEP_TRACE if( op == CSumOp ) { // CSumOp has a variable number of arguments play->reverse_csum(op, arg, i_op, i_var); } if( op == CSkipOp ) { // CSkip has a variable number of arguments play->reverse_cskip(op, arg, i_op, i_var); } size_t i_tmp = i_var; const Base* Z_tmp = Taylor + i_var * J; const Base* pZ_tmp = Partial + i_var * K; printOp( std::cout, play, i_op, i_tmp, op, arg ); if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, d + 1, Z_tmp, d + 1, pZ_tmp ); std::cout << std::endl; # endif switch( op ) { case AbsOp: reverse_abs_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_acos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddvvOp: reverse_addvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_addpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_asin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_atan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); more_operators = false; break; // -------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it one has one argument. // we must inform reverse_next of this special case. # if ! CPPAD_REVERSE_SWEEP_TRACE play->reverse_cskip(op, arg, i_op, i_var); # endif break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. # if ! CPPAD_REVERSE_SWEEP_TRACE play->reverse_csum(op, arg, i_op, i_var); # endif reverse_csum_op( d, i_var, arg, K, Partial ); // end of a cummulative summation break; // ------------------------------------------------- case CExpOp: reverse_cond_op( d, i_var, arg, num_par, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case CosOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cos_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case CoshOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_cosh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case DisOp: // Derivative of discrete operation is zero so no // contribution passes through this operation. break; // -------------------------------------------------- case DivvvOp: reverse_divvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_divpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_divvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- # if CPPAD_COMPILER_HAS_ERF case ErfOp: reverse_erf_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; # endif // -------------------------------------------------- case ExpOp: reverse_exp_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case InvOp: break; // -------------------------------------------------- case LdpOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // ------------------------------------------------- case LdvOp: reverse_load_op( op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data() ); break; // -------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: break; // ------------------------------------------------- case LogOp: reverse_log_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulvvOp: reverse_mulvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_mulpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case ParOp: break; // -------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_powvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_powpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case PowvvOp: reverse_powvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case PriOp: // no result so nothing to do break; // -------------------------------------------------- case SignOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sign_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sin_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case SinhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_sinh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case SqrtOp: reverse_sqrt_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case StppOp: break; // -------------------------------------------------- case StpvOp: break; // ------------------------------------------------- case StvpOp: break; // ------------------------------------------------- case StvvOp: break; // -------------------------------------------------- case SubvvOp: reverse_subvv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); reverse_subpv_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // -------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); reverse_subvp_op( d, i_var, arg, parameter, J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tan_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // ------------------------------------------------- case TanhOp: CPPAD_ASSERT_UNKNOWN( i_var < numvar ); reverse_tanh_op( d, i_var, arg[0], J, Taylor, K, Partial ); break; // -------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_ix.size() != user_n) user_ix.resize(user_n); if(user_tx.size() != user_n * user_k1) { user_tx.resize(user_n * user_k1); user_px.resize(user_n * user_k1); } if(user_ty.size() != user_m * user_k1) { user_ty.resize(user_m * user_k1); user_py.resize(user_m * user_k1); } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( user_k, user_tx, user_ty, user_px, user_py ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.reverse: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(j = 0; j < user_n; j++) if( user_ix[j] > 0 ) { for(ell = 0; ell < user_k1; ell++) Partial[user_ix[j] * K + ell] += user_px[j * user_k1 + ell]; } user_state = user_end; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; user_ix[user_j] = 0; user_tx[user_j * user_k1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_k1; ell++) user_tx[user_j * user_k1 + ell] = Base(0.); if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; user_ix[user_j] = arg[0]; for(ell = 0; ell < user_k1; ell++) user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell]; if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Base(0.); user_ty[user_i * user_k1 + ell] = Base(0.); } user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ]; if( user_i == 0 ) user_state = user_arg; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; for(ell = 0; ell < user_k1; ell++) { user_py[user_i * user_k1 + ell] = Partial[i_var * K + ell]; user_ty[user_i * user_k1 + ell] = Taylor[i_var * J + ell]; } if( user_i == 0 ) user_state = user_arg; break; // ------------------------------------------------------------ default: CPPAD_ASSERT_UNKNOWN(false); } } # if CPPAD_REVERSE_SWEEP_TRACE std::cout << std::endl; # endif // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); }
bool ASTPrintVisitor::visit_binop(AST_BinOp* node) { node->left->accept(this); printOp(node->op_type); node->right->accept(this); return true; }
//print code in file void printCode(char* fname) { FILE *fp=fopen(fname,"w"); if(fp==NULL) { printf("open file error\n"); return; } InterCode c=code_h; while(c!=NULL) { switch(c->kind) { case ASSIGN_K: printOp(c->u.assign.left,fp); fputs(":= ",fp); printOp(c->u.assign.right,fp); break; case ADD_K: printOp(c->u.binop.result,fp); fputs(":= ",fp); printOp(c->u.binop.op1,fp); fputs("+ ",fp); printOp(c->u.binop.op2,fp); break; case SUB_K: printOp(c->u.binop.result,fp); fputs(":= ",fp); printOp(c->u.binop.op1,fp); fputs("- ",fp); printOp(c->u.binop.op2,fp); break; case MUL_K: printOp(c->u.binop.result,fp); fputs(":= ",fp); printOp(c->u.binop.op1,fp); fputs("* ",fp); printOp(c->u.binop.op2,fp); break; case DIV_K: printOp(c->u.binop.result,fp); fputs(":= ",fp); printOp(c->u.binop.op1,fp); fputs("/ ",fp); printOp(c->u.binop.op2,fp); break; case RETURN_K: fputs("RETURN ",fp); printOp(c->u.one.op,fp); break; case LABEL_K: fputs("LABEL ",fp); printOp(c->u.one.op,fp); fputs(": ",fp); break; case GOTO_K: fputs("GOTO ",fp); printOp(c->u.one.op,fp); break; case IFGOTO_K: fputs("IF ",fp); printOp(c->u.triop.t1,fp); fputs(c->u.triop.op,fp); fputs(" ",fp); printOp(c->u.triop.t2,fp); fputs("GOTO ",fp); printOp(c->u.triop.label,fp); break; case READ_K: fputs("READ ",fp); printOp(c->u.one.op,fp); break; case WRITE_K: fputs("WRITE ",fp); printOp(c->u.one.op,fp); break; case CALL_K: printOp(c->u.assign.left,fp); fputs(":= CALL ",fp); printOp(c->u.assign.right,fp); break; case ARG_K: fputs("ARG ",fp); printOp(c->u.one.op,fp); break; case FUNCTION_K: fputs("FUNCTION ",fp); printOp(c->u.one.op,fp); fputs(":",fp); break; case PARAM_K: fputs("PARAM ",fp); printOp(c->u.one.op,fp); break; case RIGHTAT_K: printOp(c->u.assign.left,fp); fputs(":= &",fp); printOp(c->u.assign.right,fp); break; case DEC_K: fputs("DEC ",fp); printOp(c->u.dec.op,fp); char size[32]; sprintf(size,"%d",c->u.dec.size); fputs(size,fp); break; } fputs("\n",fp); c=c->next; } fclose(fp); }
void RevHesSweep( size_t n, size_t numvar, local::player<Base>* play, const Vector_set& for_jac_sparse, bool* RevJac, Vector_set& rev_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements size_t limit = rev_hes_sparse.end(); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); // check number of sets match CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == rev_hes_sparse.n_set() ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; pod_vector<bool> vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // ---------------------------------------------------------------------- // user's atomic op calculator atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator // // work space used by UserOp. vector<Base> user_x; // parameters in x as integers vector<size_t> user_ix; // variable indices for argument vector vector<size_t> user_iy; // variable indices for result vector // // information set by forward_user (initialization to avoid warnings) size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0; // information set by forward_user (necessary initialization) enum_user_state user_state = end_user; // proper initialization // ---------------------------------------------------------------------- // // pointer to the beginning of the parameter vector // (used by atomic functions const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_HES_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit); # endif bool more_operators = true; while(more_operators) { bool flag; // temporary for use in switch cases // // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_hessian_csum_op( i_var, arg, RevJac, rev_hes_sparse ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_hessian_cond_op( i_var, arg, num_par, RevJac, rev_hes_sparse ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) // derivativve is identically zero break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_div_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[2] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) // Z is already defined break; // ------------------------------------------------- case LdpOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_pow_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // Derivative is identiaclly zero break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case StppOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StpvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case StvpOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StvvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case UserOp: CPPAD_ASSERT_UNKNOWN( user_state == start_user || user_state == end_user ); flag = user_state == end_user; user_atom = play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( flag ) { user_x.resize(user_n); user_ix.resize(user_n); user_iy.resize(user_m); } else { // call users function for this operation user_atom->set_old(user_old); user_atom->rev_sparse_hes( user_x, user_ix, user_iy, for_jac_sparse, RevJac, rev_hes_sparse ); } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // argument parameter value user_x[user_j] = parameter[arg[0]]; // special variable index used for parameters user_ix[user_j] = 0; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // argument variables not available during sparsity calculations user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN(); // variable index for this argument user_ix[user_j] = arg[0]; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // special variable index used for parameters user_iy[user_i] = 0; break; case UsrrvOp: // variable result in an atomic operation sequence play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // variable index for this result user_iy[user_i] = i_var; break; // ------------------------------------------------- case ZmulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ZmulvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_HES_SWEEP_TRACE for(j = 0; j < limit; j++) { zf_value[j] = false; zh_value[j] = false; } typename Vector_set::const_iterator itr_jac(for_jac_sparse, i_var); j = *itr_jac; while( j < limit ) { zf_value[j] = true; j = *(++itr_jac); } typename Vector_set::const_iterator itr_hes(rev_hes_sparse, i_var); j = *itr_hes; while( j < limit ) { zh_value[j] = true; j = *(++itr_hes); } printOp( std::cout, play, i_op, i_var, op, arg ); // should also print RevJac[i_var], but printOpResult does not // yet allow for this if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, 1, &zf_value, 1, &zh_value ); std::cout << std::endl; } std::cout << std::endl; # else }
void RevHesSweep( size_t n, size_t numvar, player<Base> *play, Vector_set& for_jac_sparse, // should be const bool* RevJac, Vector_set& rev_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements size_t limit = rev_hes_sparse.end(); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); // check number of sets match CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == rev_hes_sparse.n_set() ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; pod_vector<bool> vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // work space used by UserOp. vector<size_t> user_ix; // variable indices for argument vector x typedef std::set<size_t> size_set; size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > set_r; // forward Jacobian sparsity for x vector< size_set > set_u; // reverse Hessian sparsity for y vector< size_set > set_v; // reverse Hessian sparsity for x // vector<bool> bool_r; // bool forward Jacobian sparsity for x vector<bool> bool_u; // bool reverse Hessian sparsity for y vector<bool> bool_v; // bool reverse Hessian sparsity for x // vectorBool pack_r; // pack forward Jacobian sparsity for x vectorBool pack_u; // pack reverse Hessian sparsity for y vectorBool pack_v; // pack reverse Hessian sparsity for x // vector<bool> user_vx; // which components of x are variables vector<bool> user_s; // reverse Jacobian sparsity for y vector<bool> user_t; // reverse Jacobian sparsity for x const size_t user_q = limit; // maximum element plus one size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_pack = false; // sparsity pattern type is pack bool user_bool = false; // sparsity pattern type is bool bool user_set = false; // sparsity pattern type is set # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_HES_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit); # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_hessian_csum_op( i_var, arg, RevJac, rev_hes_sparse ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_hessian_cond_op( i_var, arg, num_par, RevJac, rev_hes_sparse ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) // derivativve is identically zero break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_div_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[2] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) // Z is already defined break; // ------------------------------------------------- case LdpOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; # endif // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_pow_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // Derivative is identiaclly zero break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case StppOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StpvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case StvpOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StvvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), rev_hes_sparse, vecad_sparse, RevJac, vecad_jac.data() ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_pack = user_atom->sparsity() == atomic_base<Base>::pack_sparsity_enum; user_bool = user_atom->sparsity() == atomic_base<Base>::bool_sparsity_enum; user_set = user_atom->sparsity() == atomic_base<Base>::set_sparsity_enum; CPPAD_ASSERT_UNKNOWN( user_pack || user_bool || user_set ); user_ix.resize(user_n); user_vx.resize(user_n); user_s.resize(user_m); user_t.resize(user_n); // simpler to initialize all sparsity patterns as empty for(i = 0; i < user_m; i++) user_s[i] = false; for(i = 0; i < user_n; i++) user_t[i] = false; if( user_pack ) { pack_r.resize(user_n * user_q); pack_u.resize(user_m * user_q); pack_v.resize(user_n * user_q); // simpler to initialize all patterns as empty for(i = 0; i < user_m; i++) { for(j = 0; j < user_q; j++) pack_u[ i * user_q + j] = false; } for(i = 0; i < user_n; i++) { for(j = 0; j < user_q; j++) { pack_r[ i * user_q + j] = false; pack_v[ i * user_q + j] = false; } } } if( user_bool ) { bool_r.resize(user_n * user_q); bool_u.resize(user_m * user_q); bool_v.resize(user_n * user_q); // simpler to initialize all patterns as empty for(i = 0; i < user_m; i++) { for(j = 0; j < user_q; j++) bool_u[ i * user_q + j] = false; } for(i = 0; i < user_n; i++) { for(j = 0; j < user_q; j++) { bool_r[ i * user_q + j] = false; bool_v[ i * user_q + j] = false; } } } if( user_set ) { set_r.resize(user_n); set_u.resize(user_m); set_v.resize(user_n); for(i = 0; i < user_m; i++) set_u[i].clear(); for(i = 0; i < user_n; i++) { set_r[i].clear(); set_v[i].clear(); } } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); user_state = user_end; // call users function for this operation user_atom->set_id(user_id); # ifdef NDEBUG if( user_pack ) user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, pack_r, pack_u, pack_v ); if( user_bool ) user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, bool_r, bool_u, bool_v ); if( user_set ) user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, set_r, set_u, set_v ); # else if( user_pack ) user_ok = user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, pack_r, pack_u, pack_v ); if( user_bool ) user_ok = user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, bool_r, bool_u, bool_v ); if( user_set ) user_ok = user_atom->rev_sparse_hes(user_vx, user_s, user_t, user_q, set_r, set_u, set_v ); if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.rev_sparse_hes: returned false\n"; if( user_pack ) msg += "sparsity = pack_sparsity_enum"; if( user_bool ) msg += "sparsity = bool_sparsity_enum"; if( user_set ) msg += "sparsity = set_sparsity_enum"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_n; i++) if( user_ix[i] > 0 ) { size_t i_x = user_ix[i]; if( user_t[i] ) RevJac[i_x] = true; if( user_pack ) { for(j = 0; j < user_q; j++) if( pack_v[ i * user_q + j ] ) rev_hes_sparse.add_element(i_x, j); } if( user_bool ) { for(j = 0; j < user_q; j++) if( bool_v[ i * user_q + j ] ) rev_hes_sparse.add_element(i_x, j); } if( user_set ) { set_itr = set_v[i].begin(); set_end = set_v[i].end(); while( set_itr != set_end ) rev_hes_sparse.add_element(i_x, *set_itr++); } } } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; user_ix[user_j] = 0; user_vx[user_j] = false; if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; user_ix[user_j] = arg[0]; user_vx[user_j] = true; for_jac_sparse.begin(arg[0]); i = for_jac_sparse.next_element(); while( i < user_q ) { if( user_pack ) pack_r[ user_j * user_q + i ] = true; if( user_bool ) bool_r[ user_j * user_q + i ] = true; if( user_set ) set_r[user_j].insert(i); i = for_jac_sparse.next_element(); } if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; if( user_i == 0 ) user_state = user_arg; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; if( RevJac[i_var] ) { user_s[user_i] = true; } rev_hes_sparse.begin(i_var); j = rev_hes_sparse.next_element(); while( j < user_q ) { if( user_pack ) pack_u[user_i * user_q + j] = true; if( user_bool ) bool_u[user_i * user_q + j] = true; if( user_set ) set_u[user_i].insert(j); j = rev_hes_sparse.next_element(); } if( user_i == 0 ) user_state = user_arg; break; // ------------------------------------------------- case ZmulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ZmulvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_HES_SWEEP_TRACE for(j = 0; j < limit; j++) { zf_value[j] = false; zh_value[j] = false; } for_jac_sparse.begin(i_var);; j = for_jac_sparse.next_element();; while( j < limit ) { zf_value[j] = true; j = for_jac_sparse.next_element(); } rev_hes_sparse.begin(i_var);; j = rev_hes_sparse.next_element();; while( j < limit ) { zh_value[j] = true; j = rev_hes_sparse.next_element(); } printOp( std::cout, play, i_op, i_var, op, arg ); // should also print RevJac[i_var], but printOpResult does not // yet allow for this if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, 1, &zf_value, 1, &zh_value ); std::cout << std::endl; } std::cout << std::endl; # else }
size_t forward_sweep( std::ostream& s_out, const bool print, const size_t q, const size_t p, const size_t n, const size_t numvar, player<Base> *Rec, const size_t J, Base *Taylor, CppAD::vector<bool>& cskip_op ) { CPPAD_ASSERT_UNKNOWN( J >= p + 1 ); CPPAD_ASSERT_UNKNOWN( q <= p ); // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // arg (not as a constant) addr_t* non_const_arg = CPPAD_NULL; // arg (as a constant) const addr_t* arg = CPPAD_NULL; // temporary indices size_t i, ell; // initialize the comparision operator (ComOp) counter size_t compareCount = 0; pod_vector<size_t> VectorInd; // address for each element pod_vector<bool> VectorVar; // is element a variable if( q == 0 ) { // this includes order zero calculation, initialize vector indices i = Rec->num_rec_vecad_ind(); if( i > 0 ) { VectorInd.extend(i); VectorVar.extend(i); while(i--) { VectorInd[i] = Rec->GetVecInd(i); VectorVar[i] = false; } } // includes zero order, so initialize conditional skip flags for(i = 0; i < Rec->num_rec_op(); i++) cskip_op[i] = false; } // Work space used by UserOp. Note User assumes q = p. const size_t user_p1 = p+1; // number of orders for this user calculation vector<bool> user_vx; // empty vector vector<bool> user_vy; // empty vector vector<Base> user_tx; // argument vector Taylor coefficients vector<Base> user_ty; // result vector Taylor coefficients vector<size_t> user_iy; // variable indices for results vector size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_start; // check numvar argument CPPAD_ASSERT_UNKNOWN( Rec->num_rec_var() == numvar ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = Rec->num_rec_par(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = Rec->GetPar(); // length of the text vector (used by CppAD assert macros) const size_t num_text = Rec->num_rec_text(); // pointer to the beginning of the text vector const char* text = CPPAD_NULL; if( num_text > 0 ) text = Rec->GetTxt(0); // skip the BeginOp at the beginning of the recording Rec->start_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD_SWEEP_TRACE std::cout << std::endl; # endif bool more_operators = true; while(more_operators) { // this op Rec->next_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); // check if we are skipping this operation while( cskip_op[i_op] ) { if( op == CSumOp ) { // CSumOp has a variable number of arguments Rec->forward_csum(op, arg, i_op, i_var); } Rec->next_forward(op, arg, i_op, i_var); } // action depends on the operator switch( op ) { case AbsOp: forward_abs_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case CExpOp: forward_cond_op( q, p, i_var, arg, num_par, parameter, J, Taylor ); break; // --------------------------------------------------- case ComOp: if( q == 0 ) forward_comp_op_0( compareCount, arg, num_par, parameter, J, Taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op(q, p, i_var, arg[0], J, Taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // next_forward thinks it one has one argument. // we must inform next_forward of this special case. Rec->forward_cskip(op, arg, i_op, i_var); if( q == 0 ) { forward_cskip_op_0( i_var, arg, num_par, parameter, J, Taylor, cskip_op ); } break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_forward thinks it one has one argument. // we must inform next_forward of this special case. Rec->forward_csum(op, arg, i_op, i_var); forward_csum_op( q, p, i_var, arg, num_par, parameter, J, Taylor ); break; // ------------------------------------------------- case DisOp: i = q; if( i == 0 ) { forward_dis_op_0(i_var, arg, J, Taylor); i++; } while(i <= p) { Taylor[ i_var * J + i] = Base(0); i++; } break; // ------------------------------------------------- case DivvvOp: forward_divvv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ExpOp: forward_exp_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); break; // ------------------------------------------------- case LdpOp: if( q == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_p_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); if( q < p ) forward_load_op( op, q+1, p, i_var, arg, J, Taylor); } else { forward_load_op( op, q, p, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LdvOp: if( q == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_v_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); if( q < p ) forward_load_op( op, q+1, p, i_var, arg, J, Taylor); } else { forward_load_op( op, q, p, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LogOp: forward_log_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case ParOp: i = q; if( i == 0 ) { forward_par_op_0( i_var, arg, num_par, parameter, J, Taylor ); i++; } while(i <= p) { Taylor[ i_var * J + i] = Base(0); i++; } break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PriOp: if( (q == 0) & print ) forward_pri_0(s_out, i_var, arg, num_text, text, num_par, parameter, J, Taylor ); break; // ------------------------------------------------- case SignOp: // sign(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case StppOp: if( q == 0 ) { forward_store_pp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } break; // ------------------------------------------------- case StpvOp: if( q == 0 ) { forward_store_pv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } break; // ------------------------------------------------- case StvpOp: if( q == 0 ) { forward_store_vp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } break; // ------------------------------------------------- case StvvOp: if( q == 0 ) { forward_store_vv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } break; // ------------------------------------------------- case SubvvOp: forward_subvv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op(q, p, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op(q, p, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif if(user_tx.size() != user_n * user_p1) user_tx.resize(user_n * user_p1); if(user_ty.size() != user_m * user_p1) user_ty.resize(user_m * user_p1); if(user_iy.size() != user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); // call users function for this operation user_atom->set_id(user_id); CPPAD_ATOMIC_CALL( q, p, user_vx, user_vy, user_tx, user_ty ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) for(ell = q; ell <= p; ell++) Taylor[ user_iy[i] * J + ell ] = user_ty[ i * user_p1 + ell ]; user_state = user_start; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx[user_j * user_p1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_p1; ell++) user_tx[user_j * user_p1 + ell] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); for(ell = 0; ell < user_p1; ell++) user_tx[user_j * user_p1 + ell] = Taylor[ arg[0] * J + ell]; ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty[user_i * user_p1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < q; ell++) user_ty[user_i * user_p1 + ell] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; for(ell = 0; ell < q; ell++) user_ty[user_i * user_p1 + ell] = Taylor[ i_var * J + ell]; user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD_SWEEP_TRACE size_t i_tmp = i_var; Base* Z_tmp = Taylor + J * i_var; printOp( std::cout, Rec, i_op, i_tmp, op, arg, p + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); } std::cout << std::endl; # else }
void RevJacSweep( bool nz_compare, size_t n, size_t numvar, player<Base> *play, Vector_set& var_sparsity ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; size_t i, j, k; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // check numvar argument CPPAD_ASSERT_UNKNOWN( numvar > 0 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); // upper limit (exclusive) for elements in the set size_t limit = var_sparsity.end(); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index of the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparsity; vecad_sparsity.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set to proper index for this VecAD vecad_ind[j] = i; for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // work space used by UserOp. typedef std::set<size_t> size_set; size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > set_r; // set sparsity pattern for the argument x vector< size_set > set_s; // set sparisty pattern for the result y // vector<bool> bool_r; // bool sparsity pattern for the argument x vector<bool> bool_s; // bool sparisty pattern for the result y // const size_t user_q = limit; // maximum element plus one size_t user_index = 0; // indentifier for this atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator bool user_bool = false; // use bool or set sparsity ? # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_end; // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_JAC_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool z_value(limit); # endif bool more_operators = true; while(more_operators) { // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_jacobian_csum_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_jacobian_cond_op( nz_compare, i_var, arg, num_par, var_sparsity ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); // derivative is identically zero break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[0] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: reverse_sparse_jacobian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_jacobian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); break; // ------------------------------------------------- case PowvpOp: reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // derivative is identically zero break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case StppOp: // sparsity cannot proagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0); break; // ------------------------------------------------- case StpvOp: reverse_sparse_jacobian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); break; // ------------------------------------------------- case StvvOp: reverse_sparse_jacobian_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case UserOp: // start or end atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_end ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; user_atom = atomic_base<Base>::class_object(user_index); # ifndef NDEBUG if( user_atom == CPPAD_NULL ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base function has been deleted"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_bool = user_atom->sparsity() == atomic_base<Base>::bool_sparsity_enum; if( user_bool ) { if( bool_r.size() != user_m * user_q ) bool_r.resize( user_m * user_q ); if( bool_s.size() != user_n * user_q ) bool_s.resize( user_n * user_q ); for(i = 0; i < user_m; i++) for(j = 0; j < user_q; j++) bool_r[ i * user_q + j] = false; } else { if(set_r.size() != user_m ) set_r.resize(user_m); if(set_s.size() != user_n ) set_s.resize(user_n); for(i = 0; i < user_m; i++) set_r[i].clear(); } user_j = user_n; user_i = user_m; user_state = user_ret; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); # ifndef NDEBUG if( ! user_ok ) { std::string msg = atomic_base<Base>::class_name(user_index) + ": atomic_base.rev_sparse_jac: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif user_state = user_end; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_j; if( user_j == 0 ) user_state = user_start; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); --user_j; // It might be faster if we add set union to var_sparsity // where one of the sets is not in var_sparsity. if( user_bool ) { for(j = 0; j < user_q; j++) if( bool_s[ user_j * user_q + j ] ) var_sparsity.add_element(arg[0], j); } else { set_itr = set_s[user_j].begin(); set_end = set_s[user_j].end(); while( set_itr != set_end ) var_sparsity.add_element(arg[0], *set_itr++); } if( user_j == 0 ) user_state = user_start; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); --user_i; if( user_i == 0 ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_arg; } break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); --user_i; var_sparsity.begin(i_var); i = var_sparsity.next_element(); while( i < user_q ) { if( user_bool ) bool_r[ user_i * user_q + i ] = true; else set_r[user_i].insert(i); i = var_sparsity.next_element(); } if( user_i == 0 ) { // call users function for this operation user_atom->set_id(user_id); if( user_bool) CPPAD_ATOMIC_CALL( user_q, bool_r, bool_s ); else CPPAD_ATOMIC_CALL( user_q, set_r, set_s ); user_state = user_arg; } break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_JAC_SWEEP_TRACE for(j = 0; j < limit; j++) z_value[j] = false; var_sparsity.begin(i_var); j = var_sparsity.next_element(); while( j < limit ) { z_value[j] = true; j = var_sparsity.next_element(); } printOp( std::cout, play, i_op, i_var, op, arg ); if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, 0, (CppAD::vectorBool *) CPPAD_NULL, 1, &z_value ); std::cout << std::endl; } std::cout << std::endl; # else }
void forward0sweep( std::ostream& s_out, bool print, size_t n, size_t numvar, local::player<Base>* play, size_t J, Base* taylor, bool* cskip_op, pod_vector<addr_t>& var_by_load_op, size_t compare_change_count, size_t& compare_change_number, size_t& compare_change_op_index ) { CPPAD_ASSERT_UNKNOWN( J >= 1 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); // use p, q, r so other forward sweeps can use code defined here size_t p = 0; size_t q = 0; size_t r = 1; /* <!-- define forward0sweep_code_define --> */ // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; // operation argument indices const addr_t* arg = CPPAD_NULL; // initialize the comparision operator counter if( p == 0 ) { compare_change_number = 0; compare_change_op_index = 0; } // If this includes a zero calculation, initialize this information pod_vector<bool> isvar_by_ind; pod_vector<size_t> index_by_ind; if( p == 0 ) { size_t i; // this includes order zero calculation, initialize vector indices size_t num = play->num_vec_ind_rec(); if( num > 0 ) { isvar_by_ind.extend(num); index_by_ind.extend(num); for(i = 0; i < num; i++) { index_by_ind[i] = play->GetVecInd(i); isvar_by_ind[i] = false; } } // includes zero order, so initialize conditional skip flags num = play->num_op_rec(); for(i = 0; i < num; i++) cskip_op[i] = false; } // work space used by UserOp. vector<bool> user_vx; // empty vecotor vector<bool> user_vy; // empty vecotor vector<Base> user_tx; // argument vector Taylor coefficients vector<Base> user_ty; // result vector Taylor coefficients // atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator # ifndef NDEBUG bool user_ok = false; // atomic op return value # endif // // information defined by forward_user size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0; enum_user_state user_state = start_user; // proper initialization // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // pointer to the beginning of the parameter vector const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // length of the text vector (used by CppAD assert macros) const size_t num_text = play->num_text_rec(); // pointer to the beginning of the text vector const char* text = CPPAD_NULL; if( num_text > 0 ) text = play->GetTxt(0); /* <!-- end forward0sweep_code_define --> */ # if CPPAD_FORWARD0SWEEP_TRACE // flag as to when to trace user function values bool user_trace = false; // variable indices for results vector // (done differently for order zero). vector<size_t> user_iy; # endif // skip the BeginOp at the beginning of the recording play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD0SWEEP_TRACE std::cout << std::endl; # endif bool flag; // a temporary flag to use in switch cases bool more_operators = true; while(more_operators) { // this op play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var); // check if we are skipping this operation while( cskip_op[i_op] ) { switch(op) { case CSumOp: // CSumOp has a variable number of arguments play->forward_csum(op, arg, i_op, i_var); break; case CSkipOp: // CSkip has a variable number of arguments play->forward_cskip(op, arg, i_op, i_var); break; case UserOp: { // skip all operations in this user atomic call CPPAD_ASSERT_UNKNOWN( user_state == start_user ); play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); size_t n_skip = user_m + user_n + 1; for(size_t i = 0; i < n_skip; i++) { play->forward_next(op, arg, i_op, i_var); play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); } CPPAD_ASSERT_UNKNOWN( user_state == start_user ); } break; default: break; } play->forward_next(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() ); } // action to take depends on the case switch( op ) { case AbsOp: forward_abs_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acosh_op_0(i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asinh_op_0(i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atanh_op_0(i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case CExpOp: // Use the general case with d == 0 // (could create an optimzied verison for this case) forward_cond_op_0( i_var, arg, num_par, parameter, J, taylor ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op_0(i_var, arg[0], J, taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_cskip_op_0( i_var, arg, num_par, parameter, J, taylor, cskip_op ); play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // forward_next thinks it has no arguments. // we must inform forward_next of this special case. forward_csum_op( 0, 0, i_var, arg, num_par, parameter, J, taylor ); play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DisOp: forward_dis_op(p, q, r, i_var, arg, J, taylor); break; // ------------------------------------------------- case DivvvOp: forward_divvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case EqpvOp: if( compare_change_count ) { forward_eqpv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case EqvvOp: if( compare_change_count ) { forward_eqvv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case ErfOp: forward_erf_op_0(i_var, arg, parameter, J, taylor); break; # endif // ------------------------------------------------- case ExpOp: forward_exp_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: forward_expm1_op_0(i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // --------------------------------------------------- case LdpOp: forward_load_p_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); break; // ------------------------------------------------- case LdvOp: forward_load_v_op_0( play, i_var, arg, parameter, J, taylor, isvar_by_ind.data(), index_by_ind.data(), var_by_load_op.data() ); break; // ------------------------------------------------- case LepvOp: if( compare_change_count ) { forward_lepv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LevpOp: if( compare_change_count ) { forward_levp_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LevvOp: if( compare_change_count ) { forward_levv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LogOp: forward_log_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: forward_log1p_op_0(i_var, arg[0], J, taylor); break; # endif // ------------------------------------------------- case LtpvOp: if( compare_change_count ) { forward_ltpv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LtvpOp: if( compare_change_count ) { forward_ltvp_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case LtvvOp: if( compare_change_count ) { forward_ltvv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case NepvOp: if( compare_change_count ) { forward_nepv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case NevvOp: if( compare_change_count ) { forward_nevv_op_0( compare_change_number, arg, parameter, J, taylor ); { if( compare_change_count == compare_change_number ) compare_change_op_index = i_op; } } break; // ------------------------------------------------- case ParOp: forward_par_op_0( i_var, arg, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case PriOp: if( print ) forward_pri_0(s_out, arg, num_text, text, num_par, parameter, J, taylor ); break; // ------------------------------------------------- case SignOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case StppOp: forward_store_pp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StpvOp: forward_store_pv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StvpOp: forward_store_vp_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case StvvOp: forward_store_vv_op_0( i_var, arg, num_par, J, taylor, isvar_by_ind.data(), index_by_ind.data() ); break; // ------------------------------------------------- case SubvvOp: forward_subvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op_0(i_var, arg[0], J, taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence flag = user_state == start_user; user_atom = play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( flag ) { user_tx.resize(user_n); user_ty.resize(user_m); # if CPPAD_FORWARD0SWEEP_TRACE user_iy.resize(user_m); # endif } else { # ifndef NDEBUG if( ! user_ok ) { std::string msg = user_atom->afun_name() + ": atomic_base.forward: returned false"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif # if CPPAD_FORWARD0SWEEP_TRACE user_trace = true; # endif } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par ); user_tx[user_j] = parameter[ arg[0] ]; play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( user_j == user_n ) { // call users function for this operation user_atom->set_old(user_old); CPPAD_ATOMIC_CALL(p, q, user_vx, user_vy, user_tx, user_ty ); } break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); user_tx[user_j] = taylor[ arg[0] * J + 0 ]; play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( user_j == user_n ) { // call users function for this operation user_atom->set_old(user_old); CPPAD_ATOMIC_CALL(p, q, user_vx, user_vy, user_tx, user_ty ); } break; case UsrrpOp: // parameter result in an atomic operation sequence # if CPPAD_FORWARD0SWEEP_TRACE user_iy[user_i] = 0; # endif play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; case UsrrvOp: // variable result in an atomic operation sequence # if CPPAD_FORWARD0SWEEP_TRACE user_iy[user_i] = i_var; # endif taylor[ i_var * J + 0 ] = user_ty[user_i]; play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; // ------------------------------------------------- case ZmulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_zmulpv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case ZmulvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_zmulvp_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- case ZmulvvOp: forward_zmulvv_op_0(i_var, arg, parameter, J, taylor); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(false); } # if CPPAD_FORWARD0SWEEP_TRACE size_t d = 0; if( user_trace ) { user_trace = false; CPPAD_ASSERT_UNKNOWN( op == UserOp ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); for(size_t i = 0; i < user_m; i++) if( user_iy[i] > 0 ) { size_t i_tmp = (i_op + i) - user_m; printOp( std::cout, play, i_tmp, user_iy[i], UsrrvOp, CPPAD_NULL ); Base* Z_tmp = taylor + user_iy[i] * J; printOpResult( std::cout, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); std::cout << std::endl; } } Base* Z_tmp = taylor + i_var * J; const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; if( op != UsrrvOp ) { printOp( std::cout, play, i_op, i_var, op, arg_tmp ); if( NumRes(op) > 0 ) printOpResult( std::cout, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); std::cout << std::endl; } } std::cout << std::endl; # else }
size_t forward_sweep( std::ostream& s_out, bool print, size_t d, size_t n, size_t numvar, player<Base> *Rec, size_t J, Base *Taylor ) { CPPAD_ASSERT_UNKNOWN( J >= d + 1 ); // op code for current instruction OpCode op; // index for current instruction size_t i_op; // next variables size_t i_var; CPPAD_ASSERT_UNKNOWN( d == 0 || ! print ); # if CPPAD_USE_FORWARD0SWEEP CPPAD_ASSERT_UNKNOWN( d > 0 ); # else addr_t* non_const_arg; # endif const addr_t* arg = 0; // temporary indices size_t i, ell; // initialize the comparision operator (ComOp) counter size_t compareCount = 0; // if this is an order zero calculation, initialize vector indices pod_vector<size_t> VectorInd; // address for each element pod_vector<bool> VectorVar; // is element a variable i = Rec->num_rec_vecad_ind(); if( i > 0 ) { VectorInd.extend(i); VectorVar.extend(i); while(i--) { VectorInd[i] = Rec->GetVecInd(i); VectorVar[i] = false; } } // work space used by UserOp. const size_t user_k = d; // order of this forward mode calculation const size_t user_k1 = d+1; // number of orders for this calculation vector<Base> user_tx; // argument vector Taylor coefficients vector<Base> user_ty; // result vector Taylor coefficients vector<size_t> user_iy; // variable indices for results vector size_t user_index = 0; // indentifier for this user_atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_start; // check numvar argument CPPAD_ASSERT_UNKNOWN( Rec->num_rec_var() == numvar ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = Rec->num_rec_par(); // pointer to the beginning of the parameter vector const Base* parameter = 0; if( num_par > 0 ) parameter = Rec->GetPar(); # if ! CPPAD_USE_FORWARD0SWEEP // length of the text vector (used by CppAD assert macros) const size_t num_text = Rec->num_rec_text(); // pointer to the beginning of the text vector const char* text = 0; if( num_text > 0 ) text = Rec->GetTxt(0); # endif // skip the BeginOp at the beginning of the recording Rec->start_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FORWARD_SWEEP_TRACE std::cout << std::endl; # endif while(op != EndOp) { // this op Rec->next_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); // action depends on the operator switch( op ) { case AbsOp: forward_abs_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AddvvOp: forward_addvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_addpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_acos_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_asin_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_atan_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_forward thinks it one has one argument. // we must inform next_forward of this special case. Rec->forward_csum(op, arg, i_op, i_var); forward_csum_op( d, i_var, arg, num_par, parameter, J, Taylor ); break; // ------------------------------------------------- case CExpOp: forward_cond_op( d, i_var, arg, num_par, parameter, J, Taylor ); break; // --------------------------------------------------- case ComOp: # if ! USE_FORWARD0SWEEP if( d == 0 ) forward_comp_op_0( compareCount, arg, num_par, parameter, J, Taylor ); # endif break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cos_op(d, i_var, arg[0], J, Taylor); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_cosh_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case DisOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) forward_dis_op_0(i_var, arg, J, Taylor); else # endif { Taylor[ i_var * J + d] = Base(0); } break; // ------------------------------------------------- case DivvvOp: forward_divvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_divpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_divvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); break; // ------------------------------------------------- case ExpOp: forward_exp_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 ); break; // ------------------------------------------------- case LdpOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_p_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } else # endif { forward_load_op( op, d, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LdvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { non_const_arg = Rec->forward_non_const_arg(); forward_load_v_op_0( i_var, non_const_arg, num_par, parameter, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } else # endif { forward_load_op( op, d, i_var, arg, J, Taylor); } break; // ------------------------------------------------- case LogOp: forward_log_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case MulvvOp: forward_mulvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_mulpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case ParOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) forward_par_op_0( i_var, arg, num_par, parameter, J, Taylor ); else # endif { Taylor[ i_var * J + d] = Base(0); } break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_powvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_powpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PowvvOp: forward_powvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case PriOp: # if ! CPPAD_USE_FORWARD0SWEEP if( print ) forward_pri_0(s_out, i_var, arg, num_text, text, num_par, parameter, J, Taylor ); # endif break; // ------------------------------------------------- case SignOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sign_op(d, i_var, arg[0], J, Taylor); break; case SinOp: // cos(x), sin(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sin_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_sinh_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case SqrtOp: forward_sqrt_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case StppOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_pp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } # endif break; // ------------------------------------------------- case StpvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_pv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } # endif break; // ------------------------------------------------- case StvpOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_vp_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } # endif break; // ------------------------------------------------- case StvvOp: # if ! CPPAD_USE_FORWARD0SWEEP if( d == 0 ) { forward_store_vv_op_0( i_var, arg, num_par, J, Taylor, Rec->num_rec_vecad_ind(), VectorVar.data(), VectorInd.data() ); } # endif break; // ------------------------------------------------- case SubvvOp: forward_subvv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); forward_subpv_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par ); forward_subvp_op(d, i_var, arg, parameter, J, Taylor); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tan_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_UNKNOWN( i_var < numvar ); forward_tanh_op(d, i_var, arg[0], J, Taylor); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; if(user_tx.size() < user_n * user_k1) user_tx.resize(user_n * user_k1); if(user_ty.size() < user_m * user_k1) user_ty.resize(user_m * user_k1); if(user_iy.size() < user_m) user_iy.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); user_state = user_start; // call users function for this operation user_atomic<Base>::forward(user_index, user_id, user_k, user_n, user_m, user_tx, user_ty ); for(i = 0; i < user_m; i++) if( user_iy[i] > 0 ) Taylor[ user_iy[i] * J + user_k ] = user_ty[ i * user_k1 + user_k ]; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); user_tx[user_j * user_k1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_k1; ell++) user_tx[user_j * user_k1 + ell] = Base(0); ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); for(ell = 0; ell < user_k1; ell++) user_tx[user_j * user_k1 + ell] = Taylor[ arg[0] * J + ell]; ++user_j; if( user_j == user_n ) user_state = user_ret; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = 0; user_ty[user_i * user_k1 + 0] = parameter[ arg[0]]; for(ell = 1; ell < user_k; ell++) user_ty[user_i * user_k1 + ell] = Base(0); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_iy[user_i] = i_var; for(ell = 0; ell < user_k; ell++) user_ty[user_i * user_k1 + ell] = Taylor[ i_var * J + ell]; user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FORWARD_SWEEP_TRACE size_t i_tmp = i_var; Base* Z_tmp = Taylor + J * i_var; printOp( std::cout, Rec, i_tmp, op, arg, d + 1, Z_tmp, 0, (Base *) CPPAD_NULL ); } std::cout << std::endl; # else }
void ForJacSweep( size_t n , size_t numvar , player<Base>* play , Vector_set& var_sparsity ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = 0; size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_rec_var() == numvar ); CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_rec_par(); // cum_sparsity accumulates sparsity pattern a cummulative sum size_t limit = var_sparsity.end(); // vecad_sparsity contains a sparsity pattern from each VecAD object // to all the other variables. // vecad_ind maps a VecAD index (the beginning of the // VecAD object) to its from index in vecad_sparsity size_t num_vecad_ind = play->num_rec_vecad_ind(); size_t num_vecad_vec = play->num_rec_vecad_vec(); Vector_set vecad_sparsity; vecad_sparsity.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set to proper index for this VecAD vecad_ind[j] = i; for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == play->num_rec_vecad_ind() ); } // work space used by UserOp. typedef std::set<size_t> size_set; const size_t user_q = limit; // maximum element plus one size_set::iterator set_itr; // iterator for a standard set size_set::iterator set_end; // end of iterator sequence vector< size_set > user_r; // sparsity pattern for the argument x vector< size_set > user_s; // sparisty pattern for the result y size_t user_index = 0; // indentifier for this user_atomic operation size_t user_id = 0; // user identifier for this call to operator size_t user_i = 0; // index in result vector size_t user_j = 0; // index in argument vector size_t user_m = 0; // size of result vector size_t user_n = 0; // size of arugment vector // next expected operator in a UserOp sequence enum { user_start, user_arg, user_ret, user_end } user_state = user_start; # if CPPAD_FOR_JAC_SWEEP_TRACE std::cout << std::endl; CppAD::vector<bool> z_value(limit); # endif // skip the BeginOp at the beginning of the recording play->start_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); while(op != EndOp) { // this op play->next_forward(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) ); CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) ); // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_forward thinks it one has one argument. // we must inform next_forward of this special case. play->forward_csum(op, arg, i_op, i_var); forward_sparse_jacobian_csum_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case CExpOp: forward_sparse_jacobian_cond_op( i_var, arg, num_par, var_sparsity ); break; // --------------------------------------------------- case ComOp: CPPAD_ASSERT_NARG_NRES(op, 4, 0); CPPAD_ASSERT_UNKNOWN( arg[1] > 1 ); break; // -------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); var_sparsity.clear(i_var); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); // sparsity pattern is already defined break; // ------------------------------------------------- case LdpOp: forward_sparse_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LdvOp: forward_sparse_load_op( op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); var_sparsity.clear(i_var); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case StppOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); // storing a parameter does not affect vector sparsity break; // ------------------------------------------------- case StpvOp: forward_sparse_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); // storing a parameter does not affect vector sparsity break; // ------------------------------------------------- case StvvOp: forward_sparse_store_op( op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); forward_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case UserOp: // start or end an atomic operation sequence CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); if( user_state == user_start ) { user_index = arg[0]; user_id = arg[1]; user_n = arg[2]; user_m = arg[3]; if(user_r.size() < user_n ) user_r.resize(user_n); if(user_s.size() < user_m ) user_s.resize(user_m); user_j = 0; user_i = 0; user_state = user_arg; } else { CPPAD_ASSERT_UNKNOWN( user_state == user_end ); CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) ); CPPAD_ASSERT_UNKNOWN( user_id == size_t(arg[1]) ); CPPAD_ASSERT_UNKNOWN( user_n == size_t(arg[2]) ); CPPAD_ASSERT_UNKNOWN( user_m == size_t(arg[3]) ); user_state = user_start; } break; case UsrapOp: // parameter argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); // parameters have an empty sparsity pattern user_r[user_j].clear(); ++user_j; if( user_j == user_n ) { // call users function for this operation user_atomic<Base>::for_jac_sparse(user_index, user_id, user_n, user_m, user_q, user_r, user_s ); user_state = user_ret; } break; case UsravOp: // variable argument in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); CPPAD_ASSERT_UNKNOWN( user_j < user_n ); CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); // set user_r[user_j] to sparsity pattern for variable arg[0] user_r[user_j].clear(); var_sparsity.begin(arg[0]); i = var_sparsity.next_element(); while( i < user_q ) { user_r[user_j].insert(i); i = var_sparsity.next_element(); } ++user_j; if( user_j == user_n ) { // call users function for this operation user_atomic<Base>::for_jac_sparse(user_index, user_id, user_n, user_m, user_q, user_r, user_s ); user_state = user_ret; } break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); user_i++; if( user_i == user_m ) user_state = user_end; break; case UsrrvOp: // variable result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); CPPAD_ASSERT_UNKNOWN( user_i < user_m ); // It might be faster if we add set union to var_sparsity // where one of the sets is not in var_sparsity set_itr = user_s[user_i].begin(); set_end = user_s[user_i].end(); while( set_itr != set_end ) var_sparsity.add_element(i_var, *set_itr++); user_i++; if( user_i == user_m ) user_state = user_end; break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FOR_JAC_SWEEP_TRACE // value for this variable for(j = 0; j < limit; j++) z_value[j] = false; var_sparsity.begin(i_var); j = var_sparsity.next_element(); while( j < limit ) { z_value[j] = true; j = var_sparsity.next_element(); } printOp( std::cout, play, i_var, op, arg, 1, &z_value, 0, (CppAD::vector<bool> *) CPPAD_NULL ); } std::cout << std::endl; # else }
void RevJacSweep( bool dependency, size_t n, size_t numvar, local::player<Base>* play, Vector_set& var_sparsity ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; size_t i, j, k; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); // check numvar argument CPPAD_ASSERT_UNKNOWN( numvar > 0 ); CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar ); // upper limit (exclusive) for elements in the set size_t limit = var_sparsity.end(); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index of the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparsity; vecad_sparsity.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set to proper index for this VecAD vecad_ind[j] = i; for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // invalid index // start of next VecAD j += length + 1; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // ---------------------------------------------------------------------- // user's atomic op calculator atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator // // work space used by UserOp. vector<Base> user_x; // parameters in x as integers vector<size_t> user_ix; // variable indices for argument vector vector<size_t> user_iy; // variable indices for result vector // // information set by forward_user (initialization to avoid warnings) size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0; // information set by forward_user (necessary initialization) enum_user_state user_state = end_user; // proper initialization // ---------------------------------------------------------------------- // // pointer to the beginning of the parameter vector // (used by atomic functions const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // // Initialize play->reverse_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_JAC_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool z_value(limit); # endif bool more_operators = true; while(more_operators) { bool flag; // temporary for use in switch cases // // next op play->reverse_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case AcosOp: // sqrt(1 - x * x), acos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: // sqrt(x * x - 1), acosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; # endif // ------------------------------------------------- case AsinOp: // sqrt(1 - x * x), asin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AsinhOp: // sqrt(1 + x * x), asinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; # endif // ------------------------------------------------- case AtanOp: // 1 + x * x, atan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case AtanhOp: // 1 - x * x, atanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; # endif // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); more_operators = false; break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_jacobian_csum_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_jacobian_cond_op( dependency, i_var, arg, num_par, var_sparsity ); break; // --------------------------------------------------- case CosOp: // sin(x), cos(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // --------------------------------------------------- case CoshOp: // sinh(x), cosh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); // derivative is identically zero but dependency is not if( dependency ) reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[0] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Expm1Op: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; # endif // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1); break; // ------------------------------------------------- case LdpOp: reverse_sparse_jacobian_load_op( dependency, op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_jacobian_load_op( dependency, op, i_var, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- # if CPPAD_USE_CPLUSPLUS_2011 case Log1pOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; # endif // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); break; // ------------------------------------------------- case PowvpOp: reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case PriOp: CPPAD_ASSERT_NARG_NRES(op, 5, 0); break; // ------------------------------------------------- case SignOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); // derivative is identically zero but dependency is not if( dependency ) reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinOp: // cos(x), sin(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SinhOp: // cosh(x), sinh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case StppOp: // does not affect sparsity or dependency when both are parameters CPPAD_ASSERT_NARG_NRES(op, 3, 0); break; // ------------------------------------------------- case StpvOp: reverse_sparse_jacobian_store_op( dependency, op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvpOp: CPPAD_ASSERT_NARG_NRES(op, 3, 0); // storing a parameter only affects dependency reverse_sparse_jacobian_store_op( dependency, op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case StvvOp: reverse_sparse_jacobian_store_op( dependency, op, arg, num_vecad_ind, vecad_ind.data(), var_sparsity, vecad_sparsity ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanOp: // tan(x)^2, tan(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case TanhOp: // tanh(x)^2, tanh(x) CPPAD_ASSERT_NARG_NRES(op, 1, 2); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case UserOp: CPPAD_ASSERT_UNKNOWN( user_state == start_user || user_state == end_user ); flag = user_state == end_user; user_atom = play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( flag ) { // start of user atomic operation sequence user_x.resize( user_n ); user_ix.resize( user_n ); user_iy.resize( user_m ); } else { // end of users atomic operation sequence user_atom->set_old(user_old); user_atom->rev_sparse_jac( user_x, user_ix, user_iy, var_sparsity ); } break; case UsrapOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // argument parameter value user_x[user_j] = parameter[arg[0]]; // special variable index used for parameters user_ix[user_j] = 0; // break; case UsravOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // argument variables not available during sparsity calculations user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN(); // variable index for this argument user_ix[user_j] = arg[0]; break; case UsrrpOp: // parameter result in an atomic operation sequence CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // special variable index used for parameters user_iy[user_i] = 0; break; case UsrrvOp: play->reverse_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); // variable index for this result user_iy[user_i] = i_var; break; // ------------------------------------------------- case ZmulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[1], var_sparsity ); break; // ------------------------------------------------- case ZmulvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_unary_op( i_var, arg[0], var_sparsity ); break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1); reverse_sparse_jacobian_binary_op( i_var, arg, var_sparsity ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_JAC_SWEEP_TRACE for(j = 0; j < limit; j++) z_value[j] = false; typename Vector_set::const_iterator itr(var_sparsity, i_var); j = *itr; while( j < limit ) { z_value[j] = true; j = *(++itr); } printOp( std::cout, play, i_op, i_var, op, arg ); // Note that sparsity for UsrrvOp are computed before call to // atomic function so no need to delay printing (as in forward mode) if( NumRes(op) > 0 && op != BeginOp ) printOpResult( std::cout, 0, (CppAD::vectorBool *) CPPAD_NULL, 1, &z_value ); std::cout << std::endl; } std::cout << std::endl; # else }