// Implementation file for the Vector class
// Created by:		Michael Edwards
// Date Started:	6/17/04
// Date Finished:
// Compiler Used:	Microsoft Visual C++, Version 6.0 Enterprise Edition

#ifndef MCL_VECTOR_CPP
#define MCL_VECTOR_CPP

#include "Vector.h"

namespace MCL
{
	////////////////////////////////////////////////////////////////////////////////
	// VECTOR::ITERATOR METHOD DEFINITIONS
	////////////////////////////////////////////////////////////////////////////////
/*
	template <class NumberType>	
	Vector<NumberType>::Iterator::Iterator(const Vector<NumberType>* userVector, 
												unsigned userRow, unsigned userColumn):
		myVector(userVector), row(userRow), column(userColumn)
	{
		// NOTE:  Must be >= so that end iterator could be created
		assert((userVector->row >= row) && (userVector->column >= column));
		rowIterator = (userVector->row != 1) ? true: false;
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator::Iterator(const Iterator& rhs): myVector(rhs.myVector), 
		row(rhs.row), column(rhs.column), rowIterator(rhs.rowIterator)
	// copy constructor
	// PRECONDITION:  none.
	// POSTCONDITION:
	{
	}

	template <class NumberType>	
	NumberType Vector<NumberType>::Iterator::operator*() const
	// Dereferencing operator
	// PRECONDITION:  the Iterator is at a valid position
	// POSTCONDITION:
	{
		if (rowIterator)
		{
			assert(myVector->row > row);
			return myVector->data[row][0];
		}
		else
		{
			assert(myVector->column > column);
			return myVector->data[0][column];
		}
	}

	template <class NumberType>	
	NumberType& Vector<NumberType>::Iterator::operator*()
	// Dereferencing operator
	// PRECONDITION:  the Iterator is at a valid position
	// POSTCONDITION:
	{
		if (rowIterator)
		{
			assert(myVector->row > row);
			return myVector->data[row][0];
		}
		else
		{
			assert(myVector->column > column);
			return myVector->data[0][column];
		}
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator& Vector<NumberType>::Iterator::operator++()
	// Prefix increment operator
	// PRECONDITION:
	// POSTCONDITION:
	{
		if (rowIterator)
			++row;
		else
			++column;
		return *this;
	}		

	template <class NumberType>	
	Vector<NumberType>::Iterator Vector<NumberType>::Iterator::operator++(int)
	// Postfix increment operator
	// PRECONDITION:  none.
	// POSTCONDITION:
	{
		Iterator temp(*this);
		if (rowIterator)
			++row;
		else
			++column;
		return temp;
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator& Vector<NumberType>::Iterator::operator--()
	// Prefix decrement operator
	// PRECONDITION:  none.
	// POSTCONDITION:
	{
		if (rowIterator)
			--row;
		else
			--column;
		return *this;
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator Vector<NumberType>::Iterator::operator--(int)
	// Postfix decrement operator
	// PRECONDITION:  none.
	// POSTCONDITION:
	{
		Iterator temp(*this);
		if (rowIterator)
			--row;
		else
			--column;
		return temp;
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator& Vector<NumberType>::Iterator::operator=(const Iterator& rhs)
	// Assignment operator
	// PRECONDITION:  none.
	// POSTCONDITION:
	{
		myVector	= rhs.myVector;
		row			= rhs.row;
		column		= rhs.column;
		rowIterator = rhs.rowIterator;

		return *this;
	}

	template <class NumberType>	
	bool Vector<NumberType>::Iterator::operator==(const Iterator& rhs) const
	// PRECONDITION:
	// POSTCONDITION:
	{
		return ((myVector == rhs.myVector ) && (row == rhs.row) && (column == rhs.column));
	}

	template <class NumberType>	
	bool Vector<NumberType>::Iterator::operator!=(const Iterator& rhs) const
	// PRECONDITION:
	// POSTCONDITION:
	{
		return !((myVector == rhs.myVector ) && (row == rhs.row) && (column == rhs.column));
	}
*/
	////////////////////////////////////////////////////////////////////////////////
	// VECTOR METHOD DEFINITIONS
	////////////////////////////////////////////////////////////////////////////////
	template <class NumberType>	
	Vector<NumberType>::Vector(const Point<NumberType>& begin, const Point<NumberType> &end): 
		Matrix<NumberType>(1, begin.GetDimension())
	{
		assert(begin.GetDimension() == end.GetDimension());
		for (unsigned i = 0; i < column; ++i)
			data[0][i] = end[i] - begin[i];
	}

	template <class NumberType>	
	Vector<NumberType>::Vector(const Matrix<NumberType>& rhs)
	{
		if (rhs.GetColumn() != 1)
			// create a row matrix
			Matrix<NumberType>::Initialize(1, rhs.GetColumn(), (const NumberType**)rhs.Matrix<NumberType>::ToFloat());
		else
			// create a column matrix
			Matrix<NumberType>::Initialize(rhs.GetRow(), 1, (const NumberType**)rhs.Matrix<NumberType>::ToFloat());
	}

	template <class NumberType>	
	Vector<NumberType>::Vector(const Vector& rhs): Matrix<NumberType>(rhs.GetRow(), 
		rhs.GetColumn(), (const NumberType**)rhs.Matrix<NumberType>::ToFloat())
	{
	}

	template <class NumberType>	
	NumberType Vector<NumberType>::operator[](unsigned k) const
	// grabs member pk from the coordinate set
	// PRECONDITION:  k: [0, dimension)
	// POSTCONDITION: pk is returned.
	{
		if (row == 1)
		{
			assert(k < column);
			return data[0][k];
		}
		else
		{
			assert(k < row);
			return data[k][0];
		}
	}

	template <class NumberType>	
	NumberType& Vector<NumberType>::operator[](unsigned k)
	// grabs member pk from the coordinate set
	// PRECONDITION:  k: [0, dimension)
	// POSTCONDITION: pk is returned.
	{
		if (row == 1)
		{
			assert(k < column);
			return data[0][k];
		}
		else
		{
			assert(k < row);
			return data[k][0];
		}
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator Vector<NumberType>::Begin() const 
	// PRECONDITION:
	// POSTCONDITION:
	{
		return Iterator(this, 0, 0);
	}

	template <class NumberType>	
	NumberType Vector<NumberType>::Dot(const Vector& rhs)
	// returns the dot product between two Vectors
	// PRECONDITION:  the size of rhs == the size of this
	// POSTCONDITION:
	{
		NumberType dot = 0.0;
		Vector::Iterator thisIterator, rhsIterator;
		for (thisIterator = Begin(), rhsIterator = rhs.Begin();
			 (thisIterator != End()) || (rhsIterator != rhs.End());
			 ++thisIterator, ++rhsIterator)
			dot += *thisIterator * *rhsIterator;
		assert( (thisIterator == End()) && (rhsIterator == rhs.End()) );

		return dot;
	}

	template <class NumberType>	
	Vector<NumberType>::Iterator Vector<NumberType>::End() const
	// PRECONDITION:
	// POSTCONDITION:
	{
		return (row != 1) ? Iterator(this, row, 0): Iterator(this, 0, column);
	}

	template <class NumberType>	
	NumberType Vector<NumberType>::Magnitude() const
	{
		NumberType magnitude = 0.0f;
		for (Vector::Iterator thisIterator = Begin(); thisIterator != End(); ++thisIterator)
			magnitude += *thisIterator * *thisIterator;
		return magnitude;
	}

	template <class NumberType>	
	Vector<NumberType> Vector<NumberType>::Normalize() const
	// returns the normalized value of the Vector
	// PRECONDITION:
	// POSTCONDITION:
	{
		Vector temp(*this);
		NumberType magnitude = Magnitude();
		assert(magnitude != 0);
		for (Vector::Iterator tempIterator = temp.Begin(); tempIterator != temp.End(); 
		  ++tempIterator)
			*tempIterator /= magnitude;
		return temp;
	}

	template <class NumberType>	
	Vector<NumberType> Vector<NumberType>::Transpose() const
	// Transposes a vector and returns a vector
	{
		return Vector<NumberType>(this->Matrix<NumberType>::Transpose());
	}
}

#endif