//#include "snoptch.h"
#include "snopt.h"

/* *************************************************************** */

cint csnset( snProblem *prob, char Option[], cint userCall )
{
  cint   iPrint, iSumm, iExit = 0;
  cint   lenopt = strlen(Option);

  iPrint = (prob->print_file_unit && userCall) ? prob->print_file_unit : 0;
  iSumm  = (prob->sumry_file_unit && userCall) ? prob->sumry_file_unit : 0;

  snset_( Option, &iPrint, &iSumm, &iExit,
	  prob->cw, &(prob->length_cw),
	  prob->iw, &(prob->length_iw),
	  prob->rw, &(prob->length_rw),
	  lenopt,
	  prob->length_cw );

  return iExit;
}

/* *************************************************************** */

cint snSetOptionString( snProblem *prob,  char Option[] )
{
  cint userCall = 1, iExit;
  csnset( prob, Option, userCall );

  return iExit;
}

/* *************************************************************** */

cint csnseti( snProblem *prob, char Option[], cint iOption, cint userCall )
{
  cint       iPrint, iSumm, iExit = 0;
  cint       lenopt = strlen(Option);

  iPrint = (prob->print_file_unit && userCall) ? prob->print_file_unit : 0;
  iSumm  = (prob->sumry_file_unit && userCall) ? prob->sumry_file_unit : 0;

  snseti_( Option, &iOption, &iPrint, &iSumm, &iExit,
	   prob->cw, &(prob->length_cw),
	   prob->iw, &(prob->length_iw),
	   prob->rw, &(prob->length_rw),
	   lenopt,
	   prob->length_cw );

  return iExit;
}

/* *************************************************************** */

cint snSetOptionInteger( snProblem *prob, char Option[], cint iOption )
{
  cint userCall = 1, iExit;
  csnseti( prob, Option, iOption, userCall );

  return iExit;
}

/* *************************************************************** */

cint csnsetd( snProblem *prob, char Option[], double dOption, cint userCall )
{
  cint       iPrint, iSumm, iExit = 0;
  cint       lenOpt = strlen(Option);

  iPrint = (prob->print_file_unit && userCall) ? prob->print_file_unit : 0;
  iSumm  = (prob->sumry_file_unit && userCall) ? prob->sumry_file_unit : 0;

  snsetr_( Option, &dOption, &iPrint, &iSumm, &iExit,
	   prob->cw, &(prob->length_cw),
	   prob->iw, &(prob->length_iw),
	   prob->rw, &(prob->length_rw),
	   lenOpt,
	   prob->length_cw );

  return iExit;
}

/* *************************************************************** */

cint snSetOptionDouble( snProblem *prob, char Option[], double dOption )
{
  cint userCall = 1, iExit;
  csnsetd( prob, Option, dOption, userCall );

  return iExit;
}

/* *************************************************************** */

cint snSetObjectiveAdd( snProblem* prob, double objective_add )
{
  prob->option.objective_add = objective_add;
  return SN_OK;
}

/* *************************************************************** */

cint snSetObjectiveFunction( snProblem* prob, snObjectiveFunc func )
{
  prob->objective_func = func;
  return SN_OK;
}
/* *************************************************************** */

/*int snSetUserFunction( snProblem* prob, snUserFunc func )
{
  prob->user_func = func;
  return SN_OK;
  }*/
/* *************************************************************** */

cint snSetConstraintFunction( snProblem* prob, snConstraintFunc func )
{
  prob->constraint_func = func;
  return SN_OK;
}

/* *************************************************************** */

cint snSetProblemName( snProblem* prob, char *ProblemName )
{
  prob->option.ProblemName = ProblemName;
  return SN_OK;
}

/* *************************************************************** */

cint snSetVariableBounds( snProblem* prob, cint var, double lower, double upper )
{
  assert( var >= 0 && var < prob->dimension.n );

  prob->bu[ var ] = upper;
  prob->bl[ var ] = lower;

  return SN_OK;
}

/* *************************************************************** */

cint snSetConstraintBounds( snProblem* prob, cint con, double lower, double upper )
{
  assert( con >= 0 && con < prob->dimension.m );

  prob->bu[ con + prob->dimension.n ] = upper;
  prob->bl[ con + prob->dimension.n ] = lower;

  return SN_OK;
}

/* *************************************************************** */

cint snSetNonzero( snProblem *prob, cint nz, double Jcol, cint indJ )
{

  assert( nz >= 0 && nz < prob->dimension.ne );

  prob->Jcol[ nz ] = Jcol;
  prob->indJ[ nz ] = indJ;

  return SN_OK;
}

/* *************************************************************** */

cint snSetNonzeroColumnPointer( snProblem* prob, cint col, cint locJ )
{
  assert( col >= 0 && col < (prob->dimension.n + 1) );

  prob->locJ[ col ] = locJ;

  return SN_OK;
}

/* *************************************************************** */

cint snSetVariable( snProblem* prob, cint var, cint hs, double xs )
{

  assert( var >= 0 && var < prob->dimension.n );

  prob->hs[ var ] = hs;
  prob->xs[ var ] = xs;

  return SN_OK;
}

/* *************************************************************** */

cint snSetConstraint( snProblem* prob, cint con, cint hs, double xs )
{

  assert( con >= 0 && con < prob->dimension.m );

  prob->hs[ con + prob->dimension.n ] = hs;
  prob->xs[ con + prob->dimension.n ] = xs;

  return SN_OK;
}

/* *************************************************************** */

cint snSetMultiplier( snProblem* prob, cint con, double pi )
{
  assert( con >= 0 && con < prob->dimension.m );

  prob->pi[ con ] = pi;

  return SN_OK;
}

/* *************************************************************** */

cint snSetPrintFileName( snProblem* prob, char* print_file_name )
{
  cint str_len;

  if ( prob->option.sumry_file_name != NULL )
    if ( strcmp( print_file_name , prob->option.sumry_file_name ) == 0 ) {
      snSetError( prob, SN_FILE_ERROR,
		  "specified print file identical to summary file." );
      return SN_ERROR;
    }

  /* free if memory has already been assigned allocated */
  if ( prob->option.print_file_name != NULL )
    free( prob->option.print_file_name );

  str_len = strlen( print_file_name ) + 1;
  prob->option.print_file_name = (char*)malloc( sizeof(char) * str_len );
  strcpy( prob->option.print_file_name , print_file_name );

  return SN_OK;
}

/* *************************************************************** */

cint snSetSummaryFileName( snProblem* prob, char* sumry_file_name )
{
  cint str_len;

  if ( prob->option.print_file_name != NULL )
    if ( strcmp( sumry_file_name , prob->option.print_file_name ) == 0 ) {
      snSetError( prob, SN_FILE_ERROR,
		  "specified summary file identical to print file." );
      return SN_ERROR;
    }

  /* free if memory has already been assigned allocated */
  if ( prob->option.sumry_file_name != NULL )
    free( prob->option.sumry_file_name );

  str_len = strlen( sumry_file_name ) + 1;
  prob->option.sumry_file_name = (char*)malloc( sizeof(char) * str_len );
  strcpy( prob->option.sumry_file_name , sumry_file_name );

  return SN_OK;
}
