#if !defined(PETSCTAOLINESEARCH_H)
#define PETSCTAOLINESEARCH_H

typedef struct _p_TaoLineSearch *TaoLineSearch;

#include <petsctao.h>

typedef enum {
  TAOLINESEARCH_FAILED_INFORNAN     = -1,
  TAOLINESEARCH_FAILED_BADPARAMETER = -2,
  TAOLINESEARCH_FAILED_ASCENT       = -3,
  TAOLINESEARCH_CONTINUE_ITERATING  = 0,
  TAOLINESEARCH_SUCCESS             = 1,
  TAOLINESEARCH_SUCCESS_USER        = 2,
  TAOLINESEARCH_HALTED_OTHER        = 3,
  TAOLINESEARCH_HALTED_MAXFCN       = 4,
  TAOLINESEARCH_HALTED_UPPERBOUND   = 5,
  TAOLINESEARCH_HALTED_LOWERBOUND   = 6,
  TAOLINESEARCH_HALTED_RTOL         = 7,
  TAOLINESEARCH_HALTED_USER         = 8
} TaoLineSearchConvergedReason;

typedef const char *TaoLineSearchType;
#define TAOLINESEARCHUNIT     "unit"
#define TAOLINESEARCHMT       "more-thuente"
#define TAOLINESEARCHGPCG     "gpcg"
#define TAOLINESEARCHARMIJO   "armijo"
#define TAOLINESEARCHOWARMIJO "owarmijo"
#define TAOLINESEARCHIPM      "ipm"

PETSC_EXTERN PetscClassId      TAOLINESEARCH_CLASSID;
PETSC_EXTERN PetscFunctionList TaoLineSearchList;

PETSC_EXTERN PetscErrorCode TaoLineSearchCreate(MPI_Comm, TaoLineSearch *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetUp(TaoLineSearch);
PETSC_EXTERN PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *);
PETSC_EXTERN PetscErrorCode TaoLineSearchMonitor(TaoLineSearch, PetscInt, PetscReal, PetscReal);
PETSC_EXTERN PetscErrorCode TaoLineSearchView(TaoLineSearch, PetscViewer);
PETSC_EXTERN PetscErrorCode TaoLineSearchViewFromOptions(TaoLineSearch, PetscObject, const char[]);

PETSC_EXTERN PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch, const char prefix[]);
PETSC_EXTERN PetscErrorCode TaoLineSearchReset(TaoLineSearch);
PETSC_EXTERN PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch, const char[]);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch, const char *[]);
PETSC_EXTERN PetscErrorCode TaoLineSearchApply(TaoLineSearch, Vec, PetscReal *, Vec, Vec, PetscReal *, TaoLineSearchConvergedReason *);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch, PetscReal *);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch, Vec *);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch, Vec *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch, PetscReal);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch, Vec, PetscReal *, Vec, PetscReal *, TaoLineSearchConvergedReason *);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch, PetscReal *);
PETSC_EXTERN PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch, PetscInt *, PetscInt *, PetscInt *);

PETSC_EXTERN PetscErrorCode TaoLineSearchGetType(TaoLineSearch, TaoLineSearchType *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetType(TaoLineSearch, TaoLineSearchType);

PETSC_EXTERN PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch, PetscBool *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch, PetscErrorCode (*)(TaoLineSearch, Vec, Vec, PetscReal *, PetscReal *, void *), void *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch, PetscErrorCode (*)(TaoLineSearch, Vec, PetscReal *, void *), void *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch, PetscErrorCode (*)(TaoLineSearch, Vec, Vec, void *), void *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch, PetscErrorCode (*)(TaoLineSearch, Vec, PetscReal *, Vec, void *), void *);

PETSC_EXTERN PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch, Vec, PetscReal *);
PETSC_EXTERN PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch, Vec, Vec);
PETSC_EXTERN PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch, Vec, PetscReal *, Vec);
PETSC_EXTERN PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch, Vec, PetscReal *, PetscReal *);
PETSC_EXTERN PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch, Vec, Vec);

PETSC_EXTERN PetscErrorCode TaoLineSearchInitializePackage(void);
PETSC_EXTERN PetscErrorCode TaoLineSearchFinalizePackage(void);

PETSC_EXTERN PetscErrorCode TaoLineSearchRegister(const char[], PetscErrorCode (*)(TaoLineSearch));
PETSC_EXTERN PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch, Tao);

#endif
