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

static void quotient (const ACE_UINT64 dividend, const ACE_UINT32 divisor, ACE_Stats_Value &quotient)
 Utility division function, for ACE_UINT64 dividend.
static void quotient (const ACE_Stats_Value &dividend, const ACE_UINT32 divisor, ACE_Stats_Value &quotient)
 Utility division function, for ACE_Stats_Value dividend.
static 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.

References max_.

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

References 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(), sample(), samples_, 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 }

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.

References min_.

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

References ACE_TEXT, ACE_OS::fprintf(), max_, min_, overflow_, quotient(), samples(), ACE_OS::sprintf(), std_dev(), and ACE_OS::strerror().

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 }

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

References ACE_Stats_Value::fractional(), quotient(), 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 }

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

Referenced by mean(), print_summary(), quotient(), 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 }

void ACE_Stats::reset ( void   ) 

Initialize internal state.

Definition at line 202 of file Stats.cpp.

References max_, min_, number_of_samples_, overflow_, ACE_Unbounded_Queue< T >::reset(), and samples_.

Referenced by ACE_Stats().

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

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

References ACE_Unbounded_Queue< T >::enqueue_tail(), max_, min_, number_of_samples_, overflow_, and samples_.

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

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 }

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

References ACE_OS::floor().

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 }

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

References ACE_Unbounded_Queue_Iterator< T >::advance(), ACE_Unbounded_Queue_Iterator< T >::done(), mean(), ACE_Unbounded_Queue_Iterator< T >::next(), number_of_samples_, overflow_, quotient(), sample(), samples_, and square_root().

Referenced by print_summary().

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 }


Member Data Documentation

ACE_INT32 ACE_Stats::max_ [protected]

Maximum sample value.

Definition at line 208 of file Stats.h.

Referenced by max_value(), print_summary(), reset(), and sample().

ACE_INT32 ACE_Stats::min_ [protected]

Minimum sample value.

Definition at line 205 of file Stats.h.

Referenced by min_value(), print_summary(), reset(), and sample().

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.

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


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:35:40 2010 for ACE by  doxygen 1.4.7