Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

integrate.h

Go to the documentation of this file.
00001 // SuperMix version 1.0  C++ source file
00002 //
00003 // Copyright (c) 1999 California Institute of Technology.
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms for noncommercial
00007 // purposes are permitted provided that the above copyright notice and
00008 // this paragraph are duplicated in all such forms and that any
00009 // documentation and other materials related to such distribution and
00010 // use acknowledge that the software was developed by California
00011 // Institute of Technology. Redistribution and/or use in source or
00012 // binary forms is not permitted for any commercial purpose. Use of
00013 // this software does not include a permitted use of the Institute's
00014 // name or trademark for any purpose.
00015 //
00016 // DISCLAIMER:
00017 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT
00018 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR
00019 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET
00020 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
00021 // LICENSED PRODUCT, HOWEVER USED.  IN NO EVENT SHALL CALTECH/JPL BE
00022 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO
00023 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC
00024 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF
00025 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN
00026 // FACT SHALL KNOW OF THE POSSIBILITY.  THE USER BEARS ALL RISK
00027 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED
00028 // MATERIALS.
00029 //
00030 // ********************************************************************
00031 // integrate.h
00032 //
00033 // includes classes integrator<> and CauchyPV
00034 //
00035 // ********************************************************************
00036 // class integrator<>:
00037 //
00038 // Performs numerical integrations of functions of one real variable (double).
00039 // The return type of the function to integrated is determined by a template
00040 // parameter in the declaration of an integrator object. The return type
00041 // can be any sort of object which is a member of a "vector space" with the
00042 // following operations defined on it (Y is the type name of the function
00043 // return type, double is the type of the independent variable):
00044 //
00045 // double x;
00046 // Y A;         // construct an object of type Y, no particular value.
00047 // Y B(A);      // construct an independent copy of (value of type Y) A;
00048 // A = B;       // make A an independent copy of B
00049 // A *= x;      // modify A by scaling by x.
00050 // A += B;      // modify A by adding B to it
00051 // A -= B;      // modify A by subtracting B from it
00052 //
00053 // Y type objects must be a vector space, in that (A *= 2.0) is equivalent
00054 // to (A += A), and (A *= 0.0) is equivalent to (A -= A) and gives the
00055 // additive identity of Y, etc. 
00056 //
00057 // General scheme to use the integrator:
00058 //
00059 // Assume you have a complex-valued function of a real variable:
00060 // complex f(double x), that you must numerically integrate. The code could be:
00061 //
00062 //   integrator<complex> F;   // an integrator appropriate for f().
00063 //
00064 //   double a,b;              // limits of integration
00065 //   complex z = F(f,a,b);    // use the default tolerances and integrate f().
00066 //
00067 //   F.abs_tolerance = 1e-6; F.rel_tolerance = 1e-4;  // adjust tolerances
00068 //   z = F(f,a,b);            // integrate f() again, using new tolerances.
00069 //
00070 // Now assume that you need to integrate a real function: double g(double x),
00071 // which has an inverse square root singularity at the origin, and decreases
00072 // approximately like exp(-a*x), a >= 1, for x > 10. You must integrate g(x)
00073 // between -10 and +Infinity. The code would be:
00074 //
00075 //   typedef integrator<double> Ig;  // shorthand will be used repeatedly below.
00076 //   Ig G;
00077 //
00078 //   double answer = 0.0;
00079 //   anwser += G.sqrtupper()(g, -10, 0);
00080 //   anwser += G.sqrtlower()(g,  0, 10);
00081 //   anwser += G.exp()(g,10,100);       // upper limit is ignored here
00082 //
00083 // Note the concatenation of the method() and operator() calls; this works
00084 // because method returns a reference to G, which is used by operator().
00085 // The code could have used separate statements:
00086 //
00087 //   G.method(Ig::SQRTUPPER); answer += G(g, -10, 0); // etc.
00088 //
00089 //
00090 // Algorithms based on the Romberg integration methods described in 
00091 // Numerical Recipes in C, 2nd Edition (Cambridge).
00092 //
00093 // F. Rice
00094 // 7/8/99
00095 //
00096 // ********************************************************************
00097 // Cauchy_integrate(); class CauchyPV:
00098 //
00099 // Performs Cauchy principle value integrations of real functions of a
00100 // real variable (ie, like: double f(double x)) using integrator<double>.
00101 // The location of a nonintegrable, odd singularity (pole) is specified
00102 // in addition to the limits of integration. The function will not be
00103 // evaluated at the limits of integration, but it must remain finite
00104 // at them, since the integration method used is integrator<double>::OPEN.
00105 //
00106 // To calculate a Cauchy principal value integral:
00107 //
00108 // (1) using Cauchy_integrate (limits and pole are doubles, func a function):
00109 //     double answer = Cauchy_integrate(func, low_limit, pole, high_limit);
00110 //
00111 // (2) using class CauchyPV:
00112 //     CauchyPV I;  // the integrator
00113 //     double answer = I(f,a,s,b);
00114 //
00115 // Use method (2) if you want to adjust integrator controls to other than
00116 // the default values, or if you need to calculate integrals using several
00117 // different functions.
00118 //
00119 // F. Rice
00120 // 7/13/99
00121 //
00122 // ********************************************************************
00123 
00124 #ifndef INTEGRATE_H
00125 #define INTEGRATE_H
00126 
00127 #include "num_utility.h"
00128 #include <math.h>
00129 #include <pair.h>
00130 #include <vector>
00131 #include "polynomial.h"
00132 
00133 template <class Y>
00134 class integrator
00135 {
00136 public:
00137 
00138   // The following enumeration provides choices for the integration method to use
00139   // (default is CLOSED):
00140 
00141   typedef enum {
00142 
00143     CLOSED,    // Closed interval: function will be evaluated at the limits
00144     OPEN,      // Open interval: function will not be evaluated at the limits
00145     SQRTLOWER, // Open: lower limit has an inverse square root singularity
00146     SQRTUPPER, // Open: upper limit has an inverse square root singularity
00147     INFINITE,  // Open: one limit is very large; both limits must have the same sign
00148     EXP        // Function must be decreasing at +infinity AT LEAST AS FAST AS 
00149                //   exp(-x);integrates from lower limit to +infinity
00150                //   (upper limit is ignored; +infinity is assumed).
00151 
00152   } type;
00153 
00154 
00155   // --------------------------------------------------------------------
00156   // The constructor:
00157   explicit integrator(type t_ = CLOSED);
00158 
00159 
00160   // --------------------------------------------------------------------
00161   // The following variables control or limit the integration process
00162   // (default values in parentheses)
00163 
00164   unsigned order;           // (4)   the order of the Romberg extrapolation
00165   unsigned recursion_limit; // (20)  the max allowable number of interval subdivisions
00166   
00167 
00168   // If either of the following accuracy limits is met, then accuracy is o.k:
00169   double abs_tolerance;  // (1.0e-100) the max absolute error target in the integration
00170   double rel_tolerance;  // (1.0e-6)   the max relative error target in the integration
00171 
00172     
00173   // Select or change the integration method to use:
00174   integrator & closed()    { t = CLOSED; return *this; }
00175   integrator & open()      { t = OPEN; return *this; }
00176   integrator & sqrtlower() { t = SQRTLOWER; return *this; }
00177   integrator & sqrtupper() { t = SQRTUPPER; return *this; }
00178   integrator & infinite()  { t = INFINITE; return *this; }
00179   integrator & exp()       { t = EXP; return *this; }
00180   integrator & method(type t_) { t = t_; return *this; }
00181 
00182 
00183   // --------------------------------------------------------------------
00184   // Perform the integration: must pass a function and limits,
00185   // as well as a norm function for error determination. If no norm function
00186   // is specified, the default is to use a global double norm(Y), if defined.
00187   // Warning: do not call a given integrator object recursively; if you want
00188   // to do a multiple integral, create an independent integrator object for
00189   // each level of the integration.
00190 
00191   template <class F, class N> 
00192   Y operator()(
00193                F f,        // the function to be integrated
00194                double a,   // the lower integration limit
00195                double b,   // the upper integration limit
00196                N norm      // function returning the "magnitude squared" of
00197                            //   an argument of type Y, for error estimates
00198                );
00199 
00200   template <class F> 
00201   Y operator()(
00202                F f,        // the function to be integrated
00203                double a,   // the lower integration limit
00204                double b    // the upper integration limit
00205                )
00206   { return (*this)(f,a,b,norm); } // use the default norm
00207   
00208 
00209   // --------------------------------------------------------------------
00210 private:
00211 
00212   type t;               // the integration method
00213   pair<Y,Y> result;     // the final answer and error estimate
00214   typedef pair<double,Y> entry;
00215   vector<entry> s;      // vector of partial sums for extrapolation
00216   poly_fit<Y> p;        // the polynomial extrapolator
00217 
00218   // the following functional provides access to the overloaded global norm().
00219   default_norm<Y> norm ;
00220 
00221   // the following function is used to swap integration limits, to ensure
00222   // lower limit <= upper limit; operator() will handle the sign correctly.
00223   int qswap(double & a, double & b)
00224   { if (a > b) { double t = a; a = b; b = t; return 1; } else return 0; }
00225 
00226   // method implementations:
00227   template <class F, class N> 
00228   void romberg_closed(F f, double a, double b, N n,
00229                     void (integrator<Y>::*method)(F,double,double,int));
00230   template <class F, class N> 
00231   void romberg_open(F f, double a, double b, N n,
00232                     void (integrator<Y>::*method)(F,double,double,int));
00233 
00234   template <class F> void cl(F f, double a, double b, int step);
00235   template <class F> void op(F f, double a, double b, int step);
00236   template <class F> void sl(F f, double a, double b, int step);
00237   template <class F> void su(F f, double a, double b, int step);
00238   template <class F> void in(F f, double a, double b, int step);
00239   template <class F> void ex(F f, double a, double b, int step);
00240 
00241   // a class to perform change of variable needed by several of the methods:
00242   struct {
00243     Y r;
00244 
00245     // 2*x*f(a+x*x), used by sl:
00246     template <class F> Y sql(F f, double x, double a)
00247     { r = f(a+x*x); r *= 2.0*x; return r; }
00248 
00249     // 2*x*f(b-x*x), used by su:
00250     template <class F> Y squ(F f, double x, double b)
00251     {
00252       r = f(b-x*x);
00253       r *= (2.0*x);
00254 
00255 // **** WORK AROUND **** a bug in "-O2" of the Redhat 7.x g++ compiler
00256 #ifdef __linux
00257 #ifdef __GNUC_MINOR__
00258 #if __GNUC_MINOR__ == 96
00259       if(x!=x)
00260       {
00261         r *= 2.0;  // These lines should never get called.
00262         r *= 0.5;  // But just in case, we'll minimize the damage.
00263       }
00264 #endif
00265 #endif
00266 #endif
00267 // **** END WORK AROUND ****
00268 
00269       return r;
00270     }
00271 
00272     // (1/x^2)*f(1/x), used by in():
00273     template <class F> Y inv(F f, double x)
00274     { r = f(1.0/x); r *= 1.0/(x*x); return r; }
00275 
00276     // (1/x)*f(-ln(x)), used by ex():
00277     template <class F> Y exf(F f, double x)
00278     { r = f(-log(x)); r *= 1.0/x; return r; }
00279   } Func;
00280 
00281 }; // class intergrator<>
00282 
00283 // ********************************************************************
00284 // A helper class for CauchyPV calculations
00285 
00286 // a class to calculate the symmetrized function value for CauchPV
00287 template <class F>
00288 class CauchyPV_calculator { 
00289 public:
00290   F op;
00291   double x;
00292   CauchyPV_calculator(F f, double s) : op(f), x(s) { }
00293   double operator()(double t) const { return op(x+t) + op(x-t); }
00294 };
00295 
00296 
00297 // ********************************************************************
00298 class CauchyPV
00299 {
00300   typedef integrator<double> I;
00301 
00302 public:
00303   double & abs_tolerance;     // same functionality as for integrator<>
00304   double & rel_tolerance;
00305   unsigned  & order;
00306   unsigned  & recursion_limit;
00307 
00308   CauchyPV();                 // simple constructors
00309   CauchyPV(const CauchyPV &);
00310 
00311 
00312   // operator() performs the Cauchy Principal Value integration:
00313 
00314   template <class F> 
00315   double operator()(
00316                     F f,       // the function to integrate 
00317                     double a,  // lower integration limit
00318                     double s,  // the singularity location
00319                     double b   // upper integration limit
00320                     );
00321 
00322 private:
00323 
00324   I integ;  // the integrator
00325 
00326 }; // class CauchyPV
00327 
00328 template <class F>
00329 inline double Cauchy_integrate(F f, double a, double s, double b)
00330 { static CauchyPV I; return I(f,a,s,b); }
00331 
00332 #include "numerical/num_integrate.h"
00333 
00334 #endif /* INTEGRATE_H */

Please direct comments and corrections to supermix@submm.caltech.edu
Go to the supermix home page
Generated by doxygen1.2.7