#include "gpk_std.h"
#include "romberg.h"

/**\brief Midpoint rule on an open interval.
This is passed to qromo() to do a Romberg integration using
the midpoint rule.    
For midpnt(), the function is not evaluated at either boundary.
*/
method_fr midpnt(integrand_function func,	/** The thing to integrate. */
		double a,			/** Left boundary. */
		double b,			/** Right boundary. */
		int n,				/* Number of steps to use. */
		void *c,	/* To be passed to the integrand. */
		int nc		/* To be passed to the integrand. */
		)
{
 method_fr rv;
 long tnm, j;
 int i;

 if(n == 0)     {
	rv.s = (*func)(0.5*(a+b), c, nc);
	rv.ss = rv.s * rv.s;
	rv.h = rv.hext = 1.0;
	return rv;
	}
 for(tnm=1,i=0; i<n-1; i++)
	tnm *= 3;
 C double del = (b-a)/tnm;
 C double sixth = 1.0/6.0;
 C double fsixth = 5.0/6.0;
 double s1 = 0.0, s2 = 0.0, ss = 0.0;
 OPENMP(omp parallel for reduction(+: s1,s2,ss) schedule(dynamic, 8))
 for(j=0; j<tnm; j++)   {
	double tmp;
	tmp = (*func)(a + del*(j+sixth), c, nc);
	s1 += tmp;
	ss += tmp*tmp;
	tmp =  (*func)(a + del*(j+fsixth), c, nc);
	s2 += tmp;
	ss += tmp*tmp;
	}
 rv.s = s1 + s2;
 rv.ss = ss;
 rv.h = 1.0/(3*tnm);
 rv.hext = rv.h * rv.h;
 return rv;
}
