#define DDP1_BAD_VALUE 1e300
#define DDP1_STEADY_STATE_INDEX -1

typedef struct ddp1
{
  /* Inputs: These need to be set by user. */
  /* Set by initialize_lqrd() or by set_xxx() */ 

  int n_x; /* dimensionality of input vector */
  int n_u; /* dimensionality of action */
  int n_y; /* dimensionality of output vector */

  int use_u_limits;    /* Do we use u limits. */
  double *u_min;       /* minimum commands */
  double *u_max;       /* maximum commands */

  double *x;         /* The current input vector. */
  double *u;         /* The current command vector. */
  double *y;         /* The current output vector. */

  /************************************* BELOW NOT UPDATED ***********************/

  /* Other adjustable parameters */
  double epsilon_gradient;
  double epsilon_second_order;
  double delta;      /* For computing numerical derivatives. */

  /* Outputs: These are set by program. */
  /* X[][] and U[][] are set by program */
  double **Fx; // A matrix
  double **Fu; // B matrix
  double ***Fxx; // 2nd derivative terms
  double ***Fxu;
  double ***Fux;
  double ***Fuu;
  double *Lx;           /* linear state cost terms */
  double *Lu;           /* linear action cost terms */  
  double **Lxx;         /* state penalty matrix */
  double **Lxu;         /* cost cross terms matrix */  
  double **Lux;         /* cost cross terms matrix */  
  double **Luu;         /* control penalty matrix */  
  double *Ty;           /* first derivative of terminal cost */
  double **Tyy;         /* second derivative of terminal cost */
  double **K;
  double VX;
  double *Vx; // spatial derivative of V(x)
  double **Vxx;
  double VY;
  double *Vy; // spatial derivative of V(y)
  double **Vyy;
  double *Vy_terminal; // derivatives of terminal penalty
  double **Vyy_terminal;
  double *y_terminal; // above referenced to this value:
  // V(y) = VY + Vy*(y-y_terminal) + 0.5*(y-y_terminal)'*Vyy*(y-y_terminal)
  double *delta_u;       /* The command vector update. */

  double *Qx;
  double *Qu;
  double **Qxx;
  double **Qxu;
  double **Qux;
  double **Quu;
  double **Quu_L;
  double *Quu_D;

  double *tempx1;
  double *tempx2;
  double *tempx3;
  double *tempu1;
  double *tempu2;
  double *tempu3;
  double *tempy1;
  double *tempy2;
  double **tempxx1;
  double **tempxx2;
  double **tempxx3;
  double **tempxu1;
  double **tempxu2;
  double **tempuu1;
  double **tempux1;
  double **tempux2;
  double **tempyx1;
  double **tempyx2;
  double **tempxy1;
  double **tempyu1;
  double **tempyu2;
  double **tempuy1;
  double **tempyy1;

  int (*one_step_dynamics_function)();
  double (*cost_function)();
  double (*terminal_cost_function)();
  int (*compute_linear_model_function)();
  int (*analytic_cost_derivatives)();
  void *argument;
}
  DDP1;

DDP1 *ddp1_initialize( int nx, /* Dimensionality of input vector */
		       int nu, /* Dimensionality of controls */
		       int ny, /* Dimensionality of output vector */
		       int (*one_step_dynamics)(),
		       double (*cost_function)(),
		       void *argument /* argument to dynamics and cost functions */
		       );

double ddp1_total_cost( DDP1 *z );


