Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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 Methods

 ACE_Stats (void)
 Default constructor. More...

int 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. More...

ACE_UINT32 samples (void) const
 Access the number of samples provided so far. More...

ACE_INT32 min_value (void) const
 Value of the minimum sample provided so far. More...

ACE_INT32 max_value (void) const
 Value of the maximum sample provided so far. More...

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)
 Access the standard deviation, whole and fractional parts. See description of <mean> method for argument descriptions. More...

int print_summary (const u_int precision, const ACE_UINT32 scale_factor=1, FILE *=stdout) const
void reset (void)
 Initialize internal state. More...

void dump (void) const
 Print summary statistics to stdout. More...


Static Public Methods

void quotient (const ACE_UINT64 dividend, const ACE_UINT32 divisor, ACE_Stats_Value &quotient)
 Utility division function, for ACE_UINT64 dividend. More...

void quotient (const ACE_Stats_Value &dividend, const ACE_UINT32 divisor, ACE_Stats_Value &quotient)
 Utility division function, for ACE_Stats_Value dividend. More...

void square_root (const ACE_UINT64 n, ACE_Stats_Value &square_root)

Private Attributes

u_int overflow_
 Internal indication of whether there has been overflow. Contains the errno corresponding to the cause of overflow. More...

ACE_UINT32 number_of_samples_
 Number of samples. More...

ACE_INT32 min_
 Minimum sample value. More...

ACE_INT32 max_
 Maximum sample value. More...

ACE_Unbounded_Queue< ACE_INT32 > samples_
 The samples. More...


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 125 of file Stats.h.


Constructor & Destructor Documentation

ACE_INLINE ACE_Stats::ACE_Stats void   
 

Default constructor.

Definition at line 64 of file Stats.i.

References reset.

00065 {
00066   reset ();
00067 }


Member Function Documentation

ACE_INLINE void ACE_Stats::dump void    const
 

Print summary statistics to stdout.

Definition at line 92 of file Stats.i.

References print_summary.

00093 {
00094   print_summary (3u);
00095 }

ACE_INLINE ACE_INT32 ACE_Stats::max_value void    const
 

Value of the maximum sample provided so far.

Definition at line 85 of file Stats.i.

References max_.

00086 {
00087   return max_;
00088 }

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 63 of file Stats.cpp.

References ACE_UINT64, ACE_UINT64_LITERAL, ACE_Unbounded_Queue_Iterator::advance, ACE_Unbounded_Queue_Iterator::done, ACE_Stats_Value::fractional, ACE_Unbounded_Queue_Iterator::next, number_of_samples_, quotient, sample, samples_, and ACE_Stats_Value::whole.

Referenced by ACE_High_Res_Timer::calibrate, and std_dev.

00065 {
00066   if (number_of_samples_ > 0)
00067     {
00068 #if defined ACE_LACKS_LONGLONG_T
00069       // If ACE_LACKS_LONGLONG_T, then ACE_UINT64 is a user-defined class.
00070       // To prevent having to construct a static of that class, declare it
00071       // on the stack, and construct it, in each function that needs it.
00072       const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8);
00073 #else  /* ! ACE_LACKS_LONGLONG_T */
00074       const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET =
00075         ACE_UINT64_LITERAL (0x100000000);
00076 #endif /* ! ACE_LACKS_LONGLONG_T */
00077 
00078       ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET;
00079       ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00080       while (! i.done ())
00081         {
00082           ACE_INT32 *sample;
00083           if (i.next (sample))
00084             {
00085               sum += *sample;
00086               i.advance ();
00087             }
00088         }
00089 
00090       // sum_ was initialized with ACE_STATS_INTERNAL_OFFSET, so
00091       // subtract that off here.
00092       quotient (sum - ACE_STATS_INTERNAL_OFFSET,
00093                 number_of_samples_ * scale_factor,
00094                 m);
00095     }
00096   else
00097     {
00098       m.whole (0);
00099       m.fractional (0);
00100     }
00101 }

ACE_INLINE ACE_INT32 ACE_Stats::min_value void    const
 

Value of the minimum sample provided so far.

Definition at line 78 of file Stats.i.

References min_.

00079 {
00080   return min_;
00081 }

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 209 of file Stats.cpp.

References ACE_LIB_TEXT, ACE_TCHAR, ACE_UINT64, ACE_OS::fprintf, ACE_Stats_Value::fractional, max_, min_, overflow_, quotient, samples, ACE_OS::sprintf, strerror, and ACE_Stats_Value::whole.

Referenced by dump.

00212 {
00213   ACE_TCHAR mean_string [128];
00214   ACE_TCHAR std_dev_string [128];
00215   ACE_TCHAR min_string [128];
00216   ACE_TCHAR max_string [128];
00217   int success = 0;
00218 
00219   for (int tmp_precision = precision;
00220        ! overflow_  &&  ! success  &&  tmp_precision >= 0;
00221        --tmp_precision)
00222     {
00223       // Build a format string, in case the C library doesn't support %*u.
00224       ACE_TCHAR format[32];
00225       if (tmp_precision == 0)
00226         ACE_OS::sprintf (format, ACE_LIB_TEXT ("%%%d"), tmp_precision);
00227       else
00228         ACE_OS::sprintf (format, ACE_LIB_TEXT ("%%d.%%0%du"), tmp_precision);
00229 
00230       ACE_Stats_Value u (tmp_precision);
00231       ((ACE_Stats *) this)->mean (u, scale_factor);
00232       ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ());
00233 
00234       ACE_Stats_Value sd (tmp_precision);
00235       if (((ACE_Stats *) this)->std_dev (sd, scale_factor))
00236         {
00237           success = 0;
00238           continue;
00239         }
00240       else
00241         {
00242           success = 1;
00243         }
00244       ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ());
00245 
00246       ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision);
00247       if (min_ != 0)
00248         {
00249           const ACE_UINT64 m (min_);
00250           quotient (m, scale_factor, minimum);
00251         }
00252       if (max_ != 0)
00253         {
00254           const ACE_UINT64 m (max_);
00255           quotient (m, scale_factor, maximum);
00256         }
00257       ACE_OS::sprintf (min_string, format,
00258                        minimum.whole (), minimum.fractional ());
00259       ACE_OS::sprintf (max_string, format,
00260                        maximum.whole (), maximum.fractional ());
00261     }
00262 
00263   if (success == 1)
00264     {
00265       ACE_OS::fprintf (file, ACE_LIB_TEXT ("samples: %u (%s - %s); mean: ")
00266                        ACE_LIB_TEXT ("%s; std dev: %s\n"),
00267                        samples (), min_string, max_string,
00268                        mean_string, std_dev_string);
00269       return 0;
00270     }
00271   else
00272     {
00273 #if !defined (ACE_HAS_WINCE)
00274       ACE_OS::fprintf (file,
00275                        ACE_LIB_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
00276                        strerror (overflow_));
00277 #else
00278       // WinCE doesn't have strerror ;(
00279       ACE_OS::fprintf (file,
00280                        ACE_LIB_TEXT ("ACE_Stats::print_summary: OVERFLOW\n"));
00281 #endif /* ACE_HAS_WINCE */
00282       return -1;
00283     }
00284 }

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 318 of file Stats.cpp.

References ACE_Stats_Value::fractional, ACE_Stats_Value::fractional_field, ACE_Stats_Value::precision, and ACE_Stats_Value::whole.

00321 {
00322   // The whole part of the division comes from simple integer division.
00323   quotient.whole (divisor == 0  ?  0  :  dividend.whole () / divisor);
00324 
00325   if (quotient.precision () > 0  ||  divisor == 0)
00326     {
00327       const ACE_UINT32 field = quotient.fractional_field ();
00328 
00329       // Fractional = (dividend % divisor) * 10^precision / divisor.
00330       quotient.fractional (dividend.whole () % divisor * field / divisor  +
00331                            dividend.fractional () / divisor);
00332     }
00333   else
00334     {
00335       // No fractional portion is requested, so don't bother
00336       // calculating it.
00337       quotient.fractional (0);
00338     }
00339 }

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 287 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.

00290 {
00291   // The whole part of the division comes from simple integer division.
00292   quotient.whole (ACE_static_cast (ACE_UINT32,
00293     divisor == 0  ?  0  :  dividend / divisor));
00294 
00295   if (quotient.precision () > 0  ||  divisor == 0)
00296     {
00297       const ACE_UINT32 field = quotient.fractional_field ();
00298 
00299       // Fractional = (dividend % divisor) * 10^precision / divisor
00300 
00301       // It would be nice to add round-up term:
00302       // Fractional = (dividend % divisor) * 10^precision / divisor  +
00303       //                10^precision/2 / 10^precision
00304       //            = ((dividend % divisor) * 10^precision  +  divisor) /
00305       //                divisor
00306       quotient.fractional (ACE_static_cast (ACE_UINT32,
00307         dividend % divisor * field / divisor));
00308     }
00309   else
00310     {
00311       // No fractional portion is requested, so don't bother
00312       // calculating it.
00313       quotient.fractional (0);
00314     }
00315 }

void ACE_Stats::reset void   
 

Initialize internal state.

Definition at line 199 of file Stats.cpp.

References max_, min_, number_of_samples_, overflow_, ACE_Unbounded_Queue< ACE_INT32 >::reset, and samples_.

Referenced by ACE_Stats.

00200 {
00201   overflow_ = 0u;
00202   number_of_samples_ = 0u;
00203   min_ = 0x7FFFFFFF;
00204   max_ = -0x8000 * 0x10000;
00205   samples_.reset ();
00206 }

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 33 of file Stats.cpp.

References ACE_Unbounded_Queue< ACE_INT32 >::enqueue_tail, max_, min_, number_of_samples_, overflow_, and samples_.

Referenced by ACE_High_Res_Timer::calibrate, mean, and std_dev.

00034 {
00035   if (samples_.enqueue_tail (value) == 0)
00036     {
00037       ++number_of_samples_;
00038       if (number_of_samples_ == 0)
00039         {
00040           // That's a lot of samples :-)
00041           overflow_ = EFAULT;
00042           return -1;
00043         }
00044 
00045       if (value < min_)
00046         min_ = value;
00047 
00048       if (value > max_)
00049         max_ = value;
00050 
00051       return 0;
00052     }
00053   else
00054     {
00055       // Probably failed due to running out of memory when trying to
00056       // enqueue the new value.
00057       overflow_ = errno;
00058       return -1;
00059     }
00060 }

ACE_INLINE ACE_UINT32 ACE_Stats::samples void    const
 

Access the number of samples provided so far.

Definition at line 71 of file Stats.i.

References number_of_samples_.

Referenced by print_summary.

00072 {
00073   return number_of_samples_;
00074 }

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 342 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.

00344 {
00345   ACE_UINT32 floor = 0;
00346   ACE_UINT32 ceiling = 0xFFFFFFFFu;
00347   ACE_UINT32 mid = 0;
00348   u_int i;
00349 
00350   // The maximum number of iterations is log_2 (2^64) == 64.
00351   for (i = 0; i < 64; ++i)
00352     {
00353       mid = (ceiling - floor) / 2  +  floor;
00354       if (floor == mid)
00355         // Can't divide the interval any further.
00356         break;
00357       else
00358         {
00359           // Multiply carefully to avoid overflow.
00360           ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00361           if (mid_squared == n)
00362             break;
00363           else if (mid_squared < n)
00364             floor = mid;
00365           else
00366             ceiling = mid;
00367         }
00368     }
00369 
00370   square_root.whole (mid);
00371   ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00372 
00373   if (square_root.precision ()  &&  mid_squared < n)
00374     {
00375       // (mid * 10^precision + fractional)^2 ==
00376       //   n^2 * 10^(precision * 2)
00377 
00378       const ACE_UINT32 field = square_root.fractional_field ();
00379 
00380       floor = 0;
00381       ceiling = field;
00382       mid = 0;
00383 
00384       // Do the 64-bit arithmetic carefully to avoid overflow.
00385       ACE_UINT64 target = n;
00386       target *= field;
00387       target *= field;
00388 
00389       ACE_UINT64 difference = 0;
00390 
00391       for (i = 0; i < square_root.precision (); ++i)
00392         {
00393           mid = (ceiling - floor) / 2 + floor;
00394 
00395           ACE_UINT64 current = square_root.whole () * field  +  mid;
00396           current *= square_root.whole () * field  +  mid;
00397 
00398           if (floor == mid)
00399             {
00400               difference = target - current;
00401               break;
00402             }
00403           else if (current <= target)
00404             floor = mid;
00405           else
00406             ceiling = mid;
00407         }
00408 
00409       // Check to see if the fractional part should be one greater.
00410       ACE_UINT64 next = square_root.whole () * field  +  mid + 1;
00411       next *= square_root.whole () * field  +  mid + 1;
00412 
00413       square_root.fractional (next - target < difference  ?  mid + 1  :  mid);
00414     }
00415   else
00416     {
00417       // No fractional portion is requested, so don't bother
00418       // calculating it.
00419       square_root.fractional (0);
00420     }
00421 }

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 104 of file Stats.cpp.

References ACE_U64_TO_U32, ACE_UINT64, ACE_Unbounded_Queue_Iterator::advance, ACE_Unbounded_Queue_Iterator::done, ACE_Stats_Value::fractional, ACE_Stats_Value::fractional_field, mean, ACE_Unbounded_Queue_Iterator::next, number_of_samples_, overflow_, ACE_Stats_Value::precision, quotient, sample, samples_, ACE_Stats_Value::scaled_value, square_root, and ACE_Stats_Value::whole.

00106 {
00107   if (number_of_samples_ <= 1)
00108     {
00109       std_dev.whole (0);
00110       std_dev.fractional (0);
00111     }
00112   else
00113     {
00114       const ACE_UINT32 field = std_dev.fractional_field ();
00115 
00116       // The sample standard deviation is:
00117       //
00118       // sqrt (sum (sample_i - mean)^2 / (number_of_samples_ - 1))
00119 
00120       ACE_UINT64 mean_scaled;
00121       // Calculate the mean, scaled, so that we don't lose its
00122       // precision.
00123       ACE_Stats_Value avg (std_dev.precision ());
00124       mean (avg, 1u);
00125       avg.scaled_value (mean_scaled);
00126 
00127       // Calculate the summation term, of squared differences from the
00128       // mean.
00129       ACE_UINT64 sum_of_squares = 0;
00130       ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00131       while (! i.done ())
00132         {
00133           ACE_INT32 *sample;
00134           if (i.next (sample))
00135             {
00136               const ACE_UINT64 original_sum_of_squares = sum_of_squares;
00137 
00138               // Scale up by field width so that we don't lose the
00139               // precision of the mean.  Carefully . . .
00140               const ACE_UINT64 product (*sample * field);
00141 
00142               ACE_UINT64 difference;
00143               // NOTE: please do not reformat this code!  It //
00144               // works with the Diab compiler the way it is! //
00145               if  (product >= mean_scaled)                   //
00146                 {                                            //
00147                   difference = product - mean_scaled;        //
00148                 }                                            //
00149               else                                           //
00150                 {                                            //
00151                   difference = mean_scaled - product;        //
00152                 }                                            //
00153               // NOTE: please do not reformat this code!  It //
00154               // works with the Diab compiler the way it is! //
00155 
00156               // Square using 64-bit arithmetic.
00157               sum_of_squares += difference * ACE_U64_TO_U32 (difference);
00158               i.advance ();
00159 
00160               if (sum_of_squares < original_sum_of_squares)
00161                 {
00162                   overflow_ = ENOSPC;
00163                   return -1;
00164                 }
00165             }
00166         }
00167 
00168       // Divide the summation by (number_of_samples_ - 1), to get the
00169       // variance.  In addition, scale the variance down to undo the
00170       // mean scaling above.  Otherwise, it can get too big.
00171       ACE_Stats_Value variance (std_dev.precision ());
00172       quotient (sum_of_squares,
00173                 (number_of_samples_ - 1) * field * field,
00174                 variance);
00175 
00176       // Take the square root of the variance to get the standard
00177       // deviation.  First, scale up . . .
00178       ACE_UINT64 scaled_variance;
00179       variance.scaled_value (scaled_variance);
00180 
00181       // And scale up, once more, because we'll be taking the square
00182       // root.
00183       scaled_variance *= field;
00184       ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ());
00185       square_root (scaled_variance,
00186                    unscaled_standard_deviation);
00187 
00188       // Unscale.
00189       quotient (unscaled_standard_deviation,
00190                 scale_factor * field,
00191                 std_dev);
00192     }
00193 
00194   return 0;
00195 }


Member Data Documentation

ACE_INT32 ACE_Stats::max_ [private]
 

Maximum sample value.

Definition at line 204 of file Stats.h.

Referenced by max_value, print_summary, reset, and sample.

ACE_INT32 ACE_Stats::min_ [private]
 

Minimum sample value.

Definition at line 201 of file Stats.h.

Referenced by min_value, print_summary, reset, and sample.

ACE_UINT32 ACE_Stats::number_of_samples_ [private]
 

Number of samples.

Definition at line 198 of file Stats.h.

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

u_int ACE_Stats::overflow_ [private]
 

Internal indication of whether there has been overflow. Contains the errno corresponding to the cause of overflow.

Definition at line 195 of file Stats.h.

Referenced by print_summary, reset, sample, and std_dev.

ACE_Unbounded_Queue<ACE_INT32> ACE_Stats::samples_ [private]
 

The samples.

Definition at line 207 of file Stats.h.

Referenced by mean, reset, sample, and std_dev.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 12:56:37 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002