//============================================================= // Numerics Library //============================================================= // Polynomial.h // // Template for polynomials // // Copyright 1995-1996 by Scott Robert Ladd. //============================================================= #ifndef COYOTE_POLYNOMIAL_H #define COYOTE_POLYNOMIAL_H #include "stddef.h" #include "math.h" #include "float.h" #include "xcomplex.h" #include "diagnose.h" //using namespace Coyote; //namespace Coyote { //--------------------------- // Polynomial exception types //--------------------------- enum PolyError { PX_ALLOC, PX_TOOSMALL, PX_RANGE, PX_INCOMPAT, PX_OVERFLOW }; class PolyEx : public ExceptionBase { public: PolyEx ( PolyError err ) { Error = err; } PolyError WhatsWrong() { return Error; } virtual void Explain ( DiagOutput & out ); private: PolyError Error; }; //--------------------------- // Polynomial class //--------------------------- template class Polynomial { public: // constructor Polynomial ( size_t terms, const D * array = NULL ); // copy constructor Polynomial ( const Polynomial & poly ); // destructor ~Polynomial(); // assignment operator void operator = ( const Polynomial & poly ); void operator = ( const D * array ); // conversion to array operator D * () const; // increase degree Polynomial Stretch ( size_t newN ) const; // interrogation size_t Degree() const; // get coefficients D Get ( size_t term ) const; D & operator [] ( size_t term ); // evaluate a polynomial for given value D operator () ( D x ) const; // operations Polynomial operator - () const; Polynomial operator + () const; Polynomial operator + ( const Polynomial & poly ) const; void operator += ( const Polynomial & poly ); Polynomial operator - ( const Polynomial & poly ) const; void operator -= ( const Polynomial & poly ); Polynomial operator * ( const Polynomial & poly ) const; protected: D * Coeff; size_t N; }; // constructor template Polynomial::Polynomial ( size_t terms, const D * array = NULL ) { if (terms < 2) throw PolyEx(PX_TOOSMALL); N = terms; Coeff = new D [N]; if (Coeff == NULL) throw PolyEx(PX_ALLOC); if (array == NULL) { for (size_t i = 0; i < N; ++i) Coeff[i] = (D)0; } else { for (size_t i = 0; i < N; ++i) Coeff[i] = array[i]; } } // copy constructor template Polynomial::Polynomial ( const Polynomial & poly ) { N = poly.N; Coeff = new D [N]; if (Coeff == NULL) throw PolyEx(PX_ALLOC); for (size_t i = 0; i < N; ++i) Coeff[i] = poly.Coeff[i]; } // destructor template Polynomial::~Polynomial() { delete [] Coeff; } // assignment operator template void Polynomial::operator = ( const Polynomial & poly ) { if (N != poly.N) { delete [] Coeff; N = poly.N; Coeff = new D [N]; if (Coeff == NULL) throw PolyEx(PX_ALLOC); } for (size_t i = 0; i < N; ++i) Coeff[i] = poly.Coeff[i]; } template void Polynomial::operator = ( const D * array ) { if (array == NULL) return; for (size_t i = 0; i < N; ++i) Coeff[i] = array[i]; } // conversion to array template Polynomial::operator D * () const { D * result = new D [N]; for (size_t i = 0; i < N; ++i) result[i] = Coeff[i]; return result; } // increase degree template Polynomial Polynomial::Stretch ( size_t newN ) const { if (newN <= N) return (*this); Polynomial result(newN); for (size_t i = 0; i < N; ++i) result.Coeff[i] = Coeff[i]; return result; } // interrogation template inline size_t Polynomial::Degree() const { return N; } // get coefficients template D Polynomial::Get ( size_t term ) const { if (term >= N) throw PolyEx(PX_RANGE); return Coeff[term]; } template D & Polynomial::operator [] ( size_t term ) { if (term >= N) throw PolyEx(PX_RANGE); return Coeff[term]; } // evaluate a polynomial for given value template D Polynomial::operator () ( D x ) const { D y = Coeff[N - 1]; size_t i = N - 2; while(1) { y = x * y + Coeff[i]; if (i == 0) break; --i; } return y; } // operations template Polynomial Polynomial::operator - () const { Polynomial result(N); for (size_t i = 0; i < N; ++ i) result.Coeff[i] = -Coeff[i]; return result; } template inline Polynomial Polynomial::operator + () const { return *this; } template Polynomial Polynomial::operator + ( const Polynomial & poly ) const { if (N > poly.N) { Polynomial res1(*this); for (size_t i = 0; i < poly.N; ++i) res1.Coeff[i] += poly.Coeff[i]; return res1; } else { Polynomial res2(poly); for (size_t i = 0; i < N; ++i) res2.Coeff[i] += Coeff[i]; return res2; } } template inline void Polynomial::operator += ( const Polynomial & poly ) { *this = (*this) + poly; } template Polynomial Polynomial::operator - ( const Polynomial & poly ) const { if (N > poly.N) { Polynomial res1(*this); for (size_t i = 0; i < poly.N; ++i) res1.Coeff[i] -= poly.Coeff[i]; return res1; } else { Polynomial res2(-poly); for (size_t i = 0; i < N; ++i) res2.Coeff[i] += Coeff[i]; return res2; } } template inline void Polynomial::operator -= ( const Polynomial & poly ) { *this = (*this) - poly; } template Polynomial Polynomial::operator * ( const Polynomial & poly ) const { if (N != poly.N) throw PolyEx(PX_INCOMPAT); Polynomial result(2 * N - 1); for (size_t i = 0; i < N; ++i) { for (size_t j = 0; j < N; ++j) result[i + j] += Coeff[i] * poly.Coeff[j]; } return result; } //------------- // declarations //------------- typedef Polynomial FPoly; typedef Polynomial DPoly; typedef Polynomial LPoly; typedef Polynomial CFPoly; typedef Polynomial CDPoly; typedef Polynomial CLPoly; DPoly FFTMultiply ( const DPoly & p1, const DPoly & p2 ); // } // end namespace Coyote #endif