int main()
{
	// DON'T FORGET TO MODIFY EXCELIMPORTS.CPP for correct version of Excel.

	long N = 40;

	// Create abscissa x array
	Vector<double, long> x(N,0.0);
	double T = 10.0;
	double h = T/double(N);
	x[x.MinIndex()] = 0.0;
	x[x.MaxIndex()] = T;
	for (long j = x.MinIndex()+1; j <= x.MaxIndex()-1; ++j)
	{
		x[j] = x[j-1] + h;
	}

	Vector<double, long> vec1(N,0.0);
	for (long j = vec1.MinIndex(); j <= vec1.MaxIndex(); ++j)
	{
		vec1[j] = pow(-1.0, j);
	}
	
	std::cout << "Data has been created\n";

	try 
	{
		printOneExcel(x,vec1,	std::string("1 array"), std::string("Time"), std::string("Value"));
	}
	catch(DatasimException& e)
	{
		e.print();
	}

	try 
	{
		printOneExcel(x,vec1); // Default annotation settings
	}
	catch(DatasimException& e)
	{
		e.print();
	}

	return 0;
}
		void displayinExcel( OptionValueType yval)
		{

			string text("Value");
			if (yval == Delta)
			{
				text = string("Delta");
			}
			if (yval == Gamma)
			{
				text = string("Gamma");
			}

			if (yval == Vega)
			{
				text = string("Vega");
			}

			if (yval == Theta)
			{
				text = string("Theta");
			}
			if (yval == Rho)
			{
				text = string("Rho");
			}

			if (yval == Coc)
			{
				text = string("Coc");
			}

			Vector<double, long> yarr = calculate(yval);
		//	cout << "array ..."; int yy; cin >> yy;
		//	print(yarr);
			printOneExcel(XARR, yarr, text);
		}
int main()
{
	// Set all ranges
	Range<double> X(Xfrom,Xto);
	Range<double> T(Yfrom,Yto);
	
	// Declare all TwoVarDFunctions
	TwoVarDFunction<double,double,double> Sigma(*sigma);
	TwoVarDFunction<double,double,double> Mu(*mu);
	TwoVarDFunction<double,double,double> Forcing(*forcing);
	TwoVarDFunction<double,double,double> B(*b);
	
	// Declare all AtomicDFunctions
	AtomicDFunction<double,double> Ic(*IC); // Change from Call<->Put
//	AtomicDFunction<double,double> Bcr(*BCR_Topper_p11);
	AtomicDFunction<double,double> Bcr(*BCR);// Change from Call<->Put
	AtomicDFunction<double,double> Bcl(*BCL);// Change from Call<->Put
	
	// Declare the pde
	ParabolicPDE<double,double,double> pde(X,T,Sigma,Mu,B,Forcing,Ic,Bcl,Bcr);

	// Declare the finite difference scheme
//	ParabolicFDM<double,double,double> FDM(pde,XINTERVALS,YINTERVALS,THETA); // V1
	int choice = 3;
	cout << "1) Explicit Euler 2) Implicit Euler 3) Crank Nicolson ";
	cin >> choice;

	//OptionType type = AmericanCallType;
	OptionType type = EuropeanCallType;

	ParabolicFDM<double,double,double> FDM(pde,XINTERVALS,YINTERVALS,choice,
											type);

	// compute option prices
	FDM.start();
	
	// Retrieve and store option prices
	Vector <double,long> result = FDM.line(); // Does include ENDS!!


///////////////////////////////////////////////////////////

	Vector<double, long> xArr = FDM.xarr();
	Vector<double, long> tArr = FDM.tarr();

	double h = xArr[2] - xArr[1];
	double k = tArr[2] - tArr[1];

	cout << "h " << h << endl;

	// Create and fill Delta vector
	Vector <double,long> DeltaMesh(xArr.Size()-2, xArr.MinIndex());
	for (long kk = DeltaMesh.MinIndex(); kk <= DeltaMesh.MaxIndex(); kk++)
	{
		DeltaMesh[kk] = xArr[kk+1];
	}

	Vector <double,long> Delta(result.Size()-2,result.MinIndex());
	for (long i = Delta.MinIndex(); i <= Delta.MaxIndex(); i++)
	{
		Delta[i] = (result[i+1] - result[i])/(h);
	}
	print(result);
	print(Delta);

	// Create and fill Gamma vector
	Vector <double,long> GammaMesh(DeltaMesh.Size()-2, DeltaMesh.MinIndex());
	for (long p = GammaMesh.MinIndex(); p <= GammaMesh.MaxIndex(); p++)
	{
		GammaMesh[p] = DeltaMesh[p+1];
	}

	Vector <double,long> Gamma(Delta.Size()-2, Delta.MinIndex());
	for (long n = Gamma.MinIndex(); n <= Gamma.MaxIndex(); n++)
	{
		Gamma[n] = (Delta[n+1] - Delta[n])/(h);
	}

	/*// Create and fill Theta vector
	Vector <double,long> ThetaMesh(tArr.Size()-1, tArr.MinIndex());
	for (long m = ThetaMesh.MinIndex(); m <= ThetaMesh.MaxIndex(); m++)
	{
		ThetaMesh[m] = tArr[m+1];
	}*/

	long NP1 = FDM.result().MaxRowIndex();
	long NP = FDM.result().MaxRowIndex() -1;

	Vector <double,long> Theta(result.Size(), result.MinIndex());
	for (long ii = Theta.MinIndex(); ii <= Theta.MaxIndex(); ii++)
	{
		Theta[ii] = -(FDM.result()(NP1, ii) -FDM.result()(NP, ii) )/k;
	}

	try
	{
		printOneExcel(FDM.xarr(), result, string("Price"));
		printOneExcel(DeltaMesh, Delta, string("Delta"));
		printOneExcel(GammaMesh, Gamma, string("Gamma"));
		printOneExcel(FDM.xarr(), Theta, string("Theta"));

	}
	catch(DatasimException& e)
	{
		e.print();

		ExcelDriver& excel = ExcelDriver::Instance();
		excel.MakeVisible(true);	

		long y = 1;
		excel.printStringInExcel(e.Message(), y, y, string("Err"));

		list<string> dump;
		dump.push_back(e.MessageDump()[0]);
		dump.push_back(e.MessageDump()[1]);
		dump.push_back(e.MessageDump()[2]);

		excel.printStringInExcel(dump, 1, 1, string("Err"));

		return 0;
	}

	return 0;
}