// BigVector.cpp: implementation of the CBigVector class.
//
// Implementation of a vector of any arbitrary size.
// The storage for the vector elements is a double array heap
// (see DoubleArrayHeap.h) which amortizes often reallocations
// of a small number of vectors.
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GLUtils.h"
#include "BigVector.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// creates an empty vector
CBigVector::CBigVector():
	m_pCells(NULL), m_nSize(0), m_nCapacity(0)
{
}

// copies the source vector
CBigVector::~CBigVector()
{
	if (m_pCells)
		delete [m_nCapacity] m_pCells;
}

// copies the source vector
CBigVector::CBigVector (const CBigVector& vThat):
	m_pCells(NULL), m_nSize(0), m_nCapacity(0)
{
	(*this) = vThat;
}

// copies the source vector
CBigVector& CBigVector::operator = (const CBigVector& vThat)
{
	Resize (vThat.m_nCapacity);
	memcpy (m_pCells, vThat.m_pCells, m_nCapacity*sizeof(m_pCells[0]));
	m_nSize = vThat.m_nSize;
	return *this;
}

// creates a vector with the given size,
// the vector is initially filled with garbage
CBigVector::CBigVector (int nLength):
	m_pCells(NULL), m_nSize(0), m_nCapacity(0)
{
	Resize (nLength);
}

//////////////////////////////////////////////////////////////////////
// resizes the vector; the contents is completely lost
// but it is guaranteed that as long as capacity is not reached,
// the content of this vector won't be altered
//////////////////////////////////////////////////////////////////////
void CBigVector::Resize (int nNewSize)
{
	if (nNewSize > m_nCapacity)
	{
		if (m_pCells)
			delete [m_nCapacity] m_pCells;

		m_pCells = new double [m_nSize = m_nCapacity = nNewSize];
	}
	else
	{
		m_nSize = nNewSize;
	}
}

// returns the current vector size
int CBigVector::GetSize () const
{
	return m_nSize;
}

// vector maximum capacity
int CBigVector::GetCapacity() const
{
	return m_nCapacity;
}

// nCell-th vector element
double& CBigVector::operator [] (int nCell)
{
	assert(nCell >=0 && nCell < m_nSize);
	return m_pCells [nCell];
}

// nCell-th vector element
double CBigVector::operator [] (int nCell) const
{
	assert(nCell >=0 && nCell < m_nSize);
	return m_pCells[nCell];
}

// returns norm of this matrix
double CBigVector::GetNorm ()const
{
	double fSum = 0; 
	for (int i = 0; i < m_nSize; ++i)
		fSum += tsqr(m_pCells[i]);
	return fSum;
}

// zeroes out the vector elements
void CBigVector::SetZero()
{
	for (int i = 0; i < m_nSize; ++i)
		m_pCells[i] = 0;
}

// returns the maximum element in the vector
double CBigVector::GetMaxElement()
{
	assert (m_nSize > 0);
	double fResult = m_pCells[0];
	for (int i = 1; i < m_nSize; ++i)
		if (fResult < m_pCells[i])
			fResult = m_pCells[i];
	return fResult;
}

double CBigVector::GetMinElement()
{
	assert (m_nSize > 0);
	double fResult = m_pCells[0];
	for (int i = 1; i < m_nSize; ++i)
		if (fResult > m_pCells[i])
			fResult = m_pCells[i];
	return fResult;
}

// subtracts the vectors
CBigVector operator - (const CBigVector& vLeft, const CBigVector& vRight)
{
	assert (vLeft.GetSize() == vRight.GetSize());
	CBigVector bvResult(vLeft.GetSize());;
	for (int i = 0; i < bvResult.GetSize(); ++i)
		bvResult[i] = vLeft[i] - vRight[i];
	return bvResult;
}


// sorts all the elements in the vector
void CBigVector::Sort()
{
	std::sort (m_pCells, m_pCells + m_nSize);
}


void CBigVector::DebugDump()
{
	char sz[64];
	sprintf(sz, "BigVector(%d)[", GetSize());
	OutputDebugString (sz);
	for (int i = 0; i < GetSize(); ++i)
	{
		if (i)
			OutputDebugString(",");
		sprintf (sz, "%.3g", m_pCells[i]);
		OutputDebugString(sz);
	}
	OutputDebugString ("]\n");
}