//import java.awt.*;

/*
STRUKTURA Triedy Polynom:
  -Datove Pollozky: int st
                    float[] a
  -Konstruktory: Polynom() -vytvori nulovy polynom
                 Polynom(int st) -vytvori novy polynom daneho st a
                                  rezervuje pre koef.pole pozad.dlzky
                 Polynom(float[] a,int st) -vytv.novy polynom so specifik.
                                            vlastnostami(POZN:Implicitne konstruktor
                                            nezabezpeci,ze sa berie pole a len po st+1)
                 Polynom(float[] a) -vytv.novy polynom s specif.koeficientami,pricom
                                     stupen bude posled.nenulovy koeficient pola a
  -Metody: this. sucet(Polynom) -sucet polynomov
           this. sucin(Polynom) -sucin Polynomov
           this. nasob(float) -vynasobi this realnym cislom
           this. vydel(Polynom) -vydeli polynom this polynomom specif.
                                 ako argument metody
           this. zvdel(Polynom) -analogicky ako vydel(Polynom) len vrati zvysok
                                 po deleni danych polynomov
           this. deriv() -vysledkom je zderivovany polynom
           this. deriv(int) -analogicky ako deriv() s moznostou
                            specifikov.radu derivacie
           this. naRetazec() -prevedie polynom na String
           this. nulovy() -vytvori nulovy polynom
           this. jeNulovy() -vrati true,ak polynom je nulovy
           this. osetriSt() -skontroluje,ci ma polynom spravny stupen tj.
                             ci na posled.miestach nie su nuly,ak su
                             znizi stupen na skutocny
  */

public class Polynom{
 public int st;
 public float a[];

 public Polynom(){
   st=0;
   a=new float[st+1];
   a[0]=0;
 }

 public Polynom(float[] a,int st){
   this.st=st;
   this.a=a;
 }

 public Polynom(int st){ //nahadze nuly tj.nulovy
   this.st=st;
   a=new float[st+1];
   for (int i=0;i<=st;i++) a[i]=0;
 }

 public Polynom(float[] a){
    this.a=a;
    int pom=a.length-1;
    while (a[pom]==0) pom--;
    st=pom;
 }

 public Polynom nulovy(){
   Polynom pom=new Polynom(0);
   return pom;
 }

 public boolean jeNulovy(){
  boolean q=true;
  for (int i=0;i<=st;i++)
      if (a[i]!=0){ q=false; break; }
  return q;
 }

 public Polynom sucet(Polynom f){ //struktura: g.sucet(f);
  int pom;
  if (f.st>=st) pom=f.st; //zisti stupen vysled.polynomu,pre potrebu dimenzie pola
   else pom=st;

  float[] b=new float[pom+1];
  int vn=0;
  if (f.st>=st) {  vn=f.st;
                   for (int i=0;i<=st;i++) b[i]=f.a[i]+a[i];
                   for (int i=st+1;i<=f.st;i++) b[i]=f.a[i];

                  } else {
                      vn=st;
                      for (int i=0;i<=f.st;i++) b[i]=f.a[i]+a[i];
                      for (int i=f.st+1;i<=st;i++) b[i]=a[i];

                           }
  while (b[vn]==0) vn--;
  Polynom v=new Polynom(b,vn);
  return v;
 }

 public String naRetazec(){
  String s=("Polynom stupna = "+this.st+" , ");
  for (int i=0;i<=st;i++)
   s+=(" a["+i+"]="+this.a[i]+" ");
  return s;
 }

 public Polynom nasob(float c){ //struktura: f.nasob(4);
  if (c==0) { Polynom p = new Polynom();
              return p; }
     else {
  float[] b=new float[st+1];
  for (int i=0;i<=st;i++)
  b[i]=c*a[i];
  Polynom p = new Polynom(b,st);
  return p; } //else
 }

 public Polynom sucin(Polynom f){ //struktura: g.sucin(f);
  if (f.jeNulovy()) return f;
  if (this.jeNulovy()) return this;
  int vst=st+f.st;
  float[] b=new float[vst+1];
  for (int i=0;i<=st;i++)
   for (int j=0;j<=f.st;j++) b[i+j]+=a[i]*f.a[j];
  Polynom p=new Polynom(b,vst);
  return p;
 }

 public Polynom vydel(Polynom f){ //struktura: g.vydel(f);
  Polynom v;
  Polynom pom;
  Polynom zv;

  if (f.jeNulovy()) { System.out.println("WARNING: Division by zero");
                      return f; }
  if (this.jeNulovy()) { System.out.println("Delenec je nulovy");
                        return this; }
  if (st<f.st){ //System.out.println("Podiel = 0");
              v=new Polynom(0);
              return v; }
      else // stupne su ok pre delenie
    if (st==f.st) { float nas = a[st]/f.a[st];
                   boolean q=true;
                   for (int i=0;i<st;i++)
                       if (a[i]!=f.a[i]*nas){ q=false;
                                              break; }
                   if (q) { v=new Polynom(0);
                            v.a[0]=nas;
                            return v; }
                      else { v=new Polynom(0);

                             return v; }
                   }
         else { // st > f.st
       float[] b=new float[st-f.st+1];
       for (int i=0;i<b.length;i++) b[i]=0;
       int vst=st-f.st;
       int n=vst;
       zv=this;
       Polynom pom2;

      while (n>=0){
         b[n]=zv.a[zv.st]/f.a[f.st];
         v=new Polynom(b,n);
         pom=v.sucin(f);
         for (int i=0;i<=pom.st;i++) pom.a[i]=-pom.a[i];
         pom2=zv.sucet(pom);
         zv=pom2;
         if (zv.st>=f.st){ n--;
                           continue; }
            else{ v=new Polynom(b,vst);
		    	  return v; }
          } //while

      v=new Polynom(b);
      return v;
                } //else
  } //vydel


  public Polynom zvdel(Polynom f){ //struktura: g.zvdel(f);
    Polynom v;
    Polynom pom;
    Polynom zv;

    if (f.jeNulovy()) { System.out.println("WARNING: Division by zero");
                        return f; }
    if (this.jeNulovy()) { System.out.println("Delenec je nulovy");
                          return f; }
    if (st<f.st) return this;
        else // stupne su ok pre delenie
      if (st==f.st) { float nas = a[st]/f.a[st];
                      boolean q=true;
                      for (int i=0;i<st;i++)
                         if (a[i]!=f.a[i]*nas){ q=false;
                                                break; }
                      if (q) { v=new Polynom(0);
                               return v; }
                         else return this;
                     }
           else { // st > f.st
         float[] b=new float[st-f.st+1];
         for (int i=0;i<b.length;i++) b[i]=0;
         int vst=st-f.st;
         int n=vst;
         zv=this;
         Polynom pom2;

        while (n>=0){
           b[n]=zv.a[zv.st]/f.a[f.st];
           v=new Polynom(b,n);
           pom=v.sucin(f);
           for (int i=0;i<=pom.st;i++) pom.a[i]=-pom.a[i];
           pom2=zv.sucet(pom);
           zv=pom2;
           if (zv.st>=f.st){ n--;
                             continue; }
              else return zv;
                     } //while

        v=new Polynom(0);
        return v;
                  } //else
  } //zvdel

  public Polynom deriv(){
	Polynom v;
	if (st<=0){ if (st<0) { System.out.println("Chyba zaporny stupen polynomu");
	                        v=nulovy(); return v; }
	                else { v=nulovy(); return v; }  // st=0
		       }
	   else {
	   v=new Polynom(st-1);
       for (int i=st;i>0;i--) v.a[i-1]=i*a[i];
	   return v; }
  } //deriv

  public Polynom deriv(int rad){
	Polynom v;
	if (rad<0){ System.out.println("Chyba zaporny rad derivacie");
	            v=nulovy(); return v; }
	if (rad==0) return this;
    if (rad==1) { v=deriv(); return v; }
        else { //rad>1
        v=this;
        for (int i=1;i<=rad;i++) v=v.deriv();
        return v; }
  } //deriv(int)

  public void osetriSt(){
	if (a[st]==0) {
	              boolean q=true;
	              while (q) { st--;
	                          if (a[st]!=0) q=false; }
				   }
  }

} //Polynom
