/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME vtkGenericMathUtilities - helper class to cram unrelated math utilities.
// .SECTION Description
// Helper class to cram unclassifiable small functions such as compute the
// histogram etc ...

#ifndef __vtkGenericMathUtilities_h
#define __vtkGenericMathUtilities_h

#include "vtkObject.h"
#include <vtkstd/map> //
#include <limits> //

class VTK_EXPORT vtkGenericMathUtilities: public vtkObject
{
public:
  static vtkGenericMathUtilities * New();
  vtkTypeRevisionMacro(vtkGenericMathUtilities, vtkObject);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Get the median of a 1D histogram supplied as an std::map< TType, TCountType >
  // Returns the fraction of the histogram that corresponds to TType. For
  // instance if you had a map (std::map< short, unsigned int >)
  // with 4 entries:
  //
  //  -10 -> 5
  //  4   -> 1
  //  20  -> 10
  //  30  -> 4
  //
  //  Median will be 20. Return value will be 0.5
  //   
  template< class TType, class TCountType >
  static double GetMedian( std::map< TType, TCountType > &histogram, TType & median )
    {
    typedef std::map< TType, TCountType >      MapType;
    typedef std::numeric_limits< TCountType >  NumericCountTraitsType;
    TCountType minVal = NumericCountTraitsType::min();
    TType      minIdx = (TType)0;
    typename MapType::const_iterator it  = histogram.begin();
    typename MapType::const_iterator end = histogram.end();
    
    TCountType total = (TCountType)0;;
    while (it != end)
      {
      if (it->second > minVal)
        {
        minVal = it->second;
        total += it->second;
        minIdx = it->first;
        ++it;
        }
      }
      
    median = minIdx;
    return (double)minVal / (double)total;
    }
  
protected:
  vtkGenericMathUtilities();
  ~vtkGenericMathUtilities();

private:
  vtkGenericMathUtilities(const vtkGenericMathUtilities &); // Not implemented
  void      operator=(const vtkGenericMathUtilities &); // Not implemented
};

#endif
