#include "core_headers.h"

// Initialise an empirical distribution
EmpiricalDistribution::EmpiricalDistribution()
{
	Reset();
}


EmpiricalDistribution::~EmpiricalDistribution()
{
	// Here, would deallocate sample_values array
}

void EmpiricalDistribution::Reset()
{
	sum_of_samples = 0.0;
	sum_of_squared_samples = 0.0;
	number_of_samples = 0;
	minimum = std::numeric_limits<float>::max();
	maximum = - std::numeric_limits<float>::max();
	is_constant = true;
	last_added_value = 0.0;
}

void EmpiricalDistribution::AddSampleValue(float sample_value)
{
	sum_of_samples += sample_value;
	sum_of_squared_samples += pow(sample_value,2);
	number_of_samples++;
	minimum = std::min(minimum,sample_value);
	maximum = std::max(maximum,sample_value);
	if (number_of_samples == 1)
	{
		is_constant = true;
	}
	else
	{
		is_constant = is_constant && last_added_value == sample_value;
	}
	last_added_value = sample_value;
}

bool EmpiricalDistribution::IsConstant()
{
	return is_constant;
}

float EmpiricalDistribution::GetSampleSumOfSquares()
{
	return sum_of_squared_samples;
}

long EmpiricalDistribution::GetNumberOfSamples()
{
	return number_of_samples;
}

float EmpiricalDistribution::GetSampleSum()
{
	return sum_of_samples;
}

float EmpiricalDistribution::GetSampleMean()
{
	if (number_of_samples > 0)
	{
		return sum_of_samples / float(number_of_samples);
	}
	else
	{
		return 0.0;
	}
}

float EmpiricalDistribution::GetSampleVariance()
{
	if (number_of_samples > 0)
	{
		return (sum_of_squared_samples / float(number_of_samples)) - pow(sum_of_samples/float(number_of_samples),2);
	}
	else
	{
		return 0.0;
	}
}

float EmpiricalDistribution::GetUnbiasedEstimateOfPopulationVariance()
{
	if (number_of_samples > 0)
	{
		return GetSampleVariance() * float(number_of_samples) / float(number_of_samples-1);
	}
	else
	{
		return 0.0;
	}
}
