// NewtonMethod.h: interface for the CNewtonMethod class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NEWTONMETHOD_H__DC19AFC4_3263_4690_8914_B7F21D652DBD__INCLUDED_)
#define AFX_NEWTONMETHOD_H__DC19AFC4_3263_4690_8914_B7F21D652DBD__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

	// Constant Values Replacing Defined Vars in Numerical Recipes
	const int    MAXITS = 200;		// max no. of iterations used in newt()
	const double ALF = 1.0e-4;		// used to ensure suff. decr in fn value, used in lnsrch()
	const double EPS = 1.0e-4;		// epsilon
	const double TINY = 1.0e-20;	// small value used in ludcmp()
	const double TOLF = 1.0e-4;		// sets the cgce criterion on fn vals, used in newt()
	const double TOLMIN = 1.0e-6;	// sets the criterion for deciding whether spurious cgce to a min of fmin has occured, used in newt()
	const double TOLX = 1.0e-7;		// cgce criterion on delta_x, used in lnsrch() and newt()
	const double STPMX = 100.0;		// scaled max step length allowed in line searched, used in newt()

	// Merging of nrutil.h code into the Newton.h file
	static double sqrarg;
	#define SQR(a) ((sqrarg = (a)) == 0.0 ? 0.0 : sqrarg*sqrarg)	

	static double maxarg1, maxarg2;
	#define FMAX(a,b) (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? (maxarg1) : (maxarg2))

	// Satic vars
	static int prec = 15;

	// Classes
	class CNewtonMethod
	{
	public:
		
		// Constr/Destr
		CNewtonMethod();
		CNewtonMethod(int t_cnt, double t, double delta_t);
		virtual ~CNewtonMethod();
		
		// Newton Method related fns
		//void fdjac(int n, float x[], float fvec[], float **df, void (*vecfunc)(int, float [], float []));
		void fdjac(int n, double *x, double *fvec, double **df);
		double fmin(double *x, int n);
		void funcv(int n, double *x, double *f);
		//void lnsrch(int n, float xold[], float fold, float g[], float p[], float x[], float *f, float stpmax, int *check, float (*func)(float [], int n));
		int lnsrch(int n, double *xold, double fold, double *g, double *p, double *x, double *f, double stpmax, int *check);
		void lubksb(double **a, int n, int *indx, double *b);
		int ludcmp(double **a, int n, int *indx, double *d);
		double** memory_dmatrix(int nrows, int ncols);
		void memory_delete_newt(int *indx, double *g, double *p, double *xold, double **fjac, int nrows);
		double* memory_dvector(int n);
		int* memory_ivector(int n);
		//void newt(float x[], int n, int *check, void(*vecfunc)(int, float[], float[]));
		int newt(double *x, int n, int *check);
		//void (CNewtonMethod::*nrfuncv)(int n, float v[], float f[]);
		void nrerror(char *error_text, int nr_status);

		// Checking fns
		void CheckDenomZero(double denom, char *error_text);
		int CheckJacobian(double **fjac, int nrows, int ncols);

		// Printing fns
		int PrintVector(double *v, int ncols);
		int PrintMatrix(double **M, int nrows, int ncols);

	private:
		int m_t_cnt;		// time count
		double m_t;			// time value
		double m_delta_t;	// time step size delta_t
		double *fvec;
	};

#endif // !defined(AFX_NEWTONMETHOD_H__DC19AFC4_3263_4690_8914_B7F21D652DBD__INCLUDED_)
