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