#include "pexceptions.h"

#ifndef SLINPARBUF_H_SEEN
#define SLINPARBUF_H_SEEN

namespace SOPHYA {

//////////////////////////////////////////////////////////////////////////////////
class SLinParBuff {
public:
  friend class SLinParBuffMerger;

  SLinParBuff(uint_4 lenbuf,uint_4 nresynch=0,r_8 x0=0.,r_8 y0=0.,bool autoxy0=false);
  SLinParBuff(SLinParBuff& slp);
  SLinParBuff(void);
  virtual ~SLinParBuff();

  void GetX0Y0(r_8& x0,r_8& y0);
  bool GetAutoX0Y0();
  void SetX0Y0(r_8 x0=0.,r_8 y0=0.);
  void SetAutoX0Y0(bool autoxy0=false);

  void Reset(void);
  uint_4 Pop(void);
  uint_4 Push(r_8 x,r_8 y);
  inline uint_4 NPoints(void) {return mNCur;}

  r_8 SumX(void) {return mSx+mNCur*mX0;}
  r_8 SumY(void) {return mSy+mNCur*mY0;}

  uint_4 ReComputeSum(void);
  r_8 Compute(r_8& mean,bool recomputeXi2=false);
  r_8 Compute(r_8& a0,r_8 &a1,bool recomputeXi2=false);
  r_8 Compute(r_8& a0,r_8 &a1,r_8 &a2,bool recomputeXi2=false);

  void Print(int lp=0);
  void PrintCompute(int lp=0);

protected:
  uint_4 mLenBuf,mNResynch;
  r_8 *mX,*mY, mX0, mY0;
  bool mAutoXY0;
  uint_4 mNCur,mIDeb,mIResynch;
  r_8 mSx,mSy,mSx2,mSy2,mSxy, mSx3,mSx2y, mSx4;
  uint_4 mNResynchEff, mNPush, mNPop;
};


///////////////////////////////////////////////////////////////////
// That Class allows merging of SLinParBuff Class for computing  //
// parameters.
// ex:
// SLinParBuff s1;  -> Fill s1
// SLinParBuff s2;  -> Fill s2
// SLinParBuff s3;  -> Fill s3
// SLinParBuffMerger smerge(s1);
//   sig = smerge.Compute(mean); -> same as sig = s1.Compute(mean);
// smerge.Add(s2);
//   sig = smerge.Compute(mean); -> sig and mean are those for
class SLinParBuffMerger {
public:
  SLinParBuffMerger(void);
  SLinParBuffMerger(SLinParBuff& s,bool recompute=false);
  virtual ~SLinParBuffMerger(void);

  inline uint_4 NPoints(void) {return mSlp.NPoints();}
  inline void Reset(void) {mSlp.Reset(); mFirst=true;}
  void Add(SLinParBuff& s,bool recompute=false);
  inline r_8 Compute(r_8& mean) {return mSlp.Compute(mean);}
  inline r_8 Compute(r_8& a0,r_8 &a1) {return mSlp.Compute(a0,a1);}
  inline r_8 Compute(r_8& a0,r_8 &a1,r_8 &a2) {return mSlp.Compute(a0,a1,a2);}
  inline void Print(int lp=0) {mSlp.Print(lp);}
  inline void PrintCompute(int lp=0) {mSlp.PrintCompute(lp);}

protected:
  bool mFirst;
  SLinParBuff mSlp;
};

} // Fin du namespace

#endif
