My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
history.cpp
Go to the documentation of this file.
1 /*
2  * history.cpp - history class implementation
3  *
4  * Copyright (C) 2006, 2007 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: history.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 
33 #include "precision.h"
34 #include "tvector.h"
35 #include "poly.h"
36 #include "spline.h"
37 #include "history.h"
38 
39 // Constructor creates an unnamed instance of the history class.
41  age = 0;
42  t = values = NULL;
43 }
44 
45 /* The copy constructor creates a new instance based on the given
46  history object. */
48  age = h.age;
49  t = h.t;
50  values = h.values ? new tvector<nr_double_t> (*h.values) : NULL;
51 }
52 
53 // Destructor deletes a history object.
55  if (values) delete values;
56 }
57 
58 // The function appends the given value to the history.
59 void history::append (nr_double_t val) {
60  if (values == NULL) values = new tvector<nr_double_t>;
61  values->add (val);
62  if (values != t) drop ();
63 }
64 
65 // Returns left-most valid index into the time value vector.
66 int history::leftidx (void) {
67  int ts = t->getSize ();
68  int vs = values->getSize ();
69  return ts - vs > 0 ? ts - vs : 0;
70 }
71 
72 /* Returns number of unused values (time value vector shorter than
73  value vector). */
74 int history::unused (void) {
75  int ts = t->getSize ();
76  int vs = values->getSize ();
77  return vs - ts > 0 ? vs - ts : 0;
78 }
79 
80 // Returns the first (oldest) time value in the history.
81 nr_double_t history::first (void) {
82  return (t != NULL) ? t->get (leftidx ()) : 0.0;
83 }
84 
85 // Returns the last (youngest) time value in the history.
86 nr_double_t history::last (void) {
87  return (t != NULL) ? t->get (t->getSize () - 1) : 0.0;
88 }
89 
90 // Returns the duration of the history.
91 nr_double_t history::duration (void) {
92  return last () - first ();
93 }
94 
95 /* This function drops those values in the history which are older
96  than the specified age of the history instance. */
97 void history::drop (void) {
98  nr_double_t f = first ();
99  nr_double_t l = last ();
100  if (age > 0.0 && l - f > age) {
101  int r, i = leftidx ();
102  for (r = 0; i < t->getSize (); r++, i++)
103  if (l - t->get (i) < age) break;
104  r += unused () - 2; // keep 2 values being older than specified age
105  if (r > 127) values->drop (r);
106  }
107 }
108 
109 /* Interpolates a value using 2 left side and 2 right side values if
110  possible. */
111 nr_double_t history::interpol (nr_double_t tval, int idx, bool left) {
112  static spline spl (SPLINE_BC_NATURAL);
113  static tvector<nr_double_t> x (4);
114  static tvector<nr_double_t> y (4);
115 
116  int n = left ? idx + 1: idx;
117  if (n > 1 && n + 2 < values->getSize ()) {
118  int i, k, l = leftidx ();
119  for (k = 0, i = n - 2; k < 4; i++, k++) {
120  x (k) = t->get (i + l);
121  y (k) = values->get (i);
122  }
123  spl.vectors (y, x);
124  spl.construct ();
125  return spl.evaluate (tval).f0;
126  }
127  return values->get (idx);
128 }
129 
130 /* The function returns the value nearest to the given time value. If
131  the otional parameter is true then additionally cubic spline
132  interpolation is used. */
133 nr_double_t history::nearest (nr_double_t tval, bool interpolate) {
134  if (t != NULL) {
135  int l = leftidx ();
136  int r = t->getSize () - 1;
137  int i = -1;
138  nr_double_t diff = NR_MAX;
139  sign = true;
140  i = seek (tval, l, r, diff, i);
141  i = i - l;
142  if (interpolate) return interpol (tval, i, sign);
143  return values->get (i);
144  }
145  return 0.0;
146 }
147 
148 /* The function is utilized in order to find the nearest value to a
149  given time value. Since the time vector is ordered a recursive
150  lookup algorithm can be used. The function returns the current
151  index into the time vector as well as the error in time. */
152 int history::seek (nr_double_t tval, int l, int r, nr_double_t& diff,
153  int idx) {
154  int i = (l + r) / 2;
155  if (l == r) return i;
156  nr_double_t v = t->get (i);
157  nr_double_t d = v - tval;
158  if (fabs (d) < diff) {
159  // better approximation
160  diff = fabs (d);
161  sign = d < 0.0 ? true : false;
162  idx = i;
163  }
164  else if (i == l) {
165  // no better
166  return idx;
167  }
168  if (d < 0.0) {
169  // look later
170  return seek (tval, i, r, diff, idx);
171  }
172  else if (d > 0.0) {
173  // look earlier
174  return seek (tval, l, i, diff, idx);
175  }
176  return idx;
177 }