next up previous contents
Next: The Implementation: Up: Building Polynomials: The FLOAT_POLY Previous: Building Polynomials: The FLOAT_POLY

Defining the FLOAT_POLY Class:

Now that the underlying cells are defined, we can build a polynomial. We will do this also by a parent core and child method. We start with the virtual parent class FLOAT_POLY_CORE:

class FLOAT_POLY_CORE{
    friend class FLOAT_CELL_CORE;
    friend istream& operator>>(istream& in,FLOAT_POLY_CORE& A)
      {A.grab(in); return(in);};
    friend istream& operator>>(istream& in,FLOAT_POLY_CORE* A)
      {A->grab(in); return(in);};
    friend ostream& operator<<(ostream& out,const FLOAT_POLY_CORE& A)
      {A.print(out); return(out);};
    friend ostream& operator<<(ostream& out,const FLOAT_POLY_CORE* A)
      {A->print(out); return(out);};
  public:
    virtual ~FLOAT_POLY_CORE(){};
    virtual int is_empty() = 0;
    virtual void delete_power(unsigned int p) = 0;
    virtual void search_power(unsigned int p) = 0;
    virtual void build_list(FLOAT *A,int size) = 0;
    virtual unsigned int get_degree() = 0;
    virtual int insert(FLOAT new_element,unsigned int q) = 0;
    virtual FLOAT_POLY_CELL* split(FLOAT_POLY_CELL *A) = 0;
    virtual FLOAT_POLY_CELL* merge(FLOAT_POLY_CELL *A1,
                                   FLOAT_POLY_CELL *A2) = 0;
    virtual FLOAT_POLY_CELL* mergesort(FLOAT_POLY_CELL *A) = 0;
    virtual void mergesort() = 0;
    virtual istream& grab(istream& in) = 0;
    virtual ostream& print(ostream& out) const = 0;   
  };

We see that this class is quite similar to the one we built for other lists. Note we define the methods to do mergesort at this level rather than at the cell level like we did before.

The FLOAT_POLY class itself is also very derivative of what we have done before:

class FLOAT_POLY : public FLOAT_POLY_CORE{
    friend class FLOAT_POLY_CELL;
    friend class FLOATPOLYIter;
    friend FLOAT_POLY operator*(FLOAT t,FLOAT_POLY& P);
    friend FLOAT_POLY operator*(FLOAT_POLY& P,FLOAT t);
    friend FLOAT_POLY& operator*=(FLOAT t,FLOAT_POLY& P);
    friend FLOAT_POLY& operator*=(FLOAT_POLY& P,FLOAT t);
  public:
    FLOAT_POLY();
    FLOAT_POLY(FLOAT x_in,unsigned int q);
    FLOAT_POLY(const FLOAT_POLY&);
    ~FLOAT_POLY();
    FLOAT_POLY&operator=(const FLOAT_POLY&);
    // agents
    int is_empty(){return(head==NULL);};
    void delete_power(unsigned int p);
    void search_power(unsigned int p);
    void build_list(FLOAT *A,int size);
    unsigned int get_degree();
    int insert(FLOAT new_element,unsigned int q);
    int insert_nosort(FLOAT new_element,unsigned int q);
    int operator==(const FLOAT_POLY&);
    int operator!=(const FLOAT_POLY&);   
    FLOAT_POLY operator+(const FLOAT_POLY&);
    FLOAT_POLY& operator+=(const FLOAT_POLY&);
    FLOAT_POLY operator-(const FLOAT_POLY&); 
    FLOAT_POLY& operator-=(const FLOAT_POLY&);
    FLOAT_POLY operator*(const FLOAT_POLY&);
    FLOAT_POLY& operator*=(const FLOAT_POLY&);
    FLOAT_POLY integral();
    FLOAT definite_integral(FLOAT a,FLOAT b);
    FLOAT inner_product(FLOAT a,FLOAT b,FLOAT_POLY& P);
    FLOAT operator()(FLOAT x);
    FLOAT_POLY_CELL* split(FLOAT_POLY_CELL *A);
    FLOAT_POLY_CELL* merge(FLOAT_POLY_CELL *A1,FLOAT_POLY_CELL *A2);
    FLOAT_POLY_CELL* mergesort(FLOAT_POLY_CELL *A);
    void mergesort();   
    istream& grab(istream& in);
    ostream& print(ostream& out) const;
  protected:
    FLOAT_POLY_CELL *head;
    FLOAT_POLY_CELL* get_element_address(unsigned int p);
    FLOAT_POLY_CELL* get_before_element_address(unsigned int p);
    FLOAT_POLY_CELL* get_after_element_address(unsigned int p);    
  };

We must set up the usual friendships:

    friend class FLOAT_POLY_CELL;
    friend class FLOATPOLYIter;

We define overloaded multiplication operators so that we can easily multiply a polynomial by a scalar:

    friend FLOAT_POLY operator*(FLOAT t,FLOAT_POLY& P);
    friend FLOAT_POLY operator*(FLOAT_POLY& P,FLOAT t);
    friend FLOAT_POLY& operator*=(FLOAT t,FLOAT_POLY& P);
    friend FLOAT_POLY& operator*=(FLOAT_POLY& P,FLOAT t);

There are several constructors, a copy constructor, the overloaded equal and a destructor:

    FLOAT_POLY();
    FLOAT_POLY(FLOAT x_in,unsigned int q);
    FLOAT_POLY(const FLOAT_POLY&);
    FLOAT_POLY&operator=(const FLOAT_POLY&);
    ~FLOAT_POLY();

We need comparison operators:

    int operator==(const FLOAT_POLY&);
    int operator!=(const FLOAT_POLY&);

Lots of algebraic operations:

    FLOAT_POLY operator+(const FLOAT_POLY&);
    FLOAT_POLY& operator+=(const FLOAT_POLY&);
    FLOAT_POLY operator-(const FLOAT_POLY&); 
    FLOAT_POLY& operator-=(const FLOAT_POLY&);
    FLOAT_POLY operator*(const FLOAT_POLY&);
    FLOAT_POLY& operator*=(const FLOAT_POLY&);

Insert operations: the nosort version allows us to insert many terms and then call a sort manually. When we used the insertion function before in our other lists, it generally did not matter the order of the elements in the list. However, now that we interpret the list as a polynomial, we really do want the powers stored in the cells to go from highest (head cell) to lowest (tail cell). We always want the polynomial stored in this way, but it would not be efficient to do multiple inserts with automatic resorting following each insertion. So the method insert allows us to do one insert followed by an automatic mergesort, while the insert_nosort simply inserts with no sorting. So when we use the nosort version, we have to manually sort later.

    int insert(FLOAT new_element,unsigned int q);
    int insert_nosort(FLOAT new_element,unsigned int q);

Sorting methods:

    FLOAT_POLY_CELL* split(FLOAT_POLY_CELL *A);
    FLOAT_POLY_CELL* merge(FLOAT_POLY_CELL *A1,FLOAT_POLY_CELL *A2);
    FLOAT_POLY_CELL* mergesort(FLOAT_POLY_CELL *A);

Convenience methods:

    int is_empty(){return(head==NULL);};
    void delete_power(unsigned int p);
    void search_power(unsigned int p);
    void build_list(FLOAT *A,int size);
    unsigned int get_degree();

Last, there are methods specific to the polynomial class with float elements.

    FLOAT_POLY integral();
    FLOAT definite_integral(FLOAT a,FLOAT b);
    FLOAT inner_product(FLOAT a,FLOAT b,FLOAT_POLY& P);
    FLOAT operator()(FLOAT x);

We need to evaluate the polynomials at a given value of t: this is the method FLOAT operator(). Given a constructed polynomial FLOAT_POLY P() (note default constructor call), the line P(x) computes the value


P(x) = a0  +  a1x  +  a2x2  +   ...   +  anxn  

We can find an antiderivative of the given polynomial with the call P.integral () which returns the new polynomial


P(x) = 1 + a0t  +  $\displaystyle {\frac{a_1}{2}}$t2  +  $\displaystyle {\frac{a_2}{3}}$t3  +   ...   +  $\displaystyle {\frac{a_n}{n+1}}$tn + 1  

We have chosen to always return the antidervative with constant term 1 added as the tail.

The definite integral from a given a to b can then be computed as


$\displaystyle \int_{a}^{b}$P(tdt = a0(b - a)  +  $\displaystyle {\frac{a_1}{2}}$(b2 - a2)  +  $\displaystyle {\frac{a_2}{3}}$(b3 - a3)  +   ...   +  $\displaystyle {\frac{a_n}{n+1}}$(bn + 1 - an + 1)  

Finally, we will define the usual L2 dotproduct as $ \int_{a}^{b}$P(tdt for a given polynomial P on the interval [a, b]. This is the method inner_product.

Lastly, we define iterators:

class FLOATPOLYIter{
  public:
    FLOATPOLYIter(FLOAT_POLY& fsl) : sl(fsl), p(fsl.head) {;};
    FLOATPOLYIter(const FLOAT_POLY& fsl) : sl(fsl), p(fsl.head) {;};    
    ~FLOATPOLYIter(){;};
    //
    void operator++();
    FLOAT_POLY_CELL* operator()() const;
    operator const void*() const;
  private:
    const FLOAT_POLY& sl;
    FLOAT_POLY_CELL* p;
  };


next up previous contents
Next: The Implementation: Up: Building Polynomials: The FLOAT_POLY Previous: Building Polynomials: The FLOAT_POLY
Jim Peterson
1999-04-22