00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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 /** 00034 \brief Cauchy principal value integration (CERNLIB) 00035 00036 The location of the singularity must be specified before-hand in 00037 cern_cauchy::s, and the singularity must not be at one of the 00038 endpoints. Note that when integrating a function of the form \f$ 00039 \frac{f(x)}{(x-s)} \f$, the denominator \f$ (x-s) \f$ must be 00040 specified in the argument \c func to integ(). This is different 00041 from how the \ref gsl_inte_qawc operates. 00042 00043 The method from \ref Longman58 is used for the decomposition of 00044 the integral, and the resulting integrals are computed using 00045 cern_gauss. 00046 00047 The uncertainty in the integral is not calculated, and is always 00048 given as zero. The default base integration object is of type 00049 \ref cern_gauss. This is the CERNLIB default, but can be 00050 modified by calling set_inte(). If the singularity is outside 00051 the region of integration, then the result from the base 00052 integration object is returned without calling the error 00053 handler. 00054 00055 Possible errors for integ() and integ_err(): 00056 - gsl_einval - Singularity is on an endpoint 00057 - gsl_efailed - Couldn't reach requested accuracy 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 param_t, class func_t> class cern_cauchy : 00064 public inte<param_t,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 /// Set the base integration object to use 00102 int set_inte(inte<param_t,func_t> &i) { 00103 it=&i; 00104 return 0; 00105 } 00106 00107 /** \brief Integrate function \c func from \c a to \c b 00108 giving result \c res and error \c err 00109 */ 00110 virtual int integ_err(func_t &func, double a, double b, param_t &pa, 00111 double &res, double &err) { 00112 err_hnd->reset(); 00113 res=integ(func,a,b,pa); 00114 err=0.0; 00115 return err_hnd->get_errno(); 00116 } 00117 00118 /** 00119 00120 \brief Integrate function \c func from \c a to \c b 00121 */ 00122 virtual double integ(func_t &func, double a, double b, param_t &pa) { 00123 double y1, y2, y3, y4; 00124 size_t itx=0; 00125 00126 if (s==a || s==b) { 00127 set_err("Singularity on boundary in cern_cauchy::integ().", 00128 gsl_einval); 00129 return 0.0; 00130 } else if ((s<a && s<b) || (s>a && s>b)) { 00131 return it->integ(func,a,b,pa); 00132 } 00133 double h, b0; 00134 if (2.0*s<a+b) { 00135 h=it->integ(func,2.0*s-a,b,pa); 00136 b0=s-a; 00137 } else { 00138 h=it->integ(func,a,2.0*s-b,pa); 00139 b0=b-s; 00140 } 00141 double c=0.005/b0; 00142 double bb=0.0; 00143 bool loop1=true; 00144 while(loop1==true) { 00145 itx++; 00146 double s8, s16; 00147 double aa=bb; 00148 bb=b0; 00149 bool loop2=true; 00150 while(loop2==true) { 00151 double c1=(bb+aa)/2.0; 00152 double c2=(bb-aa)/2.0; 00153 double c3=s+c1; 00154 double c4=s-c1; 00155 s8=0.0; 00156 s16=0.0; 00157 for(int i=0;i<4;i++) { 00158 double u=c2*x[i]; 00159 func(c3+u,y1,pa); 00160 func(c4-u,y2,pa); 00161 func(c3-u,y3,pa); 00162 func(c4+u,y4,pa); 00163 s8+=w[i]*((y1+y2)+(y3+y4)); 00164 } 00165 s8*=c2; 00166 for(int i=4;i<12;i++) { 00167 double u=c2*x[i]; 00168 func(c3+u,y1,pa); 00169 func(c4-u,y2,pa); 00170 func(c3-u,y3,pa); 00171 func(c4+u,y4,pa); 00172 s16+=w[i]*((y1+y2)+(y3+y4)); 00173 } 00174 s16*=c2; 00175 00176 if (fabs(s16-s8)<=this->tolf*(1.0+fabs(s16))) { 00177 loop2=false; 00178 } else { 00179 bb=c1; 00180 if ((1.0+fabs(c*c2))==1.0) { 00181 loop2=false; 00182 } else { 00183 this->last_iter=itx; 00184 set_err 00185 ("Couldn't reach required accuracy in cern_cauchy::integ()", 00186 gsl_efailed); 00187 return 0.0; 00188 } 00189 } 00190 } 00191 h+=s16; 00192 if (bb==b0) loop1=false; 00193 } 00194 this->last_iter=itx; 00195 return h; 00196 } 00197 00198 /// Default integration object 00199 cern_gauss<param_t, func_t> def_inte; 00200 00201 protected: 00202 00203 #ifndef DOXYGEN_INTERNAL 00204 00205 /** \name Integration constants 00206 */ 00207 //@{ 00208 double x[12], w[12]; 00209 //@} 00210 00211 /// The base integration object 00212 inte<param_t, func_t> *it; 00213 00214 #endif 00215 00216 }; 00217 00218 #ifndef DOXYGENP 00219 } 00220 #endif 00221 00222 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page