quad_intp.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_QUAD_INTP_H
00024 #define O2SCL_QUAD_INTP_H
00025 
00026 #include <iostream>
00027 #include <string>
00028 #include <cmath>
00029 #include <map>
00030 #include <gsl/gsl_linalg.h>
00031 #include <o2scl/err_hnd.h>
00032 #include <o2scl/ovector_tlate.h>
00033 
00034 #ifndef DOXYGENP
00035 namespace o2scl {
00036 #endif
00037 
00038   /** 
00039       \brief Interpolate a function of two independent variables with 
00040       a quadratic polynomial
00041       
00042       This is a "conic-section" interpolation for two
00043       dimensions, using the function
00044       \f[
00045       z(x,y) = a_1 x^2 + a_2 x y + a_3 y^2 + a_4 x + a_5 y + a_6
00046       \f]
00047       For a set of data \f${x_i,y_i,z_i}\f$, a value of z is predicted
00048       given a value of x and y. This is done by finding the conic
00049       section obeying the above relation that goes through six closest
00050       points in the data set.
00051       
00052       This procedure does not always succeed. It fails when the 
00053       6 closest points are somehow degenerate, for example, if they
00054       are all colinear.
00055       
00056       The vector and matrix types can be any types which have
00057       suitably defined functions \c operator[]. 
00058 
00059       There is no caching so the numeric values of the data may be
00060       freely changed between calls to interp().
00061 
00062       \bug This class doesn't seem to work at present.
00063   */
00064   template<class vec_t, class mat_t> class quad_intp {
00065   public:
00066     
00067     quad_intp() {
00068       data_set=false;
00069     }
00070     
00071     typedef struct {
00072       int i;
00073       double c;
00074     } point;
00075     
00076     int compare(const void *x, const void *y) {
00077       point *p=(point *)x;
00078       point *q=(point *)y;
00079       return (p->c)>(q->c);
00080     }
00081     
00082     /** 
00083         \brief Initialize the data for the quad interpolation
00084     */
00085     int set_data(size_t n_points, vec_t &x, vec_t &y,
00086                  size_t n_dat, mat_t &dat) {
00087       if (n_points<6) {
00088         set_err_ret("Must provide at least six points in set_data()",
00089                     gsl_efailed);
00090       }
00091       np=n_points;
00092       nd=n_dat;
00093       ux=&x;
00094       uy=&y;
00095       udat=&dat;
00096       data_set=true;
00097       return 0;
00098     }
00099     
00100     /** 
00101         \brief Perform the quadratic interpolation 
00102         
00103         It is assumed that \c ip is properly allocated beforehand.
00104     */
00105     int interp(double x, double y, vec_t &ip) {
00106       int i, j, mat_ret=0;
00107   
00108       if (data_set==false) {
00109         set_err("Data not set in quad_intp::interp().",gsl_einval);
00110         return gsl_einval;
00111       }
00112       if (ip.is_owner()==false) {
00113         set_err("Provided ovector does not own its data. Proceeding anyway.",
00114                 gsl_einval);
00115       }
00116       
00117       std::map<double,int> pmap;
00118       for (i=0;i<np;i++) {
00119         pmap.insert(make_pair(sqrt(pow(x-(*ux)[i],2.0)+
00120                                    pow(y-(*uy)[i],2.0)),i));
00121       }
00122       std::map<double,int>::iterator pit;
00123 
00124       gsl_matrix *gm=gsl_matrix_alloc(6,6);
00125       gsl_vector *gx=gsl_vector_alloc(6), *gb=gsl_vector_alloc(6);
00126       
00127       for(j=0;j<nd;j++) {
00128         
00129         pit=pmap.begin();
00130         for(i=0;i<6;i++) {
00131           gsl_matrix_set(gm,i,0,(*ux)[pit->second]*(*ux)[pit->second]);
00132           gsl_matrix_set(gm,i,1,(*ux)[pit->second]*(*uy)[pit->second]);
00133           gsl_matrix_set(gm,i,2,(*uy)[pit->second]*(*uy)[pit->second]);
00134           gsl_matrix_set(gm,i,3,(*ux)[pit->second]);
00135           gsl_matrix_set(gm,i,4,(*uy)[pit->second]);
00136           gsl_matrix_set(gm,i,5,1.0);
00137           gsl_vector_set(gb,i,(*(udat[j]))[i]);
00138           pit++;
00139         }
00140         int ret=gsl_linalg_HH_solve(gm,gb,gx);
00141         if (ret!=0) mat_ret=ret;
00142         ip[j]=gsl_vector_get(gx,0)*x*x+
00143           gsl_vector_get(gx,1)*x*y+
00144           gsl_vector_get(gx,2)*y*y+
00145           gsl_vector_get(gx,3)*x+
00146           gsl_vector_get(gx,4)*y+
00147           gsl_vector_get(gx,5);
00148       }
00149   
00150       if (mat_ret!=0) {
00151         add_err("Matrix solver failed in quad_intp::interp().",
00152                 gsl_efailed);
00153       }
00154 
00155       gsl_matrix_free(gm);
00156       gsl_vector_free(gx);
00157       gsl_vector_free(gb);
00158       
00159       return mat_ret;
00160     }
00161     
00162 #ifndef DOXYGEN_INTERNAL
00163 
00164   protected:
00165 
00166     /// The number of grid points
00167     int np;
00168     /// The number of functions
00169     int nd;
00170     /// The x-values
00171     vec_t *ux;
00172     /// The y-values
00173     vec_t *uy;
00174     /// The data
00175     mat_t *udat;
00176     /// True if the data has been given by the user
00177     bool data_set;
00178     
00179     // Swap points 1 and 2
00180     int swap(int &i1, double &c1, int &i2, double &c2);
00181     
00182 #endif
00183 
00184   };
00185   
00186 #ifndef DOXYGENP
00187 }
00188 #endif
00189 
00190 #endif
00191 
00192 
00193 

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

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page