Commit 7e47022c authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - both histograms now derive from an abstract interface class. This...

[CHANGE] - both histograms now derive from an abstract interface class. This ensures uniform histogram handling in modules for both, value set histograms and other histograms.
parent 956e87f5
...@@ -23,64 +23,45 @@ ...@@ -23,64 +23,45 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <algorithm> #include <algorithm>
#include <iomanip>
#include <numeric>
#include "WAssert.h" #include "WAssert.h"
#include "WHistogram.h" #include "WHistogram.h"
#include "WLimits.h"
#include "WLogger.h"
WHistogram::WHistogram( double min, double max, size_t size ) WHistogram::WHistogram( double min, double max, size_t buckets ):
: m_bins( size, 0 ), m_minimum( min ),
m_min( min ), m_maximum( max ),
m_max( max ) m_nbBuckets( buckets )
{ {
if( min > max ) if( min > max )
{ {
std::swap( m_min, m_max ); std::swap( m_minimum, m_maximum );
} }
WAssert( m_bins.size() > 0, "Error: A histogram with a size of 0 does not make any sense" );
m_intervalWidth = std::abs( m_min - m_max ) / m_bins.size(); WAssert( buckets > 0, "Error: A histogram with a size of 0 does not make any sense." );
} }
WHistogram::~WHistogram() WHistogram::WHistogram( const WHistogram& hist ):
m_minimum( hist.m_minimum ),
m_maximum( hist.m_maximum ),
m_nbBuckets( hist.m_nbBuckets )
{ {
} }
void WHistogram::insert( double value ) WHistogram::~WHistogram()
{ {
if( value > m_max || value < m_min )
{
wlog::warn( "WHistogram" ) << std::scientific << std::setprecision( 16 ) << "Inserted value out of bounds, thread: "
<< value << " as min, resp. max: " << m_min << "," << m_max;
return; // value = ( value > m_max ? m_max : m_min );
}
if( value == m_max )
{
value = m_max - wlimits::DBL_EPS;
}
m_bins.at( static_cast< size_t >( std::abs( value - m_min ) / m_intervalWidth ) )++;
} }
size_t WHistogram::binSize() const size_t WHistogram::size() const
{ {
return m_bins.size(); return m_nbBuckets;
} }
size_t WHistogram::valuesSize() const double WHistogram::getMinimum() const
{ {
return std::accumulate( m_bins.begin(), m_bins.end(), 0 ); return m_minimum;
} }
size_t WHistogram::operator[]( size_t index ) const double WHistogram::getMaximum() const
{ {
if( index >= m_bins.size() ) return m_maximum;
{
wlog::error( "WHistogram" ) << index << "th interval is not available, there are only: " << m_bins.size();
return 0;
}
return m_bins[ index ];
} }
...@@ -25,80 +25,113 @@ ...@@ -25,80 +25,113 @@
#ifndef WHISTOGRAM_H #ifndef WHISTOGRAM_H
#define WHISTOGRAM_H #define WHISTOGRAM_H
#include <vector> #include <utility>
/** /**
* Container which associate values with (uniform width) bins (aka intervals or buckets). * Container which associate values with (uniform width) bins (aka intervals or buckets). This class implements the abstract interface and
* therefore builds the base class for all histogram classes. The interface also allows programming histogram of different bucket sizes.
*/ */
class WHistogram class WHistogram
{ {
public: public:
/** /**
* Default constructor. * Default constructor. Creates an empty histogram covering the specified min and max values with the specified number of buckets.
* *
* \param min * \param min the smallest value
* \param max * \param max the largest value
* \param size * \param buckets the number of buckets
*/ */
WHistogram( double min, double max, size_t size = 1000 ); WHistogram( double min, double max, size_t buckets = 1000 );
/**
* Copy constructor. Creates a deep copy of the specified histogram.
*
* \param hist the histogram to copy.
*/
WHistogram( const WHistogram& hist );
/** /**
* Default destructor. * Default destructor.
*/ */
~WHistogram(); virtual ~WHistogram();
/** /**
* Inserts a given value within the given range (min, max) into exactly one bin and increment its size. * Get the count of the specified bucket.
*
* \param index which buckets count is to be returned; starts with 0 which is the bucket containing the smallest values.
* *
* \param value Value to insert. * \return elements in the bucket.
*/ */
void insert( double value ); virtual size_t operator[]( size_t index ) const = 0;
/** /**
* Computes number of invervals. * Get the count of the specified bucket. Testing if the position is valid.
*
* \param index which buckets count is to be returned; starts with 0 which is the bucket containing the smallest values.
* *
* \return Number of intervals. * \return elements in the bucket
*/ */
size_t binSize() const; virtual size_t at( size_t index ) const = 0;
/** /**
* Computes the number of inserted values so far. * Returns the number of buckets in the histogram with the actual mapping.
* *
* \return Number of values so far. * \return number of buckets
*/ */
size_t valuesSize() const; virtual size_t size() const;
/** /**
* LooksUp how many elements are in this bin with the given index. * Returns the minimum value.
* *
* \param index The bin number to look up for * \return minimum
*/
virtual double getMinimum() const;
/**
* Returns the maximum value.
* *
* \return Number of values associated with this interval. * \return maximum
*/ */
size_t operator[]( size_t index ) const; virtual double getMaximum() const;
protected: /**
* Return the size of one specific bucket.
*
* \param index the width for this bucket is queried.
*
* \return the size of a bucket.
*/
virtual double getBucketSize( size_t index = 0 ) const = 0;
private:
/** /**
* Bins to associate with the values. Each bin has the width of m_intervalWidth; * Returns the actual interval associated with the given index. The interval is open, meaning that
* getIntervalForIndex( i ).second == getIntervalForIndex( i + 1 ).first but does not belong anymore to the interval itself but every value
* smaller than getIntervalForIndex( i ).second.
*
* \param index the intex
*
* \return the open interval.
*/ */
std::vector< size_t > m_bins; virtual std::pair< double, double > getIntervalForIndex( size_t index ) const = 0;
protected:
/** /**
* Minimal value * The smallest value
*/ */
double m_min; double m_minimum;
/** /**
* Maximal value * The biggest value
*/ */
double m_max; double m_maximum;
/** /**
* The width of an interval is precomputed to save performance. * The number of buckets.
*/ */
double m_intervalWidth; double m_nbBuckets;
private:
}; };
#endif // WHISTOGRAM_H #endif // WHISTOGRAM_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <algorithm>
#include <iomanip>
#include <numeric>
#include <utility>
#include "WAssert.h"
#include "WHistogramBasic.h"
#include "WLimits.h"
#include "WLogger.h"
WHistogramBasic::WHistogramBasic( double min, double max, size_t buckets ):
WHistogram( min, max, buckets ),
m_bins( buckets, 0 ),
m_intervalWidth( ( m_maximum - m_minimum ) / static_cast< double >( m_nbBuckets ) )
{
}
WHistogramBasic::WHistogramBasic( const WHistogramBasic& hist ):
WHistogram( hist ),
m_bins( hist.m_bins ),
m_intervalWidth( hist.m_intervalWidth )
{
}
WHistogramBasic::~WHistogramBasic()
{
}
size_t WHistogramBasic::operator[]( size_t index ) const
{
return m_bins[ index ];
}
size_t WHistogramBasic::at( size_t index ) const
{
if( index >= m_bins.size() )
{
wlog::error( "WHistogramBasic" ) << index << "th interval is not available, there are only: " << m_bins.size();
return 0;
}
return m_bins[ index ];
}
double WHistogramBasic::getBucketSize( size_t /* index */ ) const
{
return m_intervalWidth;
}
std::pair< double, double > WHistogramBasic::getIntervalForIndex( size_t index ) const
{
double first = m_minimum + m_intervalWidth * index;
double second = m_minimum + m_intervalWidth * ( index + 1 );
return std::make_pair( first, second );
}
void WHistogramBasic::insert( double value )
{
if( value > m_maximum || value < m_minimum )
{
wlog::warn( "WHistogramBasic" ) << std::scientific << std::setprecision( 16 ) << "Inserted value out of bounds, thread: "
<< value << " as min, resp. max: " << m_minimum << "," << m_maximum;
return; // value = ( value > m_maximum ? m_maximum : m_minimum );
}
if( value == m_maximum )
{
value = m_maximum - wlimits::DBL_EPS;
}
m_bins.at( static_cast< size_t >( std::abs( value - m_minimum ) / m_intervalWidth ) )++;
}
size_t WHistogramBasic::valuesSize() const
{
return std::accumulate( m_bins.begin(), m_bins.end(), 0 );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WHISTOGRAMBASIC_H
#define WHISTOGRAMBASIC_H
#include <utility>
#include <vector>
#include "WHistogram.h"
/**
* Container which associate values with (uniform width) bins (aka intervals or buckets). This class implements a very simple and easy to use
* generic histogram with uniform bucket sizes.
*/
class WHistogramBasic: public WHistogram
{
public:
/**
* Default constructor. Creates an empty histogram covering the specified min and max values with the specified number of buckets.
*
* \param min the smallest value
* \param max the largest value
* \param buckets the number of buckets
*/
WHistogramBasic( double min, double max, size_t buckets = 1000 );
/**
* Copy constructor. Creates a deep copy of the specified histogram.
*
* \param hist the histogram to copy.
*/
WHistogramBasic( const WHistogramBasic& hist );
/**
* Default destructor.
*/
~WHistogramBasic();
/**
* Get the count of the specified bucket.
*
* \param index which buckets count is to be returned; starts with 0 which is the bucket containing the smallest values.
*
* \return elements in the bucket.
*/
virtual size_t operator[]( size_t index ) const;
/**
* Get the count of the specified bucket. Testing if the position is valid.
*
* \param index which buckets count is to be returned; starts with 0 which is the bucket containing the smallest values.
*
* \return elements in the bucket
*/
virtual size_t at( size_t index ) const;
/**
* Return the size of one specific bucket.
*
* \param index the width for this bucket is queried.
*
* \return the size of a bucket.
*/
virtual double getBucketSize( size_t index = 0 ) const;
/**
* Returns the actual interval associated with the given index. The interval is open, meaning that
* getIntervalForIndex( i ).second == getIntervalForIndex( i + 1 ).first but does not belong anymore to the interval itself but every value
* smaller than getIntervalForIndex( i ).second.
*
* \param index the intex
*
* \return the open interval.
*/
virtual std::pair< double, double > getIntervalForIndex( size_t index ) const;
/**
* Computes the number of inserted values so far.
*
* \return Number of values so far.
*/
size_t valuesSize() const;
/**
* Inserts a given value within the given range (min, max) into exactly one bin and increment its size.
*
* \param value Value to insert.
*/
virtual void insert( double value );
protected:
private:
/**
* Bins to associate with the values. Each bin has the width of m_intervalWidth;
*/
std::vector< size_t > m_bins;
/**
* The width of an interval is precomputed to save performance.
*/
double m_intervalWidth;
};
#endif // WHISTOGRAMBASIC_H
...@@ -22,21 +22,21 @@ ...@@ -22,21 +22,21 @@
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#ifndef WHISTOGRAM_TEST_H #ifndef WHISTOGRAMBASIC_TEST_H
#define WHISTOGRAM_TEST_H #define WHISTOGRAMBASIC_TEST_H
#include <cxxtest/TestSuite.h> #include <cxxtest/TestSuite.h>
#include "../WHistogram.h" #include "../WHistogramBasic.h"
#include "../WLimits.h" #include "../WLimits.h"
#include "../WLogger.h" #include "../WLogger.h"
static WLogger logger; static WLogger logger;
/** /**
* Unit tests the WHistogram class. * Unit tests the WHistogramBasic class.
*/ */
class WHistogramTest : public CxxTest::TestSuite class WHistogramBasicTest : public CxxTest::TestSuite
{ {
public: public:
/** /**
...@@ -44,8 +44,8 @@ public: ...@@ -44,8 +44,8 @@ public:
*/ */
void testInitialization( void ) void testInitialization( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
TS_ASSERT_EQUALS( h.binSize(), 1000 ); TS_ASSERT_EQUALS( h.size(), 1000 );
TS_ASSERT_EQUALS( h.valuesSize(), 0 ); TS_ASSERT_EQUALS( h.valuesSize(), 0 );
} }
...@@ -54,9 +54,9 @@ public: ...@@ -54,9 +54,9 @@ public:
*/ */
void testInsert( void ) void testInsert( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.7234 ); h.insert( 0.7234 );
TS_ASSERT_EQUALS( h.binSize(), 1000 ); TS_ASSERT_EQUALS( h.size(), 1000 );
TS_ASSERT_EQUALS( h.valuesSize(), 1 ); TS_ASSERT_EQUALS( h.valuesSize(), 1 );
TS_ASSERT_EQUALS( h[723], 1 ); TS_ASSERT_EQUALS( h[723], 1 );
} }
...@@ -66,7 +66,7 @@ public: ...@@ -66,7 +66,7 @@ public:
*/ */
void testInsertOnIntervalBorder( void ) void testInsertOnIntervalBorder( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.001 ); h.insert( 0.001 );
TS_ASSERT_EQUALS( h[1], 1 ); TS_ASSERT_EQUALS( h[1], 1 );
h.insert( 0.0039999 ); h.insert( 0.0039999 );
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
*/ */
void testInsertMin( void ) void testInsertMin( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.0 ); h.insert( 0.0 );
TS_ASSERT_EQUALS( h[0], 1 ); TS_ASSERT_EQUALS( h[0], 1 );
TS_ASSERT_EQUALS( h[1], 0 ); TS_ASSERT_EQUALS( h[1], 0 );
...@@ -91,7 +91,7 @@ public: ...@@ -91,7 +91,7 @@ public:
*/ */
void testInsertMax( void ) void testInsertMax( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.0 ); h.insert( 0.0 );
h.insert( 1.0 ); h.insert( 1.0 );
TS_ASSERT_EQUALS( h[999], 1 ); TS_ASSERT_EQUALS( h[999], 1 );
...@@ -103,10 +103,10 @@ public: ...@@ -103,10 +103,10 @@ public:
*/ */
void testInsertOutOfBounds( void ) void testInsertOutOfBounds( void )
{ {
WHistogram h( 0.0, 1.0 ); WHistogramBasic h( 0.0, 1.0 );
h.insert( 1.0 + wlimits::DBL_EPS ); h.insert( 1.0 + wlimits::DBL_EPS );