// -*- C++ -*-
//==========================================================================
/**
* @file Stats.h
*
* @author David L. Levine
*/
//==========================================================================
#ifndef ACE_STATS_H
#define ACE_STATS_H
#include /**/ "ace/pre.h"
#include /**/ "ace/ACE_export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/Unbounded_Queue.h"
#include "ace/Log_Category.h"
#include "ace/Basic_Stats.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_Stats_Value
*
* @brief Helper class for ACE_Stats.
*
* Container struct for 64-bit signed quantity and its
* precision. It would be nicer to use a fixed-point class, but
* this is sufficient. Users typically don't need to use this
* class directly; see ACE_Stats below.
*/
class ACE_Export ACE_Stats_Value
{
public:
/**
* Constructor, which requires precision in terms of number of
* decimal digits. The more variation in the data, and the greater
* the data values, the smaller the precision must be to avoid
* overflow in the standard deviation calculation. 3 might be a
* good value, or maybe 4. 5 will probably be too large for
* non-trivial data sets.
*/
ACE_Stats_Value (const u_int precision);
/// Accessor for precision.
u_int precision () const;
/// Set the whole_ field.
void whole (const ACE_UINT32);
/// Accessor for the whole_ field.
ACE_UINT32 whole () const;
/// Set the fractional_ field.
void fractional (const ACE_UINT32);
/// Accessor for the fractional_ field.
ACE_UINT32 fractional () const;
/// Calculates the maximum value of the fractional portion, given its
/// precision.
ACE_UINT32 fractional_field () const;
/**
* Access the value as an _unsigned_ 64 bit quantity. It scales the
* value up by {precision} decimal digits, so that no precision will
* be lost. It assumes that {whole_} is >= 0.
*/
void scaled_value (ACE_UINT64 &) const;
/// Print to stdout.
void dump () const;
private:
ACE_Stats_Value () = default;
private:
/// The integer portion of the value.
ACE_UINT32 whole_;
/// The fractional portion of the value.
ACE_UINT32 fractional_;
/**
* The number of decimal digits of precision represented by
* {fractional_}. Not declared const, so the only way to change it
* is via the assignment operator.
*/
u_int precision_;
};
/**
* @class ACE_Stats
*
* @brief Provides simple statistical analysis.
*
* Simple statistical analysis package. Prominent features are:
* -# It does not use any floating point arithmetic.
* -# It handles positive and/or negative sample values. The
* sample value type is ACE_INT32.
* -# It uses 64 bit unsigned, but not 64 bit signed, quantities
* internally.
* -# It checks for overflow of internal state.
* -# It has no static variables of other than built-in types.
*
* Example usage:
*
* @verbatim
* ACE_Stats stats;
* for (u_int i = 0; i < n; ++i)
* {
* const ACE_UINT32 sample = ...;
* stats.sample (sample);
* }
* stats.print_summary (3);
* @endverbatim
*/
class ACE_Export ACE_Stats
{
public:
/// Default constructor.
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.
int sample (const ACE_INT32 value);
/// Access the number of samples provided so far.
ACE_UINT32 samples () const;
/// Value of the minimum sample provided so far.
ACE_INT32 min_value () const;
/// Value of the maximum sample provided so far.
ACE_INT32 max_value () const;
/**
* 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.
*/
void mean (ACE_Stats_Value &mean,
const ACE_UINT32 scale_factor = 1);
/// Access the standard deviation, whole and fractional parts. See
/// description of {mean} method for argument descriptions.
int std_dev (ACE_Stats_Value &std_dev,
const ACE_UINT32 scale_factor = 1);
/**
* 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.
*/
int print_summary (const u_int precision,
const ACE_UINT32 scale_factor = 1,
FILE *
#ifdef ACE_LACKS_STDOUT
= 0
#else
= stdout
#endif
) const;
/// Initialize internal state.
void reset (void);
/// Utility division function, for ACE_UINT64 dividend.
static void quotient (const ACE_UINT64 dividend,
const ACE_UINT32 divisor,
ACE_Stats_Value "ient);
/// Utility division function, for ACE_Stats_Value dividend.
static void quotient (const ACE_Stats_Value ÷nd,
const ACE_UINT32 divisor,
ACE_Stats_Value "ient);
/**
* Sqrt function, which uses an oversimplified version of Newton's
* method. It's not fast, but it doesn't require floating point
* support.
*/
static void square_root (const ACE_UINT64 n,
ACE_Stats_Value &square_root);
/// Print summary statistics to stdout.
void dump () const;
protected:
/// Internal indication of whether there has been overflow. Contains
/// the errno corresponding to the cause of overflow.
u_int overflow_;
/// Number of samples.
ACE_UINT32 number_of_samples_;
/// Minimum sample value.
ACE_INT32 min_;
/// Maximum sample value.
ACE_INT32 max_;
/// The samples.
ACE_Unbounded_Queue samples_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)
# include "ace/Stats.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ! ACE_STATS_H */