#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "gpk_std.h"
#include "bulsto.h"

#define NTV     10

#define ADDRESS	char *

GLOBAL long xdotval = 0;

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

main(int argc, char **argv)
{
 struct runge_s p;
 C LOCAL double limits[]={1.0, 1.0, 1.0};
 static double x[]={0.0, 1.0, 0.0};
 double eps, tv[NTV];
 int i;

 eps = argc>1 ? atof(argv[1]) : 1e-12;
 for(i=0;i<NTV;i++)
	tv[i] = i/10.0;
 p = bulsto(x, (void *)0, 3, 0, xdot, eps, tv, NTV, out, 3, 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+exp(-x),%g)\n", tv[i], p.xx[3*i+1]-exp(-p.xx[3*i]),
				  p.xx[3*i+1]);
	printf("x_error=%g (is %g, should be %g)\n", p.xx[3*i]-tv[i],
						p.xx[3*i], tv[i]);
	}

 printf("There were a total of %ld calls to xdot\n", xdotval);
 free((ADDRESS) p.xx);
 exit(0);
}






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

 if(nout != 3)
	return FALSE;
 xo[0] = x[0];
 xo[1] = x[1] + x[2];
 xo[2] = x[2];
 printf("out: %g %g %g\n", xo[0], xo[1], xo[2]);
 return TRUE;
}



BOOL xdot(double *xd, C double *x, int nx, void *c, int nc)
{
 IMPORT long xdotval;
 BOOL bad = FALSE;

 xd[0] = 1.0;
 xd[1] = 998*x[1] + 1998*x[2];
 xd[2] = -999*x[1] -1999*x[2];
/*
 printf("(%g,%g)\n", xd[0], xd[1]);
*/
 if(x[1]<=0.0 || x[2]<-2.0 || x[2]>2.0 || x[1]>3.0)     {
	printf("xdot:x[1]=%7.3g, x[2]=%7.3g\n", x[1], x[2]);
	bad = TRUE;
	}
 xdotval ++;
 return (xdotval%400 != 40) && !bad;
}
