![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_CERN_CAUCHY_H 00024 #define O2SCL_CERN_CAUCHY_H 00025 00026 #include <o2scl/inte.h> 00027 #include <o2scl/cern_gauss.h> 00028 00029 #ifndef DOXYGENP 00030 namespace o2scl { 00031 #endif 00032 00033 /** \brief Cauchy principal value integration (CERNLIB) 00034 00035 The location of the singularity must be specified before-hand in 00036 cern_cauchy::s, and the singularity must not be at one of the 00037 endpoints. Note that when integrating a function of the form \f$ 00038 \frac{f(x)}{(x-s)} \f$, the denominator \f$ (x-s) \f$ must be 00039 specified in the argument \c func to integ(). This is different 00040 from how the \ref gsl_inte_qawc operates. 00041 00042 The method from \ref Longman58 is used for the decomposition of 00043 the integral, and the resulting integrals are computed using 00044 a user-specified base integration object. 00045 00046 The uncertainty in the integral is not calculated, and is always 00047 given as zero. The default base integration object is of type 00048 \ref cern_gauss. This is the CERNLIB default, but can be 00049 modified by calling set_inte(). If the singularity is outside 00050 the region of integration, then the result from the base 00051 integration object is returned without calling the error 00052 handler. 00053 00054 Possible errors for integ() and integ_err(): 00055 - gsl_einval - Singularity is on an endpoint 00056 - gsl_efailed - Couldn't reach requested accuracy 00057 (occurs only if inte::err_nonconv is true) 00058 00059 This function is based on the CERNLIB routines RCAUCH and 00060 DCAUCH which are documented at 00061 http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/d104/top.html 00062 */ 00063 template<class func_t> class cern_cauchy : 00064 public inte<func_t> { 00065 00066 public: 00067 00068 cern_cauchy() { 00069 x[0]=0.96028985649753623; 00070 x[1]=0.79666647741362674; 00071 x[2]=0.52553240991632899; 00072 x[3]=0.18343464249564980; 00073 x[4]=0.98940093499164993; 00074 x[5]=0.94457502307323258; 00075 x[6]=0.86563120238783175; 00076 x[7]=0.75540440835500303; 00077 x[8]=0.61787624440264375; 00078 x[9]=0.45801677765722739; 00079 x[10]=0.28160355077925891; 00080 x[11]=0.95012509837637440e-1; 00081 00082 w[0]=0.10122853629037626; 00083 w[1]=0.22238103445337447; 00084 w[2]=0.31370664587788729; 00085 w[3]=0.36268378337836198; 00086 w[4]=0.27152459411754095e-1; 00087 w[5]=0.62253523938647893e-1; 00088 w[6]=0.95158511682492785e-1; 00089 w[7]=0.12462897125553387; 00090 w[8]=0.14959598881657673; 00091 w[9]=0.16915651939500254; 00092 w[10]=0.18260341504492359; 00093 w[11]=0.18945061045506850; 00094 00095 it=&def_inte; 00096 } 00097 00098 /// The singularity (must be set before calling integ() or integ_err()) 00099 double s; 00100 00101 /** \brief Set the base integration object to use 00102 (default is \ref cern_cauchy::def_inte of type \ref cern_gauss) 00103 */ 00104 int set_inte(inte<func_t> &i) { 00105 it=&i; 00106 return 0; 00107 } 00108 00109 /** \brief Integrate function \c func from \c a to \c b 00110 giving result \c res and error \c err 00111 */ 00112 virtual int integ_err(func_t &func, double a, double b, 00113 double &res, double &err) { 00114 if (s==a || s==b) { 00115 O2SCL_ERR_RET("Singularity on boundary in cern_cauchy::integ().", 00116 gsl_einval); 00117 } 00118 res=integ(func,a,b ); 00119 err=0.0; 00120 if (this->err_nonconv) return this->last_conv; 00121 return gsl_success; 00122 } 00123 00124 /** \brief Integrate function \c func from \c a to \c b 00125 */ 00126 virtual double integ(func_t &func, double a, double b) { 00127 double y1, y2, y3, y4; 00128 size_t itx=0; 00129 this->last_conv=0; 00130 00131 if (s==a || s==b) { 00132 O2SCL_ERR("Singularity on boundary in cern_cauchy::integ().", 00133 gsl_einval); 00134 return 0.0; 00135 } else if ((s<a && s<b) || (s>a && s>b)) { 00136 return it->integ(func,a,b ); 00137 } 00138 double h, b0; 00139 if (2.0*s<a+b) { 00140 h=it->integ(func,2.0*s-a,b ); 00141 b0=s-a; 00142 } else { 00143 h=it->integ(func,a,2.0*s-b ); 00144 b0=b-s; 00145 } 00146 double c=0.005/b0; 00147 double bb=0.0; 00148 bool loop1=true; 00149 while(loop1==true) { 00150 itx++; 00151 double s8, s16; 00152 double aa=bb; 00153 bb=b0; 00154 bool loop2=true; 00155 while(loop2==true) { 00156 double c1=(bb+aa)/2.0; 00157 double c2=(bb-aa)/2.0; 00158 double c3=s+c1; 00159 double c4=s-c1; 00160 s8=0.0; 00161 s16=0.0; 00162 for(int i=0;i<4;i++) { 00163 double u=c2*x[i]; 00164 y1=func(c3+u); 00165 y2=func(c4-u); 00166 y3=func(c3-u); 00167 y4=func(c4+u); 00168 s8+=w[i]*((y1+y2)+(y3+y4)); 00169 } 00170 s8*=c2; 00171 for(int i=4;i<12;i++) { 00172 double u=c2*x[i]; 00173 y1=func(c3+u); 00174 y2=func(c4-u); 00175 y3=func(c3-u); 00176 y4=func(c4+u); 00177 s16+=w[i]*((y1+y2)+(y3+y4)); 00178 } 00179 s16*=c2; 00180 00181 if (fabs(s16-s8)<=this->tol_rel*(1.0+fabs(s16))) { 00182 loop2=false; 00183 } else { 00184 bb=c1; 00185 if ((1.0+fabs(c*c2))==1.0) { 00186 loop2=false; 00187 } else { 00188 this->last_iter=itx; 00189 this->last_conv=gsl_efailed; 00190 O2SCL_CONV2("Couldn't reach required accuracy in cern_", 00191 "cauchy::integ()",gsl_efailed,this->err_nonconv); 00192 return 0.0; 00193 } 00194 } 00195 } 00196 h+=s16; 00197 if (bb==b0) loop1=false; 00198 } 00199 this->last_iter=itx; 00200 return h; 00201 } 00202 00203 /// Default integration object 00204 cern_gauss<func_t> def_inte; 00205 00206 protected: 00207 00208 #ifndef DOXYGEN_INTERNAL 00209 00210 /** \name Integration constants 00211 */ 00212 //@{ 00213 double x[12], w[12]; 00214 //@} 00215 00216 /// The base integration object 00217 inte<func_t> *it; 00218 00219 #endif 00220 00221 }; 00222 00223 #ifndef DOXYGENP 00224 } 00225 #endif 00226 00227 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).