#include "snopt.h"

cint snGetSolveMode( snProblem* prob )
{
  return prob->solve_mode;
}

cint snGetSuperBasicsLimit( snProblem* prob ) {
  return prob->option.superbasics_limit;
}

double snGetInfinity( snProblem* prob ) {
  return prob->option.infinity;
}

cint snGetMajorIterationLimit( snProblem* prob ) {
  return prob->option.major_iterations_limit;
}

cint snGetMinorIterationLimit( snProblem* prob ) {
  return prob->option.minor_iterations_limit;
}

double snGetMajorOptimalityTolerance( snProblem* prob ) {
  return prob->option.major_optimality_tolerance;
}

double snGetMajorFeasibilityTolerance( snProblem* prob ) {
  return prob->option.major_feasibility_tolerance;
}

cint snGetNumNonlinearConstraints( snProblem* prob )
{
  return prob->dimension.nnCon;
}

cint snGetNumVariables( snProblem* prob )
{
  return prob->dimension.n;
}

cint snGetNumConstraints( snProblem* prob ) {
  return prob->dimension.m;
}

cint snGetNumNonlinearObjectiveVariables( snProblem* prob ) {
  return prob->dimension.nnObj;
}

cint snGetNumNonlinearJacobianVariables( snProblem* prob ) {
  return prob->dimension.nnJac;
}

cint snGetNumNonzeros( snProblem* prob ) {
  return prob->dimension.ne;
}

snObjectiveFunc snGetObjectiveFunction( snProblem* prob ) {
  return prob->objective_func;
}

snConstraintFunc snGetConstraintFunction( snProblem* prob ) {
  return prob->constraint_func;
}

cint snGetVerifyLevel( snProblem* prob )
{
  return prob->option.verify_level;
}


cint snGetPrintFileName( snProblem* prob , char** file_name )
{
  if ( prob->option.print_file_name == NULL )
    *file_name = NULL;
  else
    /* freeing up file name is the caller's repsonsibility */
    *file_name = (char*)malloc( sizeof(char) *
				strlen( prob->option.print_file_name ) );

  strcpy( *file_name , prob->option.print_file_name );
  return SN_OK;
}

cint snGetSummaryFileName( snProblem* prob , char** file_name )
{
  /* freeing up file name is the caller's repsonsibility */
  *file_name = (char*)malloc( sizeof(char) *
			      strlen( prob->option.sumry_file_name ) );
  strcpy( *file_name , prob->option.sumry_file_name );
  return SN_OK;
}

double* snGetNonzeroValues( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized" );
    return NULL;
  }

  return prob->Jcol;
}

cint* snGetNonzeroRowIndices( snProblem* prob )
{
  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized" );
    return NULL;
  }

  return prob->indJ;
}

cint* snGetNonzeroColumnPointers( snProblem* prob )
{
  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }
  return prob->locJ;
}

double *snGetVariableUpperBounds( snProblem* prob )
{
  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }
  return prob->bu;
}

double *snGetVariableLowerBounds( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->bl;
}

double* snGetConstraintUpperBounds( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->bu + prob->dimension.n;
}

double* snGetConstraintLowerBounds( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized" );
    return NULL;
  }

  return prob->bl + prob->dimension.n;
}

double* snGetMultipliers( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->pi;

}

double* snGetVariables( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->xs;
}

double* snGetConstraints( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->xs + prob->dimension.n;
}

cint* snGetVariableBasisEligibilities( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->hs;
}

cint* snGetConstraintBasisEligibilities( snProblem* prob )
{

  if ( prob->iw == NULL ) {
    snSetError( prob , SN_PROBLEM_UNINITIALIZED ,
		"The problem is not initialized." );
    return NULL;
  }

  return prob->hs + prob->dimension.n;
}

cint snGetNumMinorIterations( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_minor_iterations;

}
cint snGetNumMajorIterations( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_major_iterations;

}

cint snGetNumObjectiveFunctionEvals( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_objective_function_evals;

}

cint snGetNumConstraintFunctionEvals( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_constraint_function_evals;

}

cint snGetNumSuperBasics( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_superbasics;

}

cint snGetNumDegenerateSteps( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_degenerate_steps;

}

cint snGetNumInfeasibilities( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.num_infeasibilities;

}

cint snGetSolveStatus( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return SN_ERROR;
  }

  return prob->solve_status;

}

double snGetNormScaledSolution( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.norm_scaled_solution;

}

double snGetNormSolution( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.norm_solution;

}

double snGetNormScaledMultipliers( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.norm_scaled_multipliers;

}

double snGetNormMultipliers( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.norm_multipliers;

}

double snGetPenalty ( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.penalty;

}

double snGetObjectiveValue( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.objective_value;

}

double snGetLinearObjectiveValue( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.linear_objective_value;

}

double snGetNonlinearObjectiveValue( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.nonlinear_objective_value;

}

double snGetSumInfeasibilities( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.sum_infeasibilities;

}

double snGetMaxScaledPrimalInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.max_scaled_primal_infeasibility;

}

cint snGetIMaxScaledPrimalInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.i_max_scaled_primal_infeasibility;

}

double snGetMaxScaledDualInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.max_scaled_dual_infeasibility;

}

cint snGetIMaxScaledDualInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.i_max_scaled_dual_infeasibility;

}

double snGetMaxPrimalInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.max_primal_infeasibility;

}

cint snGetIMaxPrimalInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.i_max_primal_infeasibility;

}

double snGetMaxDualInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.max_dual_infeasibility;

}

cint snGetIMaxDualInfeasibility( snProblem* prob )
{
  if ( !( prob->set_flags & SN_BIT_SOLVED )) {
    snSetError( prob , SN_PROBLEM_UNSOLVED ,
		"The problem has not been solved." );
    return 0;
  }

  return prob->stats.i_max_dual_infeasibility;

}
