GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__lin_interpn__.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2007-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "lo-ieee.h"
31#include "dNDArray.h"
32#include "oct-locbuf.h"
33
34#include "defun.h"
35#include "error.h"
36#include "ovl.h"
37
38OCTAVE_NAMESPACE_BEGIN
39
40// equivalent to isvector.m
41
42template <typename T>
43bool
44isvector (const T& array)
45{
46 const dim_vector dv = array.dims ();
47 return dv.ndims () == 2 && (dv(0) == 1 || dv(1) == 1);
48}
49
50// lookup a value in a sorted table (lookup.m)
51template <typename T>
53lookup (const T *x, octave_idx_type n, T y)
54{
56
57 if (x[0] < x[n-1])
58 {
59 // increasing x
60
61 if (y > x[n-1] || y < x[0])
62 return -1;
63
64#if defined (EXHAUSTIF)
65 for (j = 0; j < n - 1; j++)
66 {
67 if (x[j] <= y && y <= x[j+1])
68 return j;
69 }
70#else
71 octave_idx_type j0 = 0;
72 octave_idx_type j1 = n - 1;
73
74 while (true)
75 {
76 j = (j0+j1)/2;
77
78 if (y <= x[j+1])
79 {
80 if (x[j] <= y)
81 return j;
82
83 j1 = j;
84 }
85
86 if (x[j] <= y)
87 j0 = j;
88 }
89#endif
90 }
91 else
92 {
93 // decreasing x
94 // previous code with x -> -x and y -> -y
95
96 if (y > x[0] || y < x[n-1])
97 return -1;
98
99#if defined (EXHAUSTIF)
100 for (j = 0; j < n - 1; j++)
101 {
102 if (x[j+1] <= y && y <= x[j])
103 return j;
104 }
105#else
106 octave_idx_type j0 = 0;
107 octave_idx_type j1 = n - 1;
108
109 while (true)
110 {
111 j = (j0+j1)/2;
112
113 if (y >= x[j+1])
114 {
115 if (x[j] >= y)
116 return j;
117
118 j1 = j;
119 }
120
121 if (x[j] >= y)
122 j0 = j;
123 }
124#endif
125 }
126}
127
128// n-dimensional linear interpolation
129
130template <typename T>
131void
133 octave_idx_type Ni, T extrapval, const T **x,
134 const T *v, const T **y, T *vi)
135{
136 bool out = false;
137 int bit;
138
139 OCTAVE_LOCAL_BUFFER (T, coef, 2*n);
141
142 // loop over all points
143 for (octave_idx_type m = 0; m < Ni; m++)
144 {
145 // loop over all dimensions
146 for (int i = 0; i < n; i++)
147 {
148 index[i] = lookup (x[i], size[i], y[i][m]);
149 out = index[i] == -1;
150
151 if (out)
152 break;
153 else
154 {
155 octave_idx_type j = index[i];
156 coef[2*i+1] = (y[i][m] - x[i][j])/(x[i][j+1] - x[i][j]);
157 coef[2*i] = 1 - coef[2*i+1];
158 }
159 }
160
161 if (out)
162 vi[m] = extrapval;
163 else
164 {
165 vi[m] = 0;
166
167 // loop over all corners of hypercube (1<<n = 2^n)
168 for (int i = 0; i < (1 << n); i++)
169 {
170 T c = 1;
171 octave_idx_type l = 0;
172
173 // loop over all dimensions
174 for (int j = 0; j < n; j++)
175 {
176 // test if the jth bit in i is set
177 bit = i >> j & 1;
178 l += scale[j] * (index[j] + bit);
179 c *= coef[2*j+bit];
180 }
181
182 vi[m] += c * v[l];
183 }
184 }
185 }
186}
187
188template <typename T, typename M>
190lin_interpn (int n, M *X, const M V, M *Y)
191{
192 octave_value retval;
193
194 M Vi = M (Y[0].dims ());
195
196 OCTAVE_LOCAL_BUFFER (const T *, y, n);
198
199 for (int i = 0; i < n; i++)
200 {
201 y[i] = Y[i].data ();
202 size[i] = V.dims ()(i);
203 }
204
205 OCTAVE_LOCAL_BUFFER (const T *, x, n);
207
208 const T *v = V.data ();
209 T *vi = Vi.fortran_vec ();
210 octave_idx_type Ni = Vi.numel ();
211
212 T extrapval = octave_NA;
213
214 // offset in memory of each dimension
215
216 scale[0] = 1;
217
218 for (int i = 1; i < n; i++)
219 scale[i] = scale[i-1] * size[i-1];
220
221 // tests if X[0] is a vector, if yes, assume that all elements of X are
222 // in the ndgrid format.
223
224 if (! isvector (X[0]))
225 {
226 for (int i = 0; i < n; i++)
227 {
228 if (X[i].dims () != V.dims ())
229 error ("interpn: incompatible size of argument number %d", i+1);
230
231 M tmp = M (dim_vector (size[i], 1));
232
233 for (octave_idx_type j = 0; j < size[i]; j++)
234 tmp(j) = X[i](scale[i]*j);
235
236 X[i] = tmp;
237 }
238 }
239
240 for (int i = 0; i < n; i++)
241 {
242 if (! isvector (X[i]) && X[i].numel () != size[i])
243 error ("interpn: incompatible size of argument number %d", i+1);
244
245 x[i] = X[i].data ();
246 }
247
248 lin_interpn (n, size, scale, Ni, extrapval, x, v, y, vi);
249
250 retval = Vi;
251
252 return retval;
253}
254
255// Perform @var{n}-dimensional interpolation. Each element of then
256// @var{n}-dimensional array @var{v} represents a value at a location
257// given by the parameters @var{x1}, @var{x2},...,@var{xn}. The parameters
258// @var{x1}, @var{x2}, @dots{}, @var{xn} are either @var{n}-dimensional
259// arrays of the same size as the array @var{v} in the "ndgrid" format
260// or vectors. The parameters @var{y1}, @var{y2}, @dots{}, @var{yn} are
261// all @var{n}-dimensional arrays of the same size and represent the
262// points at which the array @var{vi} is interpolated.
263//
264//This function only performs linear interpolation.
265
266DEFUN (__lin_interpn__, args, ,
267 doc: /* -*- texinfo -*-
268@deftypefn {} {@var{vi} =} __lin_interpn__ (@var{x1}, @var{x2}, @dots{}, @var{xn}, @var{v}, @var{y1}, @var{y2}, @dots{}, @var{yn})
269Undocumented internal function.
270@end deftypefn */)
271{
272 int nargin = args.length ();
273
274 if (nargin < 2 || nargin % 2 == 0)
275 print_usage ();
276
277 octave_value retval;
278
279 // dimension of the problem
280 int n = (nargin-1)/2;
281
282 if (args(n).is_single_type ())
283 {
286
287 const FloatNDArray V = args(n).float_array_value ();
288
289 for (int i = 0; i < n; i++)
290 {
291 X[i] = args(i).float_array_value ();
292 Y[i] = args(n+i+1).float_array_value ();
293
294 if (Y[0].dims () != Y[i].dims ())
295 error ("interpn: incompatible size of argument number %d", n+i+2);
296 }
297
298 retval = lin_interpn<float, FloatNDArray> (n, X, V, Y);
299 }
300 else
301 {
304
305 const NDArray V = args(n).array_value ();
306
307 for (int i = 0; i < n; i++)
308 {
309 X[i] = args(i).array_value ();
310 Y[i] = args(n+i+1).array_value ();
311
312 if (Y[0].dims () != Y[i].dims ())
313 error ("interpn: incompatible size of argument number %d", n+i+2);
314 }
315
316 retval = lin_interpn<double, NDArray> (n, X, V, Y);
317 }
318
319 return retval;
320}
321
322/*
323## No test needed for internal helper function.
324%!assert (1)
325*/
326
327OCTAVE_NAMESPACE_END
OCTAVE_NAMESPACE_BEGIN bool isvector(const T &array)
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
void lin_interpn(int n, const octave_idx_type *size, const octave_idx_type *scale, octave_idx_type Ni, T extrapval, const T **x, const T *v, const T **y, T *vi)
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void error(const char *fmt,...)
Definition: error.cc:980
void scale(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5893
#define octave_NA
Definition: lo-ieee.h:41
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT & M
F77_RET_T const F77_DBLE * x
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44