1*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************
2*49cdfc7eSAndroid Build Coastguard Worker *
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright © International Business Machines Corp., 2006, 2008
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker * (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13*49cdfc7eSAndroid Build Coastguard Worker * the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker *
15*49cdfc7eSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
16*49cdfc7eSAndroid Build Coastguard Worker * along with this program; if not, write to the Free Software
17*49cdfc7eSAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*49cdfc7eSAndroid Build Coastguard Worker *
19*49cdfc7eSAndroid Build Coastguard Worker * NAME
20*49cdfc7eSAndroid Build Coastguard Worker * libstats.c
21*49cdfc7eSAndroid Build Coastguard Worker *
22*49cdfc7eSAndroid Build Coastguard Worker * DESCRIPTION
23*49cdfc7eSAndroid Build Coastguard Worker * Some basic statistical analysis convenience tools.
24*49cdfc7eSAndroid Build Coastguard Worker *
25*49cdfc7eSAndroid Build Coastguard Worker *
26*49cdfc7eSAndroid Build Coastguard Worker * USAGE:
27*49cdfc7eSAndroid Build Coastguard Worker * To be included in test cases
28*49cdfc7eSAndroid Build Coastguard Worker *
29*49cdfc7eSAndroid Build Coastguard Worker * AUTHOR
30*49cdfc7eSAndroid Build Coastguard Worker * Darren Hart <[email protected]>
31*49cdfc7eSAndroid Build Coastguard Worker *
32*49cdfc7eSAndroid Build Coastguard Worker * HISTORY
33*49cdfc7eSAndroid Build Coastguard Worker * 2006-Oct-17: Initial version by Darren Hart
34*49cdfc7eSAndroid Build Coastguard Worker * 2009-Jul-22: Addition of stats_container_append function by Kiran Prakash
35*49cdfc7eSAndroid Build Coastguard Worker *
36*49cdfc7eSAndroid Build Coastguard Worker * TODO: the save routine for gnuplot plotting should be more modular...
37*49cdfc7eSAndroid Build Coastguard Worker *
38*49cdfc7eSAndroid Build Coastguard Worker *****************************************************************************/
39*49cdfc7eSAndroid Build Coastguard Worker
40*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
41*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
42*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <math.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <libstats.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <librttest.h>
48*49cdfc7eSAndroid Build Coastguard Worker
49*49cdfc7eSAndroid Build Coastguard Worker #include "../include/realtime_config.h"
50*49cdfc7eSAndroid Build Coastguard Worker
51*49cdfc7eSAndroid Build Coastguard Worker #ifndef HAVE_EXP10
52*49cdfc7eSAndroid Build Coastguard Worker # define exp10(x) (exp((x) * log(10)))
53*49cdfc7eSAndroid Build Coastguard Worker #endif
54*49cdfc7eSAndroid Build Coastguard Worker
55*49cdfc7eSAndroid Build Coastguard Worker int save_stats = 0;
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker /* static helper functions */
stats_record_compare(const void * a,const void * b)58*49cdfc7eSAndroid Build Coastguard Worker static int stats_record_compare(const void *a, const void *b)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker int ret = 0;
61*49cdfc7eSAndroid Build Coastguard Worker stats_record_t *rec_a = (stats_record_t *) a;
62*49cdfc7eSAndroid Build Coastguard Worker stats_record_t *rec_b = (stats_record_t *) b;
63*49cdfc7eSAndroid Build Coastguard Worker if (rec_a->y < rec_b->y)
64*49cdfc7eSAndroid Build Coastguard Worker ret = -1;
65*49cdfc7eSAndroid Build Coastguard Worker else if (rec_a->y > rec_b->y)
66*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
67*49cdfc7eSAndroid Build Coastguard Worker return ret;
68*49cdfc7eSAndroid Build Coastguard Worker }
69*49cdfc7eSAndroid Build Coastguard Worker
70*49cdfc7eSAndroid Build Coastguard Worker /* function implementations */
stats_container_init(stats_container_t * data,long size)71*49cdfc7eSAndroid Build Coastguard Worker int stats_container_init(stats_container_t * data, long size)
72*49cdfc7eSAndroid Build Coastguard Worker {
73*49cdfc7eSAndroid Build Coastguard Worker data->size = size;
74*49cdfc7eSAndroid Build Coastguard Worker data->index = -1;
75*49cdfc7eSAndroid Build Coastguard Worker data->records = calloc(size, sizeof(stats_record_t));
76*49cdfc7eSAndroid Build Coastguard Worker if (!data->records)
77*49cdfc7eSAndroid Build Coastguard Worker return -1;
78*49cdfc7eSAndroid Build Coastguard Worker return 0;
79*49cdfc7eSAndroid Build Coastguard Worker }
80*49cdfc7eSAndroid Build Coastguard Worker
stats_container_append(stats_container_t * data,stats_record_t rec)81*49cdfc7eSAndroid Build Coastguard Worker int stats_container_append(stats_container_t * data, stats_record_t rec)
82*49cdfc7eSAndroid Build Coastguard Worker {
83*49cdfc7eSAndroid Build Coastguard Worker int myindex = ++data->index;
84*49cdfc7eSAndroid Build Coastguard Worker if (myindex >= data->size) {
85*49cdfc7eSAndroid Build Coastguard Worker debug(DBG_ERR, "Number of elements cannot be more than %ld\n",
86*49cdfc7eSAndroid Build Coastguard Worker data->size);
87*49cdfc7eSAndroid Build Coastguard Worker data->index--;
88*49cdfc7eSAndroid Build Coastguard Worker return -1;
89*49cdfc7eSAndroid Build Coastguard Worker }
90*49cdfc7eSAndroid Build Coastguard Worker data->records[myindex] = rec;
91*49cdfc7eSAndroid Build Coastguard Worker return myindex;
92*49cdfc7eSAndroid Build Coastguard Worker }
93*49cdfc7eSAndroid Build Coastguard Worker
stats_container_resize(stats_container_t * data,long size)94*49cdfc7eSAndroid Build Coastguard Worker int stats_container_resize(stats_container_t * data, long size)
95*49cdfc7eSAndroid Build Coastguard Worker {
96*49cdfc7eSAndroid Build Coastguard Worker stats_record_t *newrecords =
97*49cdfc7eSAndroid Build Coastguard Worker realloc(data->records, size * sizeof(stats_record_t));
98*49cdfc7eSAndroid Build Coastguard Worker if (!newrecords)
99*49cdfc7eSAndroid Build Coastguard Worker return -1;
100*49cdfc7eSAndroid Build Coastguard Worker data->records = newrecords;
101*49cdfc7eSAndroid Build Coastguard Worker if (data->size < size)
102*49cdfc7eSAndroid Build Coastguard Worker memset(data->records + data->size, 0, size - data->size);
103*49cdfc7eSAndroid Build Coastguard Worker data->size = size;
104*49cdfc7eSAndroid Build Coastguard Worker return 0;
105*49cdfc7eSAndroid Build Coastguard Worker }
106*49cdfc7eSAndroid Build Coastguard Worker
stats_container_free(stats_container_t * data)107*49cdfc7eSAndroid Build Coastguard Worker int stats_container_free(stats_container_t * data)
108*49cdfc7eSAndroid Build Coastguard Worker {
109*49cdfc7eSAndroid Build Coastguard Worker free(data->records);
110*49cdfc7eSAndroid Build Coastguard Worker return 0;
111*49cdfc7eSAndroid Build Coastguard Worker }
112*49cdfc7eSAndroid Build Coastguard Worker
stats_sort(stats_container_t * data,enum stats_sort_method method)113*49cdfc7eSAndroid Build Coastguard Worker int stats_sort(stats_container_t * data, enum stats_sort_method method)
114*49cdfc7eSAndroid Build Coastguard Worker {
115*49cdfc7eSAndroid Build Coastguard Worker /* method not implemented, always ascending on y atm */
116*49cdfc7eSAndroid Build Coastguard Worker qsort(data->records, data->index + 1, sizeof(stats_record_t),
117*49cdfc7eSAndroid Build Coastguard Worker stats_record_compare);
118*49cdfc7eSAndroid Build Coastguard Worker return 0;
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker
stats_stddev(stats_container_t * data)121*49cdfc7eSAndroid Build Coastguard Worker float stats_stddev(stats_container_t * data)
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker long i;
124*49cdfc7eSAndroid Build Coastguard Worker float sd, avg, sum, delta;
125*49cdfc7eSAndroid Build Coastguard Worker long n;
126*49cdfc7eSAndroid Build Coastguard Worker
127*49cdfc7eSAndroid Build Coastguard Worker sd = 0.0;
128*49cdfc7eSAndroid Build Coastguard Worker n = data->index + 1;
129*49cdfc7eSAndroid Build Coastguard Worker sum = 0.0;
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker /* calculate the mean */
132*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
133*49cdfc7eSAndroid Build Coastguard Worker sum += data->records[i].y;
134*49cdfc7eSAndroid Build Coastguard Worker }
135*49cdfc7eSAndroid Build Coastguard Worker avg = sum / (float)n;
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker /* calculate the standard deviation */
138*49cdfc7eSAndroid Build Coastguard Worker sum = 0.0;
139*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
140*49cdfc7eSAndroid Build Coastguard Worker delta = (data->records[i].y - avg);
141*49cdfc7eSAndroid Build Coastguard Worker sum += delta * delta;
142*49cdfc7eSAndroid Build Coastguard Worker }
143*49cdfc7eSAndroid Build Coastguard Worker sum /= n;
144*49cdfc7eSAndroid Build Coastguard Worker
145*49cdfc7eSAndroid Build Coastguard Worker sd = sqrt(sum);
146*49cdfc7eSAndroid Build Coastguard Worker
147*49cdfc7eSAndroid Build Coastguard Worker return sd;
148*49cdfc7eSAndroid Build Coastguard Worker }
149*49cdfc7eSAndroid Build Coastguard Worker
stats_avg(stats_container_t * data)150*49cdfc7eSAndroid Build Coastguard Worker float stats_avg(stats_container_t * data)
151*49cdfc7eSAndroid Build Coastguard Worker {
152*49cdfc7eSAndroid Build Coastguard Worker long i;
153*49cdfc7eSAndroid Build Coastguard Worker float avg, sum;
154*49cdfc7eSAndroid Build Coastguard Worker long n;
155*49cdfc7eSAndroid Build Coastguard Worker
156*49cdfc7eSAndroid Build Coastguard Worker n = data->index + 1;
157*49cdfc7eSAndroid Build Coastguard Worker sum = 0.0;
158*49cdfc7eSAndroid Build Coastguard Worker
159*49cdfc7eSAndroid Build Coastguard Worker /* calculate the mean */
160*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
161*49cdfc7eSAndroid Build Coastguard Worker sum += data->records[i].y;
162*49cdfc7eSAndroid Build Coastguard Worker }
163*49cdfc7eSAndroid Build Coastguard Worker avg = sum / (float)n;
164*49cdfc7eSAndroid Build Coastguard Worker
165*49cdfc7eSAndroid Build Coastguard Worker return avg;
166*49cdfc7eSAndroid Build Coastguard Worker }
167*49cdfc7eSAndroid Build Coastguard Worker
stats_min(stats_container_t * data)168*49cdfc7eSAndroid Build Coastguard Worker long stats_min(stats_container_t * data)
169*49cdfc7eSAndroid Build Coastguard Worker {
170*49cdfc7eSAndroid Build Coastguard Worker long i;
171*49cdfc7eSAndroid Build Coastguard Worker long min;
172*49cdfc7eSAndroid Build Coastguard Worker long n;
173*49cdfc7eSAndroid Build Coastguard Worker
174*49cdfc7eSAndroid Build Coastguard Worker n = data->index + 1;
175*49cdfc7eSAndroid Build Coastguard Worker
176*49cdfc7eSAndroid Build Coastguard Worker /* calculate the mean */
177*49cdfc7eSAndroid Build Coastguard Worker min = data->records[0].y;
178*49cdfc7eSAndroid Build Coastguard Worker for (i = 1; i < n; i++) {
179*49cdfc7eSAndroid Build Coastguard Worker if (data->records[i].y < min) {
180*49cdfc7eSAndroid Build Coastguard Worker min = data->records[i].y;
181*49cdfc7eSAndroid Build Coastguard Worker }
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker
184*49cdfc7eSAndroid Build Coastguard Worker return min;
185*49cdfc7eSAndroid Build Coastguard Worker }
186*49cdfc7eSAndroid Build Coastguard Worker
stats_max(stats_container_t * data)187*49cdfc7eSAndroid Build Coastguard Worker long stats_max(stats_container_t * data)
188*49cdfc7eSAndroid Build Coastguard Worker {
189*49cdfc7eSAndroid Build Coastguard Worker long i;
190*49cdfc7eSAndroid Build Coastguard Worker long max;
191*49cdfc7eSAndroid Build Coastguard Worker long n;
192*49cdfc7eSAndroid Build Coastguard Worker
193*49cdfc7eSAndroid Build Coastguard Worker n = data->index + 1;
194*49cdfc7eSAndroid Build Coastguard Worker
195*49cdfc7eSAndroid Build Coastguard Worker /* calculate the mean */
196*49cdfc7eSAndroid Build Coastguard Worker max = data->records[0].y;
197*49cdfc7eSAndroid Build Coastguard Worker for (i = 1; i < n; i++) {
198*49cdfc7eSAndroid Build Coastguard Worker if (data->records[i].y > max) {
199*49cdfc7eSAndroid Build Coastguard Worker max = data->records[i].y;
200*49cdfc7eSAndroid Build Coastguard Worker }
201*49cdfc7eSAndroid Build Coastguard Worker }
202*49cdfc7eSAndroid Build Coastguard Worker
203*49cdfc7eSAndroid Build Coastguard Worker return max;
204*49cdfc7eSAndroid Build Coastguard Worker }
205*49cdfc7eSAndroid Build Coastguard Worker
stats_quantiles_init(stats_quantiles_t * quantiles,int nines)206*49cdfc7eSAndroid Build Coastguard Worker int stats_quantiles_init(stats_quantiles_t * quantiles, int nines)
207*49cdfc7eSAndroid Build Coastguard Worker {
208*49cdfc7eSAndroid Build Coastguard Worker if (nines < 2) {
209*49cdfc7eSAndroid Build Coastguard Worker return -1;
210*49cdfc7eSAndroid Build Coastguard Worker }
211*49cdfc7eSAndroid Build Coastguard Worker quantiles->nines = nines;
212*49cdfc7eSAndroid Build Coastguard Worker /* allocate space for quantiles, starting with 0.99 (two nines) */
213*49cdfc7eSAndroid Build Coastguard Worker quantiles->quantiles = calloc(sizeof(long), (nines - 1));
214*49cdfc7eSAndroid Build Coastguard Worker if (!quantiles->quantiles) {
215*49cdfc7eSAndroid Build Coastguard Worker return -1;
216*49cdfc7eSAndroid Build Coastguard Worker }
217*49cdfc7eSAndroid Build Coastguard Worker return 0;
218*49cdfc7eSAndroid Build Coastguard Worker }
219*49cdfc7eSAndroid Build Coastguard Worker
stats_quantiles_free(stats_quantiles_t * quantiles)220*49cdfc7eSAndroid Build Coastguard Worker int stats_quantiles_free(stats_quantiles_t * quantiles)
221*49cdfc7eSAndroid Build Coastguard Worker {
222*49cdfc7eSAndroid Build Coastguard Worker free(quantiles->quantiles);
223*49cdfc7eSAndroid Build Coastguard Worker return 0;
224*49cdfc7eSAndroid Build Coastguard Worker }
225*49cdfc7eSAndroid Build Coastguard Worker
stats_quantiles_calc(stats_container_t * data,stats_quantiles_t * quantiles)226*49cdfc7eSAndroid Build Coastguard Worker int stats_quantiles_calc(stats_container_t * data,
227*49cdfc7eSAndroid Build Coastguard Worker stats_quantiles_t * quantiles)
228*49cdfc7eSAndroid Build Coastguard Worker {
229*49cdfc7eSAndroid Build Coastguard Worker int i;
230*49cdfc7eSAndroid Build Coastguard Worker int size;
231*49cdfc7eSAndroid Build Coastguard Worker int index;
232*49cdfc7eSAndroid Build Coastguard Worker
233*49cdfc7eSAndroid Build Coastguard Worker // check for sufficient data size of accurate calculation
234*49cdfc7eSAndroid Build Coastguard Worker if (data->index < 0 ||
235*49cdfc7eSAndroid Build Coastguard Worker (data->index + 1) < (long)exp10(quantiles->nines)) {
236*49cdfc7eSAndroid Build Coastguard Worker return -1;
237*49cdfc7eSAndroid Build Coastguard Worker }
238*49cdfc7eSAndroid Build Coastguard Worker
239*49cdfc7eSAndroid Build Coastguard Worker size = data->index + 1;
240*49cdfc7eSAndroid Build Coastguard Worker stats_sort(data, ASCENDING_ON_Y);
241*49cdfc7eSAndroid Build Coastguard Worker
242*49cdfc7eSAndroid Build Coastguard Worker for (i = 2; i <= quantiles->nines; i++) {
243*49cdfc7eSAndroid Build Coastguard Worker index = size - size / exp10(i);
244*49cdfc7eSAndroid Build Coastguard Worker quantiles->quantiles[i - 2] = data->records[index].y;
245*49cdfc7eSAndroid Build Coastguard Worker }
246*49cdfc7eSAndroid Build Coastguard Worker return 0;
247*49cdfc7eSAndroid Build Coastguard Worker }
248*49cdfc7eSAndroid Build Coastguard Worker
stats_quantiles_print(stats_quantiles_t * quantiles)249*49cdfc7eSAndroid Build Coastguard Worker void stats_quantiles_print(stats_quantiles_t * quantiles)
250*49cdfc7eSAndroid Build Coastguard Worker {
251*49cdfc7eSAndroid Build Coastguard Worker int i;
252*49cdfc7eSAndroid Build Coastguard Worker int fraction = 0;
253*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i <= quantiles->nines - 2; i++) {
254*49cdfc7eSAndroid Build Coastguard Worker if (i > 0)
255*49cdfc7eSAndroid Build Coastguard Worker fraction += 9 * exp10(i - 1);
256*49cdfc7eSAndroid Build Coastguard Worker printf("99.%d%% < %ld\n", fraction, quantiles->quantiles[i]);
257*49cdfc7eSAndroid Build Coastguard Worker }
258*49cdfc7eSAndroid Build Coastguard Worker }
259*49cdfc7eSAndroid Build Coastguard Worker
stats_hist(stats_container_t * hist,stats_container_t * data)260*49cdfc7eSAndroid Build Coastguard Worker int stats_hist(stats_container_t * hist, stats_container_t * data)
261*49cdfc7eSAndroid Build Coastguard Worker {
262*49cdfc7eSAndroid Build Coastguard Worker int i;
263*49cdfc7eSAndroid Build Coastguard Worker int ret;
264*49cdfc7eSAndroid Build Coastguard Worker long min, max, width;
265*49cdfc7eSAndroid Build Coastguard Worker long y, b;
266*49cdfc7eSAndroid Build Coastguard Worker
267*49cdfc7eSAndroid Build Coastguard Worker ret = 0;
268*49cdfc7eSAndroid Build Coastguard Worker
269*49cdfc7eSAndroid Build Coastguard Worker if (hist->size <= 0 || data->index < 0) {
270*49cdfc7eSAndroid Build Coastguard Worker return -1;
271*49cdfc7eSAndroid Build Coastguard Worker }
272*49cdfc7eSAndroid Build Coastguard Worker
273*49cdfc7eSAndroid Build Coastguard Worker /* calculate the range of dataset */
274*49cdfc7eSAndroid Build Coastguard Worker min = max = data->records[0].y;
275*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i <= data->index; i++) {
276*49cdfc7eSAndroid Build Coastguard Worker y = data->records[i].y;
277*49cdfc7eSAndroid Build Coastguard Worker if (y > max)
278*49cdfc7eSAndroid Build Coastguard Worker max = y;
279*49cdfc7eSAndroid Build Coastguard Worker if (y < min)
280*49cdfc7eSAndroid Build Coastguard Worker min = y;
281*49cdfc7eSAndroid Build Coastguard Worker }
282*49cdfc7eSAndroid Build Coastguard Worker
283*49cdfc7eSAndroid Build Coastguard Worker /* define the bucket ranges */
284*49cdfc7eSAndroid Build Coastguard Worker width = MAX((max - min) / hist->size, 1);
285*49cdfc7eSAndroid Build Coastguard Worker hist->records[0].x = min;
286*49cdfc7eSAndroid Build Coastguard Worker for (i = 1; i < (hist->size); i++) {
287*49cdfc7eSAndroid Build Coastguard Worker hist->records[i].x = min + i * width;
288*49cdfc7eSAndroid Build Coastguard Worker }
289*49cdfc7eSAndroid Build Coastguard Worker
290*49cdfc7eSAndroid Build Coastguard Worker /* fill in the counts */
291*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i <= data->index; i++) {
292*49cdfc7eSAndroid Build Coastguard Worker y = data->records[i].y;
293*49cdfc7eSAndroid Build Coastguard Worker b = MIN((y - min) / width, hist->size - 1);
294*49cdfc7eSAndroid Build Coastguard Worker hist->records[b].y++;
295*49cdfc7eSAndroid Build Coastguard Worker }
296*49cdfc7eSAndroid Build Coastguard Worker
297*49cdfc7eSAndroid Build Coastguard Worker return 0;
298*49cdfc7eSAndroid Build Coastguard Worker }
299*49cdfc7eSAndroid Build Coastguard Worker
stats_hist_print(stats_container_t * hist)300*49cdfc7eSAndroid Build Coastguard Worker void stats_hist_print(stats_container_t * hist)
301*49cdfc7eSAndroid Build Coastguard Worker {
302*49cdfc7eSAndroid Build Coastguard Worker long i, x;
303*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < hist->size; i++) {
304*49cdfc7eSAndroid Build Coastguard Worker x = hist->records[i].x;
305*49cdfc7eSAndroid Build Coastguard Worker if (i < hist->size - 1)
306*49cdfc7eSAndroid Build Coastguard Worker printf("[%ld,%ld) = %ld\n", x,
307*49cdfc7eSAndroid Build Coastguard Worker hist->records[i + 1].x, hist->records[i].y);
308*49cdfc7eSAndroid Build Coastguard Worker else
309*49cdfc7eSAndroid Build Coastguard Worker printf("[%ld,-) = %ld\n", x, hist->records[i].y);
310*49cdfc7eSAndroid Build Coastguard Worker }
311*49cdfc7eSAndroid Build Coastguard Worker }
312*49cdfc7eSAndroid Build Coastguard Worker
stats_container_save(char * filename,char * title,char * xlabel,char * ylabel,stats_container_t * data,char * mode)313*49cdfc7eSAndroid Build Coastguard Worker int stats_container_save(char *filename, char *title, char *xlabel,
314*49cdfc7eSAndroid Build Coastguard Worker char *ylabel, stats_container_t * data, char *mode)
315*49cdfc7eSAndroid Build Coastguard Worker {
316*49cdfc7eSAndroid Build Coastguard Worker int i;
317*49cdfc7eSAndroid Build Coastguard Worker int minx = 0, maxx = 0, miny = 0, maxy = 0;
318*49cdfc7eSAndroid Build Coastguard Worker FILE *dat_fd;
319*49cdfc7eSAndroid Build Coastguard Worker FILE *plt_fd;
320*49cdfc7eSAndroid Build Coastguard Worker char *datfile;
321*49cdfc7eSAndroid Build Coastguard Worker char *pltfile;
322*49cdfc7eSAndroid Build Coastguard Worker stats_record_t *rec;
323*49cdfc7eSAndroid Build Coastguard Worker
324*49cdfc7eSAndroid Build Coastguard Worker if (!save_stats)
325*49cdfc7eSAndroid Build Coastguard Worker return 0;
326*49cdfc7eSAndroid Build Coastguard Worker
327*49cdfc7eSAndroid Build Coastguard Worker /* generate the filenames */
328*49cdfc7eSAndroid Build Coastguard Worker if (asprintf(&datfile, "%s.dat", filename) == -1) {
329*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
330*49cdfc7eSAndroid Build Coastguard Worker "Failed to allocate string for data filename\n");
331*49cdfc7eSAndroid Build Coastguard Worker return -1;
332*49cdfc7eSAndroid Build Coastguard Worker }
333*49cdfc7eSAndroid Build Coastguard Worker if (asprintf(&pltfile, "%s.plt", filename) == -1) {
334*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
335*49cdfc7eSAndroid Build Coastguard Worker "Failed to allocate string for plot filename\n");
336*49cdfc7eSAndroid Build Coastguard Worker return -1;
337*49cdfc7eSAndroid Build Coastguard Worker }
338*49cdfc7eSAndroid Build Coastguard Worker
339*49cdfc7eSAndroid Build Coastguard Worker /* generate the data file */
340*49cdfc7eSAndroid Build Coastguard Worker if ((dat_fd = fopen(datfile, "w")) == NULL) {
341*49cdfc7eSAndroid Build Coastguard Worker perror("Failed to open dat file");
342*49cdfc7eSAndroid Build Coastguard Worker return -1;
343*49cdfc7eSAndroid Build Coastguard Worker } else {
344*49cdfc7eSAndroid Build Coastguard Worker minx = maxx = data->records[0].x;
345*49cdfc7eSAndroid Build Coastguard Worker miny = maxy = data->records[0].y;
346*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i <= data->index; i++) {
347*49cdfc7eSAndroid Build Coastguard Worker rec = &data->records[i];
348*49cdfc7eSAndroid Build Coastguard Worker minx = MIN(minx, rec->x);
349*49cdfc7eSAndroid Build Coastguard Worker maxx = MAX(maxx, rec->x);
350*49cdfc7eSAndroid Build Coastguard Worker miny = MIN(miny, rec->y);
351*49cdfc7eSAndroid Build Coastguard Worker maxy = MAX(maxy, rec->y);
352*49cdfc7eSAndroid Build Coastguard Worker fprintf(dat_fd, "%ld %ld\n", rec->x, rec->y);
353*49cdfc7eSAndroid Build Coastguard Worker }
354*49cdfc7eSAndroid Build Coastguard Worker fclose(dat_fd);
355*49cdfc7eSAndroid Build Coastguard Worker }
356*49cdfc7eSAndroid Build Coastguard Worker
357*49cdfc7eSAndroid Build Coastguard Worker /* generate the plt file */
358*49cdfc7eSAndroid Build Coastguard Worker if (!(plt_fd = fopen(pltfile, "w"))) {
359*49cdfc7eSAndroid Build Coastguard Worker perror("Failed to open plt file");
360*49cdfc7eSAndroid Build Coastguard Worker return -1;
361*49cdfc7eSAndroid Build Coastguard Worker } else {
362*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "set terminal png\n");
363*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "set output \"%s.png\"\n", pltfile);
364*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "set title \"%s\"\n", title);
365*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "set xlabel \"%s\"\n", xlabel);
366*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "set ylabel \"%s\"\n", ylabel);
367*49cdfc7eSAndroid Build Coastguard Worker fprintf(plt_fd, "plot [0:%d] [0:%d] \"%s\" with %s\n",
368*49cdfc7eSAndroid Build Coastguard Worker maxx + 1, maxy + 1, datfile, mode);
369*49cdfc7eSAndroid Build Coastguard Worker fclose(plt_fd);
370*49cdfc7eSAndroid Build Coastguard Worker }
371*49cdfc7eSAndroid Build Coastguard Worker
372*49cdfc7eSAndroid Build Coastguard Worker return 0;
373*49cdfc7eSAndroid Build Coastguard Worker }
374