• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/home/pascal/depot/filedata/src/interpolation.h

00001 /***************************************************************************
00002  *   Copyright (C) 2011 by Nicolas PASCAL                                  *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU General Public License as published by  *
00006  *   the Free Software Foundation; either version 2 of the License, or     *
00007  *   (at your option) any later version.                                   *
00008  *                                                                         *
00009  *   This program is distributed in the hope that it will be useful,       *
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012  *   GNU General Public License for more details.                          *
00013  *                                                                         *
00014  *   You should have received a copy of the GNU General Public License     *
00015  *   along with this program; if not, write to the                         *
00016  *   Free Software Foundation, Inc.,                                       *
00017  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00018  ***************************************************************************/
00019 
00020 #ifndef INTERPOLATION_H
00021 #define INTERPOLATION_H
00022 
00023 #include <cstdlib>
00024 #include <exception>
00025 #include <string>
00026 #include <algorithm>
00027 #include <cmath>
00028 using namespace std;
00029 
00030 #include "g_exception.h"
00031 #include <gsl/gsl_spline.h>
00032 #include <gsl/gsl_errno.h>
00033 
00040 template < typename T >
00041 const bool is_in_ascending_order ( const T * v, const int v_size, const T * invalid = NULL )
00042 {
00043     if ( v_size < 2 )
00044         // only one or 0 value in v -> consider it as sorted in ascending order
00045         return true;
00046 
00047     int i = 0;
00048     while ( i < v_size and v[i] == v[0] )
00049         i+=1;
00050 
00051     if ( i < v_size )
00052         return ( v[i] > v[0] );
00053     else
00054         // all values in v are equal -> consider it as sorted in ascending order
00055         return true;
00056 }
00057 
00071 template < typename T_x_in, typename T_y_in, typename T_x_out, typename T_y_out >
00072 inline T_y_out interpolate_1D (
00073                          const T_x_out & x,
00074                          const T_x_in  & x1, const T_x_in  & x2,
00075                          const T_y_in  & y1, const T_y_in  & y2,
00076                          const T_y_out * y_out_invalid,
00077                          const T_x_in  * x_in_invalid  = NULL, const T_y_in  * y_in_invalid  = NULL,
00078                          const T_x_out * x_out_invalid = NULL,
00079                          const bool extrapolate = false )
00080 {
00081     if ( y_out_invalid == NULL )
00082     {
00083         string msg ( "A not NULL invalid returned value must have been set in case of interpolation error" ) ;
00084         g_exception e( __FILE__ , __LINE__ , msg );
00085         throw e;
00086     }
00087 
00088     // check limits validity
00089     if  ( ( x_out_invalid != NULL &&   x  == *x_out_invalid ) ||
00090           ( x_in_invalid  != NULL && ( x1 == *x_in_invalid || x2 == *x_in_invalid ) ) ||
00091             y_in_invalid  != NULL && ( y1 == *y_in_invalid  || y2 == *y_in_invalid ) )
00092     {
00093         return *y_out_invalid;
00094     }
00095 
00096     // check if x1 and x2 are in or out the interpolation range
00097     if ( not extrapolate )
00098     {
00099         bool is_increasing = ( x2 >= x1 );
00100         if (     is_increasing and ( x < x1 or x > x2 ) or
00101              not is_increasing and ( x > x1 or x < x2 ) )
00102         {
00103             // out of interpolation range
00104             return *y_out_invalid;
00105         }
00106     }
00107 
00108     // compute interpolation ( or extrapolation if enabled ) using double precision
00109     double y_dbl = (double)(y1) + ( (double)(x) - (double)(x1) ) * ( (double)(y2) - (double)(y1) ) / ( (double)(x2) - (double)(x1) );
00110     return (T_y_out)(y_dbl) ;
00111 };
00112 
00113 
00127 template < typename T_x_in, typename T_y_in, typename T_x_out, typename T_y_out >
00128 inline T_y_out * v_interpolate_1D (       T_y_out * v_y_out, const T_x_out * v_x_out, const int v_out_size,
00129                                     const T_y_in  * v_y_in,  const T_x_in  * v_x_in,  const int v_in_size,
00130                                     const T_y_out * invalid_y_out,
00131                                     const T_x_in  * invalid_x_in  = NULL, const T_y_in  * invalid_y_in  = NULL,
00132                                     const T_x_out * invalid_x_out = NULL,
00133                                     const bool extrapolate = false )
00134 {
00135     // check the sorting order of v_x_in
00136     bool in_asc_order = is_in_ascending_order( v_x_in, v_in_size, invalid_x_in );
00137 
00138     // process interpolation element by element
00139     int i_in, i_out, i_min, i_max;
00140     T_x_in * low;
00141     T_y_out y_out;
00142 
00143     for ( i_out = 0 ;  i_out < v_out_size ; ++i_out )
00144     {
00145         // find indexes of bounds
00146         if (in_asc_order)
00147             low = lower_bound ( const_cast<T_x_in *>(v_x_in), const_cast<T_x_in *>(v_x_in + v_in_size), v_x_out[i_out],
00148                                 less_equal<T_x_in>() );
00149         else
00150             low = lower_bound ( const_cast<T_x_in *>(v_x_in), const_cast<T_x_in *>(v_x_in + v_in_size), v_x_out[i_out],
00151                                 greater<T_x_in>() );
00152         i_in = low - v_x_in;
00153         // set bounds for an eventual extrapolation
00154         if ( i_in <= 0 )
00155         {
00156             i_min = 0;
00157             i_max = i_min + 1;
00158         }
00159         else if ( i_in >= v_in_size )
00160         {
00161             i_max = v_in_size - 1;
00162             i_min = i_max - 1;
00163         } else {
00164             i_min = i_in -1 ;
00165             i_max = i_in ;
00166         }
00167 
00168         y_out = interpolate_1D( v_x_out[i_out], v_x_in[i_min], v_x_in[i_max], v_y_in[i_min], v_y_in[i_max],
00169                                 invalid_y_out, invalid_x_in, invalid_y_in, invalid_x_out, extrapolate );
00170         v_y_out[i_out] = y_out;
00171 
00172 // printf("----- v_interpolate_1D -----\n");
00173 // printf("x1=%f x2=%f x=%f\n",v_x_in[i_min],  v_x_in[i_max], v_x_out[i_out]);
00174 // printf("y1=%f y2=%f y=%f\n",v_y_in[i_min],  v_y_in[i_max], v_y_out[i_out]);
00175     }
00176     return v_y_out;
00177 };
00178 
00179 template < typename T_x_in, typename T_y_in, typename T_x_out, typename T_y_out >
00180 inline void spline_interp (
00181           T_y_out * y_out, const T_x_out * x_out, const int sz_out,
00182     const T_y_in  * y_in,  const T_x_in  * x_in,  const int sz_in,
00183     const T_y_out   invalid_y_out ) {
00184     // args of interpolation functions are requested as double
00185     double xi[sz_in];
00186     copy (x_in, x_in + sz_in, xi);
00187     double yi[sz_in];
00188     copy (y_in, y_in + sz_in, yi);
00189     /* gsl interpolation functions request an ascending order ->
00190        reverse the vectors if requested */
00191     bool is_ascending = (x_in[0] < x_in[1]);
00192     if (! is_ascending ) {
00193         reverse (xi, xi + sz_in);
00194         reverse (yi, yi + sz_in);
00195     }
00196 
00197     // init interpolator
00198     gsl_interp_accel * acc = gsl_interp_accel_alloc ();
00199     gsl_spline * spline = gsl_spline_alloc (gsl_interp_akima, sz_in);
00200     gsl_spline_init (spline, xi, yi, sz_in);
00201     // compute interpolations
00202     double left  = xi[0];
00203     double right = xi [sz_in - 1];
00204     for (int i = 0 ; i < sz_out ; ++i) {
00205         // filter out of interpolation range values
00206         if ((x_out[i] < left) || (x_out[i] > right)) {
00207             y_out[i] = invalid_y_out;
00208         } else {
00209             y_out[i] = gsl_spline_eval (spline, x_out[i], acc);
00210         }
00211     }
00212     // free spline
00213     gsl_spline_free (spline);
00214     gsl_interp_accel_free (acc);
00215 }
00216 /*
00217 inline void spline_interp (
00218           double * y_out, const double * x_out, const int sz_out,
00219     const double * y_in, const double  * x_in,  const int sz_in,
00220     const double invalid_y_out ) {
00221     gsl_interp_accel * acc = gsl_interp_accel_alloc ();
00222     gsl_spline * spline = gsl_spline_alloc (gsl_interp_cspline, sz_in);
00223     // compute spline interpolator. Inputs are requested as double
00224     gsl_spline_init (spline, x_in, y_in, sz_in);
00225     // compute interpolations
00226     for (int i = 0 ; i < sz_in ; ++i) {
00227         // filter out of interpolation range values
00228         if ((x_out[i] < x_in[0]) || (x_out[i] > x_in [sz_in - 1])) {
00229             y_out[i] = invalid_y_out;
00230         } else {
00231             y_out[i] = gsl_spline_eval (spline, x_out[i], acc);
00232         }
00233     }
00234     // free spline
00235     gsl_spline_free (spline);
00236     gsl_interp_accel_free (acc);
00237 }*/
00238 
00239 #endif

Generated on Thu Feb 14 2013 17:59:03 for filedata.kdevelop by  doxygen 1.7.1