#ifndef POLYNOMIUMCLASS
#define POLYNOMIUMCLASS

/*
   coeff is a map<int,double>    hence for each integer n we can look up a double value.

   hence   coeff[n] stores c*x^n
   
   Compared to an array or vector   map only stores the n values that we require in a tree.
   
   we can use coeff.begin()   coeff.end() to obtain iterators allowing us to travese
   all elements in the array.
   
   Given an iterator it to the map      it->first  is the integer  and 
                                        it->second is the double coefficient we store.


*/



#include <map>
#include <iostream>
#include <cmath>

using namespace std;


class Polynomium
{
  private:
   map<int,double> coeff;
   
  public:
   Polynomium() { ; }          // default do nothing, map is empty.

   auto begin() const          // Short cut to return first element in coefficent map
     {
       return coeff.begin();
     }

   auto end() const            // Short cut to last+1 first element in coefficent map  
     {
       return coeff.end();
     }
   
   double& operator[](int n)
    // Return the n'th coefficient. Because of double& its returns a reference to the
    // element in the map, which can be used to assign values.
    // Also works if the n'th coefficient has not been defined, due to magic map semantics.
     {
       return coeff[n]; 
     }
   
   double operator()(double x) const;    // Evaluate value of P(x) for a given x value
   void Purge();                         // remove all zero coefficients.
   
   Polynomium Diff();              // Differentiated polynomium
   Polynomium Integral();          // Integrated polynomium
     
};   // End of class

ostream& operator<<(ostream& os, Polynomium &P); 

// Operators on pairs of polynomia:
Polynomium operator+(const Polynomium& P, const Polynomium& Q);  // P+Q
Polynomium operator-(const Polynomium& P, const Polynomium& Q);  // P-Q
Polynomium operator*(const Polynomium& P, const Polynomium& Q);  // P*Q

// Operators on polynomia and a number:
Polynomium operator+(const Polynomium& P, const double& a);      // P+a
Polynomium operator+(const double& a, const Polynomium& P);      // a+P
Polynomium operator-(const Polynomium& P, const double& a);      // P-a
Polynomium operator-(const double& a, const Polynomium& P);      // a-P
Polynomium operator*(const Polynomium& P, const double& a);      // P*a
Polynomium operator*(const double& a, const Polynomium& P);      // a*P
Polynomium operator/(const Polynomium& P, const double& a);      // P/a

//
// Note we do not do P/Q or a/P since these will not be polynomia.
//

// unary -
Polynomium operator-(const Polynomium& P);                       // -P

// we do not need = which we get for free because = is defined for maps.
#endif 
