#ifndef _DDRIV2_H
#define _DDRIV2_H

#include "f_eval.h"

/*
** DDRIV2 is an Adams method documented in _Numerical Methods and
** Software_, by Kahaner, Moler, and Nash.
** n = number of equations.
** t = initial time.
** y = pointer to your array of n state variables.
** f = function of yours that computes ydot
** stiff_flag: 0 = no, 1 = yes, 2 = dynamically decided by DDRIV2
** eps = allowable relative error.
** zero = "problem zero"; I think it's allowable absolute error.
** nroot: number of roots to look for.
** g: function that computes functions in which we want to find roots.
**
*/

typedef double (*G_EVAL)(int N, double T, double *Y, int IROOT);

typedef struct _ddriv2
{
    int N, MSTATE, NROOT, MINT, LW, *IW, LIW, whichRoot;
    double T, *Y, EPS, EWT, *W;
    F_EVAL F;
    G_EVAL G;
} DDRIV2;



DDRIV2 *Ddriv2Alloc(int n, double t, double *y, F_EVAL f, int stiff_flag,
    double eps, double zero);

/*
** Ddriv2PrepRoot: initialize a root search.  You can change it on the
** fly.  Call with nroot = 0 and g = NULL to cancel a root search.
*/
void Ddriv2PrepRoot(DDRIV2 *d, int nroot, G_EVAL g);

/*
** Do the actual integration.  Return the actual TOUT
*/
double Ddriv2Integrate(DDRIV2 *d, double TOUT);

/*
** If Ddriv2Integrate returns due a root being found, this tells you
** which root it was.
*/
int Ddriv2WhichRoot(DDRIV2 *d);

/*
** Call this to free the memory used by a DDRIV2
*/
void Ddriv2Free(DDRIV2 *d);

#endif  /* _DDRIV2_H */
