Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

(Polynomial Class) (c++, must work on visual studios 2017, and must contain a fu

ID: 3750836 • Letter: #

Question

(Polynomial Class) (c++, must work on visual studios 2017, and must contain a full working program using said class)

Develop class Polynomial. The internal representation of a Polynomial is an array of terms. Each term contains a coefficient and an exponent, e.g., the term

2x4

has the coefficient 2 and the exponent 4. Develop a complete class containing proper constructor and destructor functions as well as set and get functions. The class should also provide the following overloaded operator capabilities:

a) Overload the addition operator (+) to add two Polynomials.

b) Overload the subtraction operator (-) to subtract two Polynomials.

c) Overload the assignment operator to assign one Polynomial to another.

d) Overload the multiplication operator (*) to multiply two Polynomials.

e) Overload the addition assignment operator (+=), subtraction assignment operator (-=), and multiplication assignment operator (*=).

Explanation / Answer

main.cpp

#ifdef NDEBUG

#include <iostream> // cout/endl

#include "polynomial.h" // Our polynomial class.

using std::cout;
using std::endl;

// Perform basic demonstration of Polynomial class.
int main()
{
   // Demo.
   cout << "Polynomial Class Demonstration Program ";

   // Create polynomial, 7x^4 - x^2 + 3.
   Polynomial a;
   a.setTerm(4, 7.);
   a.setTerm(2, -1.);
   a.setTerm(0, 3.);
   // Create polynomial, -3x^2 + 4 with list initalizer.
   Polynomial b({ { 2, -3. }, { 0, 4. } });

   // Output some information about polynomials.
   cout << " degree of (" << a << ") is: " << a.getDegree() << endl;
   // Get a term's coefficient.
   double c;
   if (b.getTerm(2, c))
   {
       cout << " Coefficient of 2nd term of (" << b << ") is: " << c << endl;
       //cout << " Coefficient of 2nd term of (" << b << ") is: " << b[2] << endl;
   }

   // These two methods not fully tested.
   //cout << " (" << a << ") evaluated at 2 = " << a.evaluate(2) << endl;
   //cout << " Differentiate (" << a << ") = " << a.differentiate() << endl;

   // Assignment operator.
   cout << "Assignment: ";
   cout << " a = " << a << endl;
   b = a;
   cout << " Set b = a, now b = " << b << endl;

   // Add, subtract and multiply binary operators.
   cout << "Add, subtract & multiply: ";
   cout << " (" << a << ") + (" << b << ") = " << (a + b) << endl;
   cout << " (" << a << ") - (" << b << ") = " << (a - b) << endl;
   cout << " (" << a << ") * (" << b << ") = " << (a * b) << endl;

   // Unary add, subtract and multiply.
   cout << "Unary add, subtract & multiply: ";
   a += b;
   cout << " Set a += b, now a = " << a << endl;
   a -= b;
   cout << " Set a -= b, now a = " << a << endl;
   a *= b;
   cout << " Set a *= b, now a = " << a << endl;

   // Unary negate.
   cout << "Unary negation: ";
   cout << " a = " << a << endl;
   b = -a;
   cout << " Set b = -a, now b = " << b << endl;

   // Equality.
   cout << "Equality: ";
   cout << " a = " << a << endl;
   cout << " b = " << b << endl;
   cout << " Is a == b? " << std::boolalpha << (a == b) << endl;
   cout << " b = " << -b << endl;
   cout << " Is a == -b now? " << std::boolalpha << (a == -b) << endl;

   // Divison and modulus (with remainder).
   cout << "Division & modulus (with remainder): ";
   Polynomial e({ { 3, 1. },{ 2, -2. },{ 0, -4. } });
   Polynomial f({ { 1, 1. },{ 0, -3. } });
   cout << " (" << e << ") / (" << f << ") = " << (e / f) << endl;
   cout << " (" << e << ") % (" << f << ") = " << (e % f) << endl;

   // Divison and modulus (with remainder).
   //Polynomial g({ { 4, 5. },{ 3, 2. },{ 2, -3. },{ 1, 2. },{ 0, 2. } });
   //Polynomial h({ { 2, 2. },{ 1, 3. },{ 0, 1. } });
   //cout << "(" << g << ") / (" << h << ") = " << (g / h) << endl;
   //cout << "(" << g << ") % (" << h << ") = " << (g % h) << endl;

   // Divison and modulus (without remainder).
   cout << "Division & modulus (without remainder): ";
   Polynomial i({ { 2, 1. },{ 1, 2. },{ 0, 1. } });
   Polynomial j({ { 1, 1. },{ 0, 1. } });
   cout << " (" << i << ") / (" << j << ") = " << (i / j) << endl;
   cout << " (" << i << ") % (" << j << ") = " << (i % j) << endl;

   try
   {
       Polynomial e;
       a = a / e;
   }
   catch (std::overflow_error ex)
   {
       cout << "Correctly caught attempted division by zero. ";
   }

   return 0;
}
#endif


polynomial.h

#include <iostream> // cout/endl
#include <string>    // string
#include <iomanip>   // setprecision
#include <sstream>   // stringstream
#include <map>       // map for poly terms.
#include <numeric>   // accumulate
#include <algorithm> // for_each
#include <cmath>     // fabs
#include <initializer_list>

#include "range_for_reverse_iterator.h"

// Used to calculate poly evaluation for comparison operators.
static const double EVALUATION_CONSTANT{ 1.1 };

class Polynomial
{
private:
   // Polynomial terms contained in map in format of map<exponent, coefficient>.
   std::map<unsigned, double> terms;

   // Determines if a term exists for given exponent.
   bool exists(const unsigned& exponent) const;

public:

   // Default constructor.
   Polynomial();
   // List initaializer constructor.
   Polynomial(std::initializer_list<std::pair<const unsigned, double>> init);
   // Default destructor.
   ~Polynomial() = default;

   // Setter function for term.
   void setTerm(const unsigned exponent, const double coefficient);
   // Getter function for term coefficient.
   bool const getTerm(const unsigned exponent, double& coefficient);
   // Getter function for polynomial degree.
   unsigned const getDegree();

   // Evaluate polynomial at x (used by comparison operations).
   double evaluate(double x);
   // Differentiate polynomial and return result.
   Polynomial differentiate();

   // Return polynomial coefficient at exponent index.
   double operator[] (const int exponent) const
   {
       if (exponent < 0)
           throw std::out_of_range("Index < 0");
  
       return terms.at(exponent);
   }

   // Set polynomial coefficient at exponent index.
   double& operator[] (const int exponent)
   {
       if (exponent < 0)
           throw std::out_of_range("Index < 0");
      
       return terms[exponent];
   }

   // Overload assignment operator.
   const Polynomial& operator= (const Polynomial rhs)
   {
       // Check for self-assignment.
       if (this == &rhs)
           // Skip assignment, and just return *this.
           return *this;

       // Zeroize poly, and reassign this to rhs terms.
       terms.clear();

       for (auto t : rhs.terms)
           terms[t.first] = t.second;

       return *this;
   }

   // Add polynomials via overloaded binary plus operator.
   const Polynomial operator+ (const Polynomial rhs)
   {
       // Copy this's terms to result poly.
       Polynomial result = *this;

       // Use accumulator to add rhs to lhs terms.
       result.terms = accumulate(rhs.terms.cbegin(), rhs.terms.cend(), result.terms,
           [](std::map<unsigned, double>& t, const std::pair<const unsigned, double>& p)
           {
               return (t[p.first] += p.second, t);
           }
       );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Subtract polynomials via overloaded binary minus operator.
   const Polynomial operator- (const Polynomial rhs)
   {
       // Copy this's terms to result poly.
       Polynomial result = *this;

       // Use accumulator to subtract rhs from lhs terms.
       result.terms = accumulate(rhs.terms.cbegin(), rhs.terms.cend(), result.terms,
           [](std::map<unsigned, double> &t, const std::pair<const unsigned, double> &p)
           {
               return (t[p.first] -= p.second, t);
           }
       );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Multiply Polynomials via overloaded binary multiplication operator.
   const Polynomial operator* (const Polynomial rhs)
   {
       Polynomial result;

       // Multiply all lhs (or this) terms by all rhs terms.
       for_each(this->terms.cbegin(), this->terms.cend(), [&result, rhs](auto lhsTerm)
       {
           for_each(rhs.terms.cbegin(), rhs.terms.cend(), [&result, lhsTerm](auto rhsTerm)
           {
               result.terms[lhsTerm.first + rhsTerm.first] += (lhsTerm.second * rhsTerm.second);
           } );
       } );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Overloaded unary += operator, passes our to "overloaded +".
   const Polynomial& operator+= (const Polynomial rhs)
   {
       *this = *this + rhs;
       return *this;
   }

   // Overloaded unary -= operator, passes our to "overloaded -".
   const Polynomial& operator-= (const Polynomial rhs)
   {
       *this = *this - rhs;
       return *this;
   }

   // Overloaded unary *= operator, passes to our "overloaded *".
   const Polynomial& operator*= (const Polynomial rhs)
   {
       *this = *this * rhs;
       return *this;
   }

   // Overloaded unary minus operator.
   const Polynomial operator- ()
   {
       // Iterate through all terms negating them.
       for (auto& t : (*this).terms)
           t.second = -t.second;

       return *this;
   }

   // Overload equality operator.
   const bool operator== (Polynomial rhs)
   {
       if ((*this).getDegree() != rhs.getDegree())
           return false;

       // Iterate through all terms, check equal.
       for (auto& t : (*this).terms)
           // If coefficients don't match then fail.
           if (rhs[t.first] != t.second)
               return false;

       return true;
   }

   // Overload inequality operator.
   const bool operator!= (Polynomial rhs)
   {
       return !(*this == rhs);
   }

   // Overload greater than operator.
   const bool operator> (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) > fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload greater than or equal operator.
   const bool operator>= (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) >= fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload less than operator.
   const bool operator< (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) < fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload less than or equal operator.
   const bool operator<= (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) <= fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Divide polynomials via overloaded binary modulus operator.
   const Polynomial operator% (Polynomial& divisor)
   {
       // Check for division by zero.
       if (divisor.getDegree() == 0 && divisor[0] == 0)
           throw std::overflow_error("Divide by zero");

       // Preserve this.
       Polynomial dividend = *this;

       // Is divisor larger than dividend?
       if (divisor > dividend)
           // Return zero.
           return Polynomial();

       Polynomial quotient;

       // Iterate through all dividend terms.
       do {
           // Divide coefficients of highest terms, subtract exponents, insert as new quotient term.
           quotient[dividend.getDegree() - divisor.getDegree()] = dividend[dividend.getDegree()] / divisor[divisor.getDegree()];

           // Multiply divisor by quotient and subtract from dividend.
           dividend = *this - (divisor * quotient);

           // Repeat until reaching final term or divison is complete.
       } while ((dividend.getDegree() != 0) && (dividend.getDegree() >= divisor.getDegree()));

       // Normalize polynomial.
       dividend.getDegree();

       return dividend;
   }
  
   // Polynomial long division via overloaded binary divide operator.
   const Polynomial operator/ (Polynomial& divisor)
   {
       // Check for division by zero.
       if (divisor.getDegree() == 0 && divisor[0] == 0)
           throw std::overflow_error("Divide by zero");

       // Preserve this.
       Polynomial dividend = *this;

       // Is divisor larger than dividend?
       if (divisor > dividend)
           // Return zero.
           return Polynomial();

       Polynomial quotient;

       // Iterate through all dividend terms.
       do {
           // Divide coefficients of highest terms, subtract exponents, insert as new quotient term.
           quotient[dividend.getDegree() - divisor.getDegree()] = dividend[dividend.getDegree()] / divisor[divisor.getDegree()];

           // Multiply divisor by quotient and subtract from dividend.
           dividend = *this - (divisor * quotient);

           // Repeat until reaching final term or divison is complete.
       } while ((dividend.getDegree() != 0) && (dividend.getDegree() >= divisor.getDegree()));

       // Normalize polynomial.
       quotient.getDegree();

       return quotient;
   }

   // Stream polynomial.
   friend std::ostream& operator<< (std::ostream& os, const Polynomial& p)
   {
       // Loop, filling string with poly terms.
       std::string s{ "" };

       // Check for zero polynomial first.
       if (p.terms.empty())
           s = "0";
       else
       {
           // Iterate backwards through all terms.
           for (auto& t : reverse(p.terms))
           {
               // Only terms with coefficients are printed.
               if (t.second)
               {
                   std::stringstream stream;

                   // Print/format properly leading sign.
                   s += (t == *p.terms.rbegin()) ? (t.second < 0) ? "-" : "" : (t.second > 0) ? " - " : " + ";
                   stream << std::fixed << std::setprecision(1) << abs(t.second);
                   // Skip display of superfluous 0 exponent.
                   if (t.first)
                       stream << "x^" << t.first;
                   // Add to string.
                   s += stream.str();
               }
           }
       }

       return os << s;
   }
};

// Default constructor.
Polynomial::Polynomial()
{
   // Empty polynomial.
   terms.clear();
}

// List initaializer constructor.
Polynomial::Polynomial(std::initializer_list<std::pair<const unsigned, double>> init) : terms(init) { }

// Determines if a term exists for exponent.
bool Polynomial::exists(const unsigned& exponent) const
{
   return terms.count(exponent);
}

// Setter function for term.
void Polynomial::setTerm(const unsigned exponent, const double coefficient)
{
   // Set or update an existing polynomial term.
   if (coefficient != 0.)
       terms[exponent] += coefficient;
}

// Getter function for term coefficient.
bool const Polynomial::getTerm(const unsigned exponent, double& coefficient)
{
   // Get polynomial term if exists.
   if (exists(exponent))
   {
       coefficient = terms[exponent];
       return true;
   }

   return false;
}

// Getter function for polynomial degree.
unsigned const Polynomial::getDegree()
{
   // Check for and remove any null terms.
   std::map<unsigned, double>::iterator it = terms.begin();

   while (it != terms.end())
   {
       if ((*it).second == 0.)
           it = terms.erase(it);
       else
           ++it;
   }

   // Return highest degree or zero.
   if (!terms.empty())
       return terms.rbegin()->first;
   else
       return 0;
}

// Evaluate polynomial at x.
double Polynomial::evaluate(double x)
{
   double p{ 0. };

   for (auto t : terms)
       p += (pow(x, t.first) * t.second);

   return p;
}

// Differentiate polynomial and return result.
Polynomial Polynomial::differentiate()
{
   Polynomial derivative;
   unsigned degree = getDegree();

   if (degree == 0)
       return derivative;

   //   derivative.degree = degree - 1;
   // Calculate looping through all terms.
   for (unsigned i = 0; i < degree; i++)
       if (exists(i + 1))
           derivative.terms[i] = (i + 1) * terms[i + 1];

   return derivative;
}


polynomial.cpp

#include <iostream> // cout/endl
#include <string>    // string
#include <iomanip>   // setprecision
#include <sstream>   // stringstream
#include <map>       // map for poly terms.
#include <numeric>   // accumulate
#include <algorithm> // for_each
#include <cmath>     // fabs
#include <initializer_list>

#include "range_for_reverse_iterator.h"

// Used to calculate poly evaluation for comparison operators.
static const double EVALUATION_CONSTANT{ 1.1 };

class Polynomial
{
private:
   // Polynomial terms contained in map in format of map<exponent, coefficient>.
   std::map<unsigned, double> terms;

   // Determines if a term exists for given exponent.
   bool exists(const unsigned& exponent) const;

public:

   // Default constructor.
   Polynomial();
   // List initaializer constructor.
   Polynomial(std::initializer_list<std::pair<const unsigned, double>> init);
   // Default destructor.
   ~Polynomial() = default;

   // Setter function for term.
   void setTerm(const unsigned exponent, const double coefficient);
   // Getter function for term coefficient.
   bool const getTerm(const unsigned exponent, double& coefficient);
   // Getter function for polynomial degree.
   unsigned const getDegree();

   // Evaluate polynomial at x (used by comparison operations).
   double evaluate(double x);
   // Differentiate polynomial and return result.
   Polynomial differentiate();

   // Return polynomial coefficient at exponent index.
   double operator[] (const int exponent) const
   {
       if (exponent < 0)
           throw std::out_of_range("Index < 0");
  
       return terms.at(exponent);
   }

   // Set polynomial coefficient at exponent index.
   double& operator[] (const int exponent)
   {
       if (exponent < 0)
           throw std::out_of_range("Index < 0");
      
       return terms[exponent];
   }

   // Overload assignment operator.
   const Polynomial& operator= (const Polynomial rhs)
   {
       // Check for self-assignment.
       if (this == &rhs)
           // Skip assignment, and just return *this.
           return *this;

       // Zeroize poly, and reassign this to rhs terms.
       terms.clear();

       for (auto t : rhs.terms)
           terms[t.first] = t.second;

       return *this;
   }

   // Add polynomials via overloaded binary plus operator.
   const Polynomial operator+ (const Polynomial rhs)
   {
       // Copy this's terms to result poly.
       Polynomial result = *this;

       // Use accumulator to add rhs to lhs terms.
       result.terms = accumulate(rhs.terms.cbegin(), rhs.terms.cend(), result.terms,
           [](std::map<unsigned, double>& t, const std::pair<const unsigned, double>& p)
           {
               return (t[p.first] += p.second, t);
           }
       );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Subtract polynomials via overloaded binary minus operator.
   const Polynomial operator- (const Polynomial rhs)
   {
       // Copy this's terms to result poly.
       Polynomial result = *this;

       // Use accumulator to subtract rhs from lhs terms.
       result.terms = accumulate(rhs.terms.cbegin(), rhs.terms.cend(), result.terms,
           [](std::map<unsigned, double> &t, const std::pair<const unsigned, double> &p)
           {
               return (t[p.first] -= p.second, t);
           }
       );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Multiply Polynomials via overloaded binary multiplication operator.
   const Polynomial operator* (const Polynomial rhs)
   {
       Polynomial result;

       // Multiply all lhs (or this) terms by all rhs terms.
       for_each(this->terms.cbegin(), this->terms.cend(), [&result, rhs](auto lhsTerm)
       {
           for_each(rhs.terms.cbegin(), rhs.terms.cend(), [&result, lhsTerm](auto rhsTerm)
           {
               result.terms[lhsTerm.first + rhsTerm.first] += (lhsTerm.second * rhsTerm.second);
           } );
       } );

       // Normalize polynomial.
       result.getDegree();

       return result;
   }

   // Overloaded unary += operator, passes our to "overloaded +".
   const Polynomial& operator+= (const Polynomial rhs)
   {
       *this = *this + rhs;
       return *this;
   }

   // Overloaded unary -= operator, passes our to "overloaded -".
   const Polynomial& operator-= (const Polynomial rhs)
   {
       *this = *this - rhs;
       return *this;
   }

   // Overloaded unary *= operator, passes to our "overloaded *".
   const Polynomial& operator*= (const Polynomial rhs)
   {
       *this = *this * rhs;
       return *this;
   }

   // Overloaded unary minus operator.
   const Polynomial operator- ()
   {
       // Iterate through all terms negating them.
       for (auto& t : (*this).terms)
           t.second = -t.second;

       return *this;
   }

   // Overload equality operator.
   const bool operator== (Polynomial rhs)
   {
       if ((*this).getDegree() != rhs.getDegree())
           return false;

       // Iterate through all terms, check equal.
       for (auto& t : (*this).terms)
           // If coefficients don't match then fail.
           if (rhs[t.first] != t.second)
               return false;

       return true;
   }

   // Overload inequality operator.
   const bool operator!= (Polynomial rhs)
   {
       return !(*this == rhs);
   }

   // Overload greater than operator.
   const bool operator> (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) > fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload greater than or equal operator.
   const bool operator>= (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) >= fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload less than operator.
   const bool operator< (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) < fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Overload less than or equal operator.
   const bool operator<= (Polynomial rhs)
   {
       if (fabs(evaluate(EVALUATION_CONSTANT)) <= fabs(rhs.evaluate(EVALUATION_CONSTANT)))
           return true;

       return false;
   }

   // Divide polynomials via overloaded binary modulus operator.
   const Polynomial operator% (Polynomial& divisor)
   {
       // Check for division by zero.
       if (divisor.getDegree() == 0 && divisor[0] == 0)
           throw std::overflow_error("Divide by zero");

       // Preserve this.
       Polynomial dividend = *this;

       // Is divisor larger than dividend?
       if (divisor > dividend)
           // Return zero.
           return Polynomial();

       Polynomial quotient;

       // Iterate through all dividend terms.
       do {
           // Divide coefficients of highest terms, subtract exponents, insert as new quotient term.
           quotient[dividend.getDegree() - divisor.getDegree()] = dividend[dividend.getDegree()] / divisor[divisor.getDegree()];

           // Multiply divisor by quotient and subtract from dividend.
           dividend = *this - (divisor * quotient);

           // Repeat until reaching final term or divison is complete.
       } while ((dividend.getDegree() != 0) && (dividend.getDegree() >= divisor.getDegree()));

       // Normalize polynomial.
       dividend.getDegree();

       return dividend;
   }
  
   // Polynomial long division via overloaded binary divide operator.
   const Polynomial operator/ (Polynomial& divisor)
   {
       // Check for division by zero.
       if (divisor.getDegree() == 0 && divisor[0] == 0)
           throw std::overflow_error("Divide by zero");

       // Preserve this.
       Polynomial dividend = *this;

       // Is divisor larger than dividend?
       if (divisor > dividend)
           // Return zero.
           return Polynomial();

       Polynomial quotient;

       // Iterate through all dividend terms.
       do {
           // Divide coefficients of highest terms, subtract exponents, insert as new quotient term.
           quotient[dividend.getDegree() - divisor.getDegree()] = dividend[dividend.getDegree()] / divisor[divisor.getDegree()];

           // Multiply divisor by quotient and subtract from dividend.
           dividend = *this - (divisor * quotient);

           // Repeat until reaching final term or divison is complete.
       } while ((dividend.getDegree() != 0) && (dividend.getDegree() >= divisor.getDegree()));

       // Normalize polynomial.
       quotient.getDegree();

       return quotient;
   }

   // Stream polynomial.
   friend std::ostream& operator<< (std::ostream& os, const Polynomial& p)
   {
       // Loop, filling string with poly terms.
       std::string s{ "" };

       // Check for zero polynomial first.
       if (p.terms.empty())
           s = "0";
       else
       {
           // Iterate backwards through all terms.
           for (auto& t : reverse(p.terms))
           {
               // Only terms with coefficients are printed.
               if (t.second)
               {
                   std::stringstream stream;

                   // Print/format properly leading sign.
                   s += (t == *p.terms.rbegin()) ? (t.second < 0) ? "-" : "" : (t.second > 0) ? " - " : " + ";
                   stream << std::fixed << std::setprecision(1) << abs(t.second);
                   // Skip display of superfluous 0 exponent.
                   if (t.first)
                       stream << "x^" << t.first;
                   // Add to string.
                   s += stream.str();
               }
           }
       }

       return os << s;
   }
};

// Default constructor.
Polynomial::Polynomial()
{
   // Empty polynomial.
   terms.clear();
}

// List initaializer constructor.
Polynomial::Polynomial(std::initializer_list<std::pair<const unsigned, double>> init) : terms(init) { }

// Determines if a term exists for exponent.
bool Polynomial::exists(const unsigned& exponent) const
{
   return terms.count(exponent);
}

// Setter function for term.
void Polynomial::setTerm(const unsigned exponent, const double coefficient)
{
   // Set or update an existing polynomial term.
   if (coefficient != 0.)
       terms[exponent] += coefficient;
}

// Getter function for term coefficient.
bool const Polynomial::getTerm(const unsigned exponent, double& coefficient)
{
   // Get polynomial term if exists.
   if (exists(exponent))
   {
       coefficient = terms[exponent];
       return true;
   }

   return false;
}

// Getter function for polynomial degree.
unsigned const Polynomial::getDegree()
{
   // Check for and remove any null terms.
   std::map<unsigned, double>::iterator it = terms.begin();

   while (it != terms.end())
   {
       if ((*it).second == 0.)
           it = terms.erase(it);
       else
           ++it;
   }

   // Return highest degree or zero.
   if (!terms.empty())
       return terms.rbegin()->first;
   else
       return 0;
}

// Evaluate polynomial at x.
double Polynomial::evaluate(double x)
{
   double p{ 0. };

   for (auto t : terms)
       p += (pow(x, t.first) * t.second);

   return p;
}

// Differentiate polynomial and return result.
Polynomial Polynomial::differentiate()
{
   Polynomial derivative;
   unsigned degree = getDegree();

   if (degree == 0)
       return derivative;

   //   derivative.degree = degree - 1;
   // Calculate looping through all terms.
   for (unsigned i = 0; i < degree; i++)
       if (exists(i + 1))
           derivative.terms[i] = (i + 1) * terms[i + 1];

   return derivative;
}