![]() |
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_GAUSS_H 00024 #define O2SCL_CERN_GAUSS_H 00025 00026 #include <o2scl/inte.h> 00027 00028 #ifndef DOXYGENP 00029 namespace o2scl { 00030 #endif 00031 00032 /** \brief Gaussian quadrature (CERNLIB) 00033 00034 For any interval \f$ (a,b) \f$, we define \f$ g_8(a,b) \f$ and 00035 \f$ g_{16}(a,b) \f$ to be the 8- and 16-point Gaussian 00036 quadrature approximations to 00037 \f[ 00038 I=\int_a^b f(x)~dx 00039 \f] 00040 and define 00041 \f[ 00042 r(a,b)=\frac{|g_{16}(a,b)-g_{8}(a,b)|}{1+g_{16}(a,b)} 00043 \f] 00044 The function integ() returns \f$ G \f$ given by 00045 \f[ 00046 G=\sum_{i=1}^{k} g_{16}(x_{i-1},x_i) 00047 \f] 00048 where \f$ x_0=a \f$ and \f$ x_k=b \f$ and the subdivision 00049 points \f$ x_i \f$ are given by 00050 \f[ 00051 x_i=x_{i-1}+\lambda(B-x_{i-1}) 00052 \f] 00053 where \f$ \lambda \f$ is the first number in the sequence \f$ 00054 1,\frac{1}{2},\frac{1}{4},... \f$ for which 00055 \f[ 00056 r(x_{i-1},x_i)<\mathrm{eps}. 00057 \f] 00058 If, at any stage, the ratio 00059 \f[ 00060 q=\left| \frac{x_i-x_{i-1}}{b-a} \right| 00061 \f] 00062 is so small so that \f$ 1+0.005 q \f$ is indistinguishable from 00063 unity, then the accuracy is required is not reachable and 00064 the error handler is called. 00065 00066 Unless there is severe cancellation, inte::tol_rel may be 00067 considered as specifying a bound on the relative error of the 00068 integral in the case that \f$ |I|>1 \f$ and an absolute error if 00069 \f$ |I|<1 \f$. More precisely, if \f$ k \f$ is the number of 00070 subintervals from above, and if 00071 \f[ 00072 I_{abs} = \int_a^b |f(x)|~dx 00073 \f] 00074 then 00075 \f[ 00076 \frac{|G-I|}{I_{abs}+k}<\mathrm{tol_rel} 00077 \f] 00078 will nearly always be true when no error is returned. For 00079 functions with no singualarities in the interval, the accuracy 00080 will usually be higher than this. 00081 00082 If the desired accuracy is not achieved, the integration 00083 functions will call the error handler and return the best guess, 00084 unless \ref inte::err_nonconv is false, in which case the error 00085 handler is not called. 00086 00087 This function is based on the CERNLIB routines GAUSS and 00088 DGAUSS which are documented at 00089 http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/d103/top.html 00090 00091 \future Allow user to change \c cst? 00092 */ 00093 template<class func_t=funct> class cern_gauss : public inte<func_t> { 00094 00095 public: 00096 00097 cern_gauss() { 00098 x[0]=0.96028985649753623; 00099 x[1]=0.79666647741362674; 00100 x[2]=0.52553240991632899; 00101 x[3]=0.18343464249564980; 00102 x[4]=0.98940093499164993; 00103 x[5]=0.94457502307323258; 00104 x[6]=0.86563120238783175; 00105 x[7]=0.75540440835500303; 00106 x[8]=0.61787624440264375; 00107 x[9]=0.45801677765722739; 00108 x[10]=0.28160355077925891; 00109 x[11]=0.95012509837637440e-1; 00110 00111 w[0]=0.10122853629037626; 00112 w[1]=0.22238103445337447; 00113 w[2]=0.31370664587788729; 00114 w[3]=0.36268378337836198; 00115 w[4]=0.27152459411754095e-1; 00116 w[5]=0.62253523938647893e-1; 00117 w[6]=0.95158511682492785e-1; 00118 w[7]=0.12462897125553387; 00119 w[8]=0.14959598881657673; 00120 w[9]=0.16915651939500254; 00121 w[10]=0.18260341504492359; 00122 w[11]=0.18945061045506850; 00123 } 00124 00125 /** \brief Integrate function \c func from \c a to \c b 00126 giving result \c res and error \c err 00127 */ 00128 virtual int integ_err(func_t &func, double a, double b, 00129 double &res, double &err) { 00130 res=integ(func,a,b); 00131 err=0.0; 00132 if (this->err_nonconv) return this->last_conv; 00133 return gsl_success; 00134 } 00135 00136 /** \brief Integrate function \c func from \c a to \c b. 00137 */ 00138 virtual double integ(func_t &func, double a, double b) { 00139 00140 double y1, y2; 00141 00142 this->last_conv=0; 00143 size_t itx=0; 00144 00145 int i; 00146 bool loop=true, loop2=false; 00147 static const double cst=0.005; 00148 double h=0.0; 00149 if (b==a) return 0.0; 00150 double cnst=cst/(b-a); 00151 double aa=0.0, bb=a; 00152 while (loop==true || loop2==true) { 00153 itx++; 00154 if (loop==true) { 00155 aa=bb; 00156 bb=b; 00157 } 00158 double c1=(bb+aa)/2.0; 00159 double c2=(bb-aa)/2.0; 00160 double s8=0.0; 00161 for(i=0;i<4;i++) { 00162 double u=c2*x[i]; 00163 y1=func(c1+u); 00164 y2=func(c1-u); 00165 s8+=w[i]*(y1+y2); 00166 } 00167 double s16=0.0; 00168 for(i=4;i<12;i++) { 00169 double u=c2*x[i]; 00170 y1=func(c1+u); 00171 y2=func(c1-u); 00172 s16+=w[i]*(y1+y2); 00173 } 00174 s16*=c2; 00175 00176 loop=false; 00177 loop2=false; 00178 if (fabs(s16-c2*s8)<this->tol_rel*(1.0+fabs(s16))) { 00179 h+=s16; 00180 if (bb!=b) loop=true; 00181 } else { 00182 bb=c1; 00183 if (1.0+cnst*fabs(c2)!=1.0) { 00184 loop2=true; 00185 } else { 00186 this->last_conv=gsl_efailed; 00187 this->last_iter=itx; 00188 O2SCL_CONV2("Failed to reach required accuracy in cern_", 00189 "gauss::integ().",gsl_efailed,this->err_nonconv); 00190 return h; 00191 } 00192 } 00193 } 00194 this->last_iter=itx; 00195 return h; 00196 } 00197 00198 protected: 00199 00200 #ifndef DOXYGEN_INTERNAL 00201 00202 /** \name Integration constants (Set in the constructor) 00203 */ 00204 //@{ 00205 double x[12], w[12]; 00206 //@} 00207 00208 #endif 00209 00210 }; 00211 00212 #ifndef DOXYGENP 00213 } 00214 #endif 00215 00216 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).