xref: /aosp_15_r20/external/ltp/testcases/realtime/lib/libstats.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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