00001
00010 #include "crombergintegrator.h"
00011 #include <cmath>
00012 #include <iostream>
00013
00014 using namespace std;
00015
00018 CRombergIntegrator::CRombergIntegrator()
00019 {
00020 s=0;
00021 h=0;
00022 }
00023
00026 CRombergIntegrator::CRombergIntegrator(double(*fun)(double))
00027 {
00028 mCallMethod=RI_a_function;
00029 function_fun=fun;
00030 jmax=JMAX;
00031 k=K;
00032 eps=EPS;
00033 s=new double[jmax];
00034 h=new double[jmax+1];
00035 }
00036
00042 CRombergIntegrator::CRombergIntegrator(double a_eps, int a_jmax, int a_k,double(*fun)(double))
00043 {
00044 mCallMethod=RI_a_function;
00045 function_fun=fun;
00046 jmax=a_jmax;
00047 k=a_k;
00048 eps=a_eps;
00049 s=new double[jmax];
00050 h=new double[jmax+1];
00051 }
00052
00055 CRombergIntegrator::CRombergIntegrator(void* class_ptr,double(*fun)(void*,double))
00056 {
00057 mCallMethod=RI_a_class;
00058 function_class=fun;
00059 callingClass=class_ptr;
00060 jmax=JMAX;
00061 k=K;
00062 eps=EPS;
00063 s=new double[jmax];
00064 h=new double[jmax+1];
00065 }
00066
00067 CRombergIntegrator::CRombergIntegrator(double a_eps, int a_jmax, int a_k,void* class_ptr,double(*fun)(void*,double))
00068 {
00069 mCallMethod=RI_a_class;
00070 function_class=fun;
00071 callingClass=class_ptr;
00072 jmax=a_jmax;
00073 k=a_k;
00074 eps=a_eps;
00075 s=new double[jmax];
00076 h=new double[jmax+1];
00077 }
00078
00079 double CRombergIntegrator::function(double x)
00080 {
00081 switch(mCallMethod)
00082 {
00083 case RI_a_function:
00084 return function_fun(x);
00085 break;
00086 case RI_a_class:
00087 return function_class(callingClass,x);
00088 break;
00089 default:
00090 cerr<<"you should never see this message"<<endl;
00091 return 0.0;
00092 }
00093 }
00094
00096 CRombergIntegrator::~CRombergIntegrator()
00097 {
00098 delete [] s;
00099 delete [] h;
00100 }
00101
00107 double CRombergIntegrator::compute(double a, double b)
00108 {
00109 double ss,dss;
00110 int j;
00111 h[1]=1.0;
00112 for (j=1;j<=jmax;j++) {
00113 s[j]=trapzd(a,b,j);
00114 if (j >= k) {
00115 polint(&h[j-k],&s[j-k],k,0.0,&ss,&dss);
00116 if (fabs(dss) <= eps*fabs(ss)) return ss;
00117 }
00118 h[j+1]=0.25*h[j];
00119 }
00120 cerr<<"Too many steps in routine qromb"<<endl;
00121 return ss;
00122 }
00123
00124 void CRombergIntegrator::polint(double xa[], double ya[], int n, double x, double *y, double *dy)
00125 {
00126
00127
00128
00129
00130
00131 int i,m,ns=1;
00132 double den,dif,dift,ho,hp,w;
00133 dif=fabs(x-xa[1]);
00134 double *c = new double[n+1];
00135 double *d = new double[n+1];
00136
00137 for (i=1;i<=n;i++) {
00138 if ( (dift=fabs(x-xa[i])) < dif)
00139 {
00140 ns=i;
00141 dif=dift;
00142 }
00143 c[i]=ya[i];
00144 d[i]=ya[i];
00145 }
00146 *y=ya[ns--];
00147 for (m=1;m<n;m++) {
00148 for (i=1;i<=n-m;i++) {
00149 ho=xa[i]-x;
00150 hp=xa[i+m]-x;
00151 w=c[i+1]-d[i];
00152 if ( (den=ho-hp) == 0.0) cerr<<"Error in routine polint"<<endl;
00153
00154 den=w/den;
00155 d[i]=hp*den;
00156 c[i]=ho*den;
00157 }
00158 *y += (*dy=(2*ns < (n-m) ? c[ns+1] : d[ns--]));
00159 }
00160 delete [] c;
00161 delete [] d;
00162 }
00163
00164
00165 double CRombergIntegrator::trapzd(double a, double b, int n)
00166 {
00167
00168 double x,tnm,sum,del;
00169 static double s;
00170 int it,j;
00171 if (n == 1) {
00172 return (s=0.5*(b-a)*(function(a)+function(b)));
00173 } else {
00174 for (it=1,j=1;j<n-1;j++) it <<= 1;
00175 tnm=it;
00176 del=(b-a)/tnm;
00177 x=a+0.5*del;
00178 for (sum=0.0,j=1;j<=it;j++,x+=del) sum += function(x);
00179 s=0.5*(s+(b-a)*sum/tnm);
00180 return s;
00181 }
00182 }