Sindbad~EG File Manager
/* Numerical integration of a function of one variable using
Runge-Kutta solver rk4 similar to the one in Numerical Recipes */
/* M. Beeson, for MathXpert */
/* code last modified 12.20.95
1.29.98, TRIGCALC_DLL etc.
3.25.01 changed hmin in numint to be nonzero
and changed TINY to 1.0e-10 instead of 1.0e-30
*/
#include <string.h>
#include <assert.h>
#include <math.h>
#define TRIGCALC_DLL
#include "globals.h"
#include "numint.h"
#include "ode.h"
#include "userint.h"
#include "symbols.h"
#include "errbuf.h"
#define EPS 1.0e-6
#define FIRSTSTEP 1.0e-6
#define MAXSTP 10000
#define _TINY 1.0e-10
/*_______________________________________________________________________*/
/* This function is like odeint (in ode.c) but does not draw the solution,
and nvar is 1 */
int odeint2(double ystart, /* the initial value */
double x1, /* starting value of independent variable */
double x2, /* ending value of independent variable */
double eps, /* accuracy desired */
double h1, /* guessed first stepsize */
double hmin, /* minimum allowed stepsize (can be zero) */
int *nok, /* number of good steps taken */
int *nbad, /* number of bad, but retried and fixed, steps */
term *f,
double *xptr, /* pointer to value of independent variable */
double *yptr, /* pointer to value of dependent variable */
double xtol,
double ytol
)
{ int nstp;
double x,hnext,hdid,h;
double *yscal,*y,*dydx;
double y1,yscal1,dydx1;
yscal= &yscal1-1;
y= &y1-1;
dydx= &dydx1-1;
x=x1;
h=(x2 > x1) ? fabs(h1) : -fabs(h1);
*nok = (*nbad) = 0;
y[1]=ystart;
for (nstp=1;nstp<=MAXSTP;nstp++)
{ derivs(f,1,x,y,dydx,xptr,&yptr-1);
yscal[1]=fabs(y[1])+fabs(dydx[1]*h)+_TINY;
/*
if ((nstp & 0x000f) == 0 && user_interrupt())
return 5; user interrupt
*/
if ((x+h-x2)*(x+h-x1) > 0.0) h=x2-x;
rkqc(y,dydx,1,&x,h,eps,yscal,&hdid,&hnext,f,xptr,&yptr-1,xtol,ytol);
if (hdid == h)
++(*nok);
else
++(*nbad);
if ((x-x2)*(x2-x1) >= 0.0) /* are we done? */
{ *yptr = y[1];
/* before this, *yptr contains the
NEXT TO LAST value of y, not the last one */
return 0;
}
if (fabs(hnext) <= hmin)
return 2; /* step size too small */
h=hnext;
}
return 3; /* too many steps */
}
#undef MAXSTP
#undef _TINY
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int numint(term u,term x,double a,double b,double *ans)
/* evaluate integral(u,x,a,b) numerically
using 4th-order Runge-Kutta as implemented in ode.c
*/
{ term y; /* solve y' = u */
int err;
// double hmin = 0.0; /* minimum allowed stepsize (can be zero) */
double hmin = fabs(b-a) * 1.0e-12; /* minimum allowed stepsize */
double xtol = fabs(b-a); /* not necessary but rkqc expects them */
double ytol = xtol;
int nok; /* number of good steps taken */
int nbad; /* number of bad, but retried and fixed, steps */
double ystart = 0.0;
double *xptr = (double *) x.args;
double *yptr;
y.args = (void *) mallocate(sizeof(double));
yptr = (double *) y.args;
/* pointer to value of y, which is NOT on the value list since y
is not a MathXpert object variable */
*xptr = a;
err = odeint2( ystart,a,b, EPS,FIRSTSTEP,hmin,&nok,&nbad,&u-1,xptr,yptr,xtol,ytol);
if(err)
{ errbuf(0, english(809));
/* Can't integrate numerically. There must be */
errbuf(1, english(810));
/* something unusual about this integral! */
return 1;
}
*ans = VALUE(y);
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists