#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

#include "Polino.h"
#include "Parser.h"
#include "Term.h"

Poli::Poli()
{ 
   lid= NULL;
}

Poli::Poli(const Poli& p)
{
     lid= NULL;
     Term* pp= p.Lid();
     while (pp!=NULL)
        {
         lid= Ins(lid, new Term(pp->Coef(),pp->Expo()));
         pp= pp->Sgte();
        }
}

Poli::~Poli(void)
{
   Term* pp =  lid;
   while (pp!=NULL)
      {
       Term* qq = pp;
       pp= pp->Sgte();
       delete qq;
      }
    lid= NULL;
}


ostream& Poli::Print(ostream& os) const
{
    if (Gr() == -1)
       os << " 0x0";
    else
       for (Term* t= lid; t!=NULL; t= t->Sgte())
          {
              if (t->Coef() >= 0.0)
                  os << " + " << t->Coef();
              else
                  os << " - " << -t->Coef();
              if (t->Expo()==1)
                 os << "x";
              else
                 if (t->Expo()>1)
                    os << "x" << t->Expo();
          }
       
    os << "; ";
    return os;
}

ostream& operator << (ostream& os, const Poli& p)
{
    return p.Print(os);
}

int Poli::Gr() const
{
   if (lid==NULL)
      return -1;
   else
      return lid->Expo();
}

istream& operator >> (istream& is, Poli& p)
{
    Parser E(is);
    p= E.poli();
    return is;
}

Poli& Poli::operator += (Term t)
{
   lid= Ins(lid, new Term(t.Coef(), t.Expo()));
   return *this;
}

Poli& Poli::operator -= (Term t)
{
   lid= Ins(lid, new Term(-t.Coef(), t.Expo()));
   return *this;
}


Poli operator + (const Poli& p, const Poli& q)
{
   Poli r;
   for (Term* pp= p.Lid(); pp!=NULL; pp=pp->Sgte())
       r+= *pp;
   for (Term* qq= q.Lid(); qq!=NULL; qq=qq->Sgte())
       r+= *qq;
   return r;
}


Poli operator - (const Poli& p, const Poli& q)
{
   Poli r;
   for (Term* pp= p.Lid(); pp!=NULL; pp=pp->Sgte())
       r+= *pp;
   for (Term* qq= q.Lid(); qq!=NULL; qq=qq->Sgte())
       r-= *qq;
   return r;
}

Poli::Poli(double c, int e)
{
   lid= new Term(c,e,NULL);
}

Poli& Poli::operator = (const Poli& p)
{
    Term* pp= lid;   // borrar la lista previa
    while (pp!=NULL)
        {
         Term* qq= pp;
         pp= pp->Sgte();
         delete qq; 
        }

     lid= NULL;     // copiamos la lista de p
     pp= p.Lid(); 
     while (pp!=NULL)
        {
         lid= Ins(lid, new Term(pp->Coef(),pp->Expo()));
         pp= pp->Sgte();
        }

    return *this;
}


Poli operator * (const Poli& p, const Poli& q)
{
    Poli r;
    for (Term* u= p.Lid(); u!=NULL; u= u->Sgte()) 
      for (Term* v= q.Lid(); v!=NULL; v= v->Sgte()) 
         r+= *u * *v;
    return r;
}

Poli operator / (const Poli& a, const Poli& b)
{
   Poli r= a;
   Poli q;
   while (b.Gr() <= r.Gr())
     {
      Poli t(r.Lid()->Coef() / b.Lid()->Coef(),
             r.Lid()->Expo() - b.Lid()->Expo());
      r= r-t*b; 
      q= q+t;
     }
   return q;
}


Poli operator % (const Poli& a, const Poli& b)
{
   Poli r= a;
   Poli q;
   while (b.Gr() <= r.Gr())
     {
      Poli t(r.Lid()->Coef() / b.Lid()->Coef(),
             r.Lid()->Expo() - b.Lid()->Expo());
      r= r-t*b; 
      q= q+t;
     }
   return r;
}






