00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
00104 return *y_out_invalid;
00105 }
00106 }
00107
00108
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
00136 bool in_asc_order = is_in_ascending_order( v_x_in, v_in_size, invalid_x_in );
00137
00138
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
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
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
00173
00174
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
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
00190
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
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
00202 double left = xi[0];
00203 double right = xi [sz_in - 1];
00204 for (int i = 0 ; i < sz_out ; ++i) {
00205
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
00213 gsl_spline_free (spline);
00214 gsl_interp_accel_free (acc);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 #endif