Integration.h

00001 //===========================================================================
00002 // GoTools - SINTEF Geometry Tools version 1.1
00003 //
00004 // GoTools module: CORE
00005 //
00006 // Copyright (C) 2000-2007 SINTEF ICT, Applied Mathematics, Norway.
00007 //
00008 // This program is free software; you can redistribute it and/or          
00009 // modify it under the terms of the GNU General Public License            
00010 // as published by the Free Software Foundation version 2 of the License. 
00011 //
00012 // This program is distributed in the hope that it will be useful,        
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00015 // GNU General Public License for more details.                           
00016 //
00017 // You should have received a copy of the GNU General Public License      
00018 // along with this program; if not, write to the Free Software            
00019 // Foundation, Inc.,                                                      
00020 // 59 Temple Place - Suite 330,                                           
00021 // Boston, MA  02111-1307, USA.                                           
00022 //
00023 // Contact information: E-mail: tor.dokken@sintef.no                      
00024 // SINTEF ICT, Department of Applied Mathematics,                         
00025 // P.O. Box 124 Blindern,                                                 
00026 // 0314 Oslo, Norway.                                                     
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
00032 //===========================================================================
00033 #ifndef _INTEGRATION_H_
00034 #define _INTEGRATION_H_
00035 
00036 
00037 #include <math.h>
00038 #include <functional>
00039 #include <numeric>
00040 #include <limits>
00041 #include <stdexcept>
00042 #include "errormacros.h"
00043 
00044 namespace Go {
00047 
00048 
00049 
00055 template <typename Functor>
00056 void trapezoidal(Functor& f, double a, double b, double& s, int n)
00057 {
00058     DEBUG_ERROR_IF(n < 1, "Bad function argument to trapezoidal().");
00059     if (n == 1) {
00060         s = 0.5 * (b - a) * (f(a) + f(b));
00061     } else {
00062         int num_int_pts = 1 << (n-2);
00063         //int num_int_pts = std::power(2, n-2);
00064         double spacing = (b - a) / num_int_pts;
00065         double x = a + 0.5 * spacing;
00066         double sum = 0.0;
00067         for (int i = 0; i < num_int_pts; ++i) {
00068             sum += f(x);
00069             x += spacing;
00070         }
00071         s += (b - a) * sum / num_int_pts;
00072         s *= 0.5;
00073     }
00074 }
00075 
00076 
00079 template <typename Functor>
00080 double simpsons_rule(Functor& f, double a, double b,
00081                      const double eps = 1.0e-6, const int max_iter = 20)
00082 {
00083     const double one_third = double(1) / double(3);
00084     double result = 0;
00085     double tz = 0;
00086     double last_tz = std::numeric_limits<double>::min();
00087     double last_result =  std::numeric_limits<double>::min();
00088 
00089     for (int j = 1; j <= max_iter; ++j) {
00090         trapezoidal(f, a, b, tz, j);
00091         result = (4.0 * tz - last_tz) * one_third;
00092         if ((fabs(result - last_result) < eps * fabs(last_result)) ||
00093             (fabs(result) < eps && fabs(last_result) < eps && j > 6)) {
00094             return result;
00095         }
00096         last_result = result;
00097         last_tz = tz;
00098     }
00099     MESSAGE("Too many steps in simpsons_rule.");
00100     throw std::runtime_error("Too many steps in simpsons_rule.");
00101 } // 
00102 
00105 template <typename Functor>
00106 double gaussian_quadrature(Functor& f, double a, double b)
00107 {
00108     static double x[] = { 0.1488743389, 
00109                           0.4333953941,
00110                           0.6794095682, 
00111                           0.8650633666, 
00112                           0.9739065285 };
00113     static double weight[] = { 0.2955242247, 
00114                                0.2692667193,
00115                                0.2190863625, 
00116                                0.1494513491, 
00117                                0.0666713443 };
00118 
00119     double midpt = 0.5 * (b + a);
00120     double half_length = 0.5 * (b - a);
00121     double scaled_result = double(0);
00122     double step = double(0);
00123     for (int i = 0; i < 5; ++i) {
00124         step = half_length * x[i];
00125         scaled_result += weight[i] * (f(midpt + step) + f(midpt - step));
00126     }
00127     // rescale result to correspond to actual interval size
00128     return scaled_result * half_length; 
00129 }
00130 
00131 
00132 
00133 // Help functor to simpsons_rule2D and gaussian_quadrature2D
00135 template <typename Functor>
00136 class Integrate2ndFunctor {
00137 public:
00138     Integrate2ndFunctor(Functor& f, double a, double b)
00139         : f_(f), a_(a), b_(b) { }
00140 
00141     double operator() (double t) const
00142     {
00143         std::binder1st<Functor> fu(f_, t);
00144         return gaussian_quadrature(fu, a_, b_);
00145     }
00146 
00147 private:
00148     Functor f_;
00149     double a_, b_;
00150 
00151 };
00153 
00156 template <typename Functor2D>
00157 double simpsons_rule2D(Functor2D& f,
00158                        double ax, double bx, double ay, double by,
00159                        const double eps = 1.0e-6, const int max_iter = 20)
00160 {
00161     Integrate2ndFunctor<Functor2D> fu(f, ay, by);
00162     return simpsons_rule(fu, ax, bx, eps, max_iter);
00163 }
00164 
00165 
00168 template <typename Functor2D>
00169 double gaussian_quadrature2D(Functor2D& f,
00170                              double ax, double bx, double ay, double by)
00171 {
00172     Integrate2ndFunctor<Functor2D> fu(f, ay, by);
00173     return gaussian_quadrature(fu, ax, bx);
00174 }
00175 
00176 
00178 } // namespace GO
00179 
00180 
00181 #endif // _INTEGRATION_H
00182 
00183 

Generated on Mon Jun 11 14:48:18 2007 for GoTools Core Library by  doxygen 1.5.1