#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Chart.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <Grids.hpp>
#include <TeEngine.hpp>
#include <TeeProcs.hpp>
#include <Series.hpp>
#include "AdamsStd.cpp"
#include "APErrorSeries.cpp"
#include <Math.h>
#include <Math>

//statistics table

const float chi95table[30] = {
        3.841,  5.991,  7.815,  9.488, 11.070, 12.592, 14.067, 15.507, 16.919, 18.307,
        19.675, 21.026, 22.362, 23.685, 24.996, 26.296, 27.587, 28.869, 30.144, 31.410,
        32.671, 33.924, 35.172, 36.415, 37.652, 38.885, 40.113, 41.337, 42.557, 43.773 };
const float chi80table[30] = {
        1.642,  3.219,  4.642,  5.989,  7.289,  8.558,  9.803, 11.030, 12.242, 13.442,
        14.631, 15.812, 16.985, 18.151, 19.311, 20.465, 21.615, 22.760, 23.900, 25.038,
        26.171, 27.301, 28.429, 29.553, 30.675, 31.795, 32.912, 34.027, 35.139, 36.250 };
const float chi20table[30] = {
        0.064,  0.446,  1.005,  1.649,  2.343,  3.070,  3.822,  4.594,  5.380,  6.179,
        6.989,  7.807,  8.634,  9.467, 10.307, 11.152, 12.002, 12.857, 13.716, 14.578,
        15.445, 16.314, 17.187, 18.062, 18.940, 19.820, 20.703, 21.588, 22.475, 23.364 };
const float chi05table[30] = {
        0.004,  0.103,  0.352,  0.711,  1.145,  1.635,  2.167,  2.733,  3.325,  3.940,
        4.575,  5.226,  5.892,  6.571,  7.261,  7.962,  8.672,  9.390, 10.117, 10.851,
        11.591, 12.338, 13.091, 13.848, 14.611, 15.379, 16.151, 16.928, 17.708, 18.493 };

//messages
const AnsiString chi05msg = "WARNING: The chi-square value from the fit is suspiciously small.  If your error estimates are correct, such a value has less than 1 chance in 20 of occurring.  Possibly your error estimates are too large.  If this is so, then the errors on the fitted parameters are also too large. If in doubt, consult a demonstrator.";
const AnsiString chi20msg = "WARNING: The chi-square value from the fit is small enough to be slightly worrying, but is not strong evidence of an error.  If your error estimates are correct, such a value has less than 1 chance in 5 of occurring.  Possibly your error estimates are too large.  If this is so, then the errors on the fitted parameters are also too large. If in doubt, consult a demonstrator" ;
const AnsiString chi95msg = "WARNING: The chi-square value from the fit is suspiciously large.  If your error estimates are correct, such a value has less than 1 chance in 20 of occurring.  Possibly your error estimates are too small.  If this is so, then the errors on the fitted parameters are also too small. Alternatively, this particular fit is not appropriate for your data. If in doubt, consult a demonstrator." ;
const AnsiString chi80msg = "WARNING: The chi-square value from the fit is large enough to be slightly worrying, but is not strong evidence of an error. If your error estimates are correct, such a value has less than 1 chance in 5 of occurring.  Possibly your error estimates are too small.  If this is so, then the errors on the fitted parameters are also too small. Alternatively, this particular fit is not appropriate for your data." ;

class vec{ // Vector Class declaration
   int n;
   double* p;
public: vec(int x):n(x) {p=new double [n]; }
   friend bool operator<(vec &a,vec &b);
   void newlength(const int l) {delete p; p=new double [n];}
   int no() {return n;}
   double& operator [] (int i) {return p[i];}
   vec operator*(double b);
   vec operator+(vec b);
   vec operator+=(vec b) {*this = *this + b; return *this;}
   vec operator-(vec b);
   vec operator^(double b);
   vec& assign(vec b);
 //  vec& operator= (vec b);
   double maxx();
   vec increment();
   double abssum();
   void setzero(){ for(int k=0;k<n;k++) { (*this)[k] = 0; }}
   };


class matr{ // Matrix Class declaration
	int nrows,ncols;
   vec **p;
public: matr(int r,int c);
   int nr() {return nrows;}
   int nc() {return ncols;}
   vec& operator [] (int i) {return *p[i];}
   double twobytwo(matr cm);
   double cofactor(int j,int k) {return cofactorw(j,k,*this); }
   double cofactorw(int j,int k,matr &m);
   double detm(matr *xx= 0);
   double det() { return detm(); }
   matr tran() ;
   matr operator/(double &d);
   matr operator/(float d);
   vec operator* (vec &d);
   vec operator% (vec &d) {return gaussianelim(d);}
   matr operator+ (matr mm);
   matr operator+= (matr mm){*this = *this + mm; return *this;}
   matr operator- (matr &mm);
   matr operator+ (double &dd);
   matr operator= (double &dd);
   matr operator- (double &dd);
   matr inv();
   void setzero(){ for (int k=0;k<nrows;k++) {(*this)[k].setzero(); } }
   bool sorted();
   void sort(vec &vv);
   vec gaussianelim(vec aa);

   };

template <class T> void swap (T &x, T &y) { //NOT IN USE YET!
        T temp = x; x=y; y=temp;
	}

template <class T> void sorta(T* a,int n) { //NOT IN USE YET!
	for (int i=zero;i<n-one;i++) {
   	for (int j=one+i;j<n;j++) {
      	if (a[i]<a[j])
         {swap(a[i],a[j]);} } }
}

class dataset { // Dataset Class declaration
public:
        friend class bfit;
        bool onminerr;   // if true more accurate numerical methods will be used
        bool onminerrdone; // if true calulation to determine if more accurate numerical methods has been done
        bool bettermethod();
        __property bool high = {read = bettermethod};
        double dmeanx();
        double dmeany();
        double dminx();
        double dminy();
        double dmaxx();
        double dmaxy(); //*/
        double dminywerr();
        double dmaxywerr(); //*/
        AnsiString name;
        char nset;
        int no;
        int ni;
        row<double> *x;
        row<double> *y;
        row<double> *erry;
        row<double> *w;
        long double wxiN(int i,unsigned int no=1);
        long double EwxN(unsigned int no=1);
        long double EwyxN(unsigned int no=1);
        long double EwerrxN(unsigned int no=1);
        long double Ew();
        long double Ewy();
        long double EIwxerrI2N(unsigned int no=1);
        TErrPointSeries *data;
        //TColor colour;
        TColor *colour;
        dataset(bool in=1) {
                if (in==1) {colour = new TColor;} else {colour = 0;}
                x=0; y=0; erry=0; data=0; w=0; primfit = 0; onminerr = false; onminerrdone = false;}
        void __fastcall calw();
        ~dataset() {
                if (data) delete data;
                if (colour) delete colour;
                 }
        bool ToChart(TChart *chart);
        row<double>* operator [] (int i) {
                switch (i) {
                        case 0 : return x;
                        case 1 : return y;
                        case 2 : return erry;
                        default : return x;
                }}
        int dofis(int nnp){ return x->no() - nnp -1; }
        list<bfit> myfits;
        void setprimfit(bfit *fit){myfits.grow(fit);}
        bfit* getprimfit(){return myfits.root->i;}
        __property bfit *primfit = {read = getprimfit, write = setprimfit};
        dataset copy();
        //__property bfit *primfit = {read = myfits.root->i, write = setprimfit};
        //bfit *primfit;
};

class bfit{ // Best Fitted Function Class
public:
        AnsiString name;
        TStrings *consts;
        matr *mmm;
        vec *vvv;
        vec *aaa;
        bfit(int n=2)  { vvv=0; aaa=0; mmm=0;
        bline = 0; resid = 0; lnull = 0; consts = 0; np=2;}
        ~bfit() {
        if (bline) {bline->Clear(); delete  bline; bline =0; }
        if  (mmm) {delete mmm; mmm=0; }
        if (aaa) {delete aaa; aaa=0; }
        if (vvv) {delete vvv; vvv=0; }
        if (lnull) {lnull->Clear(); delete lnull; lnull = 0;}
        if (resid) {resid->Clear(); delete resid; resid = 0;}
        downer = 0;
        }
        unsigned short np;
        double chisqu();
        double lconst[10];
        double errconst[10];
        int dofis(){ return downer->w->no() - np -1;}
        __property int dof = {read = dofis};
        dataset *downer;
        TFastLineSeries *bline;
        TFastLineSeries *lnull;
        TErrPointSeries *resid;
        void __fastcall plot(TChart *chart,TChart *rchart,int ii = 1000) ;
        void go(TChart *chart,TChart *rchart,int ii = 1000,bool mmethod=true) ;
        virtual double  equ(double x)=0;
        virtual void  fitl(bool high=0)=0;
        virtual void  genstrs(TStrings *S, bool on =1)=0;
        virtual AnsiString func(int ii)=0;
        int goodchi();
        AnsiString stringchi();
        void newtonsmethod(vec(*fx)(vec *sol,dataset *d),vec(*fxerri)(vec *sol,double x,double y,double w));
};


class lineronlym: public bfit{ // y=mx
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
public: lineronlym(int n=0) {np=0;}
        };

class linermc: public bfit{// y=mx+c
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: linermc(int n =1) {np=1;}};

class linermcPC1181D: public bfit{// y=mx+c
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S,bool on =1);
        AnsiString func(int ii);
        public: linermcPC1181D(int n =1 ) {np=1;}};

class polynom: public bfit{ // y=E{k=0:n}(a(k) * x ^k)
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: polynom(int n= 2) {np=n;}};

class multfit{ // multifit class
public:
        AnsiString name;
        multfit() { iline = new list<bfit>; matrix =0; equals = 0;}
        ~multfit() { if (iline) delete iline ;}
        list<dataset> dat;
        list<bfit> *iline;
        matr *matrix;
        vec *equals;
        int Count() {return iline->len;}
        bfit& operator[] (int i) { return *(iline->get(i)->i);}
        virtual void __fastcall set(int amount)=0;
        virtual void fitl(TChart* MChart,TChart* resid,bool high=0)=0;
};

class mbfit :public multfit { // multifit class
        void fitl(TChart* MChart,TChart* resid,bool high=0){}
        void __fastcall set(int amount) {}
};

class Mlinear :public multfit {
        void __fastcall set(int amount);
        virtual void fitl(TChart* MChart,TChart* resid,bool high=0)=0;
};
class Mlinearsamem:public Mlinear { public:  void fitl(TChart* MChart,TChart* resid,bool high=0); };
class Mlinearsamec:public Mlinear { public:  void fitl(TChart* MChart,TChart* resid,bool high=0); };



// Sample Fits Routines

class powersq: public bfit{
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: powersq(int n= 1) {np=n;}};

class resonance: public bfit{
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: resonance(int n= 2) {np=n;}};

class periodic: public bfit{
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: periodic(int n= 1) {np=n;}};


class periodicdecay: public bfit{
        double equ(double x);
        void fitl(bool high = 0);
        void genstrs(TStrings *S, bool on =1);
        AnsiString func(int ii);
        public: periodicdecay(int n= 3) {np=n;}};
