Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Histogram
view Histogram.c @ 8:c83c27796fad
Added sub from hist, added "total" to print and return when bar is zero
| author | Me |
|---|---|
| date | Sat, 20 Nov 2010 08:41:39 +0100 |
| parents | fa6a281bd854 |
| children | 060d63cb5d34 |
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"
10 #include "../vutilities.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 )
28 {
29 Histogram *hist;
30 int32 i;
33 hist = VMS__malloc( sizeof(Histogram) );
34 hist->bins = VMS__malloc( numBins * sizeof(int32) );
36 hist->numBins = numBins;
37 hist->binWidth = (endOfRange - startOfRange) / numBins;
38 hist->endOfRange = startOfRange + hist->binWidth * numBins;
39 hist->startOfRange = startOfRange;
41 for( i = 0; i < hist->numBins; i++ )
42 {
43 hist->bins[ i ] = 0;
44 }
46 hist->name = NULL;
47 return hist;
48 }
50 inline void
51 makeHist_helper( Histogram *hist, int32 numBins,
52 int32 startOfRange, int32 binWidth, char *nameCopy )
53 {
54 hist->numBins = numBins;
55 hist->binWidth = binWidth;
56 hist->endOfRange = startOfRange + hist->binWidth * numBins;
57 hist->startOfRange = startOfRange;
58 hist->name = nameCopy;
59 memset( hist->bins, 0, numBins * sizeof(int32) );
60 }
63 Histogram *
64 makeFixedBinHist( int32 numBins, int32 startOfRange, int32 binWidth,
65 char *name )
67 {
68 Histogram *hist;
70 hist = VMS__malloc( sizeof(Histogram) );
71 hist->bins = VMS__malloc( numBins * sizeof(int32) );
73 makeHist_helper( hist, numBins, startOfRange, binWidth,VMS__strDup(name));
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( int32 startIntvl, int32 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 printHist( Histogram *hist )
156 {
157 int32 binIdx, i, numBars, maxHeight, barValue, binStart, binEnd;
158 float32 total, total2, binPercent, expectedValue1, expectedValue2;
160 if( hist == NULL ) return;
162 //do all except the top bin
163 maxHeight = 0; total = 0.0; expectedValue1 = 0.0;
164 for( i = 0; i < hist->numBins -1; i++ )
165 {
166 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
167 total += hist->bins[ i ];
168 binStart = hist->startOfRange + hist->binWidth * i;
169 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
170 }
171 //copy and calc expected value minus the top bin
172 expectedValue2 = expectedValue1;
173 expectedValue2 /= total;
174 total2 = total;
175 //now do last iteration, to add the top bin
176 if( maxHeight < hist->bins[ i ] ) maxHeight = hist->bins[ i ];
177 total += hist->bins[ i ];
178 binStart = hist->startOfRange + hist->binWidth * i;
179 expectedValue1 += hist->bins[ i ] * (binStart + hist->binWidth/2.0);
181 expectedValue1 /= total;
183 barValue = maxHeight / 60; //60 spaces across page for tallest bin
185 printf( "histogram: " );
186 if( hist->name != NULL ) printf( "%s\n", hist->name );
187 else printf( "\n" );
188 printf( " num samples: %d | expected value: %3.2f \n",
189 (int)total, expectedValue1 );
190 printf( "minus top bin, num samples: %d | expected value: %3.2f \n",
191 (int)total2, expectedValue2 );
193 if( barValue == 0 ) { printf("error: bar val zero\n"); return; }
194 for( binIdx = 0; binIdx < hist->numBins; binIdx++ )
195 {
196 binStart = hist->startOfRange + hist->binWidth * binIdx;
197 binEnd = binStart + hist->binWidth - 1;
198 binPercent = 100 * hist->bins[ binIdx ] / total;
199 printf("bin range: %d - %d | %3.2f", binStart, binEnd, binPercent );
201 numBars = hist->bins[ binIdx ] / barValue;
202 //print one bin, height of bar is num dashes across page
203 for( i = 0; i < numBars; i++ )
204 {
205 printf("-");
206 }
207 printf("\n");
208 }
209 }
211 void
212 freeHist( Histogram *hist )
213 {
214 VMS__free( hist->bins );
215 VMS__free( hist->name );
216 VMS__free( hist );
217 }
218 void
219 freeHistExt( Histogram *hist )
220 {
221 free( hist->bins );
222 free( hist->name );
223 free( hist );
224 }
