// Rascal, the Advanced Scientific CALculator
// Copyright (C) 2001, 2002, Sebastian Ritterbusch (Rascal@Ritterbusch.de)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more detauls.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#ifndef POLY_HPP_INCLUDED
#define POLY_HPP_INCLUDED

#include <iostream.h>

template <class T>
class mpoly
{
   public:
      T  *a;
      int N;
      
      mpoly(void) { a=0;N=0; }
      mpoly(const T & c) { a=new T[N=1];a[0]=c; }
      mpoly(const T & c, const T & x) { a=new T[N=2];a[0]=c;a[1]=x; }
      
      mpoly(const mpoly<T> & b)
      {
         a=new T[N=b.N];
         int i;
         for(i=0;i<N;i++)
            a[i]=b.a[i];
         for(;N>0 && a[N-1]==T(0);N--);
      }
     ~mpoly(void) { delete [] a; }
      
      mpoly<T> & operator =(const mpoly<T> & c)
      {
         T *n;
         if(c.N==N)
            n=a;
         else
            n=new T[N=c.N];
         int i;
         for(i=0;i<N;i++)
            n[i]=c.a[i];
         if(n!=a)
         {
            delete [] a;
            a=n;
         }
         for(;N>0 && a[N-1]==T(0);N--);
         return *this;
      }
      int   deg(void) const
      {
         int n=N;
         for(;n>0 && a[n-1]==T(0);n--);
         return n>0?n-1:0;
      }
      int   deg(void)
      {
         for(;N>0 && a[N-1]==T(0);N--);
         return N>0?N-1:0;
      }
      mpoly<T> & foreach(T (*f)(const T &))
      {
         int i;
         for(i=0;i<N;i++)
            a[i]=f(a[i]);
         return *this;
      }
      mpoly<T> & foreach(T (*f)(T))
      {
         int i;
         for(i=0;i<N;i++)
            a[i]=f(a[i]);
         return *this;
      }
      mpoly<T> foreach(T (*f)(const T &)) const
      {
         int i;
         mpoly<T> temp(*this);
         for(i=0;i<N;i++)
            temp.a[i]=f(a[i]);
         return temp;
      }
      mpoly<T> foreach(T (*f)(T)) const
      {
         int i;
         mpoly<T> temp(*this);
         for(i=0;i<N;i++)
            temp.a[i]=f(a[i]);
         return temp;
      }
   private:
      void ensure(int n)
      {
         if(N<n)
         {
            T *u=new T[n];
            int i;
            for(i=0;i<N;i++)
               u[i]=a[i];
            for(;i<n;i++)
               u[i]=T(0);
            delete [] a;
            a=u;
            N=n;
         }
      }
   public:
      mpoly<T> & operator +=(const mpoly<T> & b)
      {
         ensure(b.N);
         int i;
         for(i=0;i<N && i<b.N;i++)
            a[i]+=b.a[i];
         for(;N>0 && a[N-1]==T(0);N--);
         return *this;
      }
      mpoly<T> & operator -=(const mpoly<T> & b)
      {
         ensure(b.N);
         int i;
         for(i=0;i<N && i<b.N;i++)
            a[i]-=b.a[i];
         for(;N>0 && a[N-1]==T(0);N--);
         return *this;
      }
      mpoly<T> & operator *=(const mpoly<T> & b)
      {
         int n;
         T *re=new T[n=b.N+N-1];
         int i,j;
         
         for(i=0;i<n;i++) re[i]=0;
         
         for(i=N-1;i>=0;i--)
            for(j=b.N-1;j>=0;j--)
               re[i+j]=re[i+j]+a[i]*b.a[j];
         delete [] a;
         a=re;
         N=n;
         for(;N>0 && a[N-1]==T(0);N--);
         return *this;
      }
      
      T operator()(const value & x) const
      {
         T res=a[N-1];
         int i;
         for(i=N-2;i>=0;i--)
            res=res*x+a[i];

         return res;
      }
      
      friend mpoly<T> operator +(mpoly<T> a,const mpoly<T> &b) { return a+=b; }
      friend mpoly<T> operator -(mpoly<T> a,const mpoly<T> &b) { return a-=b; }
      friend mpoly<T> operator *(mpoly<T> a,const mpoly<T> &b) { return a*=b; }
      friend bool     operator ==(const mpoly<T> & a,const mpoly<T> & b)
      {
         int i;
         for(i=0;i<a.N && i<b.N;i++)
            if(a.a[i]!=b.a[i])
               return false;
         for(;i<a.N;i++)
            if(a.a[i]!=T(0))
               return false;
         for(;i<b.N;i++)
            if(b.a[i]!=T(0))
               return false;
         return true;
      }
      friend bool     operator !=(const mpoly<T> & a,const mpoly<T> & b)
      {
         int i;
         for(i=0;i<a.N && i<b.N;i++)
            if(a.a[i]!=b.a[i])
               return true;
         for(;i<a.N;i++)
            if(a.a[i]!=T(0))
               return true;
         for(;i<b.N;i++)
            if(b.a[i]!=T(0))
               return true;
         return false;
      }      
      friend mpoly<T> power(mpoly<T> a,int e)
      {
         mpoly<T> res(T(1));
         while(e)
         {
            if(e&1)
               res*=a;
            e>>=1;
            if(e)
               a*=a;
         }  
         return res;
      }
      friend mpoly<T> deriv(mpoly<T> a)
      {
         int i;
         for(i=1;i<a.N;i++)
            a.a[i-1]=i*a.a[i];
         if(a.N>0)
            a.N--;
         return a;
      }      
};

#endif


syntax highlighted by Code2HTML, v. 0.9.1