My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
interpolator.cpp
Go to the documentation of this file.
1 /*
2  * interpolator.cpp - interpolator class implementation
3  *
4  * Copyright (C) 2009 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: interpolator.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 
34 #include "poly.h"
35 #include "spline.h"
36 #include "object.h"
37 #include "vector.h"
38 #include "interpolator.h"
39 
40 // Constructor creates an instance of the interpolator class.
42  rsp = isp = NULL;
43  rx = ry = NULL;
44  cy = NULL;
45  repeat = dataType = interpolType = length = 0;
46  duration = 0.0;
47 }
48 
49 
50 // Destructor deletes an instance of the interpolator class.
52  if (rsp) delete rsp;
53  if (isp) delete isp;
54  if (rx) free (rx);
55  if (ry) free (ry);
56  if (cy) free (cy);
57 }
58 
59 // Cleans up vector storage.
60 void interpolator::cleanup (void) {
61  if (rx) { free (rx); rx = NULL; }
62  if (ry) { free (ry); ry = NULL; }
63  if (cy) { free (cy); cy = NULL; }
64 }
65 
66 // Pass real interpolation datapoints as pointers.
67 void interpolator::vectors (nr_double_t * y, nr_double_t * x, int len) {
68  int len1 = len;
69  int len2 = 2 + len * sizeof (nr_double_t);
70  if (len > 0) {
71  ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
72  memcpy (ry, y, len1 * sizeof (nr_double_t));
73  }
74  if (len > 0) {
75  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
76  memcpy (rx, x, len1 * sizeof (nr_double_t));
77  }
78 
79  dataType = (DATA_REAL & DATA_MASK_TYPE);
80  length = len;
81 }
82 
83 // Pass real interpolation datapoints as vectors.
85  int len = y->getSize ();
86  int len1 = len;
87  int len2 = 2 + len * sizeof (nr_double_t);
88  cleanup ();
89  if (len > 0) {
90  ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
91  for (int i = 0; i < len1; i++) ry[i] = real (y->get (i));
92  }
93  if (len > 0) {
94  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
95  for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
96  }
97 
98  dataType = (DATA_REAL & DATA_MASK_TYPE);
99  length = len;
100 }
101 
102 // Pass complex interpolation datapoints as pointers.
103 void interpolator::vectors (nr_complex_t * y, nr_double_t * x, int len) {
104  int len1 = len;
105  int len2 = 2 + len;
106  cleanup ();
107  if (len > 0) {
108  cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
109  memcpy (cy, y, len1 * sizeof (nr_complex_t));
110  }
111  if (len > 0) {
112  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
113  memcpy (rx, x, len1 * sizeof (nr_double_t));
114  }
115 
116  dataType = (DATA_COMPLEX & DATA_MASK_TYPE);
117  length = len;
118 }
119 
120 // Pass complex interpolation datapoints as vectors.
122  int len = y->getSize ();
123  int len1 = len;
124  int len2 = 2 + len;
125  cleanup ();
126  if (len > 0) {
127  cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
128  for (int i = 0; i < len1; i++) cy[i] = y->get (i);
129  }
130  if (len > 0) {
131  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
132  for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
133  }
134 
135  dataType = (DATA_COMPLEX & DATA_MASK_TYPE);
136  length = len;
137 }
138 
139 // Prepares interpolator instance, e.g. setups spline object.
140 void interpolator::prepare (int interpol, int repitition, int domain) {
141  interpolType = interpol;
142  dataType |= (domain & DATA_MASK_DOMAIN);
143  repeat = repitition;
144 
145  // preparations for cyclic interpolations
146  if (repeat & REPEAT_YES) {
147  duration = rx[length - 1] - rx[0];
148  // set first value to the end of the value vector
149  if (cy) cy[length - 1] = cy[0];
150  if (ry) ry[length - 1] = ry[0];
151  }
152 
153  // preparations for polar complex data
154  if (cy != NULL && (domain & DATA_POLAR) && length > 1) {
155  // unwrap phase of complex data vector
156  vector ang = vector (length);
157  for (int i = 0; i < length; i++) ang (i) = arg (cy[i]);
158  ang = unwrap (ang);
159  // store complex data
160  for (int i = 0; i < length; i++) {
161  cy[i] = rect (abs (cy[i]), real (ang (i)));
162  }
163  }
164 
165  // preparations spline interpolations
166  if (interpolType & INTERPOL_CUBIC) {
167 
168  // prepare complex vector interpolation using splines
169  if (cy != NULL) {
170  // create splines if necessary
171  if (rsp) delete rsp;
172  if (isp) delete isp;
173  rsp = new spline (SPLINE_BC_NATURAL);
174  isp = new spline (SPLINE_BC_NATURAL);
175  if (repeat & REPEAT_YES) {
178  }
179  // prepare data vectors
180  vector rv = vector (length);
181  vector iv = vector (length);
182  vector rt = vector (length);
183  for (int i = 0; i < length; i++) {
184  rv (i) = real (cy[i]);
185  iv (i) = imag (cy[i]);
186  rt (i) = rx[i];
187  }
188  // pass data vectors to splines and construct these
189  rsp->vectors (rv, rt);
190  isp->vectors (iv, rt);
191  rsp->construct ();
192  isp->construct ();
193  }
194 
195  // prepare real vector interpolation using spline
196  else {
197  if (rsp) delete rsp;
198  rsp = new spline (SPLINE_BC_NATURAL);
199  if (repeat & REPEAT_YES) rsp->setBoundary (SPLINE_BC_PERIODIC);
200  rsp->vectors (ry, rx, length);
201  rsp->construct ();
202  }
203  }
204 }
205 
206 /* The function performs a binary search on the ascending sorted
207  x-vector in order to return the left-hand-side index pointer into
208  the x-vector based on the given value. */
209 int interpolator::findIndex (nr_double_t x) {
210  int lo = 0;
211  int hi = length;
212  int av;
213  while (lo < hi) {
214  av = lo + ((hi - lo) / 2);
215  if (x >= rx[av])
216  lo = av + 1;
217  else
218  // can't be hi = av-1: here rx[av] >= x,
219  // so hi can't be < av if rx[av] == x
220  hi = av;
221  }
222  // hi == lo, using hi or lo depends on taste
223  if (lo <= length && lo > 0 && x >= rx[lo - 1])
224  return lo - 1; // found
225  else
226  return 0; // not found
227 }
228 
229 /* Return the left-hand-side index pointer into the x-vector based on
230  the given value. Returns 0 or 'length' if the value is beyond the
231  x-vectors scope. */
232 int interpolator::findIndex_old (nr_double_t x) {
233  int idx = 0;
234  for (int i = 0; i < length; i++) {
235  if (x >= rx[i]) idx = i;
236  }
237  return idx;
238 }
239 
240 /* Computes simple linear interpolation value for the given values. */
241 nr_double_t interpolator::linear (nr_double_t x,
242  nr_double_t x1, nr_double_t x2,
243  nr_double_t y1, nr_double_t y2) {
244  if (x1 == x2)
245  return (y1 + y2) / 2;
246  else
247  return ((x2 - x) * y1 + (x - x1) * y2) / (x2 - x1);
248 }
249 
250 /* Returns real valued linear interpolation. */
251 nr_double_t interpolator::rlinear (nr_double_t x, int idx) {
252  return linear (x, rx[idx], rx[idx+1], ry[idx], ry[idx+1]);
253 }
254 
255 /* Returns complex valued linear interpolation. */
256 nr_complex_t interpolator::clinear (nr_double_t x, int idx) {
257  nr_double_t x1, x2, r, i;
258  nr_complex_t y1, y2;
259  x1 = rx[idx]; x2 = rx[idx+1];
260  y1 = cy[idx]; y2 = cy[idx+1];
261  r = linear (x, x1, x2, real (y1), real (y2));
262  i = linear (x, x1, x2, imag (y1), imag (y2));
263  return rect (r, i);
264 }
265 
266 /* This function interpolates for real values. Returns the linear
267  interpolation of the real y-vector for the given value in the
268  x-vector. */
269 nr_double_t interpolator::rinterpolate (nr_double_t x) {
270  int idx = -1;
271  nr_double_t res = 0.0;
272 
273  // no chance to interpolate
274  if (length <= 0) {
275  return res;
276  }
277  // no interpolation necessary
278  else if (length == 1) {
279  res = ry[0];
280  return res;
281  }
282  else if (repeat & REPEAT_YES)
283  x = x - floor (x / duration) * duration;
284 
285  // linear interpolation
286  if (interpolType & INTERPOL_LINEAR) {
287  idx = findIndex (x);
288  // dependency variable in scope or beyond
289  if (x == rx[idx])
290  res = ry[idx];
291  // dependency variable is beyond scope; use last tangent
292  else {
293  if (idx == length - 1) idx--;
294  res = rlinear (x, idx);
295  }
296  }
297  // cubic spline interpolation
298  else if (interpolType & INTERPOL_CUBIC) {
299  // evaluate spline functions
300  res = rsp->evaluate (x).f0;
301  }
302  else if (interpolType & INTERPOL_HOLD) {
303  // find appropriate dependency index
304  idx = findIndex (x);
305  res = ry[idx];
306  }
307  return res;
308 }
309 
310 /* This function interpolates for complex values. Returns the complex
311  interpolation of the real y-vector for the given value in the
312  x-vector. */
314  int idx = -1;
315  nr_complex_t res = 0.0;
316 
317  // no chance to interpolate
318  if (length <= 0) {
319  return res;
320  }
321  // no interpolation necessary
322  else if (length == 1) {
323  res = cy[0];
324  return res;
325  }
326  else if (repeat & REPEAT_YES)
327  x = x - floor (x / duration) * duration;
328 
329  // linear interpolation
330  if (interpolType & INTERPOL_LINEAR) {
331  idx = findIndex (x);
332  // dependency variable in scope or beyond
333  if (x == rx[idx])
334  res = cy[idx];
335  // dependency variable is beyond scope; use last tangent
336  else {
337  if (idx == length - 1) idx--;
338  res = clinear (x, idx);
339  }
340  }
341  // cubic spline interpolation
342  else if (interpolType & INTERPOL_CUBIC) {
343  // evaluate spline functions
344  nr_double_t r = rsp->evaluate (x).f0;
345  nr_double_t i = isp->evaluate (x).f0;
346  res = rect (r, i);
347  }
348  else if (interpolType & INTERPOL_HOLD) {
349  // find appropriate dependency index
350  idx = findIndex (x);
351  res = cy[idx];
352  }
353 
354  // depending on the data type return appropriate complex value
355  if (dataType & DATA_POLAR)
356  return polar (real (res), imag (res));
357  else
358  return res;
359 }