/*
 * Copyright 2008 Novamente LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package relex.stats;

import java.lang.Math;

/**
 * This class provides simple historgram (bin count) support.
 *
 * Copyright (C) 2008 Linas Vepstas <linas@linas.org> 
 */
public class Histogram implements TruthValue
{
	// strict histogrammng stuff
	private int nbins;
	private double min_value;
	private double max_value;
	private double rate;
	private double delta;
	private int[] bins;
	int underflow;
	int overflow;

	double all_time_high;
	double all_time_low;

	double cnt;
	double sum;
	double sumsq;

	private void init(int _nbins, double low, double high)
	{
		nbins = _nbins;
		min_value = low;
		max_value = high;
		underflow = 0;
		overflow = 0;
		bins = new int[nbins];
		for (int i=0; i<nbins; i++)
		{
			bins[i] = 0;
		}

		rate = nbins / (max_value - min_value);
		delta = 1.0/rate;

		all_time_high = -1.0e38;
		all_time_low = +1.0e38;
	}

	public Histogram(int _nbins, double low, double high)
	{
		init(_nbins, low, high);
	}

	public Histogram(int binmin, int binmax)
	{
		init(binmax-binmin, (double) binmin, (double) binmax);
	}

	public void bin(double value)
	{
		int b = (int) Math.floor (rate * (value - min_value));

		if (b < 0)
		{
			underflow ++;
		}
		else if (b >= nbins)
		{
			overflow ++;
		}
		else
		{
			bins[b] ++;
		}

		if (value < all_time_low) all_time_low = value;
		if (value > all_time_high) all_time_high = value;

		cnt ++;
		sum += value;
		sumsq += value*value;
	}

	public double getCount()
	{
		return cnt;
	}

	public double getMean()
	{
		return sum / ((double) cnt);
	}

	public double getStdDev()
	{
		double var = sumsq / ((double) cnt);
		double exp = getMean();
		var -= exp*exp;
		return Math.sqrt(var);
	}

	public double getConfidence()
	{
		return 1.0;
	}

	public double getAllTimeLow()
	{
		return all_time_low;
	}

	public double getAllTimeHigh()
	{
		return all_time_high;
	}

	public int getOverflow()
	{
		return overflow;
	}
	public int getUnderflow()
	{
		return underflow;
	}

	public double getMedian()
	{
		int half = (int) (cnt / 2.0);
		int lt = underflow;
		if (lt >= half) return min_value;
		for (int i = 0; i<nbins; i++)
		{
			lt += bins[i];
			if (lt >= half) return (((double)i) + 0.5) * delta + min_value;
		}
		return max_value;
	}

	public double getMode()
	{
		int pcnt = underflow;
		int peak = -1;
		for (int i = 0; i<nbins; i++)
		{
			if (bins[i] > pcnt)
			{
				peak = i;
				pcnt = bins[i];
			}
		}
		return (((double)peak) + 0.5) * delta + min_value;
	}

}


@@ -831,17 +831,17 @@
 istogram
-m
+i
 ng stuff
@@ -1009,24 +1009,48 @@
  overflow;%0A%0A
+%09boolean integer_bins;%0A%0A
 %09double all_
@@ -1354,16 +1354,40 @@
 0;%0A%09%09%7D%0A%0A
+%09%09integer_bins = false;%0A
 %09%09rate =
@@ -1689,16 +1689,39 @@
 inmax);%0A
+%09%09integer_bins = true;%0A
 %09%7D%0A%0A%09pub
@@ -2733,16 +2733,78 @@
 n_value;
+%0A%0A%09%09double midpoint = 0.5;%0A%09%09if (integer_bins) midpoint = 0.0;
 %0A%09%09for (
@@ -2887,27 +2887,32 @@
 double)i) + 
-0.5
+midpoint
 ) * delta + 
@@ -3122,24 +3122,85 @@
 %5D;%0A%09%09%09%7D%0A%09%09%7D%0A
+%09%09double midpoint = 0.5;%0A%09%09if (integer_bins) midpoint = 0.0;%0A
 %09%09return (((
@@ -3214,19 +3214,24 @@
 peak) + 
-0.5
+midpoint
 ) * delt

fix up mode and median for integer-sized bins.