gsl_chebapp.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 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_GSL_CHEBAPP_H
00024 #define O2SCL_GSL_CHEBAPP_H
00025 
00026 #include <o2scl/collection.h>
00027 #include <o2scl/funct.h>
00028 #include <gsl/gsl_chebyshev.h>
00029 #include <cmath>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034 
00035   /** 
00036       \brief Chebyshev approximation (GSL)
00037 
00038       Approximate a function using a Chebyshev series:
00039       \f[
00040       f(x) = \sum_n c_n T_n(x) \qquad \mathrm{where}
00041       \qquad T_n(x)=\cos(n \arccos x)
00042       \f]
00043   */
00044   template<class param_t, class func_t> class gsl_chebapp {
00045   public:
00046   
00047     gsl_chebapp() {
00048       order=5;
00049       init_called=false;
00050       gcs=gsl_cheb_alloc(order);
00051     }
00052     
00053     /** \brief Initialize a Chebyshev approximation of the function
00054         \c func over the interval from \c a to \c b
00055 
00056         The interval must be specified so that \f$ a < b \f$ .
00057     */
00058     int init(func_t &func, double a, double b, param_t &vp) {
00059       size_t k, j;
00060   
00061       if(a>=b) {
00062         set_err_ret("Interval a>=b in gsl_chebapp::init().",gsl_einval);
00063       }
00064       gcs->a=a;
00065       gcs->b=b;
00066   
00067       double bma=0.5*(gcs->b-gcs->a);
00068       double bpa=0.5*(gcs->b+gcs->a);
00069       double fac=2.0/(gcs->order+1.0);
00070   
00071       for(k=0;k<=gcs->order;k++) {
00072         double y=cos(M_PI*(k+0.5)/(gcs->order+1));
00073         gcs->f[k]=func(y*bma+bpa,vp);
00074       }
00075   
00076       for(j=0;j<=gcs->order;j++) {
00077         double sum=0.0;
00078         for(k=0;k<=gcs->order; k++) {
00079           sum+=gcs->f[k]*cos(M_PI*j*(k+0.5)/(gcs->order+1));
00080         }
00081         gcs->c[j]=fac*sum;
00082       }
00083 
00084       init_called=true;
00085 
00086       return 0;
00087     }
00088 
00089     /** 
00090         \brief Set the order (default 5)
00091         
00092         The function init() must be called after calling set_order()
00093         to reinitialize the series for the new order.
00094      */
00095     int set_order(size_t o) {
00096       order=o;
00097       init_called=false;
00098       gsl_cheb_free(gcs);
00099       gcs=gsl_cheb_alloc(order);
00100       return 0;
00101     }
00102 
00103     /** \brief Evaluate the approximation
00104      */
00105     double eval(double x) {
00106       if (init_called==false) {
00107         set_err("Series not initialized in gsl_chebapp::eval().",
00108                 gsl_einval);
00109         return 0.0;
00110       }
00111       return gsl_cheb_eval(gcs,x);
00112     }
00113     
00114     /** 
00115         \brief Return a pointer to an approximation to the derivative
00116         
00117         The new gsl_chebapp object is allocated by new, and the memory
00118         should be deallocated using delete by the user.
00119      */
00120     gsl_chebapp *deriv() {
00121       if (init_called==false) {
00122         set_err("Series not initialized in gsl_chebapp::deriv().",
00123                 gsl_einval);
00124         return 0;
00125       }
00126       gsl_chebapp *gc=new gsl_chebapp;
00127       gc->set_order(order);
00128       gc->init_called=true;
00129       gsl_cheb_calc_deriv(gc->gcs,gcs);
00130       return gc;
00131     }
00132 
00133     /** 
00134         \brief Return a pointer to an approximation to the integral
00135 
00136         The new gsl_chebapp object is allocated by new, and the memory
00137         should be deallocated using delete by the user.
00138      */
00139     gsl_chebapp *inte() {
00140       if (init_called==false) {
00141         set_err("Series not initialized in gsl_chebapp::inte().",
00142                 gsl_einval);
00143         return 0;
00144       }
00145       gsl_chebapp *gc=new gsl_chebapp;
00146       gc->set_order(order);
00147       gc->init_called=true;
00148       gsl_cheb_calc_integ(gc->gcs,gcs);
00149       return gc;
00150     }
00151 
00152     /** 
00153         \brief Get the coefficient
00154 
00155         Legal values of the argument are 0 to \c order+1
00156     */
00157     double get_coefficient(size_t ix) {
00158       if (ix<=order+1) {
00159         return gcs->c[ix];
00160       }
00161       set_err
00162         ("Requested invalid coefficient in gsl_chebapp::get_coefficient()",
00163          gsl_einval);
00164       return 0.0;
00165     }
00166 
00167 #ifndef DOXYGENP
00168 
00169   protected:
00170 
00171     /// The GSL representation of the series
00172     gsl_cheb_series *gcs;
00173 
00174     /// The order
00175     size_t order;
00176 
00177     /// True if init has been called
00178     bool init_called;
00179 
00180 #endif
00181   
00182   };
00183 
00184 #ifndef DOXYGENP
00185 }
00186 #endif
00187 
00188 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.