view Histogram.c @ 31:84601ecae690

Renamed VMS to PR, in new branch
author Sean Halle <seanhalle@yahoo.com>
date Fri, 08 Mar 2013 05:43:19 -0800
parents 5d1597d9b24a
children 8166ea441cb5
line source
1 /*
2 * Copyright 2010 OpenSourceResearchInstitute.org
3 * Licensed under GNU General Public License version 2
4 *
5 * Author: seanhalle@yahoo.com
6 *
7 */
8 #include <stdio.h>
9 #include <string.h>
10 #include "Histogram.h"
13 /*This Histogram Abstract Data Type has a number of bins plus a range of
14 * values that the bins span, both chosen at creation.
15 *
16 *One creates a Histogram instance using the makeHistogram function, then
17 * updates it with the addToHist function, and prints it out with the
18 * printHist function.
19 *
20 *Note, the bin width is an integer, so the end of the range is adjusted
21 * accordingly. Use the bin-width to calculate the bin boundaries.
22 */
25 Histogram *
26 makeHistogram( int32 numBins, int32 startOfRange, int32 endOfRange )
27 {
28 Histogram *hist;
29 int32 i;
32 hist = PR_int__malloc( sizeof(Histogram) );
33 hist->bins = PR_int__malloc( numBins * sizeof(int32) );
35 hist->numBins = numBins;
36 hist->binWidth = (endOfRange - startOfRange) / numBins;
37 hist->endOfRange = startOfRange + hist->binWidth * numBins;
38 hist->startOfRange = startOfRange;
40 for( i = 0; i < hist->numBins; i++ )
41 {
42 hist->bins[ i ] = 0;
43 }
45 hist->name = NULL;
46 return hist;
47 }
49 inline void
50 makeHist_helper( Histogram *hist, int32 numBins,
51 int32 startOfRange, int32 binWidth, char *nameCopy )
52 {
53 hist->numBins = numBins;
54 hist->binWidth = binWidth;
55 hist->endOfRange = startOfRange + hist->binWidth * numBins;
56 hist->startOfRange = startOfRange;
57 hist->name = nameCopy;
58 memset( hist->bins, 0, numBins * sizeof(int32) );
59 }
62 Histogram *
63 makeFixedBinHist( int32 numBins, int32 startOfRange, int32 binWidth,
64 char *name )
66 {
67 Histogram *hist;
69 hist = PR_int__malloc( sizeof(Histogram) );
70 hist->bins = PR_int__malloc( numBins * sizeof(int32) );
72 char *nameCopy = (char *)PR_int__strDup(name);
73 makeHist_helper( hist, numBins, startOfRange, binWidth, nameCopy);
75 return hist;
76 }
78 Histogram *
79 makeFixedBinHistExt( int32 numBins, int32 startOfRange, int32 binWidth,
80 char *name )
82 {
83 Histogram *hist;
85 hist = malloc( sizeof(Histogram) );
86 hist->bins = malloc( numBins * sizeof(int32) );
88 makeHist_helper( hist, numBins, startOfRange, binWidth, strdup(name));
90 return hist;
91 }
93 void inline
94 addToHist( int32 value, Histogram *hist )
95 {
96 int32 binIdx;
98 if( value < hist->startOfRange )
99 { binIdx = 0;
100 }
101 else if( value > hist->endOfRange )
102 { binIdx = hist->numBins - 1;
103 }
104 else
105 {
106 binIdx = (value - hist->startOfRange) / hist->binWidth;
107 }
109 hist->bins[ binIdx ] += 1;
110 }
112 void inline
113 subFromHist( int32 value, Histogram *hist )
114 {
115 int32 binIdx;
117 if( value < hist->startOfRange )
118 { binIdx = 0;
119 }
120 else if( value > hist->endOfRange )
121 { binIdx = hist->numBins - 1;
122 }
123 else
124 {
125 binIdx = (value - hist->startOfRange) / hist->binWidth;
126 }
128 hist->bins[ binIdx ] -= 1;
129 }
132 /*Inline because use with RDTSC in innermost code so need ultra-fast
133 */
134 void inline
135 addIntervalToHist( uint32 startIntvl, uint32 endIntvl, Histogram *hist )
136 {
137 int32 value;
139 value = endIntvl - startIntvl;
140 if( value < 0 || value > 10000000 ) return; //sanity check
141 addToHist( value, hist );
142 }
144 void inline
145 subIntervalFromHist( int32 startIntvl, int32 endIntvl, Histogram *hist )
146 {
147 int32 value;
149 value = endIntvl - startIntvl;
150 if( value < 0 || value > 10000000 ) return; //sanity check
151 subFromHist( value, hist );
152 }
154 void
155 saveHistToFile(Histogram *hist)
156 {
157 FILE *output;
158 int32 binIdx, binStart, binEnd, centerValue, width;
159 int32 maxHeight, i,n;
160 float32 total, total2, expectedValue1, expectedValue2;
162 if(hist == NULL || hist->name == NULL)
163 return;
165 //Calculate the average
166 //do all except the top bin
167 maxHeight = 0; total = 0.0; expectedValue1 = 0.0;
168 for( i = 0; i < hist->numBins -1; i++ )
169 {
170 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
171 total += hist->bins[ i ];
172 binStart = hist->startOfRange + hist->binWidth * i;
173 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
174 }
175 //copy and calc expected value minus the top bin
176 expectedValue2 = expectedValue1;
177 expectedValue2 /= total;
178 total2 = total;
179 //now do last iteration, to add the top bin
180 if(maxHeight < hist->bins[ i ])
181 maxHeight = hist->bins[ i ];
182 total += hist->bins[ i ];
183 binStart = hist->startOfRange + hist->binWidth * i;
184 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
186 expectedValue1 /= total;
191 //If a histogram directory does not exist, do not save to file.
192 //TODO change to argument
193 char filename[255];
194 for(n=0;n<255;n++)
195 {
196 sprintf(filename, "./histograms/%s.%d.dat", hist->name,n);
197 output = fopen(filename,"r");
198 if(output)
199 {
200 fclose(output);
201 }else{
202 break;
203 }
204 }
205 printf("Saving Hist to File: %s ...\n", filename);
206 output = fopen(filename,"w+");
207 if(output == NULL){
208 printf("[!]No histogram was saved. To save histograms create folder 'histograms'.\n");
209 return;
210 }
212 fprintf(output, "#\n# Histogram Name: %s\n", hist->name);
213 fprintf(output, "# Expected Values\n");
214 fprintf(output, "#\tnum samples: %d | expected value: %3.2f \n",
215 (int)total, expectedValue1 );
216 fprintf(output, "#\tminus top bin, num samples: %d | expected value: %3.2f \n",
217 (int)total2, expectedValue2 );
218 fprintf(output, "#\n# [Interval] [Center Value] [Count] [relative Count] [Width]\n");
220 for( binIdx = 0; binIdx < hist->numBins; binIdx++ )
221 {
222 binStart = hist->startOfRange + hist->binWidth * binIdx;
223 binEnd = binStart + hist->binWidth - 1;
224 centerValue = (binStart+binEnd)/2;
225 width = (binEnd-binStart)+1;
226 fprintf(output, "%d-%d\t%d\t%d\t%.4f\t%d\n", binStart, binEnd, centerValue,
227 hist->bins[ binIdx ],
228 hist->bins[ binIdx ]/total, width);
229 }
231 fclose(output);
232 fflush(stdout);
233 }
235 void
236 printHist( Histogram *hist )
237 {
238 int32 binIdx, i, numBars, maxHeight, barValue, binStart, binEnd;
239 float32 total, total2, binPercent, expectedValue1, expectedValue2;
241 if( hist == NULL ) return;
243 //do all except the top bin
244 maxHeight = 0; total = 0.0; expectedValue1 = 0.0;
245 for( i = 0; i < hist->numBins -1; i++ )
246 {
247 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
248 total += hist->bins[ i ];
249 binStart = hist->startOfRange + hist->binWidth * i;
250 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
251 }
252 //copy and calc expected value minus the top bin
253 expectedValue2 = expectedValue1;
254 expectedValue2 /= total;
255 total2 = total;
256 //now do last iteration, to add the top bin
257 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
258 total += hist->bins[ i ];
259 binStart = hist->startOfRange + hist->binWidth * i;
260 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
262 expectedValue1 /= total;
264 printf( "histogram: " );
265 if( hist->name != NULL ) printf( "%s\n", hist->name );
266 else printf( "\n" );
267 printf( " num samples: %d | expected value: %3.2f \n",
268 (int)total, expectedValue1 );
269 printf( "minus top bin, num samples: %d | expected value: %3.2f \n",
270 (int)total2, expectedValue2 );
272 if(maxHeight < 60){
273 barValue = 1;
274 printf("Single Bar Value: %i\n", barValue);
275 }else{
276 barValue = maxHeight / 60; //60 spaces across page for tallest bin
277 printf("Single Bar Value: %0.3f\n", (float)maxHeight /60);
278 }
280 if( barValue == 0 ) { printf("error: bar val zero\n"); return; }
281 for( binIdx = 0; binIdx < hist->numBins; binIdx++ )
282 {
283 binStart = hist->startOfRange + hist->binWidth * binIdx;
284 binEnd = binStart + hist->binWidth - 1;
285 binPercent = 100 * hist->bins[ binIdx ] / total;
286 printf("bin range: %d - %d | %3.2f", binStart, binEnd, binPercent );
288 numBars = hist->bins[ binIdx ] / barValue;
289 //print one bin, height of bar is num dashes across page
290 for( i = 0; i < numBars; i++ )
291 {
292 printf("-");
293 }
294 printf("\n");
295 }
296 }
298 void
299 freeHist( Histogram *hist )
300 {
301 PR_int__free( hist->bins );
302 PR_int__free( hist->name );
303 PR_int__free( hist );
304 }
305 void
306 freeHistExt( Histogram *hist )
307 {
308 free( hist->bins );
309 free( hist->name );
310 free( hist );
311 }