示例#1
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
	}
示例#2
0
void optimize(
	size_t                       n         ,
	CppAD::vector<size_t>&       dep_taddr ,
	player<Base>*                play      ,
	recorder<Base>*              rec       ) 
{
	// temporary indices
	size_t i, j, k;

	// temporary variables
	OpCode        op;   // current operator
	const size_t *arg;  // operator arguments
	size_t        i_var;  // index of first result for current operator

	// range and domain dimensions for F
	size_t m = dep_taddr.size();

	// number of variables in the player
	const size_t num_var = play->num_rec_var(); 

	// number of  VecAD indices 
	size_t num_vecad_ind   = play->num_rec_vecad_ind();

	// number of VecAD vectors
	size_t num_vecad_vec   = play->num_rec_vecad_vec();

	// -------------------------------------------------------------
	// data structure that maps variable index in original operation
	// sequence to corresponding operator information
	CppAD::vector<struct optimize_old_variable> tape(num_var);
	// -------------------------------------------------------------
	// Determine how each variable is connected to the dependent variables

	// initialize all variables has having no connections
	for(i = 0; i < num_var; i++)
		tape[i].connect = not_connected;

	for(j = 0; j < m; j++)
	{	// mark dependent variables as having one or more connections
		tape[ dep_taddr[j] ].connect = yes_connected;
	}

	// vecad_connect contains a value for each VecAD object.
	// vecad maps a VecAD index (which corresponds to the beginning of the
	// VecAD object) to the vecad_connect falg for the VecAD object.
	CppAD::vector<optimize_connection>   vecad_connect(num_vecad_vec);
	CppAD::vector<size_t> vecad(num_vecad_ind);
	j = 0;
	for(i = 0; i < num_vecad_vec; i++)
	{	vecad_connect[i] = not_connected;
		// length of this VecAD
		size_t length = play->GetVecInd(j);
		// set to proper index for this VecAD
		vecad[j] = i; 
		for(k = 1; k <= length; k++)
			vecad[j+k] = num_vecad_vec; // invalid index
		// start of next VecAD
		j       += length + 1;
	}
	CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind );

	// Initialize a reverse mode sweep through the operation sequence
	size_t i_op;
	play->start_reverse(op, arg, i_op, i_var);
	CPPAD_ASSERT_UNKNOWN( op == EndOp );
	size_t mask;
	while(op != BeginOp)
	{	// next op
		play->next_reverse(op, arg, i_op, i_var);
		// This if is not necessary becasue last assignment
		// with this value of i_var will have NumRes(op) > 0
		if( NumRes(op) > 0 )
		{	tape[i_var].op = op;
			tape[i_var].arg = arg;
		}
# ifndef NDEBUG
		if( i_op <= n )
		{	CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
		}
		else	CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
# endif
		switch( op )
		{
			// Unary operator where operand is arg[0]
			case AbsOp:
			case AcosOp:
			case AsinOp:
			case AtanOp:
			case CosOp:
			case CoshOp:
			case DisOp:
			case DivvpOp:
			case ExpOp:
			case LogOp:
			case PowvpOp:
			case SinOp:
			case SinhOp:
			case SqrtOp:
			if( tape[i_var].connect != not_connected )
				tape[arg[0]].connect = yes_connected;
			break; // --------------------------------------------

			// Unary operator where operand is arg[1]
			case DivpvOp:
			case MulpvOp:
			case PowpvOp:
			case PrivOp:
			if( tape[i_var].connect != not_connected )
				tape[arg[1]].connect = yes_connected;
			break; // --------------------------------------------
		
			// Special case for SubvpOp
			case SubvpOp:
			if( tape[i_var].connect != not_connected )
			{
				if( tape[arg[0]].connect == not_connected )
					tape[arg[0]].connect = sum_connected;
				else
					tape[arg[0]].connect = yes_connected;
				if( tape[i_var].connect == sum_connected )
					tape[i_var].connect = csum_connected;
			}
			break; // --------------------------------------------
		
			// Special case for AddpvOp and SubpvOp
			case AddpvOp:
			case SubpvOp:
			if( tape[i_var].connect != not_connected )
			{
				if( tape[arg[1]].connect == not_connected )
					tape[arg[1]].connect = sum_connected;
				else
					tape[arg[1]].connect = yes_connected;
				if( tape[i_var].connect == sum_connected )
					tape[i_var].connect = csum_connected;
			}
			break; // --------------------------------------------

		
			// Special case for AddvvOp and SubvvOp
			case AddvvOp:
			case SubvvOp:
			if( tape[i_var].connect != not_connected )
			{
				if( tape[arg[0]].connect == not_connected )
					tape[arg[0]].connect = sum_connected;
				else
					tape[arg[0]].connect = yes_connected;

				if( tape[arg[1]].connect == not_connected )
					tape[arg[1]].connect = sum_connected;
				else
					tape[arg[1]].connect = yes_connected;
				if( tape[i_var].connect == sum_connected )
					tape[i_var].connect = csum_connected;
			}
			break; // --------------------------------------------

			// Other binary operators 
			// where operands are arg[0], arg[1]
			case DivvvOp:
			case MulvvOp:
			case PowvvOp:
			if( tape[i_var].connect != not_connected )
			{
				tape[arg[0]].connect = yes_connected;
				tape[arg[1]].connect = yes_connected;
			}
			break; // --------------------------------------------

			// Conditional expression operators
			case CExpOp:
			CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );
			if( tape[i_var].connect != not_connected )
			{
				mask = 1;
				for(i = 2; i < 6; i++)
				{	if( arg[1] & mask )
					{	CPPAD_ASSERT_UNKNOWN( arg[i] < i_var );
						tape[arg[i]].connect = yes_connected;
					}
					mask = mask << 1;
				}
			}
			break;  // --------------------------------------------

			// Operations where there is noting to do
			case BeginOp:
			case ComOp:
			case EndOp:
			case InvOp:
			case ParOp:
			case PripOp:
			case StppOp:
			break;  // --------------------------------------------

			// Load using a parameter index
			case LdpOp:
			if( tape[i_var].connect != not_connected )
			{
				i                = vecad[ arg[0] - 1 ];
				vecad_connect[i] = yes_connected;
			}
			break; // --------------------------------------------

			// Load using a variable index
			case LdvOp:
			if( tape[i_var].connect != not_connected )
			{
				i                    = vecad[ arg[0] - 1 ];
				vecad_connect[i]     = yes_connected;
				tape[arg[1]].connect = yes_connected;
			}
			break; // --------------------------------------------

			// Store a variable using a parameter index
			case StpvOp:
			i = vecad[ arg[0] - 1 ];
			if( vecad_connect[i] != not_connected )
				tape[arg[2]].connect = yes_connected;
			break; // --------------------------------------------

			// Store a variable using a variable index
			case StvvOp:
			i = vecad[ arg[0] - 1 ];
			if( vecad_connect[i] )
			{	tape[arg[1]].connect = yes_connected;
				tape[arg[2]].connect = yes_connected;
			}
			break; // --------------------------------------------

			// all cases should be handled above
			default:
			CPPAD_ASSERT_UNKNOWN(0);
		}
	}
	// values corresponding to BeginOp
	CPPAD_ASSERT_UNKNOWN( i_op == 0 && i_var == 0 && op == BeginOp );
	tape[i_var].op = op;
	// -------------------------------------------------------------

	// Erase all information in the recording
	rec->Erase();

	// Initilaize table mapping hash code to variable index in tape
	// as pointing to the BeginOp at the beginning of the tape
	CppAD::vector<size_t>  hash_table_var(CPPAD_HASH_TABLE_SIZE);
	for(i = 0; i < CPPAD_HASH_TABLE_SIZE; i++)
		hash_table_var[i] = 0;
	CPPAD_ASSERT_UNKNOWN( tape[0].op == BeginOp );

	// initialize mapping from old variable index to new variable index
	for(i = 0; i < num_var; i++)
		tape[i].new_var = num_var; // invalid index
	

	// initialize mapping from old VecAD index to new VecAD index
	CppAD::vector<size_t> new_vecad_ind(num_vecad_ind);
	for(i = 0; i < num_vecad_ind; i++)
		new_vecad_ind[i] = num_vecad_ind; // invalid index 

	j = 0;     // index into the old set of indices
	for(i = 0; i < num_vecad_vec; i++)
	{	// length of this VecAD
		size_t length = play->GetVecInd(j);
		if( vecad_connect[i] != not_connected )
		{	// Put this VecAD vector in new recording
			CPPAD_ASSERT_UNKNOWN(length < num_vecad_ind);
			new_vecad_ind[j] = rec->PutVecInd(length);
			for(k = 1; k <= length; k++) new_vecad_ind[j+k] =
				rec->PutVecInd(
					rec->PutPar(
						play->GetPar( 
							play->GetVecInd(j+k)
			) ) );
		}
		// start of next VecAD
		j       += length + 1;
	}
	CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind );

	// start playing the operations in the forward direction
	play->start_forward(op, arg, i_op, i_var);

	// playing forward skips BeginOp at the beginning, but not EndOp at
	// the end.  Put BeginOp at beginning of recording
	CPPAD_ASSERT_UNKNOWN( op == BeginOp );
	CPPAD_ASSERT_NARG_NRES(BeginOp, 0, 1);
	tape[i_var].new_var = rec->PutOp(BeginOp);

	// temporary buffer for new argument values
	size_t new_arg[6];

	// temporary work space used by optimize_record_csum
	// (decalared here to avoid realloaction of memory)
	optimize_csum_stacks csum_work;

	while(op != EndOp)
	{	// next 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) );

		// determine if we should keep this operation in the new
		// operation sequence
		bool keep;
		switch( op )
		{	case ComOp:
			case PripOp:
			case PrivOp:
			keep = false;
			break;

			case InvOp:
			case EndOp:
			keep = true;
			break;

			case StppOp:
			case StvpOp:
			case StpvOp:
			case StvvOp:
			CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
			i = vecad[ arg[0] - 1 ];
			keep = vecad_connect[i] != not_connected;
			break;

			case AddpvOp:
			case AddvvOp:
			case SubpvOp:
			case SubvpOp:
			case SubvvOp:
			keep  = tape[i_var].connect != not_connected;
			keep &= tape[i_var].connect != csum_connected;
			break; 

			default:
			keep = tape[i_var].connect != not_connected;
			break;
		}

		size_t         match_var    = 0;
		unsigned short code         = 0;
		bool           replace_hash = false;
		if( keep ) switch( op )
		{
			// Unary operator where operand is arg[0]
			case AbsOp:
			case AcosOp:
			case AsinOp:
			case AtanOp:
			case CosOp:
			case CoshOp:
			case DisOp:
			case ExpOp:
			case LogOp:
			case SinOp:
			case SinhOp:
			case SqrtOp:
			match_var = optimize_unary_match(
				tape                ,  // inputs 
				i_var               ,
				play->num_rec_par() ,
				play->GetPar()      ,
				hash_table_var      ,
				code                  // outputs
			);
			if( match_var > 0 )
				tape[i_var].new_var = match_var;
			else
			{
				replace_hash = true;
				new_arg[0]   = tape[ arg[0] ].new_var;
				rec->PutArg( new_arg[0] );
				i                   = rec->PutOp(op);
				tape[i_var].new_var = i;
				CPPAD_ASSERT_UNKNOWN( new_arg[0] < i );
			}
			break;
			// ---------------------------------------------------
			// Binary operators where 
			// left is a variable and right is a parameter
			case SubvpOp:
			if( tape[arg[0]].connect == csum_connected )
			{
				// convert to a sequence of summation operators
				tape[i_var].new_var = optimize_record_csum(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					csum_work
				);
				// abort rest of this case
				break;
			}
			case DivvpOp:
			case PowvpOp:
			match_var = optimize_binary_match(
				tape                ,  // inputs 
				i_var               ,
				play->num_rec_par() ,
				play->GetPar()      ,
				hash_table_var      ,
				code                  // outputs
			);
			if( match_var > 0 )
				tape[i_var].new_var = match_var;
			else
			{	tape[i_var].new_var = optimize_record_vp(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					op                  ,
					arg
				);
				replace_hash = true;
			}
			break;
			// ---------------------------------------------------
			// Binary operators where 
			// left is a parameter and right is a variable
			case SubpvOp:
			case AddpvOp:
			if( tape[arg[1]].connect == csum_connected )
			{
				// convert to a sequence of summation operators
				tape[i_var].new_var = optimize_record_csum(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					csum_work
				);
				// abort rest of this case
				break;
			}
			case DivpvOp:
			case MulpvOp:
			case PowpvOp:
			match_var = optimize_binary_match(
				tape                ,  // inputs 
				i_var               ,
				play->num_rec_par() ,
				play->GetPar()      ,
				hash_table_var      ,
				code                  // outputs
			);
			if( match_var > 0 )
				tape[i_var].new_var = match_var;
			else
			{	tape[i_var].new_var = optimize_record_pv(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					op                  ,
					arg
				);
				replace_hash = true;
			}
			break;
			// ---------------------------------------------------
			// Binary operator where 
			// both operators are variables
			case AddvvOp:
			case SubvvOp:
			if( (tape[arg[0]].connect == csum_connected) |
			    (tape[arg[1]].connect == csum_connected)
			)
			{
				// convert to a sequence of summation operators
				tape[i_var].new_var = optimize_record_csum(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					csum_work
				);
				// abort rest of this case
				break;
			}
			case DivvvOp:
			case MulvvOp:
			case PowvvOp:
			match_var = optimize_binary_match(
				tape                ,  // inputs 
				i_var               ,
				play->num_rec_par() ,
				play->GetPar()      ,
				hash_table_var      ,
				code                  // outputs
			);
			if( match_var > 0 )
				tape[i_var].new_var = match_var;
			else
			{	tape[i_var].new_var = optimize_record_vv(
					tape                , // inputs
					i_var               ,
					play->num_rec_par() ,
					play->GetPar()      ,
					rec                 ,
					op                  ,
					arg
				);
				replace_hash = true;
			}
			break;
			// ---------------------------------------------------
			// Conditional expression operators
			case CExpOp:
			CPPAD_ASSERT_NARG_NRES(op, 6, 1);
			new_arg[0] = arg[0];
			new_arg[1] = arg[1];
			mask = 1;
			for(i = 2; i < 6; i++)
			{	if( arg[1] & mask )
				{	new_arg[i] = tape[arg[i]].new_var;
					CPPAD_ASSERT_UNKNOWN( 
						new_arg[i] < num_var 
					);
				}
				else	new_arg[i] = rec->PutPar( 
						play->GetPar( arg[i] )
				);
				mask = mask << 1;
			}
			rec->PutArg(
				new_arg[0] ,
				new_arg[1] ,
				new_arg[2] ,
				new_arg[3] ,
				new_arg[4] ,
				new_arg[5] 
			);
			tape[i_var].new_var = rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Operations with no arguments and no results
			case EndOp:
			CPPAD_ASSERT_NARG_NRES(op, 0, 0);
			rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Operations with no arguments and one result
			case InvOp:
			CPPAD_ASSERT_NARG_NRES(op, 0, 1);
			tape[i_var].new_var = rec->PutOp(op);
			break;
 			// ---------------------------------------------------
			// Operations with one argument that is a parameter
			case ParOp:
			CPPAD_ASSERT_NARG_NRES(op, 1, 1);
			new_arg[0] = rec->PutPar( play->GetPar(arg[0] ) );

			rec->PutArg( new_arg[0] );
			tape[i_var].new_var = rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Load using a parameter index
			case LdpOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 1);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = arg[1];
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			rec->PutArg( 
				new_arg[0], 
				new_arg[1], 
				0
			);
			tape[i_var].new_var = rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Load using a variable index
			case LdvOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 1);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = tape[arg[1]].new_var;
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
			rec->PutArg( 
				new_arg[0], 
				new_arg[1], 
				0
			);
			tape[i_var].new_var = rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Store a parameter using a parameter index
			case StppOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 0);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = rec->PutPar( play->GetPar(arg[1]) );
			new_arg[2] = rec->PutPar( play->GetPar(arg[2]) );
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			rec->PutArg(
				new_arg[0], 
				new_arg[1], 
				new_arg[2]
			);
			rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Store a parameter using a variable index
			case StvpOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 0);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = tape[arg[1]].new_var;
			new_arg[2] = rec->PutPar( play->GetPar(arg[2]) );
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
			rec->PutArg(
				new_arg[0], 
				new_arg[1], 
				new_arg[2]
			);
			rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Store a variable using a parameter index
			case StpvOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 0);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = rec->PutPar( play->GetPar(arg[1]) );
			new_arg[2] = tape[arg[2]].new_var;
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
			CPPAD_ASSERT_UNKNOWN( new_arg[2] < num_var );
			rec->PutArg(
				new_arg[0], 
				new_arg[1], 
				new_arg[2]
			);
			rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// Store a variable using a variable index
			case StvvOp:
			CPPAD_ASSERT_NARG_NRES(op, 3, 0);
			new_arg[0] = new_vecad_ind[ arg[0] ];
			new_arg[1] = tape[arg[1]].new_var;
			new_arg[2] = tape[arg[2]].new_var;
			CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_vecad_ind );
			CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
			CPPAD_ASSERT_UNKNOWN( new_arg[2] < num_var );
			rec->PutArg(
				new_arg[0], 
				new_arg[1], 
				new_arg[2]
			);
			rec->PutOp(op);
			break;
			// ---------------------------------------------------
			// all cases should be handled above
			default:
			CPPAD_ASSERT_UNKNOWN(false);

		}
		if( replace_hash )
		{	// The old variable index i_var corresponds to the 
			// new variable index tape[i_var].new_var. In addition
			// this is the most recent variable that has this code.
			hash_table_var[code] = i_var;
		}

	}
	// modify the dependent variable vector to new indices
	for(i = 0; i < dep_taddr.size(); i++ )
	{	CPPAD_ASSERT_UNKNOWN( tape[ dep_taddr[i] ].new_var < num_var );
		dep_taddr[i] = tape[ dep_taddr[i] ].new_var;
	}
}
示例#3
0
inline void reverse_asin_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      nc_taylor    , 
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( i_x + 1 < i_z );
	CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * nc_taylor;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* z  = taylor  + i_z * nc_taylor;
	Base* pz       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* b  = z  - nc_taylor; // called y in documentation
	Base* pb       = pz - nc_partial;

	// number of indices to access
	size_t j = d;
	size_t k;
	while(j)
	{
		// scale partials w.r.t b[j] by 1 / b[0]
		pb[j] /= b[0];

		// scale partials w.r.t z[j] by 1 / b[0]
		pz[j] /= b[0];

		// update partials w.r.t b^0 
		pb[0] -= pz[j] * z[j] + pb[j] * b[j]; 

		// update partial w.r.t. x^0
		px[0] -= pb[j] * x[j];

		// update partial w.r.t. x^j
		px[j] += pz[j] - pb[j] * x[0];

		// further scale partial w.r.t. z[j] by 1 / j
		pz[j] /= Base(j);

		for(k = 1; k < j; k++)
		{	// update partials w.r.t b^(j-k)
			pb[j-k] -= Base(k) * pz[j] * z[k] + pb[j] * b[k];

			// update partials w.r.t. x^k 
			px[k]   -= pb[j] * x[j-k];

			// update partials w.r.t. z^k
			pz[k]   -= pz[j] * Base(k) * b[j-k];
		}
		--j;
	}

	// j == 0 case
	px[0] += ( pz[0] - pb[0] * x[0]) / b[0];
}
示例#4
0
void ADTape<Base>::RecordCondExp(
	enum CompareOp  cop         ,
	AD<Base>       &returnValue ,
	const AD<Base> &left        ,
	const AD<Base> &right       ,
	const AD<Base> &if_true     ,
	const AD<Base> &if_false    )
{	size_t   ind0, ind1, ind2, ind3, ind4, ind5;
	size_t   returnValue_taddr;

	// taddr_ of this variable
	CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );
	returnValue_taddr = Rec_.PutOp(CExpOp);

	// ind[0] = cop
	ind0 = addr_t( cop );

	// ind[1] = base 2 representaion of the value
	// [Var(left), Var(right), Var(if_true), Var(if_false)]
	ind1 = 0;

	// Make sure returnValue is in the list of variables and set its taddr
	if( Parameter(returnValue) )
		returnValue.make_variable(id_, returnValue_taddr );
	else	returnValue.taddr_ = returnValue_taddr;

	// ind[2] = left address
	if( Parameter(left) )
		ind2 = Rec_.PutPar(left.value_);
	else
	{	ind1 += 1;
		ind2 = left.taddr_;
	}

	// ind[3] = right address
	if( Parameter(right) )
		ind3 = Rec_.PutPar(right.value_);
	else
	{	ind1 += 2;
		ind3 = right.taddr_;
	}

	// ind[4] = if_true address
	if( Parameter(if_true) )
		ind4 = Rec_.PutPar(if_true.value_);
	else
	{	ind1 += 4;
		ind4 = if_true.taddr_;
	}

	// ind[5] =  if_false address
	if( Parameter(if_false) )
		ind5 = Rec_.PutPar(if_false.value_);
	else
	{	ind1 += 8;
		ind5 = if_false.taddr_;
	}

	CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );
	CPPAD_ASSERT_UNKNOWN( ind1 > 0 );
	Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5);

	// check that returnValue is a dependent variable
	CPPAD_ASSERT_UNKNOWN( Variable(returnValue) );
}
示例#5
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
	}
示例#6
0
inline void reverse_cond_op(
	size_t         d           ,
	size_t         i_z         ,
	const addr_t*  arg         , 
	size_t         num_par     ,
	const Base*    parameter   ,
	size_t         nc_taylor   ,
	const Base*    taylor      ,
	size_t         nc_partial  ,
	Base*          partial     )
{	Base y_0, y_1;
	Base zero(0);
	Base* pz;
	Base* py_2;
	Base* py_3;

	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );
	CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );
	CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );

	pz = partial + i_z * nc_partial + 0;
	if( arg[1] & 1 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
		y_0 = taylor[ arg[2] * nc_taylor + 0 ];
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
		y_0 = parameter[ arg[2] ];
	}
	if( arg[1] & 2 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
		y_1 = taylor[ arg[3] * nc_taylor + 0 ];
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
		y_1 = parameter[ arg[3] ];
	}
	if( arg[1] & 4 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );
		py_2 = partial + arg[4] * nc_partial;
		size_t j = d + 1;
		while(j--)
		{	py_2[j] += CondExpOp(
				CompareOp( arg[0] ),
				y_0,
				y_1,
				pz[j],
				zero
			);
		}
	}
	if( arg[1] & 8 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
		py_3 = partial + arg[5] * nc_partial;
		size_t j = d + 1;
		while(j--)
		{	py_3[j] += CondExpOp(
				CompareOp( arg[0] ),
				y_0,
				y_1,
				zero,
				pz[j]
			);
		}
	}
	return;
}
示例#7
0
文件: for_hes.hpp 项目: barak/cppad
void for_hes(
    const local::player<Base>* play,
    size_t                     n,
    size_t                     numvar,
    const Vector_set&          for_jac_sparse,
    const Vector_set&          rev_jac_sparse,
    Vector_set&                for_hes_sparse,
    const RecBase&             not_used_rec_base
)
{
    // 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;
    pod_vector<size_t> vecad_ind;
    pod_vector<bool>   vecad_jac;
    if( num_vecad_vec > 0 )
    {   size_t length;
        vecad_sparse.resize(num_vecad_vec, limit);
        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 AFunOp.
    vector<Base>         atom_x;  //// value of parameter arguments to function
    vector<ad_type_enum> type_x;  // argument types
    pod_vector<size_t>   atom_ix; // variable index (on tape) for each argument
    pod_vector<size_t>   atom_iy; // variable index (on tape) for each result
    //
    // information set by atomic forward (initialization to avoid warnings)
    size_t atom_index=0, atom_old=0, atom_m=0, atom_n=0, atom_i=0, atom_j=0;
    // information set by atomic forward (necessary initialization)
    enum_atom_state atom_state = start_atom;
    // -------------------------------------------------------------------------
    //
    // pointer to the beginning of the parameter vector
    // (used by atomic functions)
    const Base* parameter = CPPAD_NULL;
    if( num_par > 0 )
        parameter = play->GetPar();
    //
    // which parametes are dynamic
    const pod_vector<bool>& dyn_par_is( play->dyn_par_is() );
    //
    // skip the BeginOp at the beginning of the recording
    play::const_sequential_iterator itr = play->begin();
    // op_info
    OpCode op;
    size_t i_var;
    const Addr*   arg;
    itr.op_info(op, arg, i_var);
    CPPAD_ASSERT_UNKNOWN( op == BeginOp );
# if CPPAD_FOR_HES_TRACE
    vector<size_t> atom_funrp; // parameter index for FunrpOp operators
    std::cout << std::endl;
    CppAD::vectorBool zf_value(limit);
    CppAD::vectorBool zh_value(limit * limit);
# endif
    bool flag; // temporary for use in switch cases below
    bool more_operators = true;
    while(more_operators)
    {
        // next op
        (++itr).op_info(op, arg, i_var);

        // does the Hessian in question have a non-zero derivative
        // with respect to this variable
        bool include = NumRes(op) > 0;
        if( include )
            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 == CSumOp;
        include |= op == AFunOp;
        include |= op == FunapOp;
        include |= op == FunavOp;
        include |= op == FunrpOp;
        include |= op == FunrvOp;
        //
        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(
                size_t(arg[0]), for_jac_sparse, for_hes_sparse
            );
            break;
            // -------------------------------------------------

            case CSkipOp:
            itr.correct_before_increment();
            break;
            // -------------------------------------------------

            case CSumOp:
            itr.correct_before_increment();
            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(
                size_t(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(
                size_t(arg[0]), for_jac_sparse, for_hes_sparse
            );
            break;
            // -------------------------------------------------

            // -------------------------------------------------
            // logical comparision operators
            case EqppOp:
            case EqpvOp:
            case EqvvOp:
            case LtppOp:
            case LtpvOp:
            case LtvpOp:
            case LtvvOp:
            case LeppOp:
            case LepvOp:
            case LevpOp:
            case LevvOp:
            case NepvOp:
            case NeppOp:
            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(
                size_t(arg[1]), for_jac_sparse, for_hes_sparse
            );
            break;
            // -------------------------------------------------

            case PowvpOp:
            CPPAD_ASSERT_NARG_NRES(op, 2, 3)
            forward_sparse_hessian_nonlinear_unary_op(
                size_t(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 AFunOp:
            // start or end an atomic function call
            CPPAD_ASSERT_UNKNOWN(
                atom_state == start_atom || atom_state == end_atom
            );
            flag = atom_state == start_atom;
            play::atom_op_info<RecBase>(
                op, arg, atom_index, atom_old, atom_m, atom_n
            );
            if( flag )
            {   atom_state = arg_atom;
                atom_i     = 0;
                atom_j     = 0;
                //
                atom_x.resize( atom_n );
                type_x.resize( atom_n );
                atom_ix.resize( atom_n );
                atom_iy.resize( atom_m );
# if CPPAD_FOR_HES_TRACE
                atom_funrp.resize( atom_m );
# endif
            }
            else
            {   CPPAD_ASSERT_UNKNOWN( atom_i == atom_m );
                CPPAD_ASSERT_UNKNOWN( atom_j == atom_n );
                atom_state = start_atom;
                //
                call_atomic_for_hes_sparsity<Base,RecBase>(
                    atom_index, atom_old, atom_x, type_x, atom_ix, atom_iy,
                    for_jac_sparse, rev_jac_sparse, for_hes_sparse
                );
            }
            break;

            case FunapOp:
            // parameter argument for a atomic function
            CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );
            CPPAD_ASSERT_UNKNOWN( atom_i == 0 );
            CPPAD_ASSERT_UNKNOWN( atom_j < atom_n );
            CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par );
            //
            atom_x[atom_j] = parameter[arg[0]];
            // argument type
            if( dyn_par_is[arg[0]] )
                type_x[atom_j] = dynamic_enum;
            else
                type_x[atom_j] = constant_enum;
            atom_ix[atom_j] = 0; // special variable used for parameters
            //
            ++atom_j;
            if( atom_j == atom_n )
                atom_state = ret_atom;
            break;

            case FunavOp:
            // variable argument for a atomic function
            CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );
            CPPAD_ASSERT_UNKNOWN( atom_i == 0 );
            CPPAD_ASSERT_UNKNOWN( atom_j < atom_n );
            //
            // arguemnt variables not avaialbe during sparisty calculations
            atom_x[atom_j] = CppAD::numeric_limits<Base>::quiet_NaN();
            type_x[atom_j] = variable_enum;
            atom_ix[atom_j] = size_t(arg[0]); // variable for this argument
            //
            ++atom_j;
            if( atom_j == atom_n )
                atom_state = ret_atom;
            break;

            case FunrpOp:
            // parameter result for a atomic function
            CPPAD_ASSERT_NARG_NRES(op, 1, 0);
            CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom );
            CPPAD_ASSERT_UNKNOWN( atom_i < atom_m );
            CPPAD_ASSERT_UNKNOWN( atom_j == atom_n );
            CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par );
            //
            atom_iy[atom_i] = 0; // special variable used for parameters
# if CPPAD_FOR_HES_TRACE
            // remember argument for delayed tracing
            atom_funrp[atom_i] = arg[0];
# endif
            ++atom_i;
            if( atom_i == atom_m )
                atom_state = end_atom;
            break;

            case FunrvOp:
            // variable result for a atomic function
            CPPAD_ASSERT_NARG_NRES(op, 0, 1);
            CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom );
            CPPAD_ASSERT_UNKNOWN( atom_i < atom_m );
            CPPAD_ASSERT_UNKNOWN( atom_j == atom_n );
            //
            atom_iy[atom_i] = i_var; // variable index for this result
            //
            ++atom_i;
            if( atom_i == atom_m )
                atom_state = end_atom;
            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_TRACE
        typedef typename Vector_set::const_iterator const_iterator;
        if( op == AFunOp && atom_state == start_atom )
        {   // print operators that have been delayed
            CPPAD_ASSERT_UNKNOWN( atom_m == atom_iy.size() );
            CPPAD_ASSERT_UNKNOWN( itr.op_index() > atom_m );
            CPPAD_ASSERT_NARG_NRES(FunrpOp, 1, 0);
            CPPAD_ASSERT_NARG_NRES(FunrvOp, 0, 1);
            addr_t arg_tmp[1];
            for(k = 0; k < atom_m; k++)
            {   size_t k_var = atom_iy[k];
                // value for this variable
                for(i = 0; i < limit; i++)
                {   zf_value[i] = false;
                    for(j = 0; j < limit; j++)
                        zh_value[i * limit + j] = false;
                }
                const_iterator itr_1(for_jac_sparse, i_var);
                j = *itr_1;
                while( j < limit )
                {   zf_value[j] = true;
                    j = *(++itr_1);
                }
                for(i = 0; i < limit; i++)
                {   const_iterator itr_2(for_hes_sparse, i);
                    j = *itr_2;
                    while( j < limit )
                    {   zh_value[i * limit + j] = true;
                        j = *(++itr_2);
                    }
                }
                OpCode op_tmp = FunrvOp;
                if( k_var == 0 )
                {   op_tmp     = FunrpOp;
                    arg_tmp[0] = atom_funrp[k];
                }
                // k_var is zero when there is no result
                printOp<Base, RecBase>(
                    std::cout,
                    play,
                    itr.op_index() - atom_m + k,
                    k_var,
                    op_tmp,
                    arg_tmp
                );
                if( k_var > 0 ) printOpResult(
                    std::cout,
                    1,
                    &zf_value,
                    1,
                    &zh_value
                );
                std::cout << std::endl;
            }
        }
        for(i = 0; i < limit; i++)
        {   zf_value[i] = false;
            for(j = 0; j < limit; j++)
                zh_value[i * limit + j] = false;
        }
        const_iterator itr_1(for_jac_sparse, i_var);
        j = *itr_1;
        while( j < limit )
        {   zf_value[j] = true;
            j = *(++itr_1);
        }
        for(i = 0; i < limit; i++)
        {   const_iterator itr_2(for_hes_sparse, i);
            j = *itr_2;
            while( j < limit )
            {   zh_value[i * limit + j] = true;
                j = *(++itr_2);
            }
        }
        // must delay print for these cases till after atomic function call
        bool delay_print = op == FunrpOp;
        delay_print     |= op == FunrvOp;
        if( ! delay_print )
        {    printOp<Base, RecBase>(
                std::cout,
                play,
                itr.op_index(),
                i_var,
                op,
                arg
            );
            if( NumRes(op) > 0 && (! delay_print) ) printOpResult(
                std::cout,
                1,
                &zf_value,
                1,
                &zh_value
            );
            std::cout << std::endl;
        }
    }
    std::cout << std::endl;
# else
    }
示例#8
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
	}
示例#9
0
AD<Base>& AD<Base>::operator -= (const AD<Base> &right)
{	ADTape<Base> *tape = AD<Base>::tape_ptr();
	size_t tape_id = 0;
	if( tape != CPPAD_NULL )
		tape_id = tape->id_;

	// id_ setting for parameters cannot match 0
	bool var_left  = id_       == tape_id;
	bool var_right = right.id_ == tape_id;
	CPPAD_ASSERT_KNOWN(
		Parameter(*this) || var_left ,
		"-=: left operand is a variable for a different thread"
	);
	CPPAD_ASSERT_KNOWN(
		Parameter(right) || var_right ,
		"-=: right operand is a variable for a different thread"
	);

	Base left;
	left    = value_;
	value_ -= right.value_;

	if( var_left )
	{	if( var_right )
		{	// this = variable - variable
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(taddr_, right.taddr_);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvvOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
		}
		else if( IdenticalZero( right.value_ ) )
		{	// this = variable - 0
		}
		else
		{	// this = variable - parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(taddr_, p);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvpOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
		}
	}
	else if( var_right  )
	{	// this = parameter - variable
		CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );

		// put operand addresses in tape
		addr_t p = tape->Rec_.PutPar(left);
		tape->Rec_.PutArg(p, right.taddr_);
		// put operator in the tape
		taddr_ = tape->Rec_.PutOp(SubpvOp);
		// make this a variable
		id_ = tape_id;
	}
	return *this;
}
示例#10
0
void ForHesSweep(
	size_t                n,
	size_t                numvar,
	local::player<Base>*  play,
	const Vector_set&     for_jac_sparse,
	const Vector_set&     rev_jac_sparse,
	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() );
	}
	// ------------------------------------------------------------------------
	// 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;   // value of parameter arguments to function
	vector<size_t>     user_ix;  // variable index (on tape) for each argument
	vector<size_t>     user_iy;  // variable index (on tape) for each result
	//
	// 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 = start_user;
	// -------------------------------------------------------------------------
	//
	// 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
	vector<size_t> user_usrrp; // parameter index for UsrrpOp operators
	CppAD::vectorBool zf_value(limit);
	CppAD::vectorBool zh_value(limit * limit);
# endif
	bool flag; // temporary for use in switch cases below
	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 == CSumOp;
		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->forward_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->forward_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:
			CPPAD_ASSERT_UNKNOWN(
				user_state == start_user || user_state == end_user
			);
			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 )
			{	// start of user atomic operation sequence
				user_x.resize( user_n );
				user_ix.resize( user_n );
				user_iy.resize( user_m );
# if CPPAD_FOR_HES_SWEEP_TRACE
				user_usrrp.resize( user_m );
# endif
			}
			else
			{	// end of user atomic operation sequence
				user_atom->set_old(user_old);
				user_atom->for_sparse_hes(
					user_x, user_ix, user_iy,
					for_jac_sparse, rev_jac_sparse, for_hes_sparse
				);
			}
			break;

			case UsrapOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
			// argument parameter value
			user_x[user_j] = parameter[arg[0]];
			// special variable user for parameters
			user_ix[user_j] = 0;
			//
			play->forward_user(op, user_state,
				user_old, user_m, user_n, user_i, user_j
			);
			break;

			case UsravOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
			CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
			// arguemnt varialbes not avaialbe during sparisty calculations
			user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN();
			// varialbe index for this argument
			user_ix[user_j] = arg[0];
			//
			play->forward_user(op, user_state,
				user_old, user_m, user_n, user_i, user_j
			);
			break;

			case UsrrpOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
			// special variable index user for parameters
			user_iy[user_i] = 0;
# if CPPAD_FOR_HES_SWEEP_TRACE
			// remember argument for delayed tracing
			user_usrrp[user_i] = arg[0];
# endif
			//
			play->forward_user(op, user_state,
				user_old, user_m, user_n, user_i, user_j
			);
			break;

			case UsrrvOp:
			// variable index for this result
			user_iy[user_i] = i_var;
			//
			play->forward_user(op, user_state,
				user_old, user_m, user_n, user_i, user_j
			);
			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
		typedef typename Vector_set::const_iterator const_iterator;
		if( op == UserOp && user_state == start_user )
		{	// print operators that have been delayed
			CPPAD_ASSERT_UNKNOWN( user_m == user_iy.size() );
			CPPAD_ASSERT_UNKNOWN( i_op > user_m );
			CPPAD_ASSERT_NARG_NRES(UsrrpOp, 1, 0);
			CPPAD_ASSERT_NARG_NRES(UsrrvOp, 0, 1);
			addr_t arg_tmp[1];
			for(k = 0; k < user_m; k++)
			{	size_t k_var = user_iy[k];
				// value for this variable
				for(i = 0; i < limit; i++)
				{	zf_value[i] = false;
					for(j = 0; j < limit; j++)
						zh_value[i * limit + j] = false;
				}
				const_iterator itr_1(for_jac_sparse, i_var);
				j = *itr_1;
				while( j < limit )
				{	zf_value[j] = true;
					j = *(++itr_1);
				}
				for(i = 0; i < limit; i++)
				{	const_iterator itr_2(for_hes_sparse, i);
					j = *itr_2;
					while( j < limit )
					{	zh_value[i * limit + j] = true;
						j = *(++itr_2);
					}
				}
				OpCode op_tmp = UsrrvOp;
				if( k_var == 0 )
				{	op_tmp     = UsrrpOp;
					arg_tmp[0] = user_usrrp[k];
				}
				// k_var is zero when there is no result
				//printOp(
				//	std::cout,
				//	play,
				//	i_op - user_m + k,
				//	k_var,
				//	op_tmp,
				//	arg_tmp
				//);
				if( k_var > 0 ){
                //    printOpResult(
				//	std::cout,
				//	1,
				//	&zf_value,
				//	1,
				//	&zh_value
				//);
                }
			}
		}
		const addr_t*   arg_tmp = arg;
		if( op == CSumOp )
			arg_tmp = arg - arg[-1] - 4;
		if( op == CSkipOp )
			arg_tmp = arg - arg[-1] - 7;
		for(i = 0; i < limit; i++)
		{	zf_value[i] = false;
			for(j = 0; j < limit; j++)
				zh_value[i * limit + j] = false;
		}
		const_iterator itr_1(for_jac_sparse, i_var);
		j = *itr_1;
		while( j < limit )
		{	zf_value[j] = true;
			j = *(++itr_1);
		}
		for(i = 0; i < limit; i++)
		{	const_iterator itr_2(for_hes_sparse, i);
			j = *itr_2;
			while( j < limit )
			{	zh_value[i * limit + j] = true;
				j = *(++itr_2);
			}
		}
		// must delay print for these cases till after atomic user call
		bool delay_print = op == UsrrpOp;
		delay_print     |= op == UsrrvOp;
		if( ! delay_print )
		{	// printOp(
			//	std::cout,
			//	play,
			//	i_op,
			//	i_var,
			//	op,
			//	arg_tmp
			//);
			if( NumRes(op) > 0 && (! delay_print) ){
        //        printOpResult(
		//		std::cout,
		//		1,
		//		&zf_value,
		//		1,
		//		&zh_value
		//	);
            }
		}
	}
# else
	}
示例#11
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
	}
示例#12
0
文件: add.hpp 项目: GodinA/adcomp
AD<Base> operator + (const AD<Base> &left , const AD<Base> &right)
{
	// compute the Base part of this AD object
	AD<Base> result;
	result.value_  = left.value_ + right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_left  = left.tape_id_  == tape_id;
	bool var_right = right.tape_id_ == tape_id;

	if( var_left )
	{	if( var_right )
		{	// result = variable + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddvvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalZero(right.value_) )
		{	// result = variable + 0
			result.make_variable(left.tape_id_, left.taddr_);
		}
		else
		{	// result = variable  + parameter
			//        = parameter + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(p, left.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_right )
	{	if( IdenticalZero(left.value_) )
		{	// result = 0 + variable
			result.make_variable(right.tape_id_, right.taddr_);
		}
		else
		{	// result = parameter + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(left.value_);
			tape->Rec_.PutArg(p, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
示例#13
0
void printOp(
	std::ostream          &os     , 
	const player<Base>   *Rec     ,
	size_t                 i_var  , 
	OpCode                 op     ,
	const addr_t          *ind    ,
	size_t                 nfz    ,
	const  Value          *fz     ,
	size_t                 nrz    ,
	const  Value          *rz     )
{	size_t i;
	
	CPPAD_ASSERT_KNOWN(
		! thread_alloc::in_parallel() ,
		"cannot print trace of AD operations in parallel mode"
	);
	static const char *CompareOpName[] = 
		{ "Lt", "Le", "Eq", "Ge", "Gt", "Ne" };
	static const char *OpName[] = {
		"Abs"   ,
		"Acos"  ,
		"Addpv" ,
		"Addvv" ,
		"Asin"  ,
		"Atan"  ,
		"Begin" ,
		"CExp"  ,
		"Com"   ,
		"Cos"   ,
		"Cosh"  ,
		"CSum"  ,
		"Dis"   ,
		"Divpv" ,
		"Divvp" ,
		"Divvv" ,
		"End"   ,
		"Exp"   ,
		"Inv"   ,
		"Ldp"   ,
		"Ldv"   ,
		"Log"   ,
		"Mulpv" ,
		"Mulvv" ,
		"Par"   ,
		"Powpv" ,
		"Powvp" ,
		"Powvv" ,
		"Pri"   ,
		"Sign"  ,
		"Sin"   ,
		"Sinh"  ,
		"Sqrt"  ,
		"Stpp"  ,
		"Stpv"  ,
		"Stvp"  ,
		"Stvv"  ,
		"Subpv" ,
		"Subvp" ,
		"Subvv" ,
		"Tan"   ,
		"Tanh"  ,
		"User"  ,
		"Usrap" ,
		"Usrav" ,
		"Usrrp" ,
		"Usrrv"
	};
	CPPAD_ASSERT_UNKNOWN( 
		size_t(NumberOp) == sizeof(OpName) / sizeof(OpName[0])
	);

	// print operator
	printOpField(os,  "i=",      i_var, 5);
	if( op == CExpOp )
	{	printOpField(os, "op=", OpName[op], 4); 
		printOpField(os, "", CompareOpName[ ind[0] ], 3);
	}
	else if( op == ComOp )
	{	printOpField(os, "op=", OpName[op], 3); 
		printOpField(os, "", CompareOpName[ ind[0] ], 4);
	}
	else	printOpField(os, "op=", OpName[op], 7); 

	// print other fields
	size_t ncol = 5;
	switch( op )
	{
		case CSumOp:
		/*
		ind[0] = number of addition variables in summation
		ind[1] = number of subtraction variables in summation
		ind[2] = index of parameter that initializes summation
		ind[3], ... , ind[2+ind[0]] = index for positive variables
		ind[3+ind[0]], ..., ind[2+ind[0]+ind[1]] = negative variables 
		ind[3+ind[0]+ind[1]] = ind[0] + ind[1]
		*/
		CPPAD_ASSERT_UNKNOWN( ind[3+ind[0]+ind[1]] == ind[0]+ind[1] );
		printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
		for(i = 0; i < ind[0]; i++)
			 printOpField(os, " +v=", ind[3+i], ncol);
		for(i = 0; i < ind[1]; i++)
			 printOpField(os, " -v=", ind[3+ind[0]+i], ncol);
		break;

		case LdpOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, "idx=", ind[1], ncol);
		break;

		case LdvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, "  v=", ind[1], ncol);
		break;

		case StppOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, "idx=", ind[1], ncol);
		printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
		break;

		case StpvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, "idx=", ind[1], ncol);
		printOpField(os, " vr=", ind[2], ncol);
		break;

		case StvpOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, " vl=", ind[1], ncol);
		printOpField(os, " pr=", Rec->GetPar(ind[2]), ncol);
		break;

		case StvvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
		printOpField(os, "off=", ind[0], ncol);
		printOpField(os, " vl=", ind[1], ncol);
		printOpField(os, " vr=", ind[2], ncol);
		break;

		case AddvvOp:
		case DivvvOp:
		case MulvvOp:
		case PowvvOp:
		case SubvvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
		printOpField(os, " vl=", ind[0], ncol);
		printOpField(os, " vr=", ind[1], ncol);
		break;

		case AddpvOp:
		case SubpvOp:
		case MulpvOp:
		case PowpvOp:
		case DivpvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
		printOpField(os, " pl=", Rec->GetPar(ind[0]), ncol);
		printOpField(os, " vr=", ind[1], ncol);
		break;

		case DivvpOp:
		case PowvpOp:
		case SubvpOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
		printOpField(os, " vl=", ind[0], ncol);
		printOpField(os, " pr=", Rec->GetPar(ind[1]), ncol);
		break;

		case AbsOp:
		case AcosOp:
		case AsinOp:
		case AtanOp:
		case CosOp:
		case CoshOp:
		case ExpOp:
		case LogOp:
		case SignOp:
		case SinOp:
		case SinhOp:
		case SqrtOp:
		case UsravOp:
		case TanOp:
		case TanhOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
		printOpField(os, "  v=", ind[0], ncol);
		break;

		case ParOp:
		case UsrapOp:
		case UsrrpOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
		printOpField(os, "  p=", Rec->GetPar(ind[0]), ncol);
		break;

		case UserOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
		{	const char* name = user_atomic<Base>::name(ind[0]);
			printOpField(os, " f=",   name, ncol);
			printOpField(os, " i=", ind[1], ncol);
			printOpField(os, " n=", ind[2], ncol);
			printOpField(os, " m=", ind[3], ncol);
		}
		break;

		case PriOp:
		CPPAD_ASSERT_NARG_NRES(op, 5, 0);
		if( ind[0] & 1 )
			printOpField(os, " v=", ind[1], ncol);
		else	printOpField(os, " p=", Rec->GetPar(ind[1]), ncol);
		os << "before=\"" << Rec->GetTxt(ind[2]) << "\"";
		if( ind[0] & 2 )
			printOpField(os, " v=", ind[3], ncol);
		else	printOpField(os, " p=", Rec->GetPar(ind[3]), ncol);
		os << "after=\"" << Rec->GetTxt(ind[4]) << "\"";
		break;

		case BeginOp:
		case EndOp:
		case InvOp:
		case UsrrvOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
		break;

		case DisOp:
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
		{	const char* name = discrete<Base>::name(ind[0]);
			printOpField(os, " f=", name, ncol);
			printOpField(os, " x=", ind[1], ncol);
		}
		break;
	

		case CExpOp:
		CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
		if( ind[1] & 1 )
			printOpField(os, " vl=", ind[2], ncol);
		else	printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol);
		if( ind[1] & 2 )
			printOpField(os, " vr=", ind[3], ncol);
		else	printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol);
		if( ind[1] & 4 )
			printOpField(os, " vt=", ind[4], ncol);
		else	printOpField(os, " pt=", Rec->GetPar(ind[4]), ncol);
		if( ind[1] & 8 )
			printOpField(os, " vf=", ind[5], ncol);
		else	printOpField(os, " pf=", Rec->GetPar(ind[5]), ncol);
		break;

		case ComOp:
		CPPAD_ASSERT_UNKNOWN(ind[1] != 0);
		CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
		if( ind[1] & 1 )
			printOpField(os, "res=", 1, ncol);
		else	printOpField(os, "res=", 0, ncol);
		if( ind[1] & 2 )
			printOpField(os, " vl=", ind[2], ncol);
		else	printOpField(os, " pl=", Rec->GetPar(ind[2]), ncol);
		if( ind[1] & 4 )
			printOpField(os, " vr=", ind[3], ncol);
		else	printOpField(os, " pr=", Rec->GetPar(ind[3]), ncol);
		break;

		default:
		CPPAD_ASSERT_UNKNOWN(0);
	}
	size_t k;
	if( NumRes(op) > 0 && (op != BeginOp) )
	{ 
		for(k = 0; k < nfz; k++)
			std::cout << "| fz[" << k << "]=" << fz[k];
		for(k = 0; k < nrz; k++)
			std::cout << "| rz[" << k << "]=" << rz[k];
	}
	std::cout << std::endl;
}
示例#14
0
文件: kasper.hpp 项目: GodinA/adcomp
void my_init(vector<bool> keepcol){
  Partial.extend(num_var_tape_ * 1);
  arg_mark_.resize(play_.op_arg_rec_.size());
  for(size_t i=0;i<arg_mark_.size();i++)arg_mark_[i]=false;
  /* Run a reverse test-sweep to store pointers once */
  tape_point tp;
  play_.reverse_start(tp.op, tp.op_arg, tp.op_index, tp.var_index);
  tp_.resize(tp.op_index+1);
  var2op_.resize(tp.var_index+1);
  op_mark_.resize(tp.op_index+1);
  for(size_t i=0;i<op_mark_.size();i++)op_mark_[i]=0;
  user_region_mark_.resize(tp.op_index+1);
  for(size_t i=0;i<user_region_mark_.size();i++)user_region_mark_[i]=0;
  tp_[tp.op_index]=tp;
  /* 1. We need to be able to find out, for a given variable, what operator created 
     the variable. This is easiest done by looping through the _operators_ because for a 
     given op we have access to all the resulting variables it creates.
     2. We precompute the a vector of "tape_points" so that instead of calling 
     "reverse_next", we simply get the next tape entry by tp_[i-1].
  */
  while(tp.op != BeginOp ){ /* tp.op_index is decremented by one in each iteration ... */
    // printTP(tp); /* For debugging */
    play_.reverse_next(tp.op, tp.op_arg, tp.op_index, tp.var_index);
    /* Csum is special case - see remarks in player.hpp and reverse_sweep.hpp */
    if(tp.op == CSumOp)play_.reverse_csum(tp.op, tp.op_arg, tp.op_index, tp.var_index);
    for(size_t i=0;i<NumRes(tp.op);i++)var2op_[tp.var_index-i]=tp.op_index;
    tp_[tp.op_index]=tp;
    markArgs(tp);
  }
  /* Lookup table: is tape_point within a UserOp region? */
  bool user_within=false;
  user_region_.resize(tp_.size());
  for(size_t i=0;i<tp_.size();i++){
    if(tp_[i].op==UserOp){
      user_region_[i]=true;
      user_within=!user_within;	
    } else {
      user_region_[i]=user_within;
    }
  }

  /* Lookup table: is tape_point a constant (=only fixed effect dependent) ? */
  constant_tape_point_.resize(tp_.size());
  int indep_var_number=0;
  for(size_t i=0;i<tp_.size();i++){
    if(tp_[i].op==InvOp){ /* All independent variables are marked according to being
			     random or fixed effect */
      constant_tape_point_[i]=!keepcol[indep_var_number];
      indep_var_number++;
    } else { /* Mark operator as constant if _all_ arguments are constant */
      constant_tape_point_[i] = is_tape_point_constant(i);
    }

    //std::cout << constant_tape_point_[i] << " "; printTP(tp_[i]);

  }
  // std::cout << "Total:   " << constant_tape_point_.size() << "\n";
  // int sum=0; for(int i=0;i<constant_tape_point_.size();i++)sum+=constant_tape_point_[i];
  // std::cout << "Constant:" << sum << "\n";


  // Calculate pattern
  int m=Range();
  colpattern.resize(m);
  for(int i=0;i<m;i++)my_pattern(i);
  for(size_t i=0;i<op_mark_.size();i++)op_mark_[i]=0; /* remember to reset marks */
  for(size_t i=0;i<user_region_mark_.size();i++)user_region_mark_[i]=0; /* remember to reset marks */
}
示例#15
0
AD<Base> operator - (const AD<Base> &left , const AD<Base> &right)
{	ADTape<Base> *tape = AD<Base>::tape_ptr();
	bool var_left, var_right;
# ifdef NDEBUG
	if( tape == CPPAD_NULL )
	{	var_left =  false;
		var_right = false;
	}
	else
	{
		var_left  = left.id_  == tape->id_;
		var_right = right.id_ == tape->id_;
	}
# else
	var_left  = Variable(left);
	var_right = Variable(right);
	CPPAD_ASSERT_KNOWN(
		(! var_left) || left.id_ == tape->id_ ,
		"- left operand is a variable for a different thread"
	);
	CPPAD_ASSERT_KNOWN(
		(! var_right) || right.id_ == tape->id_ ,
		"- right operand is a variable for a different thread"
	);
# endif

	AD<Base> result;
	result.value_  = left.value_ - right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	if( var_left )
	{	if( var_right )
		{	// result = variable - variable
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(SubvvOp);
			// make result a variable
			result.id_ = tape->id_;
		}
		else if( IdenticalZero(right.value_) )
		{	// result = variable - 0
			result.make_variable(left.id_, left.taddr_);
		}
		else
		{	// result = variable - parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );

			// put operand addresses in tape
			size_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(left.taddr_, p);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(SubvpOp);
			// make result a variable
			result.id_ = tape->id_;
		}
	}
	else if( var_right )
	{	// result = parameter - variable
		CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );

		// put operand addresses in tape
		size_t p = tape->Rec_.PutPar(left.value_);
		tape->Rec_.PutArg(p, right.taddr_);
		// put operator in the tape
		result.taddr_ = tape->Rec_.PutOp(SubpvOp);
		// make result a variable
		result.id_ = tape->id_;
	}
	return result;
}
示例#16
0
void random_setup(
    size_t                                    num_var    ,
    const pod_vector<opcode_t>&               op_vec     ,
    const pod_vector<addr_t>&                 arg_vec    ,
    pod_vector<Addr>*                         op2arg_vec ,
    pod_vector<Addr>*                         op2var_vec ,
    pod_vector<Addr>*                         var2op_vec )
{
    if( op2arg_vec->size() != 0 )
    {   CPPAD_ASSERT_UNKNOWN( op2arg_vec->size() == op_vec.size() );
        CPPAD_ASSERT_UNKNOWN( op2var_vec->size() == op_vec.size() );
        CPPAD_ASSERT_UNKNOWN( var2op_vec->size() == num_var        );
        return;
    }
    CPPAD_ASSERT_UNKNOWN( op2var_vec->size() == 0         );
    CPPAD_ASSERT_UNKNOWN( op2var_vec->size() == 0         );
    CPPAD_ASSERT_UNKNOWN( var2op_vec->size() == 0         );
    CPPAD_ASSERT_UNKNOWN( OpCode( op_vec[0] ) == BeginOp );
    CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);
    //
    size_t num_op     = op_vec.size();
    size_t  var_index = 0;
    size_t  arg_index = 0;
    //
    op2arg_vec->resize( num_op );
    op2var_vec->resize( num_op );
    var2op_vec->resize( num_var  );
# ifndef NDEBUG
    // value of var2op for auxillary variables is num_op (invalid)
    for(size_t i_var = 0; i_var < num_var; ++i_var)
        (*var2op_vec)[i_var] = Addr( num_op );
    // value of op2var is num_var (invalid) when NumRes(op) = 0
    for(size_t i_op = 0; i_op < num_op; ++i_op)
        (*op2var_vec)[i_op] = Addr( num_var );
# endif
    for(size_t i_op = 0; i_op < num_op; ++i_op)
    {   OpCode  op          = OpCode( op_vec[i_op] );
        //
        // index of first argument for this operator
        (*op2arg_vec)[i_op]   = Addr( arg_index );
        arg_index            += NumArg(op);
        //
        // index of first result for next operator
        var_index  += NumRes(op);
        if( NumRes(op) > 0 )
        {   // index of last (primary) result for this operator
            (*op2var_vec)[i_op] = Addr( var_index - 1 );
            //
            // mapping from primary variable to its operator
            (*var2op_vec)[var_index - 1] = Addr( i_op );
        }
        // CSumOp
        if( op == CSumOp )
        {   CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
            //
            // pointer to first argument for this operator
            const addr_t* op_arg = arg_vec.data() + arg_index;
            //
            // The actual number of arugments for this operator is
            // op_arg[4] + 1
            // Correct index of first argument for next operator
            arg_index += size_t(op_arg[4] + 1);
        }
        //
        // CSkip
        if( op == CSkipOp )
        {   CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );
            //
            // pointer to first argument for this operator
            const addr_t* op_arg = arg_vec.data() + arg_index;
            //
            // The actual number of arugments for this operator is
            // 7 + op_arg[4] + op_arg[5].
            // Correct index of first argument for next operator.
            arg_index += size_t(7 + op_arg[4] + op_arg[5]);
        }
    }
}
示例#17
0
inline void forward_cond_op(
	size_t         q           ,
	size_t         p           ,
	size_t         i_z         ,
	const addr_t*  arg         , 
	size_t         num_par     ,
	const Base*    parameter   ,
	size_t         nc_taylor   ,
	Base*          taylor      )
{	Base y_0, y_1, y_2, y_3;
	Base zero(0);
	Base* z = taylor + i_z * nc_taylor;

	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );
	CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );
	CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );

	if( arg[1] & 1 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
		y_0 = taylor[ arg[2] * nc_taylor + 0 ];
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
		y_0 = parameter[ arg[2] ];
	}
	if( arg[1] & 2 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
		y_1 = taylor[ arg[3] * nc_taylor + 0 ];
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
		y_1 = parameter[ arg[3] ];
	}
	if( q == 0 )
	{	if( arg[1] & 4 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );
			y_2 = taylor[ arg[4] * nc_taylor + 0 ];
		}
		else
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );
			y_2 = parameter[ arg[4] ];
		}
		if( arg[1] & 8 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
			y_3 = taylor[ arg[5] * nc_taylor + 0 ];
		}
		else
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );
			y_3 = parameter[ arg[5] ];
		}
		z[0] = CondExpOp(
			CompareOp( arg[0] ),
			y_0,
			y_1,
			y_2,
			y_3
		);
		q++;
	}
	for(size_t d = q; d <= p; d++)
	{	if( arg[1] & 4 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );
			y_2 = taylor[ arg[4] * nc_taylor + d];
		}
		else	y_2 = zero;
		if( arg[1] & 8 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
			y_3 = taylor[ arg[5] * nc_taylor + d];
		}
		else	y_3 = zero;
		z[d] = CondExpOp(
			CompareOp( arg[0] ),
			y_0,
			y_1,
			y_2,
			y_3
		);
	}
	return;
}
示例#18
0
inline void reverse_erf_op(
    size_t        d           ,
    size_t        i_z         ,
    const addr_t* arg         ,
    const Base*   parameter   ,
    size_t        cap_order   ,
    const Base*   taylor      ,
    size_t        nc_partial  ,
    Base*         partial     )
{
    // check assumptions
    CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
    CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
    CPPAD_ASSERT_UNKNOWN( d < cap_order );

    // array used to pass parameter values for sub-operations
    addr_t addr[2];

    // If pz is zero, make sure this operation has no effect
    // (zero times infinity or nan would be non-zero).
    Base* pz  = partial + i_z * nc_partial;
    bool skip(true);
    for(size_t i_d = 0; i_d <= d; i_d++)
        skip &= IdenticalZero(pz[i_d]);
    if( skip )
        return;

    // convert from final result to first result
    i_z -= 4; // 4 = NumRes(ErfOp) - 1;

    // Taylor coefficients and partials corresponding to x
    const Base* x  = taylor  + arg[0]  * cap_order;
    Base* px       = partial + arg[0] * nc_partial;

    // Taylor coefficients and partials corresponding to z_3
    const Base* z_3  = taylor  + (i_z+3) * cap_order;
    Base* pz_3       = partial + (i_z+3) * nc_partial;

    // Taylor coefficients and partials corresponding to z_4
    Base* pz_4 = partial + (i_z+4) * nc_partial;

    // Reverse z_4
    size_t j = d;
    while(j)
    {   pz_4[j] /= Base(j);
        for(size_t k = 1; k <= j; k++)
        {   px[k]     += pz_4[j] * z_3[j-k] * Base(k);
            pz_3[j-k] += pz_4[j] * x[k] * Base(k);
        }
        j--;
    }
    px[0] += pz_4[0] * z_3[0];

    // z_3 = (2 / sqrt(pi)) * exp( - x * x )
    addr[0] = arg[2];  // 2 / sqrt(pi)
    addr[1] = i_z + 2; // z_2
    reverse_mulpv_op(
        d, i_z+3, addr, parameter, cap_order, taylor, nc_partial, partial
    );

    // z_2 = exp( - x * x )
    reverse_exp_op(
        d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
    );

    // z_1 = - x * x
    addr[0] = arg[1]; // zero
    addr[1] = i_z;    // z_0
    reverse_subpv_op(
        d, i_z+1, addr, parameter, cap_order, taylor, nc_partial, partial
    );

    // z_0 = x * x
    addr[0] = arg[0]; // x
    addr[1] = arg[0]; // x
    reverse_mulvv_op(
        d, i_z+0, addr, parameter, cap_order, taylor, nc_partial, partial
    );

}
示例#19
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
	}
示例#20
0
文件: azmul.hpp 项目: barak/CppAD-1
// case where x and y are AD<Base> -------------------------------------------
template <class Base> AD<Base>
azmul(const AD<Base>& x, const AD<Base>& y)
{
	// compute the Base part
	AD<Base> result;
	result.value_ = azmul(x.value_, y.value_);

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_x = x.tape_id_ == tape_id;
	bool var_y = y.tape_id_ == tape_id;

	if( var_x )
	{	if( var_y )
		{	// result = azmul(variable, variable)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(x.taddr_, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulvvOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalZero( y.value_ ) )
		{	// result = variable * 0
		}
		else if( IdenticalOne( y.value_ ) )
		{	// result = variable * 1
			result.make_variable(x.tape_id_, x.taddr_);
		}
		else
		{	// result = zmul(variable, parameter)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(y.value_);
			tape->Rec_.PutArg(x.taddr_, p);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulvpOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_y )
	{	if( IdenticalZero(x.value_) )
		{	// result = 0 * variable
		}
		else if( IdenticalOne( x.value_ ) )
		{	// result = 1 * variable
			result.make_variable(y.tape_id_, y.taddr_);
		}
		else
		{	// result = zmul(parameter, variable)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(x.value_);
			tape->Rec_.PutArg(p, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulpvOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
示例#21
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
	}
示例#22
0
文件: get_rev.hpp 项目: barak/cppad
void subgraph_info::get_rev(
    const play::const_random_iterator<Addr>&   random_itr  ,
    const pod_vector<size_t>&                  dep_taddr   ,
    addr_t                                     i_dep       ,
    pod_vector<addr_t>&                        subgraph    )
{   // check sizes
    CPPAD_ASSERT_UNKNOWN( map_user_op_.size()   == n_op_ );

    // process_range_
    CPPAD_ASSERT_UNKNOWN( process_range_[i_dep] == false );
    process_range_[i_dep] = true;

    // special value; see init_rev_in_subgraph
    addr_t depend_yes = addr_t( n_dep_ );

    // assumption on i_dep
    CPPAD_ASSERT_UNKNOWN( i_dep < depend_yes );

    // start with an empty subgraph for this dependent variable
    subgraph.resize(0);

    // tape index corresponding to this dependent variable
    size_t i_var = dep_taddr[i_dep];

    // operator corresponding to this dependent variable
    size_t i_op = random_itr.var2op(i_var);
    i_op        = size_t( map_user_op_[i_op] );

    // if this variable depends on the selected indepent variables
    // process its subgraph
    CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] != i_dep )
    if( in_subgraph_[i_op] <= depend_yes )
    {   subgraph.push_back( addr_t(i_op) );
        in_subgraph_[i_op] = i_dep;
    }

    // space used to return set of arguments that are variables
    pod_vector<size_t> argument_variable;

    // temporary space used by get_argument_variable
    pod_vector<bool> work;

    // scan all the operators in this subgraph
    size_t sub_index = 0;
    while(sub_index < subgraph.size() )
    {   // this operator connected to this dependent and selected independent
        i_op = size_t( subgraph[sub_index] );
        CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] == i_dep );
        //
        // There must be a result for this operator
# ifndef NDEBUG
        OpCode op = random_itr.get_op(i_op);
        CPPAD_ASSERT_UNKNOWN(op == AFunOp || NumRes(op) > 0 );
# endif
        //
        // which variables are connected to this operator
        get_argument_variable(random_itr, i_op, argument_variable, work);
        for(size_t j = 0; j < argument_variable.size(); ++j)
        {   // add the corresponding operators to the subgraph
            size_t j_var = argument_variable[j];
            size_t j_op  = random_itr.var2op(j_var);
            j_op         = size_t( map_user_op_[j_op] );
            bool add = in_subgraph_[j_op] <= depend_yes;
            add     &= in_subgraph_[j_op] != i_dep;
            if( random_itr.get_op(j_op) == InvOp )
            {   CPPAD_ASSERT_UNKNOWN( j_op == j_var );
                add &= select_domain_[j_var - 1];
            }
            if( add )
            {   subgraph.push_back( addr_t(j_op) );
                in_subgraph_[j_op] = i_dep;
            }
        }
        // we are done scaning this subgraph operator
        ++sub_index;
    }
}
示例#23
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;
			// -------------------------------------------------

			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;
			// -------------------------------------------------

			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;
			// -------------------------------------------------

			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_COMPILER_HAS_ERF
			case ErfOp:
			CPPAD_ASSERT_UNKNOWN( CPPAD_COMPILER_HAS_ERF );
			// 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;
			// ---------------------------------------------------

			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;
			// -------------------------------------------------

			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
	}
示例#24
0
文件: acos_op.hpp 项目: GodinA/adcomp
inline void reverse_acos_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* z  = taylor  + i_z * cap_order;
	Base* pz       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* b  = z  - cap_order; // called y in documentation
	Base* pb       = pz - nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	// number of indices to access
	size_t j = d;
	size_t k;
	while(j)
	{
		// scale partials w.r.t b[j] by 1 / b[0]
		pb[j] /= b[0];

		// scale partials w.r.t z[j] by 1 / b[0]
		pz[j] /= b[0];

		// update partials w.r.t b^0
		pb[0] -= pz[j] * z[j] + pb[j] * b[j];

		// update partial w.r.t. x^0
		px[0] -= pb[j] * x[j];

		// update partial w.r.t. x^j
		px[j] -= pz[j] + pb[j] * x[0];

		// further scale partial w.r.t. z[j] by 1 / j
		pz[j] /= Base(j);

		for(k = 1; k < j; k++)
		{	// update partials w.r.t b^(j-k)
			pb[j-k] -= Base(k) * pz[j] * z[k] + pb[j] * b[k];

			// update partials w.r.t. x^k
			px[k]   -= pb[j] * x[j-k];

			// update partials w.r.t. z^k
			pz[k]   -= pz[j] * Base(k) * b[j-k];
		}
		--j;
	}

	// j == 0 case
	px[0] -= ( pz[0] + pb[0] * x[0]) / b[0];
}
示例#25
0
inline size_t optimize_binary_match(
	const CppAD::vector<struct optimize_old_variable>& tape           ,
	size_t                                             current        ,
	size_t                                             npar           ,
	const Base*                                        par            ,
	const CppAD::vector<size_t>&                       hash_table_var ,
	unsigned short&                                    code           )
{	OpCode        op         = tape[current].op;
	const size_t* arg        = tape[current].arg;
	size_t        new_arg[2];
	bool          parameter[2];

	// initialize return value
	size_t  match_var = 0;

	CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
	CPPAD_ASSERT_UNKNOWN( NumRes(op) >  0 );
	switch(op)
	{	// parameter op variable ----------------------------------
		case AddpvOp:
		case MulpvOp:
		case DivpvOp:
		case PowpvOp:
		case SubpvOp:
		// arg[0]
		parameter[0] = true;
		new_arg[0]   = arg[0];
		CPPAD_ASSERT_UNKNOWN( arg[0] < npar );
		// arg[1]
		parameter[1] = false;
		new_arg[1]   = tape[arg[1]].new_var;
		CPPAD_ASSERT_UNKNOWN( arg[1] < current );
		break;

		// variable op parameter -----------------------------------
		case DivvpOp:
		case PowvpOp:
		case SubvpOp:
		// arg[0]
		parameter[0] = false;
		new_arg[0]   = tape[arg[0]].new_var;
		CPPAD_ASSERT_UNKNOWN( arg[0] < current );
		// arg[1]
		parameter[1] = true;
		new_arg[1]   = arg[1];
		CPPAD_ASSERT_UNKNOWN( arg[1] < npar );
		break;

		// variable op variable -----------------------------------
		case AddvvOp:
		case MulvvOp:
		case DivvvOp:
		case PowvvOp:
		case SubvvOp:
		// arg[0]
		parameter[0] = false;
		new_arg[0]   = tape[arg[0]].new_var;
		CPPAD_ASSERT_UNKNOWN( arg[0] < current );
		// arg[1]
		parameter[1] = false;
		new_arg[1]   = tape[arg[1]].new_var;
		CPPAD_ASSERT_UNKNOWN( arg[1] < current );
		break;

		// must be one of the cases above
		default:
		CPPAD_ASSERT_UNKNOWN(false);
	}
	code = hash_code(
		op                  , 
		new_arg             ,
		npar                ,
		par
	);
	size_t  i  = hash_table_var[code];
	CPPAD_ASSERT_UNKNOWN( i < current );
	if( op == tape[i].op )
	{	bool match = true;
		size_t j;
		for(j = 0; j < 2; j++)
		{	size_t k = tape[i].arg[j];
			if( parameter[j] )
			{	CPPAD_ASSERT_UNKNOWN( k < npar );
				match &= IdenticalEqualPar(
					par[ arg[j] ], par[k]
				);
			}
			else
			{	CPPAD_ASSERT_UNKNOWN( k < i );
				match &= (new_arg[j] == tape[k].new_var);
			}
		}
		if( match )
			match_var = tape[i].new_var;
	}
	if( (match_var > 0) | ( (op != AddvvOp) & (op != MulvvOp ) ) )
		return match_var;

	// check for match with argument order switched ----------------------
	CPPAD_ASSERT_UNKNOWN( op == AddvvOp || op == MulvvOp );
	i          = new_arg[0];
	new_arg[0] = new_arg[1];
	new_arg[1] = i;
	unsigned short code_switch = hash_code(
		op                  , 
		new_arg             ,
		npar                ,
		par
	);
	i  = hash_table_var[code_switch];
	CPPAD_ASSERT_UNKNOWN( i < current );
	if( op == tape[i].op )
	{	bool match = true;
		size_t j;
		for(j = 0; j < 2; j++)
		{	size_t k = tape[i].arg[j];
			CPPAD_ASSERT_UNKNOWN( k < i );
			match &= (new_arg[j] == tape[k].new_var);
		}
		if( match )
			match_var = tape[i].new_var;
	}
	return match_var;
} 
示例#26
0
文件: div.hpp 项目: GodinA/adcomp
AD<Base> operator / (const AD<Base> &left , const AD<Base> &right)
{
	// compute the Base part
	AD<Base> result;
	result.value_  = left.value_ / right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_left  = left.tape_id_  == tape_id;
	bool var_right = right.tape_id_ == tape_id;

	if( var_left )
	{	if( var_right )
		{	// result = variable / variable
			CPPAD_ASSERT_KNOWN(
				left.tape_id_ == right.tape_id_,
				"Dividing AD objects that are"
				" variables on different tapes."
			);
			CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivvvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalOne(right.value_) )
		{	// result = variable / 1
			result.make_variable(left.tape_id_, left.taddr_);
		}
		else
		{	// result = variable / parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(left.taddr_, p);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivvpOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_right )
	{	if( IdenticalZero(left.value_) )
		{	// result = 0 / variable
		}
		else
		{	// result = parameter / variable
			CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(left.value_);
			tape->Rec_.PutArg(p, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
示例#27
0
文件: acosh_op.hpp 项目: fduffy/CppAD
inline void reverse_acosh_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* z  = taylor  + i_z * cap_order;
	Base* pz       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* b  = z  - cap_order; // called y in documentation
	Base* pb       = pz - nc_partial;

	Base inv_b0 = Base(1) / b[0];

	// number of indices to access
	size_t j = d;
	size_t k;
	while(j)
	{
		// scale partials w.r.t b[j] by 1 / b[0]
		pb[j]  = azmul(pb[j], inv_b0);

		// scale partials w.r.t z[j] by 1 / b[0]
		pz[j]  = azmul(pz[j], inv_b0);

		// update partials w.r.t b^0
		pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);

		// update partial w.r.t. x^0
		px[0] += azmul(pb[j], x[j]);

		// update partial w.r.t. x^j
		px[j] += pz[j] + azmul(pb[j], x[0]);

		// further scale partial w.r.t. z[j] by 1 / j
		pz[j] /= Base(j);

		for(k = 1; k < j; k++)
		{	// update partials w.r.t b^(j-k)
			pb[j-k] -= Base(k) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);

			// update partials w.r.t. x^k
			px[k]   += azmul(pb[j], x[j-k]);

			// update partials w.r.t. z^k
			pz[k]   -= Base(k) * azmul(pz[j], b[j-k]);
		}
		--j;
	}

	// j == 0 case
	px[0] += azmul(pz[0] + azmul(pb[0], x[0]),  inv_b0);
}
示例#28
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
	}
示例#29
0
void ADFun<Base>::Dependent(ADTape<Base> *tape, const ADvector &y)
{
	size_t   m = y.size();
	size_t   n = tape->size_independent_;
	size_t   i, j;
	size_t   y_taddr;

	// check ADvector is Simple Vector class with AD<Base> elements
	CheckSimpleVector< AD<Base>, ADvector>();

	CPPAD_ASSERT_KNOWN(
		y.size() > 0,
		"ADFun operation sequence dependent variable size is zero size"
	);
	// ---------------------------------------------------------------------
	// Begin setting ad_fun.hpp private member data
	// ---------------------------------------------------------------------
	// dep_parameter_, dep_taddr_
	CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );
	dep_parameter_.resize(m);
	dep_taddr_.resize(m);
	for(i = 0; i < m; i++)
	{	dep_parameter_[i] = CppAD::Parameter(y[i]);
		if( dep_parameter_[i] )
		{	// make a tape copy of dependent variables that are parameters,
			y_taddr = tape->RecordParOp( y[i].value_ );
		}
		else	y_taddr = y[i].taddr_;

		CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
		dep_taddr_[i] = y_taddr;
	}

	// put an EndOp at the end of the tape
	tape->Rec_.PutOp(EndOp);

	// some size_t values in ad_fun.hpp
	has_been_optimized_        = false;
	compare_change_count_      = 1;
	compare_change_number_     = 0;
	compare_change_op_index_   = 0;
	num_order_taylor_          = 0;
	num_direction_taylor_      = 0;
	cap_order_taylor_          = 0;

	// num_var_tape_
	// Now that all the variables are in the tape, we can set this value.
	num_var_tape_       = tape->Rec_.num_var_rec();

	// taylor_
	taylor_.erase();

	// cskip_op_
	cskip_op_.erase();
	cskip_op_.extend( tape->Rec_.num_op_rec() );

	// load_op_
	load_op_.erase();
	load_op_.extend( tape->Rec_.num_load_op_rec() );

	// play_
	// Now that each dependent variable has a place in the tape,
	// and there is a EndOp at the end of the tape, we can transfer the
	// recording to the player and and erase the tape.
	play_.get(tape->Rec_);

	// ind_taddr_
	// Note that play_ has been set, we can use it to check operators
	ind_taddr_.resize(n);
	CPPAD_ASSERT_UNKNOWN( n < num_var_tape_);
	for(j = 0; j < n; j++)
	{	CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp );
		ind_taddr_[j] = j+1;
	}

	// for_jac_sparse_pack_, for_jac_sparse_set_
	for_jac_sparse_pack_.resize(0, 0);
	for_jac_sparse_set_.resize(0,0);
	// ---------------------------------------------------------------------
	// End set ad_fun.hpp private member data
	// ---------------------------------------------------------------------

	// now we can delete the tape
	AD<Base>::tape_manage(tape_manage_delete);

	// total number of varables in this recording
	CPPAD_ASSERT_UNKNOWN( num_var_tape_  == play_.num_var_rec() );

	// used to determine if there is an operation sequence in *this
	CPPAD_ASSERT_UNKNOWN( num_var_tape_  > 0 );

}
示例#30
0
文件: op_code.hpp 项目: barak/cppad
void printOp(
    std::ostream&          os     ,
    const local::player<Base>* play,
    size_t                 i_op   ,
    size_t                 i_var  ,
    OpCode                 op     ,
    const addr_t*          arg    )
{
    CPPAD_ASSERT_KNOWN(
        ! thread_alloc::in_parallel() ,
        "cannot print trace of AD operations in parallel mode"
    );
    static const char *CompareOpName[] =
        { "Lt", "Le", "Eq", "Ge", "Gt", "Ne" };

    // print operator
    printOpField(os,  "o=",      i_op,  5);
    if( NumRes(op) > 0 && op != BeginOp )
        printOpField(os,  "v=",      i_var, 5);
    else
        printOpField(os,  "v=",      "",    5);
    if( op == CExpOp || op == CSkipOp )
    {   printOpField(os, "", OpName(op), 5);
        printOpField(os, "", CompareOpName[ arg[0] ], 3);
    }
    else
        printOpField(os, "", OpName(op), 8);

    // print other fields
    size_t ncol = 5;
    switch( op )
    {
        case CSkipOp:
        /*
        arg[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne
        arg[1] & 1 = is left a variable
        arg[1] & 2 = is right a variable
        arg[2]     = index correspoding to left
        arg[3]     = index correspoding to right
        arg[4] = number of operations to skip if CExpOp comparision is true
        arg[5] = number of operations to skip if CExpOp comparision is false
        arg[6] -> arg[5+arg[4]]               = skip operations if true
        arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false
        arg[6+arg[4]+arg[5]] = arg[4] + arg[5]
        */
        CPPAD_ASSERT_UNKNOWN( arg[6+arg[4]+arg[5]] == arg[4]+arg[5] );
        CPPAD_ASSERT_UNKNOWN(arg[1] != 0);
        if( arg[1] & 1 )
            printOpField(os, " vl=", arg[2], ncol);
        else
            printOpField(os, " pl=", play->GetPar(arg[2]), ncol);
        if( arg[1] & 2 )
            printOpField(os, " vr=", arg[3], ncol);
        else
            printOpField(os, " pr=", play->GetPar(arg[3]), ncol);
        if( size_t(arg[4]) < 3 )
        {   for(addr_t i = 0; i < arg[4]; i++)
                printOpField(os, " ot=", arg[6+i], ncol);
        }
        else
        {   printOpField(os, "\n\tot=", arg[6+0], ncol);
            for(addr_t i = 1; i < arg[4]; i++)
                printOpField(os, " ot=", arg[6+i], ncol);
        }
        if( size_t(arg[5]) < 3 )
        {   for(addr_t i = 0; i < arg[5]; i++)
                printOpField(os, " of=", arg[6+arg[4]+i], ncol);
        }
        else
        {   printOpField(os, "\n\tof=", arg[6+arg[4]+0], ncol);
            {   for(addr_t i = 1; i < arg[5]; i++)
                    printOpField(os, " of=", arg[6+arg[4]+i], ncol);
            }
        }
        break;

        case CSumOp:
        /*
        arg[0] = index of parameter that initializes summation
        arg[1] = end in arg of addition variables in summation
        arg[2] = end in arg of subtraction variables in summation
        arg[3] = end in arg of addition dynamic parameters in summation
        arg[4] = end in arg of subtraction dynamic parameters in summation
        arg[5],      ... , arg[arg[1]-1]: indices for addition variables
        arg[arg[1]], ... , arg[arg[2]-1]: indices for subtraction variables
        arg[arg[2]], ... , arg[arg[3]-1]: indices for additon dynamics
        arg[arg[3]], ... , arg[arg[4]-1]: indices for subtraction dynamics
        arg[arg[4]] = arg[4]
        */
        CPPAD_ASSERT_UNKNOWN( arg[arg[4]] == arg[4] );
        printOpField(os, " pr=", play->GetPar(arg[0]), ncol);
        for(addr_t i = 5; i < arg[1]; i++)
             printOpField(os, " +v=", arg[i], ncol);
        for(addr_t i = arg[1]; i < arg[2]; i++)
             printOpField(os, " -v=", arg[i], ncol);
        for(addr_t i = arg[2]; i < arg[3]; i++)
             printOpField(os, " +d=", play->GetPar(arg[i]), ncol);
        for(addr_t i = arg[3]; i < arg[4]; i++)
             printOpField(os, " -d=", play->GetPar(arg[i]), ncol);
        break;

        case LdpOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, "idx=", arg[1], ncol);
        break;

        case LdvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, "  v=", arg[1], ncol);
        break;

        case StppOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, "idx=", arg[1], ncol);
        printOpField(os, " pr=", play->GetPar(arg[2]), ncol);
        break;

        case StpvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, "idx=", arg[1], ncol);
        printOpField(os, " vr=", arg[2], ncol);
        break;

        case StvpOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, " vl=", arg[1], ncol);
        printOpField(os, " pr=", play->GetPar(arg[2]), ncol);
        break;

        case StvvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        printOpField(os, "off=", arg[0], ncol);
        printOpField(os, " vl=", arg[1], ncol);
        printOpField(os, " vr=", arg[2], ncol);
        break;

        case AddvvOp:
        case DivvvOp:
        case EqvvOp:
        case LevvOp:
        case LtvvOp:
        case NevvOp:
        case MulvvOp:
        case PowvvOp:
        case SubvvOp:
        case ZmulvvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
        printOpField(os, " vl=", arg[0], ncol);
        printOpField(os, " vr=", arg[1], ncol);
        break;

        case AddpvOp:
        case EqpvOp:
        case DivpvOp:
        case LepvOp:
        case LtpvOp:
        case NepvOp:
        case SubpvOp:
        case MulpvOp:
        case PowpvOp:
        case ZmulpvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
        printOpField(os, " pl=", play->GetPar(arg[0]), ncol);
        printOpField(os, " vr=", arg[1], ncol);
        break;

        case DivvpOp:
        case LevpOp:
        case LtvpOp:
        case PowvpOp:
        case SubvpOp:
        case ZmulvpOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
        printOpField(os, " vl=", arg[0], ncol);
        printOpField(os, " pr=", play->GetPar(arg[1]), ncol);
        break;

        case AbsOp:
        case AcosOp:
        case AcoshOp:
        case AsinOp:
        case AsinhOp:
        case AtanOp:
        case AtanhOp:
        case CosOp:
        case CoshOp:
        case ExpOp:
        case Expm1Op:
        case LogOp:
        case Log1pOp:
        case SignOp:
        case SinOp:
        case SinhOp:
        case SqrtOp:
        case FunavOp:
        case TanOp:
        case TanhOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
        printOpField(os, "  v=", arg[0], ncol);
        break;

        case ErfOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
        // arg[1] points to the parameter 0
        // arg[2] points to the parameter 2 / sqrt(pi)
        printOpField(os, "  v=", arg[0], ncol);
        break;

        case ParOp:
        case FunapOp:
        case FunrpOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
        printOpField(os, "  p=", play->GetPar(arg[0]), ncol);
        break;

        case AFunOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );
        {
            // get the name of this atomic function
            bool         set_null   = false;
            size_t       atom_index = size_t( arg[0] );
            size_t       type       = 0;          // set to avoid warning
            std::string name;
            void*        v_ptr    = CPPAD_NULL; // set to avoid warning
            atomic_index<RecBase>(set_null, atom_index, type, &name, v_ptr);
            printOpField(os, " f=",   name.c_str(), ncol);
            printOpField(os, " i=", arg[1], ncol);
            printOpField(os, " n=", arg[2], ncol);
            printOpField(os, " m=", arg[3], ncol);
        }
        break;

        case PriOp:
        CPPAD_ASSERT_NARG_NRES(op, 5, 0);
        if( arg[0] & 1 )
            printOpField(os, " v=", arg[1], ncol);
        else
            printOpField(os, " p=", play->GetPar(arg[1]), ncol);
        os << "before=\"" << play->GetTxt(arg[2]) << "\"";
        if( arg[0] & 2 )
            printOpField(os, " v=", arg[3], ncol);
        else
            printOpField(os, " p=", play->GetPar(arg[3]), ncol);
        os << "after=\"" << play->GetTxt(arg[4]) << "\"";
        break;

        case BeginOp:
        // argument not used (created by independent)
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
        break;

        case EndOp:
        case InvOp:
        case FunrvOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );
        break;

        case DisOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
        {   const char* name = discrete<Base>::name(arg[0]);
            printOpField(os, " f=", name, ncol);
            printOpField(os, " x=", arg[1], ncol);
        }
        break;


        case CExpOp:
        CPPAD_ASSERT_UNKNOWN(arg[1] != 0);
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );
        if( arg[1] & 1 )
            printOpField(os, " vl=", arg[2], ncol);
        else
            printOpField(os, " pl=", play->GetPar(arg[2]), ncol);
        if( arg[1] & 2 )
            printOpField(os, " vr=", arg[3], ncol);
        else
            printOpField(os, " pr=", play->GetPar(arg[3]), ncol);
        if( arg[1] & 4 )
            printOpField(os, " vt=", arg[4], ncol);
        else
            printOpField(os, " pt=", play->GetPar(arg[4]), ncol);
        if( arg[1] & 8 )
            printOpField(os, " vf=", arg[5], ncol);
        else
            printOpField(os, " pf=", play->GetPar(arg[5]), ncol);
        break;

        case EqppOp:
        case LeppOp:
        case LtppOp:
        case NeppOp:
        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
        printOpField(os, " pl=", play->GetPar(arg[0]), ncol);
        printOpField(os, " pr=", play->GetPar(arg[1]), ncol);
        break;

        default:
        CPPAD_ASSERT_UNKNOWN(0);
    }
}