Example #1
0
inline void forward_sparse_jacobian_cond_op(
	bool               dependency    ,
	size_t             i_z           ,
	const addr_t*      arg           ,
	size_t             num_par       ,
	Vector_set&        sparsity      )
{
	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 );
# ifndef NDEBUG
	size_t k = 1;
	for( size_t j = 0; j < 4; j++)
	{	if( ! ( arg[1] & k ) )
			CPPAD_ASSERT_UNKNOWN( size_t(arg[2+j]) < num_par );
		k *= 2;
	}
# endif
	sparsity.clear(i_z);
	if( dependency )
	{	if( arg[1] & 1 )
			sparsity.binary_union(i_z, i_z, arg[2], sparsity);
		if( arg[1] & 2 )
			sparsity.binary_union(i_z, i_z, arg[3], sparsity);
	}
	if( arg[1] & 4 )
		sparsity.binary_union(i_z, i_z, arg[4], sparsity);
	if( arg[1] & 8 )
		sparsity.binary_union(i_z, i_z, arg[5], sparsity);
	return;
}
Example #2
0
inline void reverse_sparse_hessian_cond_op(
	size_t               i_z           ,
	const addr_t*        arg           ,
	size_t               num_par       ,
	bool*                jac_reverse   ,
	Vector_set&          hes_sparsity  )
{

	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 );
# ifndef NDEBUG
	size_t k = 1;
	for( size_t j = 0; j < 4; j++)
	{	if( ! ( arg[1] & k ) )
			CPPAD_ASSERT_UNKNOWN( size_t(arg[2+j]) < num_par );
		k *= 2;
	}
# endif
	if( arg[1] & 4 )
	{
		hes_sparsity.binary_union(arg[4], arg[4], i_z, hes_sparsity);
		jac_reverse[ arg[4] ] |= jac_reverse[i_z];
	}
	if( arg[1] & 8 )
	{
		hes_sparsity.binary_union(arg[5], arg[5], i_z, hes_sparsity);
		jac_reverse[ arg[5] ] |= jac_reverse[i_z];
	}
	return;
}
inline void reverse_sparse_hessian_div_op(
	size_t               i_z                ,
	const addr_t*        arg                ,
	bool*                jac_reverse        ,
	Vector_set&          for_jac_sparsity   ,
	Vector_set&          rev_hes_sparsity   )
{	
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );

	rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
	rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);

	if( jac_reverse[i_z] )
	{	rev_hes_sparsity.binary_union(
			arg[0], arg[0], arg[1], for_jac_sparsity); 
		rev_hes_sparsity.binary_union(
			arg[1], arg[1], arg[0], for_jac_sparsity); 
		rev_hes_sparsity.binary_union(
			arg[1], arg[1], arg[1], for_jac_sparsity); 
	}

	jac_reverse[arg[0]] |= jac_reverse[i_z];
	jac_reverse[arg[1]] |= jac_reverse[i_z];
	return;
}	
inline void reverse_sparse_hessian_pow_op(
	size_t               i_z                ,
	const addr_t*        arg                ,
	bool*                jac_reverse        ,
	Vector_set&          for_jac_sparsity   ,
	Vector_set&          rev_hes_sparsity   )
{	
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );

	rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
	rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);

	if( jac_reverse[i_z] )
	{
		rev_hes_sparsity.binary_union(
			arg[0], arg[0], arg[0], for_jac_sparsity); 
		rev_hes_sparsity.binary_union(
			arg[0], arg[0], arg[1], for_jac_sparsity); 

		rev_hes_sparsity.binary_union(
			arg[1], arg[1], arg[0], for_jac_sparsity); 
		rev_hes_sparsity.binary_union(
			arg[1], arg[1], arg[1], for_jac_sparsity); 
	}

	// I cannot think of a case where this is necessary, but it including
	// it makes it like the other cases.
	jac_reverse[arg[0]] |= jac_reverse[i_z];
	jac_reverse[arg[1]] |= jac_reverse[i_z];
	return;
}	
Example #5
0
inline void forward_sparse_hessian_pow_op(
	const addr_t*        arg              ,
	Vector_set&         for_jac_sparsity  ,
	Vector_set&         for_hes_sparsity  )
{	// --------------------------------------------------
	// set of independent variables that v0 depends on
	for_jac_sparsity.begin(arg[0]);

	// loop over dependent variables with non-zero partial
	size_t i_x = for_jac_sparsity.next_element();
	while( i_x < for_jac_sparsity.end() )
	{	// N(i_x) = N(i_x) union L(v0)
		for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
		// N(i_x) = N(i_x) union L(v1)
		for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
		i_x = for_jac_sparsity.next_element();
	}
	// --------------------------------------------------
	// set of independent variables that v1 depends on
	for_jac_sparsity.begin(arg[1]);

	// loop over dependent variables with non-zero partial
	i_x = for_jac_sparsity.next_element();
	while( i_x < for_jac_sparsity.end() )
	{	// N(i_x) = N(i_x) union L(v0)
		for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
		// N(i_x) = N(i_x) union L(v1)
		for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
		i_x = for_jac_sparsity.next_element();
	}
	return;
}
Example #6
0
inline void reverse_sparse_jacobian_cond_op(
	bool                nz_compare    ,
	size_t              i_z           ,
	const addr_t*       arg           , 
	size_t              num_par       ,
	Vector_set&         sparsity      )
{	
	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 );

# ifndef NDEBUG
	if( arg[1] & 1 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
	}
	if( arg[1] & 2 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
	}
	if( ! ( arg[1] & 4 ) )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );
	}
	if( ! ( arg[1] & 8 ) )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );
	}
# endif
	if( nz_compare )
	{	if( arg[1] & 1 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
			sparsity.binary_union(arg[2], arg[2], i_z, sparsity);
		}
		if( arg[1] & 2 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
			sparsity.binary_union(arg[3], arg[3], i_z, sparsity);
		}
	}
	// --------------------------------------------------------------------
	if( arg[1] & 4 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );
		sparsity.binary_union(arg[4], arg[4], i_z, sparsity);
	}
	if( arg[1] & 8 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
		sparsity.binary_union(arg[5], arg[5], i_z, sparsity);
	}
	return;
}
Example #7
0
inline void reverse_sparse_hessian_cond_op(
	size_t               i_z           ,
	const addr_t*        arg           , 
	size_t               num_par       ,
	bool*                jac_reverse   ,
	Vector_set&          hes_sparsity  )
{	

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

# ifndef NDEBUG
	if( arg[1] & 1 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
	}
	if( arg[1] & 2 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
	}
	if( ! ( arg[1] & 4 ) )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );
	}
	if( ! ( arg[1] & 8 ) )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );
	}
# endif
	if( arg[1] & 4 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );

		hes_sparsity.binary_union(arg[4], arg[4], i_z, hes_sparsity);
		jac_reverse[ arg[4] ] |= jac_reverse[i_z];
	}
	if( arg[1] & 8 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );

		hes_sparsity.binary_union(arg[5], arg[5], i_z, hes_sparsity);
		jac_reverse[ arg[5] ] |= jac_reverse[i_z];
	}
	return;
}
Example #8
0
inline void reverse_sparse_hessian_nonlinear_unary_op(
	size_t              i_z               ,
	size_t              i_x               ,
	bool*               rev_jacobian      ,
	const Vector_set&   for_jac_sparsity  ,
	Vector_set&         rev_hes_sparsity  )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( i_x < i_z );

	rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity);
	if( rev_jacobian[i_z] )
		rev_hes_sparsity.binary_union(i_x, i_x, i_x, for_jac_sparsity);

	rev_jacobian[i_x] |= rev_jacobian[i_z];
	return;
}
Example #9
0
inline void reverse_sparse_jacobian_unary_op(
	size_t     i_z                     ,
	size_t     i_x                     ,
	Vector_set&            sparsity    )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( i_x < i_z );

	sparsity.binary_union(i_x, i_x, i_z, sparsity);

	return;
}
inline void forward_sparse_jacobian_binary_op(
	size_t            i_z           ,
	const addr_t*     arg           ,
	Vector_set&       sparsity      )
{	
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );

	sparsity.binary_union(i_z, arg[0], arg[1], sparsity);

	return;
}	
Example #11
0
inline void reverse_sparse_jacobian_binary_op(
	size_t              i_z           ,
	const size_t*       arg           ,
	Vector_set&         sparsity      )
{	
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( arg[0] < i_z );
	CPPAD_ASSERT_UNKNOWN( arg[1] < i_z );

	sparsity.binary_union(arg[0], arg[0], i_z, sparsity);
	sparsity.binary_union(arg[1], arg[1], i_z, sparsity);

	return;
}	
Example #12
0
inline void forward_sparse_jacobian_cond_op(
	size_t             i_z           ,
	const addr_t*      arg           , 
	size_t             num_par       ,
	Vector_set&        sparsity      )
{
	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 );

# ifndef NDEBUG
	if( arg[1] & 1 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
	}
	if( arg[1] & 2 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < i_z );
	}
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
	}
# endif
	if( arg[1] & 4 )
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < i_z );
		if( arg[1] & 8 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
			sparsity.binary_union(i_z, arg[4], arg[5], sparsity);
		}
		else
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );
			sparsity.assignment(i_z, arg[4], sparsity);
		}
	}	
	else
	{	CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );
		if( arg[1] & 8 )
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < i_z );
			sparsity.assignment(i_z, arg[5], sparsity);
		}
		else
		{	CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );
			sparsity.clear(i_z);
		}
	}
	return;
}
Example #13
0
inline void reverse_sparse_jacobian_csum_op(
	size_t           i_z         ,
	const addr_t*    arg         ,
	Vector_set&      sparsity    )
{
	size_t i, j;
	i = arg[0] + arg[1];
	j = 2;
	while(i--)
	{	++j;
		CPPAD_ASSERT_UNKNOWN( size_t(arg[j]) < i_z );
		sparsity.binary_union(
			arg[j]     , // index in sparsity for result
			arg[j]     , // index in sparsity for left operand
			i_z        , // index for right operand
			sparsity     // sparsity vector for right operand
		);
	}
}
Example #14
0
inline void forward_sparse_hessian_nonlinear_unary_op(
	size_t              i_v               ,
	const Vector_set&   for_jac_sparsity  ,
	Vector_set&         for_hes_sparsity  )
{
	// set of independent variables that v depends on
	typename Vector_set::const_iterator itr(for_jac_sparsity, i_v);

	// next independent variables that v depends on
	size_t i_x = *itr;

	// loop over dependent variables with non-zero partial
	while( i_x < for_jac_sparsity.end() )
	{	// N(i_x) = N(i_x) union L(i_v)
		for_hes_sparsity.binary_union(i_x, i_x, i_v, for_jac_sparsity);
		i_x = *(++itr);
	}
	return;
}
Example #15
0
inline void reverse_sparse_jacobian_load_op(
	OpCode             op             ,
	size_t             i_z            ,
	const addr_t*      arg            , 
	size_t             num_combined   ,
	const size_t*      combined       ,
	Vector_set&        var_sparsity   ,
	Vector_set&        vecad_sparsity )
{
	CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
	CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
	CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
	size_t i_v = combined[ arg[0] - 1 ];
	CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );

	vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity);

	return;
}
Example #16
0
inline void forward_sparse_store_op(
	OpCode              op             ,
	const addr_t*       arg            , 
	size_t              num_combined   ,
	const size_t*       combined       ,
	Vector_set&         var_sparsity   ,
	Vector_set&         vecad_sparsity )
{
	CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
	CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
	CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
	size_t i_v = combined[ arg[0] - 1 ];
	CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() );

	vecad_sparsity.binary_union(i_v, i_v, arg[2], var_sparsity);

	return;
}
Example #17
0
inline void reverse_sparse_hessian_store_op(
	OpCode             op           ,
	const addr_t*      arg          , 
	size_t             num_combined ,
	const size_t*      combined     ,
	Vector_set&        var_sparsity ,
	Vector_set&        vecad_sparsity ,
	bool*              var_jacobian   ,
	bool*              vecad_jacobian )
{
	CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
	CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
	CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
	size_t i_v = combined[ arg[0] - 1 ];
	CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
	CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() );

	var_sparsity.binary_union(arg[2], arg[2], i_v, vecad_sparsity);

	var_jacobian[ arg[2] ] |= vecad_jacobian[i_v];

	return;
}
Example #18
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
	}