someinterp.c

Go to the documentation of this file.
00001 /* 
00002  * a routine for n-dim linear interpolation together
00003  * with its utility routines
00004  *
00005  *  AUTHOR
00006  *    Bruno Pincon <Bruno.Pincon@iecn.u-nancy.fr>
00007  */
00008 
00009 #include "stack-c.h"
00010 #include <math.h>
00011 
00012 enum {NOT_A_KNOT, NATURAL, CLAMPED, PERIODIC, FAST, FAST_PERIODIC, 
00013       MONOTONE, BY_ZERO, C0, LINEAR, BY_NAN};
00014 
00015 #ifdef _MSC_VER
00016 extern int C2F(isanan)();
00017 extern double C2F(returnanan)();
00018 #endif
00019 
00020 static int isearch(double t, double x[], int n) 
00021 {
00022   /*     PURPOSE
00023    *        x[0..n-1] being an array (with strict increasing order and n >=2)
00024    *        representing intervals, this routine return i such that :
00025    *           
00026    *           x[i] <= t <= x[i+1]
00027    *          
00028    *        and -1 if t is not in [x[0], x[n-1]] 
00029    */
00030   int i1, i2, i;
00031   if ( x[0] <= t  &&  t <= x[n-1] )
00032     {
00033      i1 = 0; i2 = n-1;
00034      while ( i2 - i1 > 1 )
00035        {
00036          i = (i1 + i2)/2;
00037          if ( t <= x[i] )
00038            i2 = i;
00039          else
00040            i1 = i;
00041        }
00042      return (i1);
00043     }
00044   else
00045     return (-1);
00046 }
00047 
00048 static void fast_int_search(double xx, double x[], int nx, int *i)
00049 {
00050   if ( *i == -1 )
00051     *i = isearch(xx, x, nx);
00052   else if ( !  (x[*i] <= xx && xx <= x[*i+1]) )
00053     *i = isearch(xx, x, nx);
00054 }
00055 
00056 
00057 static void coord_by_periodicity(double *t, double x[], int n, int *i)
00058 {
00059   /*
00060    *     PURPOSE
00061    *        recompute t such that t in [x[0], x[n-1]] by periodicity :
00062    *        and then the interval i of this new t
00063    */
00064   double r, L;
00065   L = x[n-1] - x[0];
00066   r = (*t - x[0]) / L;
00067   if (r >= 0.0)
00068     *t = x[0] + (r - floor(r))*L;
00069   else
00070     *t = x[n-1] + (r - ceil(r))*L;
00071 
00072   /*  some cautions in case of roundoff errors (is necessary ?) */
00073   if (*t < x[0])
00074     {
00075       *t = x[0];
00076       *i = 0;
00077     }
00078   else if (*t > x[n-1])
00079     {
00080       *t = x[n-1];
00081       *i  = n-2;
00082     }
00083   else
00084     *i = isearch(*t, x, n);
00085 }
00086 void nlinear_interp(double **x , double val[], int dim[], int n,
00087                     double **xp, double yp[], int np, int outmode, 
00088                     double u[], double v[], int ad[], int k[])
00089 {
00090   /*  interpolation lineaire nb_dim-dimensionnelle
00091    *  --------------------------------------------
00092 
00093    interface scilab ?
00094 
00095    yp = linear_interpn(xp1, ..., xpN, x1, ..., xN, val, outmode)
00096 
00097 
00098 
00099    *     x[j][] : the grid abscissae in the dim j
00100    *     dim[j] : nb of points in the dim j
00101    *     n      : number of dimension
00102    *     val[]  : array of the grid node values, for instance if nbdim = 3
00103    *              and dim = [nx ny nz] then val(i,j,k) is stored in
00104    *              i + nx( j + ny k ) 
00105    *     xp[][] : the coordinates where we have to interpolate
00106    *              the coordinate of the i th point are stored 
00107    *              at xp[0][i] ..... xp[n-1][i]
00108    *     yp[]   : the result (an array 0...np-1)
00109    *     np     : nb of points for the evaluation
00110    *     outmode: specify the method of evaluation when a point is 
00111    *              outside the grid
00112    *     u, v, ad, k : work arrays
00113    */  
00114 
00115   int i, j, l, p, temp, b,/* toto,*/ two_p_n;
00116   double xx;
00117 
00118   /*   
00119    *   calcul des decalages d'indices pour retrouver les valeurs
00120    *   de l'hypercube encadrant le point � interpoler 
00121    */
00122   ad[0] = 0; ad[1] = 1;
00123   temp = 1 ; p = 1;
00124   for ( j = 0; j < n-1; j++)
00125     {
00126       temp = temp * dim[j];
00127       p = 2*p;
00128       for ( i = 0; i < p; i++ )
00129         ad[p+i] = ad[i] + temp;
00130     };
00131   /* a ce niveau on a  p = 2^(n-1)  */
00132   two_p_n = 2*p;
00133 
00134   /* initialisation pour recherche d'intervalle rapide */
00135   for ( j = 0; j < n; j++ ) k[j] = -1;
00136 
00137   for ( i = 0; i < np; i++ )
00138     {
00139       /* interpolation du i eme point */
00140       
00141       /*  1 - recherche des intervalles  */
00142       for ( j = 0; j < n; j++ )
00143         {
00144           xx = xp[j][i];
00145           if ( C2F(isanan)(&xx) )
00146             {
00147               v[0] = C2F(returnanan)(); goto fin;
00148             }
00149           fast_int_search(xx, x[j], dim[j], &(k[j]));
00150           if ( k[j] == -1 )   /* le point est a l'exterieur */ 
00151             switch (outmode)
00152               {
00153               case BY_NAN :
00154                 v[0] = C2F(returnanan)();
00155                 goto fin;
00156 
00157               case BY_ZERO :
00158                 v[0] = 0.0;
00159                 goto fin;
00160 
00161               case NATURAL :
00162                 if (xx < x[j][0])
00163                   k[j] = 0;
00164                 else
00165                   k[j] = dim[j]-2;
00166                 break;
00167 
00168               case C0 :
00169                 if (xx < x[j][0])
00170                   { 
00171                     u[j] = 0.0; k[j] = 0;
00172                   }  
00173                 else
00174                   {
00175                     u[j] = 1.0; k[j] = dim[j]-2;
00176                   }
00177                 continue;
00178 
00179               case PERIODIC :
00180                 coord_by_periodicity(&xx, x[j], dim[j], &(k[j]));
00181                 break;
00182 
00183               }
00184           u[j] = (xx - x[j][k[j]])/( x[j][k[j]+1] -  x[j][k[j]]);  /* coord bary */
00185         }
00186 
00187       /* 2 - calcul de l'indice de base */
00188       b = k[n-1];
00189       for ( j = n-2; j >= 0; j-- )
00190         b = k[j] + dim[j]*b;
00191 
00192       /* 3 - mise des valeurs de l'hypercube dans v */
00193       for ( j = 0; j < two_p_n; j++ )
00194         v[j] = val[b + ad[j]];
00195 
00196       /* 4 - interpolation */
00197       temp = 1; p = two_p_n;
00198       for ( j = 0; j < n ; j++ )
00199         {
00200           for ( l = 0; l < two_p_n; l+=2*temp)
00201             {
00202               v[l] = v[l]*(1.0 - u[j]) + v[l+temp]*u[j];
00203             }
00204           p = p/2; 
00205           temp = 2*temp; 
00206         }
00207 
00208       /* 5 - on met le resultat a sa place */
00209     fin:
00210       yp[i] = v[0];
00211     
00212     }
00213 }
00214 
00215 
00216 
00217 
00218         
00219               
00220             
00221   

Generated on Sun Mar 4 15:03:57 2007 for Scilab [trunk] by  doxygen 1.5.1