#include "protoAverage.h"
#include "protoDebug.h"
#include "math.h"
#include <limits>
using std::numeric_limits;
ProtoAverage::ProtoAverage() : count(0)
{
}
ProtoAverage::~ProtoAverage()
{
}
void
ProtoAverage::Reset()
{
list.Destroy();
count = 0;
}
bool
ProtoAverage::AddNumber(double number)
{
count++;
if(list.IsEmpty())
{
AverageItem* newItem = new AverageItem(number);
list.Prepend(*newItem);
return true;
}
if(list.GetHead()->GetDepth()!=0) {
AverageItem* newItem = new AverageItem(number);
list.Prepend(*newItem);
} else { AverageList::Iterator iterator(list);
AverageItem tempItem(number);
AverageItem* firstItemPtr = &tempItem;
AverageItem* secondItemPtr = list.GetHead();
while(firstItemPtr->GetDepth()==secondItemPtr->GetDepth())
{
if(!secondItemPtr->Merge(*firstItemPtr))
{
TRACE("failed merging numbers!\n");
return false;
}
if(firstItemPtr==list.GetHead())
{
firstItemPtr = list.RemoveHead();
delete firstItemPtr;
}
iterator.Reset();
firstItemPtr = iterator.GetNextItem();
secondItemPtr = iterator.GetNextItem();
if(secondItemPtr==NULL)
{
return true;
}
}
}
return true;
}
double
ProtoAverage::GetAverage()
{
AverageList::Iterator iterator(list);
AverageItem* item = iterator.GetNextItem();
if(item!=NULL)
{
ProtoAverage::AverageItem tempItem(item->GetValue()); tempItem.SetDepth(item->GetDepth());
double x , y, z;
double dpx=0;
double dpy=0;
double dpz=0;
double numeral;
double denom;
while((item = iterator.GetNextItem()))
{
x = tempItem.GetValue();
dpx = tempItem.GetDepth();
y = item->GetValue();
dpy = item->GetDepth();
numeral = (x + y * pow(2,dpy-dpx));
if(numeral==numeric_limits<double>::infinity()){
numeral = (x * pow(2,dpx-dpy) + y);
denom = (pow(2,dpx-dpy)+1);
}
else
{
denom = (1+pow(2,dpy-dpx));
}
z = numeral/denom; dpz = log(denom)/log(2)+dpx; dpz = log(1+pow(2,dpy-dpx))/log(2)+dpx;
tempItem.SetValue(z);
tempItem.SetDepth(dpz);
}
return tempItem.GetValue();
}
return 0;
}
unsigned long
ProtoAverage::GetCount() const
{
return count;
}
void
ProtoAverage::Print()
{
AverageList::Iterator iterator(list);
AverageItem* item;
while((item = iterator.GetNextItem()))
{
TRACE("(%f,%f) ",item->GetValue(),item->GetDepth());
}
TRACE("\n");
}
bool
ProtoAverage::AverageItem::Merge(const ProtoAverage::AverageItem &otherItem)
{
double tempvalue = 0;
if(otherItem.GetDepth()!=GetDepth())
{
return false;
}
tempvalue = (value + otherItem.GetValue())/2;
if(tempvalue==numeric_limits<double>::infinity())
{
value = value/2 + otherItem.GetValue()/2;
} else {
value = tempvalue;
}
if(value==numeric_limits<double>::infinity())
{
TRACE("still getting inf\n");
TRACE("%f\n\n",value/2);
TRACE("%f\n\n",otherItem.GetValue()/2);
TRACE("%f\n\n",value/2+otherItem.GetValue()/2);
return false;
}
depth = depth+1;
return true;
}
void
ProtoAverage::AverageItem::SetValue(double v)
{
value = v;
return;
}
void
ProtoAverage::AverageItem::SetDepth(double d)
{
depth = d;
return;
}