Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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$
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 namespace qucs {
41 
42 // Constructor creates an instance of the interpolator class.
44  rsp = isp = NULL;
45  rx = ry = NULL;
46  cy = NULL;
48  duration = 0.0;
49 }
50 
51 
52 // Destructor deletes an instance of the interpolator class.
54  if (rsp) delete rsp;
55  if (isp) delete isp;
56  if (rx) free (rx);
57  if (ry) free (ry);
58  if (cy) free (cy);
59 }
60 
61 // Cleans up vector storage.
62 void interpolator::cleanup (void) {
63  if (rx) { free (rx); rx = NULL; }
64  if (ry) { free (ry); ry = NULL; }
65  if (cy) { free (cy); cy = NULL; }
66 }
67 
68 // Pass real interpolation datapoints as pointers.
69 void interpolator::vectors (nr_double_t * y, nr_double_t * x, int len) {
70  int len1 = len;
71  int len2 = 2 + len * sizeof (nr_double_t);
72  if (len > 0) {
73  ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
74  memcpy (ry, y, len1 * sizeof (nr_double_t));
75  }
76  if (len > 0) {
77  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
78  memcpy (rx, x, len1 * sizeof (nr_double_t));
79  }
80 
82  length = len;
83 }
84 
85 // Pass real interpolation datapoints as vectors.
87  int len = y->getSize ();
88  int len1 = len;
89  int len2 = 2 + len * sizeof (nr_double_t);
90  cleanup ();
91  if (len > 0) {
92  ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
93  for (int i = 0; i < len1; i++) ry[i] = real (y->get (i));
94  }
95  if (len > 0) {
96  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
97  for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
98  }
99 
101  length = len;
102 }
103 
104 // Pass complex interpolation datapoints as pointers.
105 void interpolator::vectors (nr_complex_t * y, nr_double_t * x, int len) {
106  int len1 = len;
107  int len2 = 2 + len;
108  cleanup ();
109  if (len > 0) {
110  cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
111  memcpy (cy, y, len1 * sizeof (nr_complex_t));
112  }
113  if (len > 0) {
114  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
115  memcpy (rx, x, len1 * sizeof (nr_double_t));
116  }
117 
119  length = len;
120 }
121 
122 // Pass complex interpolation datapoints as vectors.
124  int len = y->getSize ();
125  int len1 = len;
126  int len2 = 2 + len;
127  cleanup ();
128  if (len > 0) {
129  cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
130  for (int i = 0; i < len1; i++) cy[i] = y->get (i);
131  }
132  if (len > 0) {
133  rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
134  for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
135  }
136 
138  length = len;
139 }
140 
141 // Prepares interpolator instance, e.g. setups spline object.
142 void interpolator::prepare (int interpol, int repitition, int domain) {
143  interpolType = interpol;
144  dataType |= (domain & DATA_MASK_DOMAIN);
145  repeat = repitition;
146 
147  // preparations for cyclic interpolations
148  if (repeat & REPEAT_YES) {
149  duration = rx[length - 1] - rx[0];
150  // set first value to the end of the value vector
151  if (cy) cy[length - 1] = cy[0];
152  if (ry) ry[length - 1] = ry[0];
153  }
154 
155  // preparations for polar complex data
156  if (cy != NULL && (domain & DATA_POLAR) && length > 1) {
157  // unwrap phase of complex data vector
158  vector ang = vector (length);
159  for (int i = 0; i < length; i++) ang (i) = arg (cy[i]);
160  ang = unwrap (ang);
161  // store complex data
162  for (int i = 0; i < length; i++) {
163  cy[i] = nr_complex_t (abs (cy[i]), real (ang (i)));
164  }
165  }
166 
167  // preparations spline interpolations
169 
170  // prepare complex vector interpolation using splines
171  if (cy != NULL) {
172  // create splines if necessary
173  if (rsp) delete rsp;
174  if (isp) delete isp;
175  rsp = new spline (SPLINE_BC_NATURAL);
176  isp = new spline (SPLINE_BC_NATURAL);
177  if (repeat & REPEAT_YES) {
180  }
181  // prepare data vectors
182  vector rv = vector (length);
183  vector iv = vector (length);
184  vector rt = vector (length);
185  for (int i = 0; i < length; i++) {
186  rv (i) = real (cy[i]);
187  iv (i) = imag (cy[i]);
188  rt (i) = rx[i];
189  }
190  // pass data vectors to splines and construct these
191  rsp->vectors (rv, rt);
192  isp->vectors (iv, rt);
193  rsp->construct ();
194  isp->construct ();
195  }
196 
197  // prepare real vector interpolation using spline
198  else {
199  if (rsp) delete rsp;
200  rsp = new spline (SPLINE_BC_NATURAL);
201  if (repeat & REPEAT_YES) rsp->setBoundary (SPLINE_BC_PERIODIC);
202  rsp->vectors (ry, rx, length);
203  rsp->construct ();
204  }
205  }
206 }
207 
208 /* The function performs a binary search on the ascending sorted
209  x-vector in order to return the left-hand-side index pointer into
210  the x-vector based on the given value. */
211 int interpolator::findIndex (nr_double_t x) {
212  int lo = 0;
213  int hi = length;
214  int av;
215  while (lo < hi) {
216  av = lo + ((hi - lo) / 2);
217  if (x >= rx[av])
218  lo = av + 1;
219  else
220  // can't be hi = av-1: here rx[av] >= x,
221  // so hi can't be < av if rx[av] == x
222  hi = av;
223  }
224  // hi == lo, using hi or lo depends on taste
225  if (lo <= length && lo > 0 && x >= rx[lo - 1])
226  return lo - 1; // found
227  else
228  return 0; // not found
229 }
230 
231 /* Return the left-hand-side index pointer into the x-vector based on
232  the given value. Returns 0 or 'length' if the value is beyond the
233  x-vectors scope. */
234 int interpolator::findIndex_old (nr_double_t x) {
235  int idx = 0;
236  for (int i = 0; i < length; i++) {
237  if (x >= rx[i]) idx = i;
238  }
239  return idx;
240 }
241 
242 /* Computes simple linear interpolation value for the given values. */
243 nr_double_t interpolator::linear (nr_double_t x,
244  nr_double_t x1, nr_double_t x2,
245  nr_double_t y1, nr_double_t y2) {
246  if (x1 == x2)
247  return (y1 + y2) / 2;
248  else
249  return ((x2 - x) * y1 + (x - x1) * y2) / (x2 - x1);
250 }
251 
252 /* Returns real valued linear interpolation. */
253 nr_double_t interpolator::rlinear (nr_double_t x, int idx) {
254  return linear (x, rx[idx], rx[idx+1], ry[idx], ry[idx+1]);
255 }
256 
257 /* Returns complex valued linear interpolation. */
258 nr_complex_t interpolator::clinear (nr_double_t x, int idx) {
259  nr_double_t x1, x2, r, i;
260  nr_complex_t y1, y2;
261  x1 = rx[idx]; x2 = rx[idx+1];
262  y1 = cy[idx]; y2 = cy[idx+1];
263  r = linear (x, x1, x2, real (y1), real (y2));
264  i = linear (x, x1, x2, imag (y1), imag (y2));
265  return nr_complex_t (r, i);
266 }
267 
268 /* This function interpolates for real values. Returns the linear
269  interpolation of the real y-vector for the given value in the
270  x-vector. */
271 nr_double_t interpolator::rinterpolate (nr_double_t x) {
272  int idx = -1;
273  nr_double_t res = 0.0;
274 
275  // no chance to interpolate
276  if (length <= 0) {
277  return res;
278  }
279  // no interpolation necessary
280  else if (length == 1) {
281  res = ry[0];
282  return res;
283  }
284  else if (repeat & REPEAT_YES)
285  x = x - std::floor (x / duration) * duration;
286 
287  // linear interpolation
289  idx = findIndex (x);
290  // dependency variable in scope or beyond
291  if (x == rx[idx])
292  res = ry[idx];
293  // dependency variable is beyond scope; use last tangent
294  else {
295  if (idx == length - 1) idx--;
296  res = rlinear (x, idx);
297  }
298  }
299  // cubic spline interpolation
300  else if (interpolType & INTERPOL_CUBIC) {
301  // evaluate spline functions
302  res = rsp->evaluate (x).f0;
303  }
304  else if (interpolType & INTERPOL_HOLD) {
305  // find appropriate dependency index
306  idx = findIndex (x);
307  res = ry[idx];
308  }
309  return res;
310 }
311 
312 /* This function interpolates for complex values. Returns the complex
313  interpolation of the real y-vector for the given value in the
314  x-vector. */
316  int idx = -1;
317  nr_complex_t res = 0.0;
318 
319  // no chance to interpolate
320  if (length <= 0) {
321  return res;
322  }
323  // no interpolation necessary
324  else if (length == 1) {
325  res = cy[0];
326  return res;
327  }
328  else if (repeat & REPEAT_YES)
329  x = x - std::floor (x / duration) * duration;
330 
331  // linear interpolation
333  idx = findIndex (x);
334  // dependency variable in scope or beyond
335  if (x == rx[idx])
336  res = cy[idx];
337  // dependency variable is beyond scope; use last tangent
338  else {
339  if (idx == length - 1) idx--;
340  res = clinear (x, idx);
341  }
342  }
343  // cubic spline interpolation
344  else if (interpolType & INTERPOL_CUBIC) {
345  // evaluate spline functions
346  nr_double_t r = rsp->evaluate (x).f0;
347  nr_double_t i = isp->evaluate (x).f0;
348  res = nr_complex_t (r, i);
349  }
350  else if (interpolType & INTERPOL_HOLD) {
351  // find appropriate dependency index
352  idx = findIndex (x);
353  res = cy[idx];
354  }
355 
356  // depending on the data type return appropriate complex value
357  if (dataType & DATA_POLAR)
358  return std::polar (real (res), imag (res));
359  else
360  return res;
361 }
362 
363 } // namespace qucs
#define DATA_REAL
Definition: interpolator.h:40
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
nr_complex_t clinear(nr_double_t, int)
poly evaluate(nr_double_t)
Definition: spline.cpp:285
void prepare(int, int, int domain=DATA_RECTANGULAR)
matrix real(matrix a)
Real part matrix.
Definition: matrix.cpp:568
matrix abs(matrix a)
Computes magnitude of each matrix element.
Definition: matrix.cpp:531
int getSize(void) const
Definition: vector.cpp:192
void vectors(qucs::vector, qucs::vector)
Definition: spline.cpp:85
void construct(void)
Definition: spline.cpp:135
nr_double_t rinterpolate(nr_double_t)
#define REPEAT_YES
Definition: interpolator.h:34
r
Definition: parse_mdl.y:515
#define DATA_POLAR
Definition: interpolator.h:37
i
Definition: parse_mdl.y:516
nr_double_t * rx
Definition: interpolator.h:73
matrix imag(matrix a)
Imaginary part matrix.
Definition: matrix.cpp:581
nr_double_t linear(nr_double_t, nr_double_t, nr_double_t, nr_double_t, nr_double_t)
void cvectors(qucs::vector *, qucs::vector *)
#define INTERPOL_HOLD
Definition: interpolator.h:31
#define DATA_MASK_TYPE
Definition: interpolator.h:41
#define INTERPOL_LINEAR
Definition: interpolator.h:29
#define INTERPOL_CUBIC
Definition: interpolator.h:30
#define DATA_MASK_DOMAIN
Definition: interpolator.h:38
nr_double_t * ry
Definition: interpolator.h:74
free($1)
x
Definition: parse_mdl.y:498
nr_complex_t floor(const nr_complex_t z)
Complex floor.
Definition: complex.cpp:623
void setBoundary(int b)
Definition: spline.h:57
nr_double_t rlinear(nr_double_t, int)
nr_complex_t * cy
Definition: interpolator.h:77
void vectors(nr_double_t *, nr_double_t *, int)
y
Definition: parse_mdl.y:499
nr_complex_t cinterpolate(nr_double_t)
nr_complex_t polar(const nr_double_t mag, const nr_double_t ang)
Construct a complex number using polar notation.
Definition: complex.cpp:551
int findIndex_old(nr_double_t)
int findIndex(nr_double_t)
nr_double_t duration
Definition: interpolator.h:75
nr_complex_t get(int)
Definition: vector.cpp:179
nr_double_t f0
Definition: poly.h:46
matrix arg(matrix a)
Computes the argument of each matrix element.
Definition: matrix.cpp:555
#define DATA_COMPLEX
Definition: interpolator.h:39
void rvectors(qucs::vector *, qucs::vector *)
vector unwrap(vector, nr_double_t tol=M_PI, nr_double_t step=2 *M_PI)
Definition: vector.cpp:235