00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "lo-ieee.h"
00028 #include "dNDArray.h"
00029 #include "oct-locbuf.h"
00030
00031 #include "defun-dld.h"
00032 #include "error.h"
00033 #include "oct-obj.h"
00034
00035
00036
00037 template <class T>
00038 bool
00039 isvector (const T& array)
00040 {
00041 const dim_vector dv = array.dims ();
00042 return dv.length () == 2 && (dv(0) == 1 || dv(1) == 1);
00043 }
00044
00045
00046 template <class T>
00047 octave_idx_type
00048 lookup (const T *x, octave_idx_type n, T y)
00049 {
00050 octave_idx_type j;
00051
00052 if (x[0] < x[n-1])
00053 {
00054
00055
00056 if (y > x[n-1] || y < x[0])
00057 return -1;
00058
00059 #ifdef EXHAUSTIF
00060 for (j = 0; j < n - 1; j++)
00061 {
00062 if (x[j] <= y && y <= x[j+1])
00063 return j;
00064 }
00065 #else
00066 octave_idx_type j0 = 0;
00067 octave_idx_type j1 = n - 1;
00068
00069 while (true)
00070 {
00071 j = (j0+j1)/2;
00072
00073 if (y <= x[j+1])
00074 {
00075 if (x[j] <= y)
00076 return j;
00077
00078 j1 = j;
00079 }
00080
00081 if (x[j] <= y)
00082 j0 = j;
00083 }
00084 #endif
00085 }
00086 else
00087 {
00088
00089
00090
00091 if (y > x[0] || y < x[n-1])
00092 return -1;
00093
00094 #ifdef EXHAUSTIF
00095 for (j = 0; j < n - 1; j++)
00096 {
00097 if (x[j+1] <= y && y <= x[j])
00098 return j;
00099 }
00100 #else
00101 octave_idx_type j0 = 0;
00102 octave_idx_type j1 = n - 1;
00103
00104 while (true)
00105 {
00106 j = (j0+j1)/2;
00107
00108 if (y >= x[j+1])
00109 {
00110 if (x[j] >= y)
00111 return j;
00112
00113 j1 = j;
00114 }
00115
00116 if (x[j] >= y)
00117 j0 = j;
00118 }
00119 #endif
00120 }
00121 }
00122
00123
00124
00125 template <class T>
00126 void
00127 lin_interpn (int n, const octave_idx_type *size, const octave_idx_type *scale,
00128 octave_idx_type Ni, T extrapval, const T **x,
00129 const T *v, const T **y, T *vi)
00130 {
00131 bool out = false;
00132 int bit;
00133
00134 OCTAVE_LOCAL_BUFFER (T, coef, 2*n);
00135 OCTAVE_LOCAL_BUFFER (octave_idx_type, index, n);
00136
00137
00138 for (octave_idx_type m = 0; m < Ni; m++)
00139 {
00140
00141 for (int i = 0; i < n; i++)
00142 {
00143 index[i] = lookup (x[i], size[i], y[i][m]);
00144 out = index[i] == -1;
00145
00146 if (out)
00147 break;
00148 else
00149 {
00150 octave_idx_type j = index[i];
00151 coef[2*i+1] = (y[i][m] - x[i][j])/(x[i][j+1] - x[i][j]);
00152 coef[2*i] = 1 - coef[2*i+1];
00153 }
00154 }
00155
00156
00157 if (out)
00158 vi[m] = extrapval;
00159 else
00160 {
00161 vi[m] = 0;
00162
00163
00164 for (int i = 0; i < (1 << n); i++)
00165 {
00166 T c = 1;
00167 octave_idx_type l = 0;
00168
00169
00170 for (int j = 0; j < n; j++)
00171 {
00172
00173 bit = i >> j & 1;
00174 l += scale[j] * (index[j] + bit);
00175 c *= coef[2*j+bit];
00176 }
00177
00178 vi[m] += c * v[l];
00179 }
00180 }
00181 }
00182 }
00183
00184 template <class T, class M>
00185 octave_value
00186 lin_interpn (int n, M *X, const M V, M *Y)
00187 {
00188 octave_value retval;
00189
00190 M Vi = M (Y[0].dims ());
00191
00192 OCTAVE_LOCAL_BUFFER (const T *, y, n);
00193 OCTAVE_LOCAL_BUFFER (octave_idx_type, size, n);
00194
00195 for (int i = 0; i < n; i++)
00196 {
00197 y[i] = Y[i].data ();
00198 size[i] = V.dims()(i);
00199 }
00200
00201 OCTAVE_LOCAL_BUFFER (const T *, x, n);
00202 OCTAVE_LOCAL_BUFFER (octave_idx_type, scale, n);
00203
00204 const T *v = V.data ();
00205 T *vi = Vi.fortran_vec ();
00206 octave_idx_type Ni = Vi.numel ();
00207
00208 T extrapval = octave_NA;
00209
00210
00211
00212 scale[0] = 1;
00213
00214 for (int i = 1; i < n; i++)
00215 scale[i] = scale[i-1] * size[i-1];
00216
00217
00218
00219
00220 if (! isvector (X[0]))
00221 {
00222 for (int i = 0; i < n; i++)
00223 {
00224 if (X[i].dims () != V.dims ())
00225 {
00226 error ("interpn: incompatible size of argument number %d", i+1);
00227 return retval;
00228 }
00229 else
00230 {
00231 M tmp = M (dim_vector (size[i], 1));
00232
00233 for (octave_idx_type j = 0; j < size[i]; j++)
00234 tmp(j) = X[i](scale[i]*j);
00235
00236 X[i] = tmp;
00237 }
00238 }
00239 }
00240
00241 for (int i = 0; i < n; i++)
00242 {
00243 if (! isvector (X[i]) && X[i].numel () != size[i])
00244 {
00245 error ("interpn: incompatible size of argument number %d", i+1);
00246 return retval;
00247 }
00248 else
00249 x[i] = X[i].data ();
00250 }
00251
00252 lin_interpn (n, size, scale, Ni, extrapval, x, v, y, vi);
00253
00254 retval = Vi;
00255
00256 return retval;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 DEFUN_DLD (__lin_interpn__, args, ,
00271 "-*- texinfo -*-\n\
00272 @deftypefn {Loadable Function} {@var{vi} =} __lin_interpn__ (@var{x1}, @var{x2}, @dots{}, @var{xn}, @var{v}, @var{y1}, @var{y2}, @dots{}, @var{yn})\n\
00273 Undocumented internal function.\n\
00274 @end deftypefn")
00275 {
00276 octave_value retval;
00277
00278 int nargin = args.length ();
00279
00280 if (nargin < 2 || nargin % 2 == 0)
00281 {
00282 print_usage ();
00283 return retval;
00284 }
00285
00286
00287 int n = (nargin-1)/2;
00288
00289 if (args(n).is_single_type())
00290 {
00291 OCTAVE_LOCAL_BUFFER (FloatNDArray, X, n);
00292 OCTAVE_LOCAL_BUFFER (FloatNDArray, Y, n);
00293
00294 const FloatNDArray V = args(n).float_array_value ();
00295
00296 if (error_state)
00297 {
00298 print_usage ();
00299 return retval;
00300 }
00301
00302 for (int i = 0; i < n; i++)
00303 {
00304 X[i] = args(i).float_array_value ();
00305 Y[i] = args(n+i+1).float_array_value ();
00306
00307 if (error_state)
00308 {
00309 print_usage ();
00310 return retval;
00311 }
00312
00313 if (Y[0].dims () != Y[i].dims ())
00314 {
00315 error ("interpn: incompatible size of argument number %d", n+i+2);
00316 return retval;
00317 }
00318 }
00319
00320 retval = lin_interpn<float, FloatNDArray> (n, X, V, Y);
00321 }
00322 else
00323 {
00324 OCTAVE_LOCAL_BUFFER (NDArray, X, n);
00325 OCTAVE_LOCAL_BUFFER (NDArray, Y, n);
00326
00327 const NDArray V = args(n).array_value ();
00328
00329 if (error_state)
00330 {
00331 print_usage ();
00332 return retval;
00333 }
00334
00335 for (int i = 0; i < n; i++)
00336 {
00337 X[i] = args(i).array_value ();
00338 Y[i] = args(n+i+1).array_value ();
00339
00340 if (error_state)
00341 {
00342 print_usage ();
00343 return retval;
00344 }
00345
00346 if (Y[0].dims () != Y[i].dims ())
00347 {
00348 error ("interpn: incompatible size of argument number %d", n+i+2);
00349 return retval;
00350 }
00351 }
00352
00353 retval = lin_interpn<double, NDArray> (n, X, V, Y);
00354 }
00355
00356 return retval;
00357 }
00358
00359
00360
00361
00362
00363
00364