Ejemplo n.º 1
0
bool ASTPrintVisitor::visit_augassign(AST_AugAssign* node) {
    node->target->accept(this);
    printOp(node->op_type);
    stream << '=';
    node->value->accept(this);
    return true;
}
Ejemplo n.º 2
0
bool ASTPrintVisitor::visit_augbinop(AST_AugBinOp* node) {
    node->left->accept(this);
    stream << '=';
    printOp(node->op_type);
    node->right->accept(this);
    return true;
}
Ejemplo n.º 3
0
  void NodeUnaryOp::printPostfix(File * fp)
  {
    if(m_node)
      m_node->printPostfix(fp);
    else
      fp->write("<NULL>");

    printOp(fp); //operators last
  } //printPostfix
Ejemplo n.º 4
0
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";
}
Ejemplo n.º 5
0
  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
Ejemplo n.º 6
0
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
	}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 9
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
	}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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
	}
Ejemplo n.º 12
0
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 );
}
Ejemplo n.º 13
0
bool ASTPrintVisitor::visit_binop(AST_BinOp* node) {
    node->left->accept(this);
    printOp(node->op_type);
    node->right->accept(this);
    return true;
}
Ejemplo n.º 14
0
//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);
}
Ejemplo n.º 15
0
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
	}
Ejemplo n.º 16
0
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
	}
Ejemplo n.º 17
0
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
	}
Ejemplo n.º 18
0
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
	}
Ejemplo n.º 19
0
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
	}
Ejemplo n.º 20
0
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
	}
Ejemplo n.º 21
0
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
	}
Ejemplo n.º 22
0
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
	}