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