00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 (occurs only if inte::err_nonconv is true) 00059 00060 This function is based on the CERNLIB routines RCAUCH and 00061 DCAUCH which are documented at 00062 http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/d104/top.html 00063 */ 00064 template<class param_t, class func_t> class cern_cauchy : 00065 public inte<param_t,func_t> { 00066 00067 public: 00068 00069 cern_cauchy() { 00070 x[0]=0.96028985649753623; 00071 x[1]=0.79666647741362674; 00072 x[2]=0.52553240991632899; 00073 x[3]=0.18343464249564980; 00074 x[4]=0.98940093499164993; 00075 x[5]=0.94457502307323258; 00076 x[6]=0.86563120238783175; 00077 x[7]=0.75540440835500303; 00078 x[8]=0.61787624440264375; 00079 x[9]=0.45801677765722739; 00080 x[10]=0.28160355077925891; 00081 x[11]=0.95012509837637440e-1; 00082 00083 w[0]=0.10122853629037626; 00084 w[1]=0.22238103445337447; 00085 w[2]=0.31370664587788729; 00086 w[3]=0.36268378337836198; 00087 w[4]=0.27152459411754095e-1; 00088 w[5]=0.62253523938647893e-1; 00089 w[6]=0.95158511682492785e-1; 00090 w[7]=0.12462897125553387; 00091 w[8]=0.14959598881657673; 00092 w[9]=0.16915651939500254; 00093 w[10]=0.18260341504492359; 00094 w[11]=0.18945061045506850; 00095 00096 it=&def_inte; 00097 } 00098 00099 /// The singularity (must be set before calling integ() or integ_err()) 00100 double s; 00101 00102 /// Set the base integration object to use 00103 int set_inte(inte<param_t,func_t> &i) { 00104 it=&i; 00105 return 0; 00106 } 00107 00108 /** \brief Integrate function \c func from \c a to \c b 00109 giving result \c res and error \c err 00110 */ 00111 virtual int integ_err(func_t &func, double a, double b, param_t &pa, 00112 double &res, double &err) { 00113 if (s==a || s==b) { 00114 O2SCL_ERR_RET("Singularity on boundary in cern_cauchy::integ().", 00115 gsl_einval); 00116 } 00117 res=integ(func,a,b,pa); 00118 err=0.0; 00119 if (this->err_nonconv) return this->last_conv; 00120 return gsl_success; 00121 } 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, param_t &pa) { 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,pa); 00137 } 00138 double h, b0; 00139 if (2.0*s<a+b) { 00140 h=it->integ(func,2.0*s-a,b,pa); 00141 b0=s-a; 00142 } else { 00143 h=it->integ(func,a,2.0*s-b,pa); 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 func(c3+u,y1,pa); 00165 func(c4-u,y2,pa); 00166 func(c3-u,y3,pa); 00167 func(c4+u,y4,pa); 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 func(c3+u,y1,pa); 00174 func(c4-u,y2,pa); 00175 func(c3-u,y3,pa); 00176 func(c4+u,y4,pa); 00177 s16+=w[i]*((y1+y2)+(y3+y4)); 00178 } 00179 s16*=c2; 00180 00181 if (fabs(s16-s8)<=this->tolf*(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_CONV 00191 ("Couldn't reach required accuracy in cern_cauchy::integ()", 00192 gsl_efailed,this->err_nonconv); 00193 return 0.0; 00194 } 00195 } 00196 } 00197 h+=s16; 00198 if (bb==b0) loop1=false; 00199 } 00200 this->last_iter=itx; 00201 return h; 00202 } 00203 00204 /// Default integration object 00205 cern_gauss<param_t, func_t> def_inte; 00206 00207 protected: 00208 00209 #ifndef DOXYGEN_INTERNAL 00210 00211 /** \name Integration constants 00212 */ 00213 //@{ 00214 double x[12], w[12]; 00215 //@} 00216 00217 /// The base integration object 00218 inte<param_t, func_t> *it; 00219 00220 #endif 00221 00222 }; 00223 00224 #ifndef DOXYGENP 00225 } 00226 #endif 00227 00228 #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