#include <iostream>
#include "wielomian.h"
using namespace std;

Wielomian::Wielomian()
{
	st=0;
	wsp=new double[1];
	*wsp=0;
}

Wielomian::Wielomian(double *w,int st)
{
	this->st=st;
	wsp=new double[st+1];
	for(int i=0; i<=st; i++)
		*(wsp+i)=*(w+i);
}

Wielomian::Wielomian(int st)
{
   if(st<0) st = 0;
   this->st=st;
	wsp=new double[st+1];
}

Wielomian::Wielomian(const Wielomian & w)
{
	int stopien=w.st;
	this->st=stopien;
	wsp=new double[stopien+1];
	for(int i=0; i<=stopien; i++)
		*(wsp+i)=*(w.wsp+i);
}

Wielomian Wielomian::Pochodna(int st)
{
   if(st==1)
   {

      Wielomian w;
      if(this->st>0)
      {
         w.st=this->st-1;
         delete [] w.wsp;
         w.wsp = new double [w.st+1];

         for(int i=0; i<=w.st; i++)   w.wsp[i]=this->wsp[i+1]*(i+1);
      }
      return w;
   }
   return Pochodna().Pochodna(st-1); //trik
}


Wielomian Wielomian::operator*()
{
   return this->Pochodna();
}

void Wielomian::Wyswietl()
{
   cout << *this << endl;
}

Wielomian::~Wielomian()
{
	delete [] wsp;
}

Wielomian operator+(const Wielomian &w1,const Wielomian &w2)
{
   const Wielomian *max=&w2;
   const Wielomian *min=&w1;
   if(max->st < min->st) 
   {
      max=&w1;
      min=&w2;
   }
   Wielomian w(*max);
   for(int i=0;i<=min->st;i++) w.wsp[i]+=min->wsp[i];
   return w;
}

Wielomian Wielomian::operator*(double x)
{
   Wielomian w(*this);
   int i=w.st;
   while(i>=0) w.wsp[i--]*=x;
   return w;
}

Wielomian &Wielomian::operator=(const Wielomian  &w)
{
   if(st!=w.st)
   {
      st=w.st;
      delete [] wsp;
      wsp = new double[st+1];
   }
   for(int i=0;i<=st;i++) wsp[i]=w.wsp[i];
   return *this;
}

Wielomian &Wielomian::operator*=(double x)
{
	
	return *this=*this*x;
}
   
   
ostream &operator<<(ostream &o,const Wielomian &w)
{
   o << "Wielomian " << w.st << " stopnia  f(x)= "; 
	for(int i=w.st; i>0; i--)
		if(w.wsp[i]!=0) 
			o << w.wsp[i] << "x^" << i << " + ";
	
	o << w.wsp[0];
   return o;
}

istream &operator>>(istream &in, Wielomian &w)
{
   in >> w.st;
   delete [] w.wsp;
   w.wsp=new double[w.st+1];

   for(int i=w.st; i>=0; i--)
   {
      in >> w.wsp[i];
   }
   return in;
}

Wielomian& Wielomian::Wczytaj()
{
   int st;
   cout << "Podaj stopien wielomianu a anastepnie wszystkie wspolczynniki:" << endl ;
   cin >> *this;
   return *this;
}

bool operator==(const Wielomian &w1,const Wielomian &w2)
{
	if(w1.st != w2.st) return false;
	int i=w1.st;
	while (i>=0)
	{
		if(w1.wsp[i]!=w2.wsp[i]) return false;
		i--;
	}
	return true;
}

Wielomian &Wielomian::operator*=(const Wielomian &w)
{
	int ost=st;
	double * owsp = wsp;
	st+=w.st;
	wsp = new double[st+1];
	for(int i=0;i<st+1;i++) wsp[i]=0.0;

	for(int i=0;i<ost+1;i++)
		for(int j=0;j<w.st+1;j++) 
			wsp[i+j]+=w.wsp[j]*owsp[i];
	
	delete [] owsp;
	return *this;
}

Wielomian &Wielomian::operator+=(const Wielomian &w)
{
	return *this = *this + w;
}

Wielomian operator*(const Wielomian &w1,const Wielomian &w2)
{
	Wielomian w=w1;
	w*=w2;
	return w;
}
double Wielomian::operator()(double x)
{
	int i=st;
	double y=wsp[i];
	while (i>0)
	{
		y*=x;
		y+=wsp[--i];
	}
	return y;

}

Wielomian operator-(const Wielomian &w)
{
	Wielomian w2(w);
	for(int i=0;i<w2.st+1;i++) w2.wsp[i]=-w2.wsp[i];
	return w2;
}

Wielomian::Wielomian(double x)
{
	wsp=new double[1];
	st=0;
	*wsp=x;
}

Wielomian operator-(const Wielomian &w1,const Wielomian &w2)
{
	return -w2+w1;
}