// This may look like C code, but it is really -*- C++ -*-
//                         C.Magneville          04/99
#ifndef GENERALDATA_SEEN
#define GENERALDATA_SEEN

#include "objfio.h"
#include <iostream.h>
#include "pexceptions.h"
#include "ppersist.h"
#include "ntupintf.h"
#include "poly.h"

namespace SOPHYA {

class GeneralFit;

//================================================================
// GENERALFITDATA
//================================================================

class GeneralFitData : public AnyDataObj , public NTupleInterface {
  friend class GeneralFit;
  friend class ObjFileIO<GeneralFitData>;
public:
  enum {Def_ErrF = 1, Def_ErrX = 0};

  GeneralFitData(unsigned int nVar, unsigned int nDataAlloc, uint_2 errx=0);
  GeneralFitData(const GeneralFitData& data, bool clean=false);
  GeneralFitData();
  virtual ~GeneralFitData();

  void Alloc(unsigned int nVar, unsigned int nDataAlloc, int_2 errx=-1);
  void SetDataPtr(int ptr = 0);

  void KillData(int i);
  void KillData(int i1,int i2);

  void ValidData(int i);
  void ValidData(int i1,int i2);
  void ValidData();

  void RedefineData1(int i,double x,double f,double err=Def_ErrF,double errx=Def_ErrX);
  void RedefineData2(int i,double x,double y,double f,double err=Def_ErrF
                    ,double errx=Def_ErrX,double erry=Def_ErrX);
  void RedefineData(int i,double* xp,double f,double err=Def_ErrF,double* errxp=NULL);

  void AddData1(double x, double f, double err=Def_ErrF,double errx=Def_ErrX);
  void AddData2(double x, double y, double f, double err=Def_ErrF
               ,double errx=Def_ErrX,double erry=Def_ErrX);
  void AddData(double* xp, double f, double err=Def_ErrF,double* errxp=NULL);
  void AddData(float* xp, float f, float err=Def_ErrF,float* errxp=NULL);

  void SetData1(int nData,double* x,double* f,double *err=NULL,double *errx=NULL);
  void SetData1(int nData,float* x,float* f,float* err=NULL,float *errx=NULL);
  void SetData2(int nData,double* x,double* y,double* f,double *err=NULL
               ,double *errx=NULL,double *erry=NULL);
  void SetData2(int nData,float* x,float* y,float* f,float* err=NULL
               ,float *errx=NULL,float *erry=NULL);
  void SetData(int nData,double** xp,double *f,double *err=NULL,double** errxp=NULL);
  void SetData(int nData,float** xp,float* f,float* err=NULL,float** errxp=NULL);

  void PrintStatus();
  void PrintData(int i);
  void PrintData(int i1,int i2);
  void PrintData();
  void Show(ostream& os) const;
  inline void Show() const {Show(cout);}

  inline int GetSpaceFree() const { return mNDataAlloc - mNData; }
  inline int NVar()       const {return mNVar;}
  inline int NData()      const {return mNData;}
  inline int NDataGood()  const {return mNDataGood;}
  inline int NDataAlloc() const {return mNDataAlloc;}

  inline unsigned short int IsValid(int i) const
                {if(i>=0 && i<mNData) return mOK[i]; else return 0;}
  inline bool HasXErrors() {if(mErrXP) return true; else return false;}

  inline double X1(int i) const
                {if(i>=0 && i<mNData) return mXP[i]; else return 0.;}
  inline double X(int i) const
                {if(i>=0 && i<mNData) return mXP[i*mNVar]; else return 0.;}
  inline double Y(int i) const
                {if(i>=0 && i<mNData && 1<mNVar) return mXP[i*mNVar+1]; else return 0.;}
  inline double Z(int i) const
                {if(i>=0 && i<mNData && 2<mNVar) return mXP[i*mNVar+2]; else return 0.;}
  inline double Absc(int j,int i) const
                {if(i>=0 && i<mNData && j<mNVar)return mXP[i*mNVar+j]; else return 0.;}
  inline double Val(int i) const
                {if(i>=0 && i<mNData) return mF[i]; else return 0.;}

  inline double EX1(int i) const
                {if(mErrXP && i>=0 && i<mNData) return mErrXP[i]; else return 0.;}
  inline double EX(int i) const
                {if(mErrXP && i>=0 && i<mNData) return mErrXP[i*mNVar]; else return 0.;}
  inline double EY(int i) const
                {if(mErrXP && i>=0 && i<mNData && 1<mNVar) return mErrXP[i*mNVar+1];
                 else return 0.;}
  inline double EZ(int i) const
                {if(mErrXP && i>=0 && i<mNData && 2<mNVar) return mErrXP[i*mNVar+2];
                 else return 0.;}
  inline double EAbsc(int j,int i) const
                {if(mErrXP && i>=0 && i<mNData && j<mNVar) return mErrXP[i*mNVar+j];
                 else return 0.;}
  inline double EVal(int i) const
                {if(i>=0 && i<mNData) return mErr[i]; else return 0.;}

  r_8* GetVec(int n, r_8* ret=NULL)  const;
  r_4* GetVecR4(int n, r_4* ret=NULL)  const;
  int GetMnMx(int var,int& imin,int& imax) const;
  int GetMnMx(int var,double& min,double& max) const;
  int GetMeanSigma(int var,double& mean,double& sigma,double min=1.,double max=-1.);
  int GetMoMeMed(int var,double& mode,double& mean,double& median,
                 double min=1.,double max=-1.,double coeff=0.8);
  int GetMode(int var,double& mode,double min=1.,double max=-1.,double coeff=0.8);
  double PolFit(int varx,Poly& pol,int degre,bool ey=true);
  double PolFit(int varx,int vary,Poly2& pol,int degre1,int degre2=-1,bool ez=true);
  GeneralFitData FitResidus(GeneralFit& gfit);
  GeneralFitData FitFunction(GeneralFit& gfit);

// Declaration de l interface NTuple
  virtual uint_4        NbLines() const;
  virtual uint_4        NbColumns() const;
  virtual r_8 *         GetLineD(int n) const;
  virtual r_8		GetCell(int n, int k) const;
  virtual r_8		GetCell(int n, string const & nom) const;
  virtual void		GetMinMax(int k, double& min, double& max) const; 
  virtual void		GetMinMax(string const & nom, double& min, double& max) const;
  virtual int           ColumnIndex(string const & nom) const;
  virtual string        ColumnName(int k) const;
  virtual string	VarList_C(const char* nomx=NULL) const;

protected:
  void Delete();

  int_4   mNVar;
  int_4   mNDataAlloc;
  int_4   mNData;
  int_4   mNDataGood;
  uint_2  mOk_EXP;
  r_8* mXP;             // x0 y0 z0, x1 y1 z1, ..., xn yn zn 
  r_8* mErrXP;          // Ex0 Ey0 Ez0, Ex1 Ey1 Ez1, ..., Exn Eyn Ezn 
  r_8* mF;              // F0, F1, ...., Fn
  r_8* mErr;            // EF0, EF1, ...., EFn
  uint_2* mOK; // 1 si pt valid, 0 sinon
  r_8* BuffVar;
  r_4* BuffVarR4;
};

inline ostream& operator << (ostream& s, GeneralFitData const & g)
                         {g.Show(s); return(s);}

/////////////////////////////////////////////////////////////////////////
// Classe pour la gestion de persistance

inline POutPersist& operator << (POutPersist& os, GeneralFitData & obj)
{ ObjFileIO<GeneralFitData> fio(&obj);  fio.Write(os);  return(os); }
inline PInPersist& operator >> (PInPersist& is, GeneralFitData & obj)
{ ObjFileIO<GeneralFitData> fio(&obj);  fio.Read(is);  return(is); }

// Classe pour la gestion de persistance
// ObjFileIO<GeneralFitData>

} // Fin du namespace

#endif
