//==================================================================================================
// S t a t i s t i c s                                                                    Interface
// C o l l e c t o r
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides facilities to collect statistical data. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "statistics/collector.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guStatisticsCollector
#define guStatisticsCollector

// Headers //---------------------------------------------------------------------------------------
#include <set> /*INCLUDE*/
#include <bpp/standard.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef STATISTICS_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  statisticsCollector
#define private_area statisticsCollector_private

namespace public_area  { /*NAMESPACE*/ using namespace standard; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clCollector;
 class clStorageCollector;
 class clMeanCollector;
 class clVarianceCollector;
 class clExtremaCollector;
 class clMedianCollector;
 class clStatisticsCollector;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clCollector           ctCollector;
 typedef const clStorageCollector    ctStorageCollector;
 typedef const clMeanCollector       ctMeanCollector;
 typedef const clVarianceCollector   ctVarianceCollector;
 typedef const clExtremaCollector    ctExtremaCollector;
 typedef const clMedianCollector     ctMedianCollector;
 typedef const clStatisticsCollector ctStatisticsCollector;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  {}
namespace private_area { testing_mode ( function void test(void); ) }

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// C o l l e c t o r  Interface //------------------------------------------------------------------
namespace public_area {
 /*CLASS clCollector */
 /* Represents a collector of real values. It provides statistical information on the collection.
    It is an abstract class. */
 class clCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property tyCardinal atCounter;

  private_property virtual void clean(void) = 0;
  private_property virtual void update(tyReal) = 0;
  //------------------------------------------------------------------------------------------Public
  public_property constructor        clCollector(void);
  public_property constructor        clCollector(ctCollector &);
  public_property virtual destructor clCollector(void);

  public_property clCollector & operator = (ctCollector &);

  public_property void       add(tyReal);
  public_property tyCardinal length(void) const;
  public_property void       reset(void);
 };
}

// S t o r a g e C o l l e c t o r  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clStorageCollector */
 /* Represents a collector of real values. All the values are stored for further analysis. */
 class clStorageCollector : public virtual clCollector {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clStorageCollector */ /* Type of the list of collected values. */
  public_property typedef std_vector(tyReal) clValueS;

  /*TYPE clStorageCollector */ /* Type of the iterators on the list of collected values. */
  public_property typedef clValueS::const_iterator clValueIterator;
  //-----------------------------------------------------------------------------------------Private
  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clStorageCollector */ /* List of the collected values. */
  read_only_attribute(clValueS,atValueS,values);

  public_property constructor clStorageCollector(void);
  public_property constructor clStorageCollector(ctStorageCollector &);
  public_property destructor  clStorageCollector(void);

  public_property clStorageCollector & operator = (ctStorageCollector &);
 };
}

// M e a n C o l l e c t o r  Interface //----------------------------------------------------------
namespace public_area {
 /*CLASS clMeanCollector */
 /* Represents a collector of real values. It provides the mean value of the collection. */
 class clMeanCollector : public virtual clCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property tyReal atSum;

  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clMeanCollector(void);
  public_property constructor clMeanCollector(ctMeanCollector &);
  public_property destructor  clMeanCollector(void);

  public_property clMeanCollector & operator = (ctMeanCollector &);

  public_property tyReal mean(void) const;
 };
}

// V a r i a n c e C o l l e c t o r  Interface //--------------------------------------------------
namespace public_area {
 /*CLASS clVarianceCollector */
 /* Represents a collector of real values. It provides the variance value of the collection. */
 class clVarianceCollector : public clMeanCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property tyReal atSquareSum;

  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clVarianceCollector(void);
  public_property constructor clVarianceCollector(ctVarianceCollector &);
  public_property destructor  clVarianceCollector(void);

  public_property clVarianceCollector & operator = (ctVarianceCollector &);

  public_property tyReal variance(void) const;
 };
}

// E x t r e m a C o l l e c t o r  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clExtremaCollector */
 /* Represents a collector of real values. It provides the minimum and maximum value of the
    collection. */
 class clExtremaCollector : public virtual clCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property tyReal atMinimum;
  private_property tyReal atMaximum;

  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clExtremaCollector(void);
  public_property constructor clExtremaCollector(ctExtremaCollector &);
  public_property destructor  clExtremaCollector(void);

  public_property clExtremaCollector & operator = (ctExtremaCollector &);

  public_property tyReal maximum(void) const;
  public_property tyReal minimum(void) const;
 };
}

// M e d i a n C o l l e c t o r  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clMedianCollector */
 /* Represents a collector of real values. It provides the median value of the collection. */
 class clMedianCollector : public virtual clCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property typedef std_set(tyReal) clValueS;

  private_property mutable tyBoolean atComputed;
  private_property mutable tyReal    atMedian;
  private_property clValueS          atValueS;

  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clMedianCollector(void);
  public_property constructor clMedianCollector(ctMedianCollector &);
  public_property destructor  clMedianCollector(void);

  public_property clMedianCollector & operator = (ctMedianCollector &);

  public_property tyReal median(void) const;
 };
}

// S t a t i s t i c s C o l l e c t o r  Interface //----------------------------------------------
namespace public_area {
 /*CLASS clStatisticsCollector */
 /* Represents a collector of real values. It provides several statistical informations on the
    collection: mean, variance, minimum, maximum and median. */
 class clStatisticsCollector : public clVarianceCollector,
                               public clExtremaCollector,
                               public clMedianCollector {
  //-----------------------------------------------------------------------------------------Private
  private_property void clean(void);
  private_property void update(tyReal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clStatisticsCollector(void);
  public_property constructor clStatisticsCollector(ctStatisticsCollector &);
  public_property destructor  clStatisticsCollector(void);

  public_property clStatisticsCollector & operator = (ctStatisticsCollector &);
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// C o l l e c t o r  Inline //---------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clCollector */ /* Builds a collector. */
 inline clCollector::clCollector(void) : atCounter(0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clCollector */ /* Builds a collector by copying another one. */
 inline clCollector::clCollector(ctCollector & agCollector) : atCounter(agCollector.atCounter) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clCollector */ /* Destructs the collector. */
 inline clCollector::~clCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clCollector */ /* Copies a collector. */
 inline clCollector & clCollector::operator = (ctCollector & agCollector) {
  atCounter=agCollector.atCounter;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Add
 /*METHOD clCollector */ /* Collects a value. */
 inline void clCollector::add(tyReal agValue) {
  ++atCounter;
  update(agValue);
 }
 //-------------------------------------------------------------------------------------------Length
 /*METHOD clCollector */ /* Returns the number of collected values. */
 inline tyCardinal clCollector::length(void) const { return (atCounter); }
 //--------------------------------------------------------------------------------------------Reset
 /*METHOD clCollector */ /* Resets the object for a new collection. */
 inline void clCollector::reset(void) {
  atCounter=0;
  clean();
 }
}

// S t o r a g e C o l l e c t o r  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clStorageCollector */ /* Builds a storage collector. */
 inline clStorageCollector::clStorageCollector(void) : clCollector(),atValueS() {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clStorageCollector */ /* Builds a storage collector by copying another one. */
 inline clStorageCollector::clStorageCollector(ctStorageCollector & agCollector)
 : clCollector(agCollector),atValueS(agCollector.values()) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clStorageCollector */ /* Destructs the collector. */
 inline clStorageCollector::~clStorageCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clStorageCollector */ /* Copies a storage collector. */
 inline clStorageCollector & clStorageCollector::operator = (ctStorageCollector & agCollector) {
  clCollector::operator=(agCollector);
  atValueS=agCollector.values();

  return (*this);
 }
}

// M e a n C o l l e c t o r  Inline //-------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMeanCollector */ /* Builds a mean collector. */
 inline clMeanCollector::clMeanCollector(void) : clCollector(),atSum(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMeanCollector */ /* Builds a mean collector by copying another one. */
 inline clMeanCollector::clMeanCollector(ctMeanCollector & agCollector)
 : clCollector(agCollector),atSum(agCollector.atSum) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clMeanCollector */ /* Destructs the collector. */
 inline clMeanCollector::~clMeanCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clMeanCollector */ /* Copies a mean collector. */
 inline clMeanCollector & clMeanCollector::operator = (ctMeanCollector & agCollector) {
  clCollector::operator=(agCollector);
  atSum=agCollector.atSum;

  return (*this);
 }
 //---------------------------------------------------------------------------------------------Mean
 /*METHOD clMeanCollector */ /* Returns the mean value of the collection. */
 inline tyReal clMeanCollector::mean(void) const {
  if (atCounter==0) return (0.0);
  return (atSum/atCounter);
 }
}

// V a r i a n c e C o l l e c t o r  Inline //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVarianceCollector */ /* Builds a variance collector. */
 inline clVarianceCollector::clVarianceCollector(void)
 : clCollector(),clMeanCollector(),atSquareSum(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVarianceCollector */ /* Builds a variance collector by copying another one. */
 inline clVarianceCollector::clVarianceCollector(ctVarianceCollector & agCollector)
 : clCollector(agCollector),clMeanCollector(agCollector),atSquareSum(agCollector.atSquareSum) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clVarianceCollector */ /* Destructs the collector. */
 inline clVarianceCollector::~clVarianceCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clVarianceCollector */ /* Copies a variance collector. */
 inline clVarianceCollector & clVarianceCollector::operator = (ctVarianceCollector & agCollector) {
  clMeanCollector::operator=(agCollector);
  atSquareSum=agCollector.atSquareSum;

  return (*this);
 }
 //-----------------------------------------------------------------------------------------Variance
 /*METHOD clVarianceCollector */ /* Returns the variance of the collection. */
 inline tyReal clVarianceCollector::variance(void) const {
  tyReal lcMean;
  tyReal lcSquareMean;

  if (atCounter==0) return (0.0);
  lcMean=atSum/atCounter;
  lcSquareMean=atSquareSum/atCounter;

  if (atCounter==1) return (lcSquareMean-lcMean*lcMean);
  return (tyReal(atCounter)/tyReal(atCounter-1)*(lcSquareMean-lcMean*lcMean));
 }
}

// E x t r e m a C o l l e c t o r  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clExtremaCollector */ /* Builds an extrema collector. */
 inline clExtremaCollector::clExtremaCollector(void)
 : clCollector(),atMinimum(0.0),atMaximum(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clExtremaCollector */ /* Builds an extrema collector by copying another one. */
 inline clExtremaCollector::clExtremaCollector(ctExtremaCollector & agCollector)
 : clCollector(agCollector),atMinimum(agCollector.atMinimum),atMaximum(agCollector.atMaximum) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clExtremaCollector */ /* Destructs the collector. */
 inline clExtremaCollector::~clExtremaCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clExtremaCollector */ /* Copies an extrema collector. */
 inline clExtremaCollector & clExtremaCollector::operator = (ctExtremaCollector & agCollector) {
  clCollector::operator=(agCollector);
  atMinimum=agCollector.atMinimum;
  atMaximum=agCollector.atMaximum;

  return (*this);
 }
 //------------------------------------------------------------------------------------------Maximum
 /*METHOD clExtremaCollector */ /* Returns the maximum value of the collection. */
 inline tyReal clExtremaCollector::maximum(void) const { return (atMaximum); }
 //------------------------------------------------------------------------------------------Minimum
 /*METHOD clExtremaCollector */ /* Returns the minimum value of the collection. */
 inline tyReal clExtremaCollector::minimum(void) const { return (atMinimum); }
}

// M e d i a n C o l l e c t o r  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMedianCollector */ /* Builds a median collector. */
 inline clMedianCollector::clMedianCollector(void)
 : clCollector(),atComputed(true),atMedian(0.0),atValueS() {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMedianCollector */ /* Builds a median collector by copying another one. */
 inline clMedianCollector::clMedianCollector(ctMedianCollector & agCollector)
 : clCollector(agCollector),atComputed(agCollector.atComputed),atMedian(agCollector.atMedian),
   atValueS(agCollector.atValueS) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clMedianCollector */ /* Destructs the collector. */
 inline clMedianCollector::~clMedianCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clMedianCollector */ /* Copies a median collector. */
 inline clMedianCollector & clMedianCollector::operator = (ctMedianCollector & agCollector) {
  clCollector::operator=(agCollector);
  atComputed=agCollector.atComputed;
  atMedian=agCollector.atMedian;
  atValueS=agCollector.atValueS;

  return (*this);
 }
 //-------------------------------------------------------------------------------------------Median
 /*METHOD clMedianCollector */ /* Returns the median value of the collection. */
 inline tyReal clMedianCollector::median(void) const {
  if (not atComputed) {
   clValueS::const_iterator lcIterator;

   atComputed=true;
   lcIterator=atValueS.begin();

   if (atValueS.size()%2==0) {
    std_advance(lcIterator,atValueS.size()/2-1);
    atMedian=*lcIterator;
    atMedian+=*(++lcIterator);
    atMedian/=2;
   }
   else {
    std_advance(lcIterator,atValueS.size()/2);
    atMedian=*lcIterator;
   }
  }

  return (atMedian);
 }
}

// S t a t i s t i c s C o l l e c t o r  Inline //-------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clStatisticsCollector */ /* Builds a statistics collector. */
 inline clStatisticsCollector::clStatisticsCollector(void)
 : clCollector(),clVarianceCollector(),clExtremaCollector(),clMedianCollector() {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clStatisticsCollector */ /* Builds a statistics collector by copying another one. */
 inline clStatisticsCollector::clStatisticsCollector(ctStatisticsCollector & agCollector)
 : clCollector(agCollector),clVarianceCollector(agCollector),clExtremaCollector(agCollector),
   clMedianCollector(agCollector) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clStatisticsCollector */ /* Destructs the collector. */
 inline clStatisticsCollector::~clStatisticsCollector(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clStatisticsCollector */ /* Copies a statistics collector. */
 inline clStatisticsCollector &
 clStatisticsCollector::operator = (ctStatisticsCollector & agCollector) {
  clVarianceCollector::operator=(agCollector);
  clExtremaCollector::operator=(agCollector);
  clMedianCollector::operator=(agCollector);

  return (*this);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// S t a t i s t i c s                                                               Implementation
// C o l l e c t o r
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "statistics/collector.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define STATISTICS_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/statistics/collector.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  statisticsCollector
#define private_area statisticsCollector_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Statistics/Collector");

// Initialization //--------------------------------------------------------------------------------

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// S t o r a g e C o l l e c t o r  Implementation //-----------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clean
 property void clStorageCollector::clean(void) { atValueS.erase(atValueS.begin(),atValueS.end()); }
 //-------------------------------------------------------------------------------------------Update
 property void clStorageCollector::update(tyReal agValue) { atValueS.push_back(agValue); }
}

// M e a n C o l l e c t o r  Implementation //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clean
 property void clMeanCollector::clean(void) { atSum=0.0; }
 //-------------------------------------------------------------------------------------------Update
 property void clMeanCollector::update(tyReal agValue) { atSum+=agValue; }
}

// V a r i a n c e C o l l e c t o r  Implementation //---------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clean
 property void clVarianceCollector::clean(void) {
  clMeanCollector::clean();
  atSquareSum=0.0;
 }
 //-------------------------------------------------------------------------------------------Update
 property void clVarianceCollector::update(tyReal agValue) {
  clMeanCollector::update(agValue);
  atSquareSum+=agValue*agValue;
 }
}

// E x t r e m a C o l l e c t o r  Implementation //-----------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clean
 property void clExtremaCollector::clean(void) {
  atMinimum=0.0;
  atMaximum=0.0;
 }
 //-------------------------------------------------------------------------------------------Update
 property void clExtremaCollector::update(tyReal agValue) {
  if (atCounter==1) {
   atMinimum=agValue;
   atMaximum=agValue;
  }
  else {
   atMinimum=mini(atMinimum,agValue);
   atMaximum=maxi(atMaximum,agValue);
  }
 }
}

// M e d i a n C o l l e c t o r  Implementation //-------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clean
 property void clMedianCollector::clean(void) {
  atComputed=true;
  atMedian=0.0;
  atValueS.erase(atValueS.begin(),atValueS.end());
 }
 //-------------------------------------------------------------------------------------------Update
 property void clMedianCollector::update(tyReal agValue) {
  atComputed=false;
  atValueS.insert(agValue);
 }
}

// S t a t i s t i c s C o l l e c t o r  Implementation //-----------------------------------------
namespace public_area {
 //-------------------------------------------------------------------------------------------Update
 property void clStatisticsCollector::update(tyReal agValue) {
  clVarianceCollector::update(agValue);
  clExtremaCollector::update(agValue);
  clMedianCollector::update(agValue);
 }
 //--------------------------------------------------------------------------------------------Clean
 property void clStatisticsCollector::clean(void) {
  clVarianceCollector::clean();
  clExtremaCollector::clean();
  clMedianCollector::clean();
 }
}

// End //-------------------------------------------------------------------------------------------
}