#if !defined (DATASET_H)
 #define DATASET_H
 #include "datapoint.h"
 #include <vector>
 #include <valarray>
 #include <string>
 using namespace std;
 
 class Function;
 
 class Dataset
 {
  protected:
   int numberpoints;
   vector<Datapoint> dplist;  
   string comment;
  public:
   static const int ok=0;
   static const int out_of_bounds=1;
   static const int div_zero=2;
   static const int log_neg=4;
   static const int log_zero=8;
   static const int empty=16;
   Dataset();
   ~Dataset();
   Dataset(const int& np);
   Dataset(const Dataset &data);
   Dataset(const char* filename);
   Dataset(const string& filename);
   Dataset(const int& np,const double* xin,const double* yin);
   Dataset(const int& np,const double& minxin,const double& maxxin);
   Dataset(const vector<Datapoint>& dplistin);
         Dataset(const valarray<double>& dplistinx,const valarray<double>& dplistiny);
         Dataset(const valarray<double>& dplistiny);
   Dataset(const vector<double>& dplistin);
   void SetComment(const string& asin) {comment=asin;}
   string& GetComment() {return comment;}
   int TakeLogX();
   int TakeLogY();
   int SetDatapoint(const int& i,const Datapoint& dpin);
   int RemoveDatapoint(const int& no);
   int Save(const string& filename) const;
   int Load(const string& filename);
   int Save(const char* filename) const;
   int Load(const char* filename);
   int Init(const int& np);
   int BinValue(const double& value,double v=1.0);
   int ShiftToValue(const double& xval,const double& value);
   int NormaliseToValue(const double& xval,const double& value);
   int SetTo(const int& i,const double& value);
   int AddTo(const int& i,const double& value);
   int AddTo(const double& xval,const double& value);
   int SetTo(const double& xval,const double& value);
   Dataset Subset(const double& xmin,const double& xmax) const;
   valarray<double> getX(void) const;
   valarray<double> getY(void) const;
   Dataset getYHistogram(const int& np,const double& x1,const double& x2) const;
   Dataset getXHistogram(const int& np,const double& x1,const double& x2) const;
   Dataset getXHistogram(const int& np,const double& x1,const double& x2,const valarray<double>& w) const;
   Dataset getYHistogram(const int& np,const double& x1,const double& x2,const valarray<double>& w) const;
   friend Dataset operator+( const Dataset &data1, const Dataset &data2);
   Dataset operator+(const Dataset &data2);
   friend Dataset operator-(const Dataset &data1,const Dataset &data2);
   Dataset operator-(const Dataset &data2);
   friend Dataset operator/(const Dataset &data1,const Dataset &data2);
   Dataset operator/(const Dataset &data2);
   friend Dataset operator*(const Dataset &data1,const Dataset &data2);
   Dataset operator*(const Dataset &data2);
   friend Dataset operator/(const Dataset &data1,const double& number);
   friend Dataset operator/(const double& number,const Dataset &data1);
   Dataset operator/(const double& number);
   Dataset operator+(const double& number);
   Dataset operator-(const double& number);
   friend Dataset operator*(const Dataset &data1,const double& number);
   Dataset operator*(const double& number);
   friend Dataset operator*(const Dataset &data1,Function &funct);
   friend Dataset operator/(const Dataset &data1,Function &funct);
   friend double SigDiff(const Dataset &data1,const double& val);
   Dataset& operator=(const Dataset &data); 
   Dataset Differential() const;
   Dataset Integrate() const;
   Dataset IntegrateCum(const double& a,const double& b) const;
   Dataset IntegrateInvCum(const double& a,const double& b) const;
   int NumberPeaks() const;
   void Multiply(const double& factor);
   void TextDump();
   int ReBin(const int& newbin);
   int InitFunction(double (*function)(double x));
   void Cumulative();
   void InvCumulative();
   int Normalize();
   int Smooth(int numin=1);
   int IncreaseDensity(int numin=2);
   double Sum() const;
   Datapoint Sum(const double& a,const double& b) const;
   Datapoint Integrate(const double& a,const double& b) const;
   double Xi(double (*function) (double x),const double& min,const double& max) const;
   double GetValue(const int& point) const {return dplist[point].GetY();}
   double GetX(const int& point) const {return dplist[point].GetX();}
   int GetSize() const {return numberpoints;}
   Datapoint& operator[](const int& point) {return dplist[point];}
   Datapoint& ringacc(const int& point) {int p=point;if (p>numberpoints-1) p-=numberpoints;if (p<0) p+=numberpoints;return dplist[p];}
   Datapoint GetDatapoint(const int& point) const {if (point>=0 && point<numberpoints) return dplist[point];else return (Datapoint(0.0,0.0));}
   double GetValue(const double& xval) const;
   int GetIndex(const double& xval) const;
   void DeleteLast() {RemoveDatapoint(numberpoints-1);}
   Datapoint GetMax() const;
   Datapoint GetMin() const;
   Datapoint GetMaxX() const;
   Datapoint GetMinX() const;
   void ZeroAll();
   int FindIndex(const double& xval) const;
   int SwapXY();
   int SwapX();
   int SwapY();
   int Close();
   int Split(vector<Dataset>& result,double t=5.0) const;
   vector<Dataset> Split(double t=5.0) const;
   friend ostream& operator<<(ostream& out,const Dataset& dat);
   friend istream& operator>>(istream& input,Dataset& dat);
   istream& loadAscii(istream& in_file);
   istream& loadAscii(istream& infile,const int& xi,const int& yi);
   int loadAscii(const char* infname,const int& xi,const int& yi);
   int loadAscii(const string& infname,const int& xi,const int& yi);
   int fill(const double& fillwhat,const double& fillwith);
 };
 
 Dataset& Sqrt(Dataset& datin);
 #endif