Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Histogram
view Histogram.c @ 21:4d9af65ad3df
removed print-to-file hack that wasn't generic and fixed include paths
| author | Some Random Person <seanhalle@yahoo.com> |
|---|---|
| date | Fri, 09 Mar 2012 22:16:40 -0800 |
| parents | f4d96eaf374a |
| children | 6cee2e00eacb |
line source
1 /*
2 * Copyright 2010 OpenSourceStewardshipFoundation.org
3 * Licensed under GNU General Public License version 2
4 *
5 * Author: seanhalle@yahoo.com
6 *
7 */
8 #include <stdio.h>
9 #include "Histogram.h"
12 /*This Histogram Abstract Data Type has a number of bins plus a range of
13 * values that the bins span, both chosen at creation.
14 *
15 *One creates a Histogram instance using the makeHistogram function, then
16 * updates it with the addToHist function, and prints it out with the
17 * printHist function.
18 *
19 *Note, the bin width is an integer, so the end of the range is adjusted
20 * accordingly. Use the bin-width to calculate the bin boundaries.
21 */
24 Histogram *
25 makeHistogram( int32 numBins, int32 startOfRange, int32 endOfRange )
26 {
27 Histogram *hist;
28 int32 i;
31 hist = VMS_int__malloc( sizeof(Histogram) );
32 hist->bins = VMS_int__malloc( numBins * sizeof(int32) );
34 hist->numBins = numBins;
35 hist->binWidth = (endOfRange - startOfRange) / numBins;
36 hist->endOfRange = startOfRange + hist->binWidth * numBins;
37 hist->startOfRange = startOfRange;
39 for( i = 0; i < hist->numBins; i++ )
40 {
41 hist->bins[ i ] = 0;
42 }
44 hist->name = NULL;
45 return hist;
46 }
48 inline void
49 makeHist_helper( Histogram *hist, int32 numBins,
50 int32 startOfRange, int32 binWidth, char *nameCopy )
51 {
52 hist->numBins = numBins;
53 hist->binWidth = binWidth;
54 hist->endOfRange = startOfRange + hist->binWidth * numBins;
55 hist->startOfRange = startOfRange;
56 hist->name = nameCopy;
57 memset( hist->bins, 0, numBins * sizeof(int32) );
58 }
61 Histogram *
62 makeFixedBinHist( int32 numBins, int32 startOfRange, int32 binWidth,
63 char *name )
65 {
66 Histogram *hist;
68 hist = VMS_int__malloc( sizeof(Histogram) );
69 hist->bins = VMS_int__malloc( numBins * sizeof(int32) );
71 makeHist_helper( hist, numBins, startOfRange, binWidth,VMS_int__strDup(name));
73 return hist;
74 }
76 Histogram *
77 makeFixedBinHistExt( int32 numBins, int32 startOfRange, int32 binWidth,
78 char *name )
80 {
81 Histogram *hist;
83 hist = malloc( sizeof(Histogram) );
84 hist->bins = malloc( numBins * sizeof(int32) );
86 makeHist_helper( hist, numBins, startOfRange, binWidth, strdup(name));
88 return hist;
89 }
91 void inline
92 addToHist( int32 value, Histogram *hist )
93 {
94 int32 binIdx;
96 if( value < hist->startOfRange )
97 { binIdx = 0;
98 }
99 else if( value > hist->endOfRange )
100 { binIdx = hist->numBins - 1;
101 }
102 else
103 {
104 binIdx = (value - hist->startOfRange) / hist->binWidth;
105 }
107 hist->bins[ binIdx ] += 1;
108 }
110 void inline
111 subFromHist( int32 value, Histogram *hist )
112 {
113 int32 binIdx;
115 if( value < hist->startOfRange )
116 { binIdx = 0;
117 }
118 else if( value > hist->endOfRange )
119 { binIdx = hist->numBins - 1;
120 }
121 else
122 {
123 binIdx = (value - hist->startOfRange) / hist->binWidth;
124 }
126 hist->bins[ binIdx ] -= 1;
127 }
130 /*Inline because use with RDTSC in innermost code so need ultra-fast
131 */
132 void inline
133 addIntervalToHist( uint32 startIntvl, uint32 endIntvl, Histogram *hist )
134 {
135 int32 value;
137 value = endIntvl - startIntvl;
138 if( value < 0 || value > 10000000 ) return; //sanity check
139 addToHist( value, hist );
140 }
142 void inline
143 subIntervalFromHist( int32 startIntvl, int32 endIntvl, Histogram *hist )
144 {
145 int32 value;
147 value = endIntvl - startIntvl;
148 if( value < 0 || value > 10000000 ) return; //sanity check
149 subFromHist( value, hist );
150 }
152 void
153 saveHistToFile(Histogram *hist)
154 {
155 FILE *output;
156 int32 binIdx, binStart, binEnd, centerValue, width;
157 int32 maxHeight, i,n;
158 float32 total, total2, expectedValue1, expectedValue2;
160 if(hist == NULL || hist->name == NULL)
161 return;
163 //Calculate the average
164 //do all except the top bin
165 maxHeight = 0; total = 0.0; expectedValue1 = 0.0;
166 for( i = 0; i < hist->numBins -1; i++ )
167 {
168 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
169 total += hist->bins[ i ];
170 binStart = hist->startOfRange + hist->binWidth * i;
171 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
172 }
173 //copy and calc expected value minus the top bin
174 expectedValue2 = expectedValue1;
175 expectedValue2 /= total;
176 total2 = total;
177 //now do last iteration, to add the top bin
178 if(maxHeight < hist->bins[ i ])
179 maxHeight = hist->bins[ i ];
180 total += hist->bins[ i ];
181 binStart = hist->startOfRange + hist->binWidth * i;
182 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
184 expectedValue1 /= total;
189 //If a histogram directory does not exist, do not save to file.
190 //TODO change to argument
191 char filename[255];
192 for(n=0;n<255;n++)
193 {
194 sprintf(filename, "./histograms/%s.%d.dat", hist->name,n);
195 output = fopen(filename,"r");
196 if(output)
197 {
198 fclose(output);
199 }else{
200 break;
201 }
202 }
203 printf("Saving Hist to File: %s ...\n", filename);
204 output = fopen(filename,"w+");
205 if(output == NULL){
206 printf("[!]No histogram was saved. To save histograms create folder 'histograms'.\n");
207 return;
208 }
210 fprintf(output, "#\n# Histogram Name: %s\n", hist->name);
211 fprintf(output, "# Expected Values\n");
212 fprintf(output, "#\tnum samples: %d | expected value: %3.2f \n",
213 (int)total, expectedValue1 );
214 fprintf(output, "#\tminus top bin, num samples: %d | expected value: %3.2f \n",
215 (int)total2, expectedValue2 );
216 fprintf(output, "#\n# [Interval] [Center Value] [Count] [relative Count] [Width]\n");
218 for( binIdx = 0; binIdx < hist->numBins; binIdx++ )
219 {
220 binStart = hist->startOfRange + hist->binWidth * binIdx;
221 binEnd = binStart + hist->binWidth - 1;
222 centerValue = (binStart+binEnd)/2;
223 width = (binEnd-binStart)+1;
224 fprintf(output, "%d-%d\t%d\t%d\t%.4f\t%d\n", binStart, binEnd, centerValue,
225 hist->bins[ binIdx ],
226 hist->bins[ binIdx ]/total, width);
227 }
229 fclose(output);
230 fflush(stdout);
231 }
233 void
234 printHist( Histogram *hist )
235 {
236 int32 binIdx, i, numBars, maxHeight, barValue, binStart, binEnd;
237 float32 total, total2, binPercent, expectedValue1, expectedValue2;
239 if( hist == NULL ) return;
241 //do all except the top bin
242 maxHeight = 0; total = 0.0; expectedValue1 = 0.0;
243 for( i = 0; i < hist->numBins -1; i++ )
244 {
245 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
246 total += hist->bins[ i ];
247 binStart = hist->startOfRange + hist->binWidth * i;
248 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
249 }
250 //copy and calc expected value minus the top bin
251 expectedValue2 = expectedValue1;
252 expectedValue2 /= total;
253 total2 = total;
254 //now do last iteration, to add the top bin
255 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
256 total += hist->bins[ i ];
257 binStart = hist->startOfRange + hist->binWidth * i;
258 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
260 expectedValue1 /= total;
262 printf( "histogram: " );
263 if( hist->name != NULL ) printf( "%s\n", hist->name );
264 else printf( "\n" );
265 printf( " num samples: %d | expected value: %3.2f \n",
266 (int)total, expectedValue1 );
267 printf( "minus top bin, num samples: %d | expected value: %3.2f \n",
268 (int)total2, expectedValue2 );
270 if(maxHeight < 60){
271 barValue = 1;
272 printf("Single Bar Value: %i\n", barValue);
273 }else{
274 barValue = maxHeight / 60; //60 spaces across page for tallest bin
275 printf("Single Bar Value: %0.3f\n", (float)maxHeight /60);
276 }
278 if( barValue == 0 ) { printf("error: bar val zero\n"); return; }
279 for( binIdx = 0; binIdx < hist->numBins; binIdx++ )
280 {
281 binStart = hist->startOfRange + hist->binWidth * binIdx;
282 binEnd = binStart + hist->binWidth - 1;
283 binPercent = 100 * hist->bins[ binIdx ] / total;
284 printf("bin range: %d - %d | %3.2f", binStart, binEnd, binPercent );
286 numBars = hist->bins[ binIdx ] / barValue;
287 //print one bin, height of bar is num dashes across page
288 for( i = 0; i < numBars; i++ )
289 {
290 printf("-");
291 }
292 printf("\n");
293 }
294 }
296 void
297 freeHist( Histogram *hist )
298 {
299 VMS_int__free( hist->bins );
300 VMS_int__free( hist->name );
301 VMS_int__free( hist );
302 }
303 void
304 freeHistExt( Histogram *hist )
305 {
306 free( hist->bins );
307 free( hist->name );
308 free( hist );
309 }
