00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef O2SCL_CERN_DERIV_H
00024 #define O2SCL_CERN_DERIV_H
00025
00026 #include <o2scl/deriv.h>
00027
00028 #ifndef DOXYGENP
00029 namespace o2scl {
00030 #endif
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 template<class param_t, class func_t>
00059 class cern_deriv : public deriv<param_t,func_t> {
00060
00061 public:
00062
00063
00064 double delta;
00065
00066
00067 double eps;
00068
00069 cern_deriv() {
00070
00071 dx[0]=0.0256;
00072 dx[1]=0.0192;
00073 dx[2]=0.0128;
00074 dx[3]=0.0096;
00075 dx[4]=0.0064;
00076 dx[5]=0.0048;
00077 dx[6]=0.0032;
00078 dx[7]=0.0024;
00079 dx[8]=0.0016;
00080 dx[9]=0.0012;
00081
00082 w[1][1]=1.3333333333333333;
00083 w[3][1]=1.0666666666666667;
00084 w[5][1]=1.0158730158730159;
00085 w[7][1]=1.0039215686274510;
00086
00087 w[2][1]=3.3333333333333333e-1;
00088 w[4][1]=6.6666666666666667e-2;
00089 w[6][1]=1.5873015873015873e-2;
00090 w[8][1]=3.9215686274509804e-3;
00091
00092 w[0][2]=2.2857142857142857;
00093 w[2][2]=1.1636363636363636;
00094 w[4][2]=1.0364372469635628;
00095 w[6][2]=1.0088669950738916;
00096 w[8][2]=1.0022021042329337;
00097
00098 w[1][2]=1.2857142857142857;
00099 w[3][2]=1.6363636363636364e-1;
00100 w[5][2]=3.6437246963562753e-2;
00101 w[7][2]=8.8669950738916256e-3;
00102 w[9][2]=2.2021042329336922e-3;
00103
00104 w[0][3]=1.8000000000000000;
00105 w[2][3]=1.1250000000000000;
00106 w[4][3]=1.0285714285714286;
00107 w[6][3]=1.0069930069930070;
00108 w[8][3]=1.0017391304347826;
00109
00110 w[1][3]=8.0000000000000000e-1;
00111 w[3][3]=1.2500000000000000e-1;
00112 w[5][3]=2.8571428571428571e-2;
00113 w[7][3]=6.9930069930069930e-3;
00114 w[9][3]=1.7391304347826087e-3;
00115
00116 delta=1.0;
00117 eps=5.0e-14;
00118 }
00119
00120 virtual int calc_err(double x, param_t &pa, func_t &func,
00121 double &dfdx, double &err) {
00122
00123 double t[10][10], a[10], del, hh;
00124 bool lev[10]={1,0,1,0,1,0,1,0,1,0}, lmt;
00125 int is, k, m;
00126
00127 err_hnd->reset();
00128
00129 del=10.0*fabs(delta);
00130 is=10;
00131
00132 do {
00133 is--;
00134 del=del/10.0;
00135
00136 if (is==0 || x+del*dx[9]==x) {
00137 delta=del;
00138 dfdx=0.0;
00139 err=0.0;
00140 set_err_ret
00141 ("Calculation of derivative failed in cern_deriv::calc().",
00142 gsl_efailed);
00143 }
00144
00145 for(k=0;k<=9;k++) {
00146 hh=del*dx[k];
00147 t[k][0]=(func(x+hh,pa)-func(x-hh,pa))/(hh+hh);
00148 a[k]=t[k][0];
00149 }
00150
00151 if (a[0]>=a[9]) {
00152 for(k=0;k<=9;k++) a[k]=-a[k];
00153 }
00154
00155 lmt=true;
00156 for(k=1;k<=9;k++) {
00157 hh=a[k-1]-a[k];
00158 lmt=(lmt && (hh<=0.0 || fabs(hh)<=eps*fabs(a[k])));
00159 }
00160
00161 if (this->verbose>0) {
00162 std::cout << "cern_deriv, iteration: " << 10-is << std::endl;
00163 std::cout << "(hh, a[k], derivative) list: "
00164 << std::endl;
00165 for(k=1;k<=9;k++) {
00166 std::cout << a[k-1]-a[k] << " " << eps*fabs(a[k]) << " "
00167 << t[k][0] << std::endl;
00168 }
00169 std::cout << "Converged: " << lmt << std::endl;
00170 if (this->verbose>1) {
00171 char ch;
00172 std::cin >> ch;
00173 }
00174 }
00175
00176 } while (lmt==false);
00177
00178 for(m=1;m<=9;m++) {
00179 for(k=0;k<=9-m;k++) {
00180 if (lev[m]) {
00181 t[k][m]=w[m-1][1]*t[k+1][m-1]-w[m][1]*t[k][m-1];
00182 } else if (lev[k]) {
00183 t[k][m]=w[m-1][2]*t[k+1][m-1]-w[m][2]*t[k][m-1];
00184 } else {
00185 t[k][m]=w[m-1][3]*t[k+1][m-1]-w[m][3]*t[k][m-1];
00186 }
00187 }
00188 }
00189 dfdx=t[0][9];
00190 if (dfdx!=0.0) err=(dfdx-t[0][8])/dfdx;
00191 else err=0.0;
00192 delta=del;
00193
00194 return 0;
00195 }
00196
00197 virtual int calc_err_int
00198 (double x, typename deriv<param_t,func_t>::dpars &pa,
00199 funct<typename deriv<param_t,func_t>::dpars> &func,
00200 double &dfdx, double &err) {
00201
00202 double t[10][10], a[10], del, hh;
00203 bool lev[10]={1,0,1,0,1,0,1,0,1,0}, lmt;
00204 int is, k, m;
00205
00206 err_hnd->reset();
00207
00208 del=10.0*fabs(delta);
00209 is=10;
00210
00211 do {
00212 is--;
00213 del=del/10.0;
00214 if (is==0 || x+del*dx[9]==x) {
00215 delta=del;
00216 set_err("Calculation of derivative failed in cern_deriv::calc().",
00217 gsl_efailed);
00218 dfdx=0.0;
00219 err=0.0;
00220 return 1;
00221 }
00222
00223 for(k=0;k<=9;k++) {
00224 hh=del*dx[k];
00225 t[k][0]=(func(x+hh,pa)-func(x-hh,pa))/(hh+hh);
00226 a[k]=t[k][0];
00227 }
00228
00229 if (a[0]>=a[9]) {
00230 for(k=0;k<=9;k++) a[k]=-a[k];
00231 }
00232
00233 lmt=true;
00234 for(k=1;k<=9;k++) {
00235 hh=a[k-1]-a[k];
00236 lmt=(lmt && (hh<=0.0 || fabs(hh)<=eps*fabs(a[k])));
00237 }
00238
00239 } while (lmt==false);
00240
00241 for(m=1;m<=9;m++) {
00242 for(k=0;k<=9-m;k++) {
00243 if (lev[m]) {
00244 t[k][m]=w[m-1][1]*t[k+1][m-1]-w[m][1]*t[k][m-1];
00245 } else if (lev[k]) {
00246 t[k][m]=w[m-1][2]*t[k+1][m-1]-w[m][2]*t[k][m-1];
00247 } else {
00248 t[k][m]=w[m-1][3]*t[k+1][m-1]-w[m][3]*t[k][m-1];
00249 }
00250 }
00251 }
00252 dfdx=t[0][9];
00253 if (dfdx!=0.0) err=(dfdx-t[0][8])/dfdx;
00254 else err=0.0;
00255 delta=del;
00256
00257 return 0;
00258 }
00259
00260
00261 virtual const char *type() { return "cern_deriv"; }
00262
00263 protected:
00264
00265 #ifndef DOXYGEN_INTERNAL
00266
00267
00268
00269 double dx[10];
00270 double w[10][4];
00271
00272
00273 #endif
00274
00275 };
00276
00277 #ifndef DOXYGENP
00278 }
00279 #endif
00280
00281 #endif
00282
00283