Object-oriented Scientific Computing Library: Version 0.910
cern_cauchy.h
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
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.