#include <Stats.h>
Collaboration diagram for ACE_Stats:
Public Member Functions | |
ACE_Stats (void) | |
Default constructor. | |
int | sample (const ACE_INT32 value) |
ACE_UINT32 | samples (void) const |
Access the number of samples provided so far. | |
ACE_INT32 | min_value (void) const |
Value of the minimum sample provided so far. | |
ACE_INT32 | max_value (void) const |
Value of the maximum sample provided so far. | |
void | mean (ACE_Stats_Value &mean, const ACE_UINT32 scale_factor=1) |
int | std_dev (ACE_Stats_Value &std_dev, const ACE_UINT32 scale_factor=1) |
int | print_summary (const u_int precision, const ACE_UINT32 scale_factor=1, FILE *=stdout) const |
void | reset (void) |
Initialize internal state. | |
void | dump (void) const |
Print summary statistics to stdout. | |
Static Public Member Functions | |
void | quotient (const ACE_UINT64 dividend, const ACE_UINT32 divisor, ACE_Stats_Value "ient) |
Utility division function, for ACE_UINT64 dividend. | |
void | quotient (const ACE_Stats_Value ÷nd, const ACE_UINT32 divisor, ACE_Stats_Value "ient) |
Utility division function, for ACE_Stats_Value dividend. | |
void | square_root (const ACE_UINT64 n, ACE_Stats_Value &square_root) |
Protected Attributes | |
u_int | overflow_ |
ACE_UINT32 | number_of_samples_ |
Number of samples. | |
ACE_INT32 | min_ |
Minimum sample value. | |
ACE_INT32 | max_ |
Maximum sample value. | |
ACE_Unbounded_Queue< ACE_INT32 > | samples_ |
The samples. |
Simple statistical analysis package. Prominent features are:
Example usage:
* ACE_Stats stats; * for (u_int i = 0; i < n; ++i) * { * const ACE_UINT32 sample = ...; * stats.sample (sample); * } * stats.print_summary (3); *
Definition at line 129 of file Stats.h.
|
Default constructor.
Definition at line 69 of file Stats.inl. References reset().
00070 { 00071 reset (); 00072 } |
|
Print summary statistics to stdout.
Definition at line 97 of file Stats.inl. References print_summary().
00098 { 00099 #if defined (ACE_HAS_DUMP) 00100 print_summary (3u); 00101 #endif /* ACE_HAS_DUMP */ 00102 } |
|
Value of the maximum sample provided so far.
Definition at line 90 of file Stats.inl.
00091 { 00092 return max_; 00093 } |
|
Access the mean of all samples provided so far. The fractional part is to the specified number of digits. E.g., 3 fractional digits specifies that the fractional part is in thousandths. Definition at line 66 of file Stats.cpp. References ACE_UINT64, ACE_UINT64_LITERAL, ACE_Unbounded_Queue_Iterator< T >::advance(), ACE_Unbounded_Queue_Iterator< T >::done(), ACE_Stats_Value::fractional(), ACE_Unbounded_Queue_Iterator< T >::next(), number_of_samples_, quotient(), and ACE_Stats_Value::whole(). Referenced by ACE_High_Res_Timer::calibrate(), and std_dev().
00068 { 00069 if (number_of_samples_ > 0) 00070 { 00071 #if defined ACE_LACKS_LONGLONG_T 00072 // If ACE_LACKS_LONGLONG_T, then ACE_UINT64 is a user-defined class. 00073 // To prevent having to construct a static of that class, declare it 00074 // on the stack, and construct it, in each function that needs it. 00075 const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8); 00076 #else /* ! ACE_LACKS_LONGLONG_T */ 00077 const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET = 00078 ACE_UINT64_LITERAL (0x100000000); 00079 #endif /* ! ACE_LACKS_LONGLONG_T */ 00080 00081 ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET; 00082 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_); 00083 while (! i.done ()) 00084 { 00085 ACE_INT32 *sample; 00086 if (i.next (sample)) 00087 { 00088 sum += *sample; 00089 i.advance (); 00090 } 00091 } 00092 00093 // sum_ was initialized with ACE_STATS_INTERNAL_OFFSET, so 00094 // subtract that off here. 00095 quotient (sum - ACE_STATS_INTERNAL_OFFSET, 00096 number_of_samples_ * scale_factor, 00097 m); 00098 } 00099 else 00100 { 00101 m.whole (0); 00102 m.fractional (0); 00103 } 00104 } |
|
Value of the minimum sample provided so far.
Definition at line 83 of file Stats.inl.
00084 { 00085 return min_; 00086 } |
|
Print summary statistics. If scale_factor is not 1, then the results are divided by it, i.e., each of the samples is scaled down by it. If internal overflow is reached with the specified scale factor, it successively tries to reduce it. Returns -1 if there is overflow even with a 0 scale factor. Definition at line 212 of file Stats.cpp. References ACE_TCHAR, ACE_TEXT, ACE_UINT64, ACE_OS::fprintf(), ACE_Stats_Value::fractional(), overflow_, quotient(), samples(), ACE_OS::sprintf(), and ACE_Stats_Value::whole(). Referenced by dump().
00215 { 00216 ACE_TCHAR mean_string [128]; 00217 ACE_TCHAR std_dev_string [128]; 00218 ACE_TCHAR min_string [128]; 00219 ACE_TCHAR max_string [128]; 00220 int success = 0; 00221 00222 for (int tmp_precision = precision; 00223 ! overflow_ && ! success && tmp_precision >= 0; 00224 --tmp_precision) 00225 { 00226 // Build a format string, in case the C library doesn't support %*u. 00227 ACE_TCHAR format[32]; 00228 if (tmp_precision == 0) 00229 ACE_OS::sprintf (format, ACE_TEXT ("%%%d"), tmp_precision); 00230 else 00231 ACE_OS::sprintf (format, ACE_TEXT ("%%d.%%0%du"), tmp_precision); 00232 00233 ACE_Stats_Value u (tmp_precision); 00234 ((ACE_Stats *) this)->mean (u, scale_factor); 00235 ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ()); 00236 00237 ACE_Stats_Value sd (tmp_precision); 00238 if (((ACE_Stats *) this)->std_dev (sd, scale_factor)) 00239 { 00240 success = 0; 00241 continue; 00242 } 00243 else 00244 { 00245 success = 1; 00246 } 00247 ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ()); 00248 00249 ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision); 00250 if (min_ != 0) 00251 { 00252 const ACE_UINT64 m (min_); 00253 quotient (m, scale_factor, minimum); 00254 } 00255 if (max_ != 0) 00256 { 00257 const ACE_UINT64 m (max_); 00258 quotient (m, scale_factor, maximum); 00259 } 00260 ACE_OS::sprintf (min_string, format, 00261 minimum.whole (), minimum.fractional ()); 00262 ACE_OS::sprintf (max_string, format, 00263 maximum.whole (), maximum.fractional ()); 00264 } 00265 00266 if (success == 1) 00267 { 00268 ACE_OS::fprintf (file, ACE_TEXT ("samples: %u (%s - %s); mean: ") 00269 ACE_TEXT ("%s; std dev: %s\n"), 00270 samples (), min_string, max_string, 00271 mean_string, std_dev_string); 00272 return 0; 00273 } 00274 else 00275 { 00276 #if !defined (ACE_HAS_WINCE) 00277 ACE_OS::fprintf (file, 00278 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"), 00279 ACE_OS::strerror (overflow_)); 00280 #else 00281 // WinCE doesn't have strerror ;( 00282 ACE_OS::fprintf (file, 00283 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW\n")); 00284 #endif /* ACE_HAS_WINCE */ 00285 return -1; 00286 } 00287 } |
|
Utility division function, for ACE_Stats_Value dividend.
Definition at line 321 of file Stats.cpp. References ACE_Stats_Value::fractional(), ACE_Stats_Value::fractional_field(), ACE_Stats_Value::precision(), and ACE_Stats_Value::whole().
00324 { 00325 // The whole part of the division comes from simple integer division. 00326 quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor); 00327 00328 if (quotient.precision () > 0 || divisor == 0) 00329 { 00330 const ACE_UINT32 field = quotient.fractional_field (); 00331 00332 // Fractional = (dividend % divisor) * 10^precision / divisor. 00333 quotient.fractional (dividend.whole () % divisor * field / divisor + 00334 dividend.fractional () / divisor); 00335 } 00336 else 00337 { 00338 // No fractional portion is requested, so don't bother 00339 // calculating it. 00340 quotient.fractional (0); 00341 } 00342 } |
|
Utility division function, for ACE_UINT64 dividend.
Definition at line 290 of file Stats.cpp. References ACE_UINT64, ACE_Stats_Value::fractional(), ACE_Stats_Value::fractional_field(), ACE_Stats_Value::precision(), and ACE_Stats_Value::whole(). Referenced by mean(), print_summary(), and std_dev().
00293 { 00294 // The whole part of the division comes from simple integer division. 00295 quotient.whole (static_cast<ACE_UINT32> (divisor == 0 00296 ? 0 : dividend / divisor)); 00297 00298 if (quotient.precision () > 0 || divisor == 0) 00299 { 00300 const ACE_UINT32 field = quotient.fractional_field (); 00301 00302 // Fractional = (dividend % divisor) * 10^precision / divisor 00303 00304 // It would be nice to add round-up term: 00305 // Fractional = (dividend % divisor) * 10^precision / divisor + 00306 // 10^precision/2 / 10^precision 00307 // = ((dividend % divisor) * 10^precision + divisor) / 00308 // divisor 00309 quotient.fractional (static_cast<ACE_UINT32> ( 00310 dividend % divisor * field / divisor)); 00311 } 00312 else 00313 { 00314 // No fractional portion is requested, so don't bother 00315 // calculating it. 00316 quotient.fractional (0); 00317 } 00318 } |
|
Initialize internal state.
Definition at line 202 of file Stats.cpp. References number_of_samples_, overflow_, and ACE_Unbounded_Queue< ACE_INT32 >::reset(). Referenced by ACE_Stats().
|
|
Provide a new sample. Returns 0 on success, -1 if it fails due to running out of memory, or to rolling over of the sample count. Definition at line 36 of file Stats.cpp. References ACE_Unbounded_Queue< ACE_INT32 >::enqueue_tail(), number_of_samples_, and overflow_. Referenced by ACE_High_Res_Timer::calibrate().
00037 { 00038 if (samples_.enqueue_tail (value) == 0) 00039 { 00040 ++number_of_samples_; 00041 if (number_of_samples_ == 0) 00042 { 00043 // That's a lot of samples :-) 00044 overflow_ = EFAULT; 00045 return -1; 00046 } 00047 00048 if (value < min_) 00049 min_ = value; 00050 00051 if (value > max_) 00052 max_ = value; 00053 00054 return 0; 00055 } 00056 else 00057 { 00058 // Probably failed due to running out of memory when trying to 00059 // enqueue the new value. 00060 overflow_ = errno; 00061 return -1; 00062 } 00063 } |
|
Access the number of samples provided so far.
Definition at line 76 of file Stats.inl. References number_of_samples_. Referenced by print_summary().
00077 { 00078 return number_of_samples_; 00079 } |
|
Sqrt function, which uses an oversimplified version of Newton's method. It's not fast, but it doesn't require floating point support. Definition at line 345 of file Stats.cpp. References ACE_UINT64, ACE_Stats_Value::fractional(), ACE_Stats_Value::fractional_field(), ACE_Stats_Value::precision(), and ACE_Stats_Value::whole(). Referenced by std_dev().
00347 { 00348 ACE_UINT32 floor = 0; 00349 ACE_UINT32 ceiling = 0xFFFFFFFFu; 00350 ACE_UINT32 mid = 0; 00351 u_int i; 00352 00353 // The maximum number of iterations is log_2 (2^64) == 64. 00354 for (i = 0; i < 64; ++i) 00355 { 00356 mid = (ceiling - floor) / 2 + floor; 00357 if (floor == mid) 00358 // Can't divide the interval any further. 00359 break; 00360 else 00361 { 00362 // Multiply carefully to avoid overflow. 00363 ACE_UINT64 mid_squared = mid; mid_squared *= mid; 00364 if (mid_squared == n) 00365 break; 00366 else if (mid_squared < n) 00367 floor = mid; 00368 else 00369 ceiling = mid; 00370 } 00371 } 00372 00373 square_root.whole (mid); 00374 ACE_UINT64 mid_squared = mid; mid_squared *= mid; 00375 00376 if (square_root.precision () && mid_squared < n) 00377 { 00378 // (mid * 10^precision + fractional)^2 == 00379 // n^2 * 10^(precision * 2) 00380 00381 const ACE_UINT32 field = square_root.fractional_field (); 00382 00383 floor = 0; 00384 ceiling = field; 00385 mid = 0; 00386 00387 // Do the 64-bit arithmetic carefully to avoid overflow. 00388 ACE_UINT64 target = n; 00389 target *= field; 00390 target *= field; 00391 00392 ACE_UINT64 difference = 0; 00393 00394 for (i = 0; i < square_root.precision (); ++i) 00395 { 00396 mid = (ceiling - floor) / 2 + floor; 00397 00398 ACE_UINT64 current = square_root.whole () * field + mid; 00399 current *= square_root.whole () * field + mid; 00400 00401 if (floor == mid) 00402 { 00403 difference = target - current; 00404 break; 00405 } 00406 else if (current <= target) 00407 floor = mid; 00408 else 00409 ceiling = mid; 00410 } 00411 00412 // Check to see if the fractional part should be one greater. 00413 ACE_UINT64 next = square_root.whole () * field + mid + 1; 00414 next *= square_root.whole () * field + mid + 1; 00415 00416 square_root.fractional (next - target < difference ? mid + 1 : mid); 00417 } 00418 else 00419 { 00420 // No fractional portion is requested, so don't bother 00421 // calculating it. 00422 square_root.fractional (0); 00423 } 00424 } |
|
Access the standard deviation, whole and fractional parts. See description of {mean} method for argument descriptions. Definition at line 107 of file Stats.cpp. References ACE_UINT64, ACE_Unbounded_Queue_Iterator< T >::advance(), ACE_Unbounded_Queue_Iterator< T >::done(), ACE_Stats_Value::fractional(), ACE_Stats_Value::fractional_field(), mean(), ACE_Unbounded_Queue_Iterator< T >::next(), number_of_samples_, overflow_, ACE_Stats_Value::precision(), quotient(), ACE_Stats_Value::scaled_value(), square_root(), and ACE_Stats_Value::whole().
00109 { 00110 if (number_of_samples_ <= 1) 00111 { 00112 std_dev.whole (0); 00113 std_dev.fractional (0); 00114 } 00115 else 00116 { 00117 const ACE_UINT32 field = std_dev.fractional_field (); 00118 00119 // The sample standard deviation is: 00120 // 00121 // sqrt (sum (sample_i - mean)^2 / (number_of_samples_ - 1)) 00122 00123 ACE_UINT64 mean_scaled; 00124 // Calculate the mean, scaled, so that we don't lose its 00125 // precision. 00126 ACE_Stats_Value avg (std_dev.precision ()); 00127 mean (avg, 1u); 00128 avg.scaled_value (mean_scaled); 00129 00130 // Calculate the summation term, of squared differences from the 00131 // mean. 00132 ACE_UINT64 sum_of_squares = 0; 00133 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_); 00134 while (! i.done ()) 00135 { 00136 ACE_INT32 *sample; 00137 if (i.next (sample)) 00138 { 00139 const ACE_UINT64 original_sum_of_squares = sum_of_squares; 00140 00141 // Scale up by field width so that we don't lose the 00142 // precision of the mean. Carefully . . . 00143 const ACE_UINT64 product (*sample * field); 00144 00145 ACE_UINT64 difference; 00146 // NOTE: please do not reformat this code! It // 00147 // works with the Diab compiler the way it is! // 00148 if (product >= mean_scaled) // 00149 { // 00150 difference = product - mean_scaled; // 00151 } // 00152 else // 00153 { // 00154 difference = mean_scaled - product; // 00155 } // 00156 // NOTE: please do not reformat this code! It // 00157 // works with the Diab compiler the way it is! // 00158 00159 // Square using 64-bit arithmetic. 00160 sum_of_squares += difference * ACE_U64_TO_U32 (difference); 00161 i.advance (); 00162 00163 if (sum_of_squares < original_sum_of_squares) 00164 { 00165 overflow_ = ENOSPC; 00166 return -1; 00167 } 00168 } 00169 } 00170 00171 // Divide the summation by (number_of_samples_ - 1), to get the 00172 // variance. In addition, scale the variance down to undo the 00173 // mean scaling above. Otherwise, it can get too big. 00174 ACE_Stats_Value variance (std_dev.precision ()); 00175 quotient (sum_of_squares, 00176 (number_of_samples_ - 1) * field * field, 00177 variance); 00178 00179 // Take the square root of the variance to get the standard 00180 // deviation. First, scale up . . . 00181 ACE_UINT64 scaled_variance; 00182 variance.scaled_value (scaled_variance); 00183 00184 // And scale up, once more, because we'll be taking the square 00185 // root. 00186 scaled_variance *= field; 00187 ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ()); 00188 square_root (scaled_variance, 00189 unscaled_standard_deviation); 00190 00191 // Unscale. 00192 quotient (unscaled_standard_deviation, 00193 scale_factor * field, 00194 std_dev); 00195 } 00196 00197 return 0; 00198 } |
|
Maximum sample value.
|
|
Minimum sample value.
|
|
Number of samples.
Definition at line 202 of file Stats.h. Referenced by mean(), reset(), sample(), samples(), and std_dev(). |
|
Internal indication of whether there has been overflow. Contains the errno corresponding to the cause of overflow. Definition at line 199 of file Stats.h. Referenced by print_summary(), reset(), sample(), and std_dev(). |
|
The samples.
|