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

[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 @@
//---------------------------------------------------------------------------
#include <algorithm>
#include <iomanip>
#include <numeric>
#include "WAssert.h"
#include "WHistogram.h"
#include "WLimits.h"
#include "WLogger.h"
WHistogram::WHistogram( double min, double max, size_t size )
: m_bins( size, 0 ),
m_min( min ),
m_max( max )
WHistogram::WHistogram( double min, double max, size_t buckets ):
m_minimum( min ),
m_maximum( max ),
m_nbBuckets( buckets )
{
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() )
{
wlog::error( "WHistogram" ) << index << "th interval is not available, there are only: " << m_bins.size();
return 0;
}
return m_bins[ index ];
return m_maximum;
}
......@@ -25,80 +25,113 @@
#ifndef 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
{
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 max
* \param size
* \param min the smallest value
* \param max the largest value
* \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.
*/
~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
//---------------------------------------------------------------------------
//
// 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 @@
//
//---------------------------------------------------------------------------
#ifndef WHISTOGRAM_TEST_H
#define WHISTOGRAM_TEST_H
#ifndef WHISTOGRAMBASIC_TEST_H
#define WHISTOGRAMBASIC_TEST_H
#include <cxxtest/TestSuite.h>
#include "../WHistogram.h"
#include "../WHistogramBasic.h"
#include "../WLimits.h"
#include "../WLogger.h"
static WLogger logger;
/**
* Unit tests the WHistogram class.
* Unit tests the WHistogramBasic class.
*/
class WHistogramTest : public CxxTest::TestSuite
class WHistogramBasicTest : public CxxTest::TestSuite
{
public:
/**
......@@ -44,8 +44,8 @@ public:
*/
void testInitialization( void )
{
WHistogram h( 0.0, 1.0 );
TS_ASSERT_EQUALS( h.binSize(), 1000 );
WHistogramBasic h( 0.0, 1.0 );
TS_ASSERT_EQUALS( h.size(), 1000 );
TS_ASSERT_EQUALS( h.valuesSize(), 0 );
}
......@@ -54,9 +54,9 @@ public:
*/
void testInsert( void )
{
WHistogram h( 0.0, 1.0 );
WHistogramBasic h( 0.0, 1.0 );
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[723], 1 );
}
......@@ -66,7 +66,7 @@ public:
*/
void testInsertOnIntervalBorder( void )
{
WHistogram h( 0.0, 1.0 );
WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.001 );
TS_ASSERT_EQUALS( h[1], 1 );
h.insert( 0.0039999 );
......@@ -80,7 +80,7 @@ public:
*/
void testInsertMin( void )
{
WHistogram h( 0.0, 1.0 );
WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.0 );
TS_ASSERT_EQUALS( h[0], 1 );
TS_ASSERT_EQUALS( h[1], 0 );
......@@ -91,7 +91,7 @@ public:
*/
void testInsertMax( void )
{
WHistogram h( 0.0, 1.0 );
WHistogramBasic h( 0.0, 1.0 );
h.insert( 0.0 );
h.insert( 1.0 );
TS_ASSERT_EQUALS( h[999], 1 );
......@@ -103,10 +103,10 @@ public:
*/
void testInsertOutOfBounds( void )
{
WHistogram h( 0.0, 1.0 );
WHistogramBasic h( 0.0, 1.0 );
h.insert( 1.0 + wlimits::DBL_EPS );
h.insert( 0.0 - wlimits::DBL_EPS );
for( size_t i = 0; i < h.binSize(); ++i )
for( size_t i = 0; i < h.size(); ++i )
{
TS_ASSERT_EQUALS( h[i], 0 );
}
......@@ -117,8 +117,8 @@ public:
*/
void testOperatorToGetNumberOfElementsInsideTheBin( void )
{
WHistogram h( 0.0, 1.0 );
for( size_t i = 0; i < h.binSize(); ++i )
WHistogramBasic h( 0.0, 1.0 );
for( size_t i = 0; i < h.size(); ++i )
{
TS_ASSERT_EQUALS( h[i], 0 );
}
......@@ -128,4 +128,4 @@ public:
}
};
#endif // WHISTOGRAM_TEST_H
#endif // WHISTOGRAMBASIC_TEST_H
......@@ -32,8 +32,7 @@
#include "WValueSetHistogram.h"
WValueSetHistogram::WValueSetHistogram( boost::shared_ptr< WValueSetBase > valueSet, size_t buckets ):
m_minimum( valueSet->getMinimumValue() ),
m_maximum( valueSet->getMaximumValue() )
WHistogram( valueSet->getMinimumValue(), valueSet->getMaximumValue(), buckets )
{
// create base histogram
WAssert( buckets > 1, "WValueSetHistogram::WValueSetHistogram : number of buckets needs to be larger than 1." );
......@@ -67,8 +66,7 @@ WValueSetHistogram::WValueSetHistogram( boost::shared_ptr< WValueSetBase > value
}
WValueSetHistogram::WValueSetHistogram( const WValueSetBase& valueSet, size_t buckets ):
m_minimum( valueSet.getMinimumValue() ),
m_maximum( valueSet.getMaximumValue() )
WHistogram( valueSet.getMinimumValue(), valueSet.getMaximumValue(), buckets )
{
// create base histogram
WAssert( buckets > 1, "WValueSetHistogram::WValueSetHistogram : number of buckets needs to be larger than 1." );
......@@ -102,8 +100,7 @@ WValueSetHistogram::WValueSetHistogram( const WValueSetBase& valueSet, size_t bu
}
WValueSetHistogram::WValueSetHistogram( const WValueSetHistogram& histogram, size_t buckets ):
m_minimum( histogram.m_minimum ),
m_maximum( histogram.m_maximum ),
WHistogram( histogram ),
m_initialBucketSize( histogram.m_initialBucketSize ),
m_initialBuckets( histogram.m_initialBuckets ),
m_nInitialBuckets( histogram.m_nInitialBuckets ),
......@@ -188,8 +185,9 @@ double WValueSetHistogram::getInitialBucketSize() const
return m_initialBucketSize;
}
double WValueSetHistogram::getBucketSize() const
double WValueSetHistogram::getBucketSize( size_t /* index */ ) const
{
// ignore index as each bucket has the same width
return m_mappedBucketSize;
}
......@@ -215,17 +213,7 @@ size_t WValueSetHistogram::at( size_t index ) const
size_t WValueSetHistogram::size() const
{
return m_nMappedBuckets;
}
double WValueSetHistogram::getMinimum() const
{
return m_minimum;
}
double WValueSetHistogram::getMaximum() const
{
return m_maximum;
return m_nMappedBuckets; // overwrite the WHistogram::size here as we have our own size.
}
std::pair< double, double > WValueSetHistogram::getIntervalForIndex( size_t index ) const
......
......@@ -33,6 +33,7 @@
#include <boost/scoped_array.hpp>
#include <boost/shared_array.hpp>