Pull in a bit more data for filtering the start of the boost
[fw/altos] / ao-tools / lib / cc-analyse.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "cc.h"
19 #include <math.h>
20
21 void
22 cc_timedata_limits(struct cc_timedata *d, double min_time, double max_time, int *start, int *stop)
23 {
24         int     i;
25
26         *start = -1;
27         for (i = 0; i < d->num; i++) {
28                 if (*start < 0 && min_time <= d->data[i].time)
29                         *start = i;
30                 if (d->data[i].time <= max_time)
31                         *stop = i;
32         }
33 }
34
35 int
36 cc_timedata_min(struct cc_timedata *d, double min_time, double max_time)
37 {
38         int     i;
39         int     set = 0;
40         int     min_i = -1;
41         double  min;
42
43         if (d->num == 0)
44                 return -1;
45         for (i = 0; i < d->num; i++)
46                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
47                         if (!set || d->data[i].value < min) {
48                                 min_i = i;
49                                 min = d->data[i].value;
50                                 set = 1;
51                         }
52         return min_i;
53 }
54
55 int
56 cc_timedata_min_mag(struct cc_timedata *d, double min_time, double max_time)
57 {
58         int     i;
59         int     set = 0;
60         int     min_i = -1;
61         double  min;
62
63         if (d->num == 0)
64                 return -1;
65         for (i = 0; i < d->num; i++)
66                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
67                         if (!set || fabs(d->data[i].value) < min) {
68                                 min_i = i;
69                                 min = fabs(d->data[i].value);
70                                 set = 1;
71                         }
72         return min_i;
73 }
74
75 int
76 cc_timedata_max(struct cc_timedata *d, double min_time, double max_time)
77 {
78         int     i;
79         double  max;
80         int     max_i = -1;
81         int     set = 0;
82
83         if (d->num == 0)
84                 return -1;
85         for (i = 0; i < d->num; i++)
86                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
87                         if (!set || d->data[i].value > max) {
88                                 max_i = i;
89                                 max = d->data[i].value;
90                                 set = 1;
91                         }
92         return max_i;
93 }
94
95 int
96 cc_timedata_max_mag(struct cc_timedata *d, double min_time, double max_time)
97 {
98         int     i;
99         double  max;
100         int     max_i = -1;
101         int     set = 0;
102
103         if (d->num == 0)
104                 return -1;
105         for (i = 0; i < d->num; i++)
106                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
107                         if (!set || fabs(d->data[i].value) > max) {
108                                 max_i = i;
109                                 max = fabs(d->data[i].value);
110                                 set = 1;
111                         }
112         return max_i;
113 }
114
115 double
116 cc_timedata_average(struct cc_timedata *td, double start_time, double stop_time)
117 {
118         int                     i;
119         double                  prev_time;
120         double                  next_time;
121         double                  interval;
122         double                  sum = 0.0;
123         double                  period = 0.0;
124
125         prev_time = start_time;
126         for (i = 0; i < td->num; i++) {
127                 if (start_time <= td->data[i].time && td->data[i].time <= stop_time) {
128                         if (i < td->num - 1 && td->data[i+1].time < stop_time)
129                                 next_time = (td->data[i].time + td->data[i+1].time) / 2.0;
130                         else
131                                 next_time = stop_time;
132                         interval = next_time - prev_time;
133                         sum += td->data[i].value * interval;
134                         period += interval;
135                         prev_time = next_time;
136                 }
137         }
138         return sum / period;
139 }
140
141 int
142 cc_perioddata_limits(struct cc_perioddata *d, double min_time, double max_time, int *start, int *stop)
143 {
144         double  start_d, stop_d;
145
146         if (d->num == 0)
147                 return 0;
148         start_d = ceil((min_time - d->start) / d->step);
149         if (start_d < 0)
150                 start_d = 0;
151         stop_d = floor((max_time - d->start) / d->step);
152         if (stop_d >= d->num)
153                 stop_d = d->num - 1;
154         if (stop_d < start_d)
155                 return 0;
156         *start = (int) start_d;
157         *stop = (int) stop_d;
158         return 1;
159 }
160
161 int
162 cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time)
163 {
164         int     i;
165         double  min;
166         int     min_i;
167         int     start, stop;
168
169         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
170                 return -1;
171         min = d->data[start];
172         min_i = start;
173         for (i = start + 1; i <= stop; i++)
174                 if (d->data[i] < min) {
175                         min = d->data[i];
176                         min_i = i;
177                 }
178         return min_i;
179 }
180
181 int
182 cc_perioddata_min_mag(struct cc_perioddata *d, double min_time, double max_time)
183 {
184         int     start, stop;
185         int     i;
186         double  min;
187         int     min_i;
188
189         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
190                 return -1;
191         min = d->data[start];
192         min_i = start;
193         for (i = start + 1; i <= stop; i++)
194                 if (fabs(d->data[i]) < min) {
195                         min = fabs(d->data[i]);
196                         min_i = i;
197                 }
198         return min_i;
199 }
200
201 int
202 cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time)
203 {
204         int     start, stop;
205         int     i;
206         double  max;
207         int     max_i;
208
209         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
210                 return -1;
211         max = d->data[start];
212         max_i = start;
213         for (i = start + 1; i <= stop; i++)
214                 if (d->data[i] > max) {
215                         max = d->data[i];
216                         max_i = i;
217                 }
218         return max_i;
219 }
220
221 int
222 cc_perioddata_max_mag(struct cc_perioddata *d, double min_time, double max_time)
223 {
224         int     start, stop;
225         int     i;
226         double  max;
227         int     max_i;
228
229         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
230                 return -1;
231         max = d->data[start];
232         max_i = start;
233         for (i = start + 1; i <= stop; i++)
234                 if (fabs(d->data[i]) > max) {
235                         max = fabs(d->data[i]);
236                         max_i = i;
237                 }
238         return max_i;
239 }
240
241 double
242 cc_perioddata_average(struct cc_perioddata *d, double min_time, double max_time)
243 {
244         int     start, stop;
245         int     i;
246         double  sum = 0.0;
247
248         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
249                 return 0.0;
250         for (i = start; i <= stop; i++)
251                 sum += d->data[i];
252         return sum / (stop - start + 1);
253 }
254
255 double
256 cc_perioddata_average_mag(struct cc_perioddata *d, double min_time, double max_time)
257 {
258         int     start, stop;
259         int     i;
260         double  sum = 0.0;
261
262         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
263                 return 0.0;
264         for (i = start; i <= stop; i++)
265                 sum += fabs(d->data[i]);
266         return sum / (stop - start + 1);
267 }