// File:            vector.cpp
// ----------------------------------------------------------------------
//         Author:  Russell Lowke, lowke@fas.harvard.edu
//             TF:  Francis Crick
//  Date modified:  7/24/2002
//     Assignment:  Unit 6 Main programming exercises
//        Version:	1
//
//    Description: Class named vector that can be used to represent ordered
//				   tuples of integers.
//
//        Methods:
// 		   vector() - Primary constructor
// 		  ~vector() - Destructor
// 		   vector() - deep copy constructor
// initComponents() - ensure all values in components = 0
//      set_value() - set value of vector [i] to [value]
//      get_value() - return value at [i]
//       get_norm() - return 'norm' of values in the vector   v_0^2 + v_1^2 + ... + v_n^2
//    operator <<() - overload << to print/output vectors
//    operator ==() - overload == to compare two vectors
//     operator +() - overload + to add two vectors
//     operator -() - overload - to subtract two vectors
//     operator *() - overload * to return sum of the pairwise products
//     operator =() - overload = assign one vector to another using deep copies
//
//          Notes:	(none)
//

#include "vector.hpp"


//
// Primary constructor
//
vector::vector(int n)
{
    length = n;
    components = new int[length];
    initComponents();
}


//
//  destructor
//
vector::~vector()
{
	delete [] components;
}


//
//  deep copy constructor
//
vector::vector(const vector& v)
{
    length = v.length;
    components = new int[length];
    initComponents();
    for (int i = 0; i < length; i++) {
    	components[i] = v.components[i];
    }
}


//
//  ensure all values in components = 0
//
void vector::initComponents()
{
	for (int i = 0; i < length; i++) {
		components[i] = 0;
	}
}


//
//  set value of vector [i] to [value]
//
void vector::set_value(int i, int value)
{
	assert(i >= 0 && i < length);	// ensure valid i
	components[i] = value;
}


//
//  return value at [i]
//
int vector::get_value(int i)
{
	assert(i >= 0 && i < length);	// ensure valid i
	return (components[i]);
}


//
//  return norm of values in the vector
//  v_0^2 + v_1^2 + ... + v_n^2
//
double vector::get_norm()
{
	int value = 0;
	
	for (int i = 0; i < length; i++) {
		value += components[i] * components[i];
	}
	return sqrt(value);
}

//
//  overload << to print/output vectors
//
ostream& operator <<(ostream& os, const vector& v)
{ 
	os << "{ ";
	for (int i = 0; i < v.length; i++) {
		os << v.components[i] << " ";
	}
	os << "}";
	
    return os;
}


//
//  overload == to compare two vectors
//
bool operator ==(const vector& v1, const vector& v2)
{
	if (v1.length != v2.length) {			// test lengths are equal
		return false;
		
	} else {
	
		// check each component
		for (int i = 0; i < v1.length; i++) {	
			if ( v1.components[i] != v2.components[i] ) {
				return false;
			}
		}
	}
	
	return true;							// must be equal
}


//
//  overload + to add two vectors
//
vector operator +(const vector& v1, const vector& v2)
{
	assert(v1.length == v2.length);
	
	vector nVect(v1.length);
	
	for(int i = 0; i < v1.length; i++) {
		nVect.components[i] = v1.components[i] + v2.components[i];
	}
	
	return nVect;
}


//
//  overload - to subtract two vectors
//
vector operator -(const vector& v1, const vector& v2)
{
	assert(v1.length == v2.length);
	
	vector nVect(v1.length);
	
	for(int i = 0; i < v1.length; i++) {
		nVect.components[i] = v1.components[i] - v2.components[i];
	}
	
	return nVect;
}


//
//  overload * to return sum of the pairwise products
//
int operator *(const vector& v1, const vector& v2)
{
	int mVal = 0;
	
	assert(v1.length == v2.length);
	
	for(int i = 0; i < v1.length; i++) {
		mVal += v1.components[i] * v2.components[i];
	}
	
	return mVal;
}

//
//  overload = assign one vector to another using deep copies
//
const vector& vector::operator =(const vector& v)
{
    // Make sure not to erase when we try to assign to itself.
    if (&v != this) {
    
    	// deep copy
		length = v.length;
    	if (components != NULL) {
    		delete [] components;
    	}
    	components = new int[length];
    	initComponents();
    	for (int i = 0; i < length; i++) {
    		components[i] = v.components[i];
    	}
    }
    
    return *this;
}