#include <gpk_std.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#ifdef THREE
# include "runge6.h"
#endif
#ifdef BULSTO
# include "runge6.h"
#include "bulsto.h"
#endif

#ifndef F
# ifndef THREE
#  ifndef BULSTO
#   define TWO
#  endif
# endif
#endif

int xdotval = 0;

BOOL out(double *xo, C double *x, int nx, void *c, int nc, int nout)
{

 printf("\tout((%g,%g),%d,xxx,0,%d)\n", x[0], x[1], nx, nout);

 if(nout != 2)
	return FALSE;
 xo[0] = x[1];
 xo[1] = x[1] - 1/(1+100*x[0]*x[0]);
 return TRUE;
}

BOOL xdot(double *xd, C double *x, int nx, void *c, int nc)
{
 extern int xdotval;

/*
 printf("\txdot((%g,%g),%d,xxxx,0)=", x[0], x[1], nx);
*/
 xd[0] = 1.0;
 xd[1] = -200.0*x[0]*x[1]*x[1];
/*
 printf("(%g,%g)\n", xd[0], xd[1]);
*/
 if(x[1]<=0.0)
	printf("xdot:x[1]=%7.3g<0.0\n", x[1]);
 xdotval ++;
 return x[1]>0.0;
}



main(int argc, char **argv)
{
 double x[2], tv[100], eps;
 int i;
 extern int xdotval;
#ifdef F
 double *p;
#endif
#ifdef TWO
 double *p;
#endif
#ifdef THREE
 struct runge_s  p;
 LOCAL double limits[] = {0.0, 0.0};
#endif
#ifdef BULSTO
 struct runge_s  p;
 LOCAL double limits[] = {0.0, 0.0};
#endif

 eps = argc>1 ? atof(argv[1]) : 1e-12;
 for(i=0;i<10;i++)
	tv[i] = -3.0 + 3.0*i/9.0;
 x[0] = -3.0;
 x[1] = 1.0/901.;
#ifdef TWO
 p = runge2(x, NULL, 2, 0, xdot, eps, tv, 10, out, 2);
 if(!p)
	printf("p==NULL\n");
 for(i=0;i<10;i++)
	printf("y[%g]=%g, err=%g\n", tv[i], p[2*i], p[2*i+1]);

 free((void *) p);
#endif
#ifdef F
 p = rungeF(x, NULL, 2, 0, xdot, eps, tv, 10, out, 2);
 if(!p)
	printf("p==NULL\n");
 for(i=0;i<10;i++)
	printf("y[%g]=%g, err=%g\n", tv[i], p[2*i], p[2*i+1]);

 free((void *) p);
#endif
#ifdef THREE
 p = runge3(x, NULL, 2, 0, xdot, eps, tv, 10, out, 2, limits);
 if(!p.xx)      {
	printf("p==NULL\n");
	exit(-1);
	}
 if(!p.isgood)  printf("error %d in runge3\n", p.errtype);
 for(i=0;i<p.stepcount;i++)
	printf("y[%g]=%g, err=%g\n", tv[i], p.xx[2*i], p.xx[2*i+1]);

 free((void *) p.xx);
#endif
#ifdef BULSTO
 p = bulsto(x, (void *)0, 2, 0, xdot, eps, tv, 10, out, 2, limits);
 if(!p.xx)      {
	printf("p==NULL\n");
	exit(-1);
	}
 if(!p.isgood)  printf("error %d in bulsto\n", p.errtype);
 for(i=0;i<p.stepcount;i++)
	printf("y[%g]=%g, err=%g\n", tv[i], p.xx[2*i], p.xx[2*i+1]);

 free((char *) p.xx);
#endif
 printf("Total of %d calls to xdot\n", xdotval);
 exit(0);
}
