Mercurial > hg > octave-nkf
diff src/DLD-FUNCTIONS/__lin_interpn__.cc @ 7789:82be108cc558
First attempt at single precision tyeps
* * *
corrections to qrupdate single precision routines
* * *
prefer demotion to single over promotion to double
* * *
Add single precision support to log2 function
* * *
Trivial PROJECT file update
* * *
Cache optimized hermitian/transpose methods
* * *
Add tests for tranpose/hermitian and ChangeLog entry for new transpose code
author | David Bateman <dbateman@free.fr> |
---|---|
date | Sun, 27 Apr 2008 22:34:17 +0200 |
parents | a938cd7869b2 |
children | 25bc2d31e1bf |
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/__lin_interpn__.cc +++ b/src/DLD-FUNCTIONS/__lin_interpn__.cc @@ -32,16 +32,18 @@ // equivalent to isvector.m +template <class T> bool -isvector (const NDArray& array) +isvector (const T& array) { const dim_vector dv = array.dims (); return dv.length () == 2 && (dv(0) == 1 || dv(1) == 1); } // lookup a value in a sorted table (lookup.m) +template <class T> octave_idx_type -lookup (const double *x, octave_idx_type n, double y) +lookup (const T *x, octave_idx_type n, T y) { octave_idx_type j; @@ -118,15 +120,16 @@ // n-dimensional linear interpolation +template <class T> void lin_interpn (int n, const octave_idx_type *size, const octave_idx_type *scale, - octave_idx_type Ni, double extrapval, const double **x, - const double *v, const double **y, double *vi) + octave_idx_type Ni, T extrapval, const T **x, + const T *v, const T **y, T *vi) { bool out = false; int bit; - OCTAVE_LOCAL_BUFFER (double, coef, 2*n); + OCTAVE_LOCAL_BUFFER (T, coef, 2*n); OCTAVE_LOCAL_BUFFER (octave_idx_type, index, n); // loop over all points @@ -158,7 +161,7 @@ // loop over all corners of hypercube (1<<n = 2^n) for (int i = 0; i < (1 << n); i++) { - double c = 1; + T c = 1; octave_idx_type l = 0; // loop over all dimensions @@ -176,6 +179,81 @@ } } +template <class T, class M> +octave_value +lin_interpn (int n, M *X, const M V, M *Y) +{ + octave_value retval; + + M Vi = M (Y[0].dims ()); + + OCTAVE_LOCAL_BUFFER (const T *, y, n); + OCTAVE_LOCAL_BUFFER (octave_idx_type, size, n); + + for (int i = 0; i < n; i++) + { + y[i] = Y[i].data (); + size[i] = V.dims()(i); + } + + OCTAVE_LOCAL_BUFFER (const T *, x, n); + OCTAVE_LOCAL_BUFFER (octave_idx_type, scale, n); + + const T *v = V.data (); + T *vi = Vi.fortran_vec (); + octave_idx_type Ni = Vi.numel (); + + T extrapval = octave_NA; + + // offset in memory of each dimension + + scale[0] = 1; + + for (int i = 1; i < n; i++) + scale[i] = scale[i-1] * size[i-1]; + + // tests if X[0] is a vector, if yes, assume that all elements of X are + // in the ndgrid format. + + if (! isvector (X[0])) + { + for (int i = 0; i < n; i++) + { + if (X[i].dims () != V.dims ()) + { + error ("interpn: incompatible size of argument number %d", i+1); + return retval; + } + else + { + M tmp = M (dim_vector (size[i], 1)); + + for (octave_idx_type j = 0; j < size[i]; j++) + tmp(j) = X[i](scale[i]*j); + + X[i] = tmp; + } + } + } + + for (int i = 0; i < n; i++) + { + if (! isvector (X[i]) && X[i].numel () != size[i]) + { + error ("interpn: incompatible size of argument number %d", i+1); + return retval; + } + else + x[i] = X[i].data (); + } + + lin_interpn (n, size, scale, Ni, extrapval, x, v, y, vi); + + retval = Vi; + + return retval; +} + // Perform @var{n}-dimensional interpolation. Each element of then // @var{n}-dimensional array @var{v} represents a value at a location // given by the parameters @var{x1}, @var{x2},...,@var{xn}. The parameters @@ -206,33 +284,12 @@ // dimension of the problem int n = (nargin-1)/2; - OCTAVE_LOCAL_BUFFER (NDArray, X, n); - OCTAVE_LOCAL_BUFFER (NDArray, Y, n); - - OCTAVE_LOCAL_BUFFER (const double *, x, n); - OCTAVE_LOCAL_BUFFER (const double *, y, n); - OCTAVE_LOCAL_BUFFER (octave_idx_type, scale, n); - OCTAVE_LOCAL_BUFFER (octave_idx_type, size, n); - - const NDArray V = args(n).array_value (); - NDArray Vi = NDArray (args(n+1).dims ()); - - if (error_state) + if (args(n).is_single_type()) { - print_usage (); - return retval; - } + OCTAVE_LOCAL_BUFFER (FloatNDArray, X, n); + OCTAVE_LOCAL_BUFFER (FloatNDArray, Y, n); - const double *v = V.data (); - double *vi = Vi.fortran_vec (); - octave_idx_type Ni = Vi.numel (); - - double extrapval = octave_NA; - - for (int i = 0; i < n; i++) - { - X[i] = args(i).array_value (); - Y[i] = args(n+i+1).array_value (); + const FloatNDArray V = args(n).float_array_value (); if (error_state) { @@ -240,61 +297,59 @@ return retval; } - y[i] = Y[i].data (); - size[i] = V.dims()(i); - - if (Y[0].dims () != Y[i].dims ()) - { - error ("interpn: incompatible size of argument number %d", n+i+2); - return retval; - } - } - - // offset in memory of each dimension - - scale[0] = 1; - - for (int i = 1; i < n; i++) - scale[i] = scale[i-1] * size[i-1]; - - // tests if X[0] is a vector, if yes, assume that all elements of X are - // in the ndgrid format. - - if (! isvector (X[0])) - { for (int i = 0; i < n; i++) { - if (X[i].dims () != V.dims ()) + X[i] = args(i).float_array_value (); + Y[i] = args(n+i+1).float_array_value (); + + if (error_state) { - error ("interpn: incompatible size of argument number %d", i+1); + print_usage (); return retval; } - else + + if (Y[0].dims () != Y[i].dims ()) { - NDArray tmp = NDArray (dim_vector (size[i], 1)); - - for (octave_idx_type j = 0; j < size[i]; j++) - tmp(j) = X[i](scale[i]*j); - - X[i] = tmp; + error ("interpn: incompatible size of argument number %d", n+i+2); + return retval; } } + + retval = lin_interpn<float, FloatNDArray> (n, X, V, Y); } - - for (int i = 0; i < n; i++) + else { - if (! isvector (X[i]) && X[i].numel () != size[i]) + OCTAVE_LOCAL_BUFFER (NDArray, X, n); + OCTAVE_LOCAL_BUFFER (NDArray, Y, n); + + const NDArray V = args(n).array_value (); + + if (error_state) { - error ("interpn: incompatible size of argument number %d", i+1); + print_usage (); return retval; } - else - x[i] = X[i].data (); - } + + for (int i = 0; i < n; i++) + { + X[i] = args(i).array_value (); + Y[i] = args(n+i+1).array_value (); - lin_interpn (n, size, scale, Ni, extrapval, x, v, y, vi); + if (error_state) + { + print_usage (); + return retval; + } - retval = Vi; + if (Y[0].dims () != Y[i].dims ()) + { + error ("interpn: incompatible size of argument number %d", n+i+2); + return retval; + } + } + + retval = lin_interpn<double, NDArray> (n, X, V, Y); + } return retval; }