#ifndef DATASET_HH
#define DATASET_HH

// Filename: dataset.hh
// Author:   Mike Rust and Ian Weiner
// Modified: Michael P. Schubmehl
// Date(s):  07/13/2000
// Purpose:    This file contains the interface for the dataSet class used in
//           the Mie scattering programs snell and fitmie. This class supports
//           reading a dataset from an input stream, and holds intensity vs
//           angle information.
//
// Notes:      Implemented in dataset.cpp


// Classes ********************************************************************
class dataPoint;                              // A single data point
class dataSet;                                // An entire set of data
class polynomial;                             // Used for interpolation
template <typename T> class List;             // Templated list class
template <typename T> class ListIter;         // List class iterator
class ostream;                                // For << operator
// END Classes ****************************************************************


// class dataPoint ************************************************************
class dataPoint {
  friend class dataSet;                       // Give dataSets direct access to
                                              //   the values in a dataPoint.
  public:
    dataPoint();                              // Constructors
    dataPoint(double angle_, double value_,
              double sigma_);

    dataPoint& operator=(const dataPoint& source); // Assignment operator

    void set(double angle_, double value_,    // Sets the dataPoint to the
             double sigma_);                  //   values provided.
    void set(double angle_, double value_);

    double getAngle();                        // Accessor functions
    double getValue();
    double getSigma();

  private:
    double angle;                             // Angle in degrees off beam line
    double value;                             // Intensity (theory or data)
    double sigma;                             // Uncertainty in data

    friend ostream& operator<<(ostream& stream,  // Needed for << operator
                               const dataSet& source);
};
// END class dataPoint ********************************************************


// class dataSet **************************************************************
class dataSet  {
  public:
    dataSet();                                // Default constructor
    ~dataSet();                               // Destructor

    void setPolarization(int polarization_);  // Set dataSet's polarization
    void setMaxOutputAngle(double maxOutputAngle_); // Set maxOutputAngle
    void setFitHook(int hook);                // Sets the dataSet's fit hook

    double getStepSize();                     // Accessor function for stepSize

    bool loadData(ifstream &file);            // Load experimental data
    bool loadTheory(ifstream &file,           // Load theory with specified
                   int polarization);         //   polarization from file. Note
                                              //   that this routine expects
                                              //   the * sentinel immediately
                                              //   preceeding the data to have
                                              //   been read already, as it has
                                              //   been when the size parameter
                                              //   has been stored.

    double getMinAngle();                     // Returns minimum and maximum
    double getMaxAngle();                     //   angle in this set.
    int getSize();                            // Returns size of this set.
    dataPoint* getPoint(int i);               // Returns a pointer to the ith
                                              //   point in the set.
    double interpolateIntensity(double theta);// Interpolates intensity using
                                              //   Lagrange's formula (cubic).
    double interpolateIntegral(double theta0, // Integrates the interpolating
                               double theta1);//   polynomial between points.

  private:
    bool   isExperimental;                    // True for experimental data

    int    size;                              // Number of dataPoints in set
    double stepSize;                          // Difference in angle between
                                              //   consecutive theory points.
    double minAngle;                          // The minimum and maximum angles
    double maxAngle;                          //   present in the data.
    double maxOutputAngle;                    // Maximum angle to output.

    int    polarization;                      // Polarization of this dataSet

    dataPoint* data;                          // Array of dataPoints containing
                                              //   intensity vs angle data.
    polynomial** interpolatingPolynomials;    // Array of interpolating polys
                                              //   to be used with the data.

    void constructInterpPoly(int index);      // Construct the polynomial
                                              //   needed to interpolate just
                                              //   above the given array index.

    friend ostream& operator<<(ostream& stream,  // Needed for << operator
                               const dataSet& source);
};
// END class dataSet **********************************************************

ostream& operator<<(ostream& stream,          // Operator to output an entire
                    const dataSet& source);   //   dataSet to an output stream.

#endif // DATASET_HH