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 a user-specified base integration object. 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 /** \brief Set the base integration object to use 00103 (default is \ref cern_cauchy::def_inte of type \ref cern_gauss) 00104 */ 00105 int set_inte(inte<param_t,func_t> &i) { 00106 it=&i; 00107 return 0; 00108 } 00109 00110 /** \brief Integrate function \c func from \c a to \c b 00111 giving result \c res and error \c err 00112 */ 00113 virtual int integ_err(func_t &func, double a, double b, param_t &pa, 00114 double &res, double &err) { 00115 if (s==a || s==b) { 00116 O2SCL_ERR_RET("Singularity on boundary in cern_cauchy::integ().", 00117 gsl_einval); 00118 } 00119 res=integ(func,a,b,pa); 00120 err=0.0; 00121 if (this->err_nonconv) return this->last_conv; 00122 return gsl_success; 00123 } 00124 00125 /** 00126 \brief Integrate function \c func from \c a to \c b 00127 */ 00128 virtual double integ(func_t &func, double a, double b, param_t &pa) { 00129 double y1, y2, y3, y4; 00130 size_t itx=0; 00131 this->last_conv=0; 00132 00133 if (s==a || s==b) { 00134 O2SCL_ERR("Singularity on boundary in cern_cauchy::integ().", 00135 gsl_einval); 00136 return 0.0; 00137 } else if ((s<a && s<b) || (s>a && s>b)) { 00138 return it->integ(func,a,b,pa); 00139 } 00140 double h, b0; 00141 if (2.0*s<a+b) { 00142 h=it->integ(func,2.0*s-a,b,pa); 00143 b0=s-a; 00144 } else { 00145 h=it->integ(func,a,2.0*s-b,pa); 00146 b0=b-s; 00147 } 00148 double c=0.005/b0; 00149 double bb=0.0; 00150 bool loop1=true; 00151 while(loop1==true) { 00152 itx++; 00153 double s8, s16; 00154 double aa=bb; 00155 bb=b0; 00156 bool loop2=true; 00157 while(loop2==true) { 00158 double c1=(bb+aa)/2.0; 00159 double c2=(bb-aa)/2.0; 00160 double c3=s+c1; 00161 double c4=s-c1; 00162 s8=0.0; 00163 s16=0.0; 00164 for(int i=0;i<4;i++) { 00165 double u=c2*x[i]; 00166 func(c3+u,y1,pa); 00167 func(c4-u,y2,pa); 00168 func(c3-u,y3,pa); 00169 func(c4+u,y4,pa); 00170 s8+=w[i]*((y1+y2)+(y3+y4)); 00171 } 00172 s8*=c2; 00173 for(int i=4;i<12;i++) { 00174 double u=c2*x[i]; 00175 func(c3+u,y1,pa); 00176 func(c4-u,y2,pa); 00177 func(c3-u,y3,pa); 00178 func(c4+u,y4,pa); 00179 s16+=w[i]*((y1+y2)+(y3+y4)); 00180 } 00181 s16*=c2; 00182 00183 if (fabs(s16-s8)<=this->tolf*(1.0+fabs(s16))) { 00184 loop2=false; 00185 } else { 00186 bb=c1; 00187 if ((1.0+fabs(c*c2))==1.0) { 00188 loop2=false; 00189 } else { 00190 this->last_iter=itx; 00191 this->last_conv=gsl_efailed; 00192 O2SCL_CONV 00193 ("Couldn't reach required accuracy in cern_cauchy::integ()", 00194 gsl_efailed,this->err_nonconv); 00195 return 0.0; 00196 } 00197 } 00198 } 00199 h+=s16; 00200 if (bb==b0) loop1=false; 00201 } 00202 this->last_iter=itx; 00203 return h; 00204 } 00205 00206 /// Default integration object 00207 cern_gauss<param_t, func_t> def_inte; 00208 00209 protected: 00210 00211 #ifndef DOXYGEN_INTERNAL 00212 00213 /** \name Integration constants 00214 */ 00215 //@{ 00216 double x[12], w[12]; 00217 //@} 00218 00219 /// The base integration object 00220 inte<param_t, func_t> *it; 00221 00222 #endif 00223 00224 }; 00225 00226 #ifndef DOXYGENP 00227 } 00228 #endif 00229 00230 #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