ACE_Stats Class Reference

Provides simple statistical analysis. More...

#include <Stats.h>

Collaboration diagram for ACE_Stats:

Collaboration graph
[legend]
List of all members.

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 &quotient)
 Utility division function, for ACE_UINT64 dividend.

void quotient (const ACE_Stats_Value &dividend, const ACE_UINT32 divisor, ACE_Stats_Value &quotient)
 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.


Detailed Description

Provides simple statistical analysis.

Simple statistical analysis package. Prominent features are:

  1. It does not use any floating point arithmetic.
  2. It handles positive and/or negative sample values. The sample value type is ACE_INT32.
  3. It uses 64 bit unsigned, but not 64 bit signed, quantities internally.
  4. It checks for overflow of internal state.
  5. It has no static variables of other than built-in types.

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.


Constructor & Destructor Documentation

ACE_INLINE ACE_Stats::ACE_Stats void   ) 
 

Default constructor.

Definition at line 69 of file Stats.inl.

References reset().

00070 {
00071   reset ();
00072 }


Member Function Documentation

ACE_INLINE void ACE_Stats::dump void   )  const
 

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 }

ACE_INLINE ACE_INT32 ACE_Stats::max_value void   )  const
 

Value of the maximum sample provided so far.

Definition at line 90 of file Stats.inl.

00091 {
00092   return max_;
00093 }

void ACE_Stats::mean ACE_Stats_Value mean,
const ACE_UINT32  scale_factor = 1
 

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 }

ACE_INLINE ACE_INT32 ACE_Stats::min_value void   )  const
 

Value of the minimum sample provided so far.

Definition at line 83 of file Stats.inl.

00084 {
00085   return min_;
00086 }

int ACE_Stats::print_summary const u_int  precision,
const ACE_UINT32  scale_factor = 1,
FILE *  = stdout
const
 

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 }

void ACE_Stats::quotient const ACE_Stats_Value dividend,
const ACE_UINT32  divisor,
ACE_Stats_Value quotient
[static]
 

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 }

void ACE_Stats::quotient const ACE_UINT64  dividend,
const ACE_UINT32  divisor,
ACE_Stats_Value quotient
[static]
 

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 }

void ACE_Stats::reset void   ) 
 

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().

00204 {
00205   overflow_ = 0u;
00206   number_of_samples_ = 0u;
00207   min_ = 0x7FFFFFFF;
00208   max_ = -0x8000 * 0x10000;
00209   samples_.reset ();
00210 }

int ACE_Stats::sample const ACE_INT32  value  ) 
 

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 }

ACE_INLINE ACE_UINT32 ACE_Stats::samples void   )  const
 

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 }

void ACE_Stats::square_root const ACE_UINT64  n,
ACE_Stats_Value square_root
[static]
 

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 }

int ACE_Stats::std_dev ACE_Stats_Value std_dev,
const ACE_UINT32  scale_factor = 1
 

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 }


Member Data Documentation

ACE_INT32 ACE_Stats::max_ [protected]
 

Maximum sample value.

Definition at line 208 of file Stats.h.

ACE_INT32 ACE_Stats::min_ [protected]
 

Minimum sample value.

Definition at line 205 of file Stats.h.

ACE_UINT32 ACE_Stats::number_of_samples_ [protected]
 

Number of samples.

Definition at line 202 of file Stats.h.

Referenced by mean(), reset(), sample(), samples(), and std_dev().

u_int ACE_Stats::overflow_ [protected]
 

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().

ACE_Unbounded_Queue<ACE_INT32> ACE_Stats::samples_ [protected]
 

The samples.

Definition at line 211 of file Stats.h.


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:30:11 2006 for ACE by doxygen 1.3.6