Ejemplo n.º 1
0
size_t 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;

	// initialize the comparision operator (ComOp) counter
	const size_t compareCount = 0;

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

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

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

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

			case CExpOp:
			forward_cond_op_dir(
				q, r, i_var, arg, num_par, parameter, J, taylor
			);
			break;
			// ---------------------------------------------------

			case ComOp:
			CPPAD_ASSERT_UNKNOWN(q > 0 );
			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;
			// -------------------------------------------------

			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 LogOp:
			forward_log_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			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;
			for(ell = 0; ell < r; ell++)
				taylor[k + ell] = Base(0); 
			break;
			// -------------------------------------------------

			case PowpvOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
			forward_powpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case PowvpOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
			forward_powvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case PowvvOp:
			forward_powvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case PriOp:
			CPPAD_ASSERT_UNKNOWN(q > 0);
			break;
			// -------------------------------------------------

			case SignOp:
			// sign(x)
			CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
			forward_sign_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case SinOp:
			// cos(x), sin(x)
			CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
			forward_sin_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case SinhOp:
			// cosh(x), sinh(x)
			CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
			forward_sinh_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case SqrtOp:
			forward_sqrt_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case StppOp:
			case StpvOp:
			case StvpOp:
			case StvvOp:
			CPPAD_ASSERT_UNKNOWN(q > 0 );
			break;
			// -------------------------------------------------

			case SubvvOp:
			forward_subvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case SubpvOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
			forward_subpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case SubvpOp:
			CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
			forward_subvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
			break;
			// -------------------------------------------------

			case TanOp:
			// tan(x)^2, tan(x)
			CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
			forward_tan_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case TanhOp:
			// tanh(x)^2, tanh(x)
			CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
			forward_tanh_op_dir(q, r, i_var, arg[0], J, taylor);
			break;
			// -------------------------------------------------

			case UserOp:
			// start or end an atomic operation sequence
			CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 );
			CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 );
			if( user_state == user_start )
			{	user_index = arg[0];
				user_id    = arg[1];
				user_n     = arg[2];
				user_m     = arg[3];
				user_atom  = atomic_base<Base>::class_object(user_index);
# ifndef NDEBUG
				if( user_atom == CPPAD_NULL )
				{	std::string msg = 
						atomic_base<Base>::class_name(user_index)
						+ ": atomic_base function has been deleted";
					CPPAD_ASSERT_KNOWN(false, msg.c_str() );
				}
# endif
				if(user_tx_one.size() != user_n * user_q1)
					user_tx_one.resize(user_n * user_q1);
				if( user_tx_all.size() != user_n * (q * r + 1) )
					user_tx_all.resize(user_n * (q * r + 1));
				//
				if(user_ty_one.size() != user_m * user_q1)
					user_ty_one.resize(user_m * user_q1);
				if( user_ty_all.size() != user_m * (q * r + 1) )
					user_ty_all.resize(user_m * (q * r + 1));
				//
				if(user_iy.size() != user_m)
					user_iy.resize(user_m);
				user_j     = 0;
				user_i     = 0;
				user_state = user_arg;
			}
			else
			{	CPPAD_ASSERT_UNKNOWN( user_state == user_end );
				CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) );
				CPPAD_ASSERT_UNKNOWN( user_id    == size_t(arg[1]) );
				CPPAD_ASSERT_UNKNOWN( user_n     == size_t(arg[2]) );
				CPPAD_ASSERT_UNKNOWN( user_m     == size_t(arg[3]) );

				// call users function for this operation
				user_atom->set_id(user_id);
				for(ell = 0; ell < r; ell++)
				{	// set user_tx
					for(j = 0; j < user_n; j++)
					{	size_t j_all     = j * (q * r + 1);
						size_t j_one     = j * user_q1;
						user_tx_one[j_one+0] = user_tx_all[j_all+0];
						for(k = 1; k < user_q1; k++)
						{	size_t k_all       = j_all + (k-1)*r+1+ell;
							size_t k_one       = j_one + k;
							user_tx_one[k_one] = user_tx_all[k_all];
						}
					}
					// set user_ty
					for(i = 0; i < user_m; i++)
					{	size_t i_all     = i * (q * r + 1);
						size_t i_one     = i * user_q1;
						user_ty_one[i_one+0] = user_ty_all[i_all+0];
						for(k = 1; k < q; k++)
						{	size_t k_all       = i_all + (k-1)*r+1+ell;
							size_t k_one       = i_one + k;
							user_ty_one[k_one] = user_ty_all[k_all];
						}
					}
					CPPAD_ATOMIC_CALL(
					q, q, user_vx, user_vy, user_tx_one, user_ty_one
					);
# ifndef NDEBUG
					if( ! user_ok )
					{	std::string msg = 
							atomic_base<Base>::class_name(user_index)
							+ ": atomic_base.forward: returned false";
						CPPAD_ASSERT_KNOWN(false, msg.c_str() );
					}
# endif
					for(i = 0; i < user_m; i++) 
					{	if( user_iy[i] > 0 )
						{	size_t i_taylor = user_iy[i]*((J-1)*r+1); 
							size_t q_taylor = i_taylor + (q-1)*r+1+ell;
							size_t q_one    = i * user_q1 + q;
							taylor[q_taylor] = user_ty_one[q_one];
						}
					}
				}
# if CPPAD_FORWARD2SWEEP_TRACE
				user_state = user_trace;
# else
				user_state = user_start;
# endif
			}
			break;

			case UsrapOp:
			// parameter argument in an atomic operation sequence
			CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
			CPPAD_ASSERT_UNKNOWN( user_j < user_n );
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
			user_tx_all[user_j*(q*r+1) + 0] = parameter[ arg[0]];
			for(ell = 0; ell < r; ell++)
				for(k = 1; k < user_q1; k++)
					user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = Base(0);
			++user_j;
			if( user_j == user_n )
				user_state = user_ret;
			break;

			case UsravOp:
			// variable argument in an atomic operation sequence
			CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
			CPPAD_ASSERT_UNKNOWN( user_j < user_n );
			CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
			user_tx_all[user_j*(q*r+1)+0] = taylor[arg[0]*((J-1)*r+1)+0];
			for(ell = 0; ell < r; ell++)
			{	for(k = 1; k < user_q1; k++)
				{	user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = 
						taylor[arg[0]*((J-1)*r+1) + (k-1)*r+1+ell];
				}
			}
			++user_j;
			if( user_j == user_n )
				user_state = user_ret;
			break;

			case UsrrpOp:
			// parameter result in an atomic operation sequence
			CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
			CPPAD_ASSERT_UNKNOWN( user_i < user_m );
			user_iy[user_i] = 0;
			user_ty_all[user_i*(q*r+1) + 0] = parameter[ arg[0]];
			for(ell = 0; ell < r; ell++)
				for(k = 1; k < user_q1; k++)
					user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = Base(0);
			user_i++;
			if( user_i == user_m )
				user_state = user_end;
			break;

			case UsrrvOp:
			// variable result in an atomic operation sequence
			CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
			CPPAD_ASSERT_UNKNOWN( user_i < user_m );
			user_iy[user_i] = i_var;
			user_ty_all[user_i*(q*r+1)+0] = taylor[i_var*((J-1)*r+1)+0];
			for(ell = 0; ell < r; ell++)
			{	for(k = 1; k < user_q1; k++)
				{	user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = 
						taylor[i_var*((J-1)*r+1) + (k-1)*r+1+ell];
				}
			}
			user_i++;
			if( user_i == user_m )
				user_state = user_end;
			break;
			// -------------------------------------------------

			default:
			CPPAD_ASSERT_UNKNOWN(0);
		}
# if CPPAD_FORWARD2SWEEP_TRACE
		if( user_state == user_trace )
		{	user_state = user_start;
			CPPAD_ASSERT_UNKNOWN( op == UserOp );
			CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 );
			for(i = 0; i < user_m; i++) if( user_iy[i] > 0 )
			{	size_t i_tmp   = (i_op + i) - user_m;
				printOp(
					std::cout, 
					play,
					i_tmp,
					user_iy[i],
					UsrrvOp, 
					CPPAD_NULL
				);
				Base* Z_tmp = taylor + user_iy[i]*((J-1) * r + 1);
				{	Z_vec[0]    = Z_tmp[0];
					for(ell = 0; ell < r; ell++)
					{	std::cout << std::endl << "     ";
						for(size_t p_tmp = 1; p_tmp <= q; p_tmp++)
							Z_vec[p_tmp] = Z_tmp[(p_tmp-1)*r+ell+1];
						printOpResult(
							std::cout, 
							q + 1, 
							Z_vec.data(),
							0, 
							(Base *) CPPAD_NULL
						);
					}
				}
				std::cout << std::endl;
			}
		}
		const addr_t*   arg_tmp = arg;
		if( op == CSumOp )
			arg_tmp = arg - arg[-1] - 4;
		if( op == CSkipOp )
			arg_tmp = arg - arg[-1] - 7;
		if( op != UsrrvOp )
		{	printOp(
				std::cout, 
				play,
				i_op,
				i_var,
				op, 
				arg_tmp
			);
			Base* Z_tmp = CPPAD_NULL;
			if( op == UsravOp )
				Z_tmp = taylor + arg[0]*((J-1) * r + 1);
			else if( NumRes(op) > 0 )
				Z_tmp = taylor + i_var*((J-1)*r + 1);
			if( Z_tmp != CPPAD_NULL )
			{	Z_vec[0]    = Z_tmp[0];
				for(ell = 0; ell < r; ell++)
				{	std::cout << std::endl << "     ";
					for(size_t p_tmp = 1; p_tmp <= q; p_tmp++)
						Z_vec[p_tmp] = Z_tmp[ (p_tmp-1)*r + ell + 1];
					printOpResult(
						std::cout, 
						q + 1, 
						Z_vec.data(),
						0, 
						(Base *) CPPAD_NULL
					);
				}
			}
			std::cout << std::endl;
		}
	}
	std::cout << std::endl;
# else
	}
Ejemplo n.º 2
0
int LuRatio(SizeVector &ip, SizeVector &jp, ADvector &LU, AD<Base> &ratio) //
{
	typedef ADvector FloatVector;                                       //
	typedef AD<Base>       Float;                                       //

	// check numeric type specifications
	CheckNumericType<Float>();

	// check simple vector class specifications
	CheckSimpleVector<Float, FloatVector>();
	CheckSimpleVector<size_t, SizeVector>();

	size_t  i, j;          // some temporary indices
	const Float zero( 0 ); // the value zero as a Float object
	size_t  imax;          // row index of maximum element
	size_t  jmax;          // column indx of maximum element
	Float    emax;         // maximum absolute value
	size_t  p;             // count pivots
	int     sign;          // sign of the permutation
	Float   etmp;          // temporary element
	Float   pivot;         // pivot element

	// -------------------------------------------------------
	size_t n = size_t(ip.size());
	CPPAD_ASSERT_KNOWN(
		size_t(jp.size()) == n,
		"Error in LuFactor: jp must have size equal to n"
	);
	CPPAD_ASSERT_KNOWN(
		size_t(LU.size()) == n * n,
		"Error in LuFactor: LU must have size equal to n * m"
	);
	// -------------------------------------------------------

	// initialize row and column order in matrix not yet pivoted
	for(i = 0; i < n; i++)
	{	ip[i] = i;
		jp[i] = i;
	}
	// initialize the sign of the permutation
	sign = 1;
	// initialize the ratio                                             //
	ratio = Float(1);                                                   //
	// ---------------------------------------------------------

	// Reduce the matrix P to L * U using n pivots
	for(p = 0; p < n; p++)
	{	// determine row and column corresponding to element of
		// maximum absolute value in remaining part of P
		imax = jmax = n;
		emax = zero;
		for(i = p; i < n; i++)
		{	for(j = p; j < n; j++)
			{	CPPAD_ASSERT_UNKNOWN(
					(ip[i] < n) & (jp[j] < n)
				);
				etmp = LU[ ip[i] * n + jp[j] ];

				// check if maximum absolute value so far
				if( AbsGeq (etmp, emax) )
				{	imax = i;
					jmax = j;
					emax = etmp;
				}
			}
		}
		for(i = p; i < n; i++)                                       //
		{	for(j = p; j < n; j++)                               //
			{	etmp  = abs(LU[ ip[i] * n + jp[j] ] / emax); //
				ratio =                                      //
				CondExpGt(etmp, ratio, etmp, ratio);         //
			}                                                    //
		}                                                            //
		CPPAD_ASSERT_KNOWN(
			(imax < n) & (jmax < n) ,
			"AbsGeq must return true when second argument is zero"
		);
		if( imax != p )
		{	// switch rows so max absolute element is in row p
			i        = ip[p];
			ip[p]    = ip[imax];
			ip[imax] = i;
			sign     = -sign;
		}
		if( jmax != p )
		{	// switch columns so max absolute element is in column p
			j        = jp[p];
			jp[p]    = jp[jmax];
			jp[jmax] = j;
			sign     = -sign;
		}
		// pivot using the max absolute element
		pivot   = LU[ ip[p] * n + jp[p] ];

		// check for determinant equal to zero
		if( pivot == zero )
		{	// abort the mission
			return   0;
		}

		// Reduce U by the elementary transformations that maps
		// LU( ip[p], jp[p] ) to one.  Only need transform elements
		// above the diagonal in U and LU( ip[p] , jp[p] ) is
		// corresponding value below diagonal in L.
		for(j = p+1; j < n; j++)
			LU[ ip[p] * n + jp[j] ] /= pivot;

		// Reduce U by the elementary transformations that maps
		// LU( ip[i], jp[p] ) to zero. Only need transform elements
		// above the diagonal in U and LU( ip[i], jp[p] ) is
		// corresponding value below diagonal in L.
		for(i = p+1; i < n; i++ )
		{	etmp = LU[ ip[i] * n + jp[p] ];
			for(j = p+1; j < n; j++)
			{	LU[ ip[i] * n + jp[j] ] -=
					etmp * LU[ ip[p] * n + jp[j] ];
			}
		}
	}
	return sign;
}