#include "VectorCpx.h"
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <limits>
#include <iostream>
#include <fstream>

using namespace std;

/*
第一段是Complex class，除了Complex與VectorCpx之間乘法的operator函式以外，都是用助教提供的
*/
/***********************************constructor***********************************/
Complex::Complex(double _real, double _imag): mReal(_real), mImag(_imag)
{

}
/***********************************constructor***********************************/

/*************************************功能函式************************************/
const double& Complex::real() const
{
    return mReal;
}

const double& Complex::imag() const
{
	return mImag;
}

void Complex::real(double value)
{
	mReal = value;
}

void Complex::imag(double value)
{ 
	mImag = value;
}
/*************************************功能函式************************************/

/************************************重載運算子***********************************/
Complex	Complex::operator + (const Complex& cpx)const
{
	Complex cpOut;
	cpOut.real(mReal + cpx.real());
	cpOut.imag(mImag + cpx.imag());
	return cpOut;
}

Complex	Complex::operator - (const Complex& cpx)const
{
	Complex cpOut;
	cpOut.real(mReal - cpx.real());
	cpOut.imag(mImag - cpx.imag());
	return cpOut;
}

Complex	Complex::operator * (const Complex& cpx)const
{
	Complex cpOut;
	cpOut.real( mReal * cpx.real() - mImag * cpx.imag() );
	cpOut.imag( mReal * cpx.imag() + mImag * cpx.real() );
	return cpOut;
}

VectorCpx Complex::operator * (const VectorCpx& vc)const	//Complex*vector的自定義乘法，把每個vector裡的資料都再乘以Complex值。這段要自己寫
{
	VectorCpx outVec;
	
	for(unsigned int i = 0; i < vc.size(); i++)
	{
		Complex cpOut;
		cpOut.real( mReal * vc[i].real() - mImag * vc[i].imag() );
		cpOut.imag( mReal * vc[i].imag() + mImag * vc[i].real() );
		outVec.push_back(cpOut);
	}

	return outVec;
}

Complex	Complex::operator / (const Complex& cpx)const
{
	Complex cpOut;
	double rDiv = cpx.real() * cpx.real() + cpx.imag() * cpx.imag();
	if( rDiv < DBL_MIN) return cpOut;
    cpOut.real( (mReal * cpx.real() + mImag * cpx.imag()) / rDiv );
    cpOut.imag( (mImag * cpx.real() - mReal * cpx.imag()) / rDiv );
	return cpOut;
}
/************************************重載運算子***********************************/

/************************************自定義輸出***********************************/
ostream& operator<<(ostream& ostr, const Complex& cp)
{
    ostr << "R:" << cp.real() << ", I:" << cp.imag();
    return ostr;
}
/************************************自定義輸出***********************************/


//////////////////////////////////////////////////////VectorCpx//////////////////////////////////////////////////////////////////////


/***********************************constructor***********************************/
VectorCpx::VectorCpx():pCpx(NULL),mSize(0),mCapacity(0)	//default constructor，不給預設值的話會造成程式崩潰
{
	//耶不用寫
}

VectorCpx::VectorCpx(unsigned size, const Complex& cpx)	//constructor
{
	int capacity = 1;
	while(size > capacity)	//一直乘到capacity比size大，因為capacity一定是2的次方因此乘以2
		capacity *= 2;

	pCpx = new Complex[capacity];	//最後new出一個該大小的新陣列，把給定的Complex值填進去
	for(int i = 0; i < size; i++)
		pCpx[i] = cpx;

	mSize = size;
	mCapacity = capacity;
}

VectorCpx::VectorCpx(unsigned capacity)	//constructor，因為實在很不爽一定要給資料數量和資料內容才能做vector，所以自己寫了一個只要給capatity就可以做出一個空vector
{
	pCpx = new Complex[capacity];
	mSize = 0;
	mCapacity = capacity;
}

VectorCpx::VectorCpx(const VectorCpx& vc) //copy constructor
{
	mSize = vc.mSize;
	mCapacity = vc.mCapacity;

	pCpx = new Complex[mCapacity];

	for(unsigned int i = 0; i < mSize; i++)
		pCpx[i] = vc.pCpx[i];
}

VectorCpx::~VectorCpx()	//destructor
{
	delete[] pCpx;
}
/***********************************constructor***********************************/

/*************************************功能函式************************************/
VectorCpx& VectorCpx::push_back(const Complex& cpx)	//這個函式是要把一個值存到vector裡
{
	if(mSize == mCapacity)	//如果原本的vector已經滿了，那就做一個新的vector，大小會是原本vector兩倍
	{
		VectorCpx newVec(mCapacity + 1, cpx);	//這裡的mCapacity+1，事實上等於newVec的mSize。為了省事全部填入cpx
		for(unsigned int i = 0; i < mSize; i++)	//然後除了位於位置mCapacity+1上的cpx，前面全部換回原本pCpx vector裡的所有值
		{
			const Complex reg = pCpx[i];
			newVec.pCpx[i] = reg;
		}
		delete[] pCpx;	//別忘記砍掉它，它已經沒有利用價值了

		return newVec;
	}
	else
	{
		pCpx[mSize] = cpx;	//沒滿的話就直接扔進去就好
		return *this;
	}
}

VectorCpx& VectorCpx::resize(unsigned place)
{
	VectorCpx newVec(place, Complex(0.0,0.0));
	delete[] pCpx;
	return newVec;
}

VectorCpx& VectorCpx::resize(unsigned place, const Complex& cpx)
{
	/*
	這個函式會傳入一個整數place，可能還會有一個Complex cpx。
	如果傳入的整數比vector的大小還大，那就把vector擴張到適合的大小，並且從原本的資料之後一直到place的位置都填入cpx，如果當初沒有傳入cpx則填0
	如果傳入的整數比vector裡面資料個數還少，那vector大小不變，但原本的資料從尾開始砍到剩下符合的數量
	*/
	if(place >= mSize)
	{
		VectorCpx newVecBig(place, cpx);

		for(unsigned int i = 0; i < mSize; i++)
			newVecBig.pCpx[i] = pCpx[i];

		delete[] pCpx;
		return newVecBig;
	}
	else
	{
		VectorCpx newVecSmall(mCapacity);

		for(unsigned int i = 0; i < place; i++)
			newVecSmall.pCpx[i] = pCpx[i];

		delete[] pCpx;
		newVecSmall.mSize = place;
		return newVecSmall;
	}
}

unsigned VectorCpx::size() const	//回傳size大小
{
	return mSize;
}

unsigned VectorCpx::capacity() const	//回傳capacity大小
{
	return mCapacity;
}

/*Complex VectorCpx::output(int place) const	//回傳vector裡特定位置的值
{
	return pCpx[place];
}*/
/*************************************功能函式************************************/

/************************************重載運算子***********************************/
Complex VectorCpx::operator*(const VectorCpx& vc) const	//vector*vector的自定義乘法，把每個香對應位置的Complex值乘起來之後全部加起來回傳，有多出來的不用管他
{
	Complex result;

	if(mSize >= vc.mSize)
	{
		for(unsigned int i = 0; i < vc.mSize; i++)
			result = result + pCpx[i] * vc.pCpx[i];
	}
	else
	{
		for(unsigned int i = 0; i < mSize; i++)
			result = result + pCpx[i] * vc.pCpx[i];
	}

	return result;
}

VectorCpx VectorCpx::operator*(const Complex& cpx) const	//vector*Complex的自定義乘法，把每個vector裡的資料都再乘以Complex值
{
	for(unsigned int i = 0; i < mSize; i++)
		pCpx[i] = pCpx[i] * cpx;

	return *this;
}

Complex& VectorCpx::operator[](const int& place) const	//vector的自定義中括號，vc[i]即可得到位於vector vc中i位置的值
{
	if(place < 0)	//如果輸入位置小於0，則自動變成0
		return pCpx[0];
	else if(place >= mSize)	//如果輸入位置超過資料數目，則扔出最後一筆
		return pCpx[mSize - 1];
	else
		return pCpx[place];
}

VectorCpx VectorCpx::operator=(const VectorCpx vc) const	//vector的自定義=符號
{
	VectorCpx newVec(vc.mSize, Complex(0.0,0.0));

	for(unsigned int i = 0; i < mSize; i++)
		newVec.pCpx[i] = vc.pCpx[i];

	delete[] pCpx;
	return newVec;
}
/************************************重載運算子***********************************/

/************************************自定義輸出***********************************/
ostream& operator<<(ostream& ostr, const VectorCpx vc)
{
	unsigned int size = vc.size();
	
	if(size==0)	//由於size和vc.size()都是unsigned型態，如果直接在下面的for迴圈0-1，會直接跳到最大值去，造成程式無法結束，因此要另外設一個size==0的if判斷式
	{
		ostr << endl;
		return ostr;
	}

	for(unsigned int i = 0; i < size - 1; i++)
		ostr << vc[i] << "; ";

	ostr << vc[size - 1] << endl;

	return ostr;
}
/************************************自定義輸出***********************************/