Laurent Polynomial Class

Initialization

Laurent<double> poly1;
      	

Associated Functions

void    setPoly (const vector< T > &coef_i, int hdeg)
void    getPoly (vector< T > &vec)
void    dispPoly ()
void    printPoly ()
int     degree ()
int     highdeg ()
void    LaurentAdd (Laurent &A, Laurent &B)
void    LaurentSub (Laurent &A, Laurent &B)
void    LaurentMult (Laurent &A, Laurent &B)
void    One ()
void    Zero ()
int     isZero ()
void    scale (T s)
void    zinv (Laurent &A)
void    merge (Laurent &X, Laurent &Y)
      	

setPoly is used to set the values of the Laurent Polynomial. Example usage is

Laurent<double> poly1;
int mp=2;
vector<double> coeff;
coeff.push_back(1.0);
coeff.push_back(-0.5);
poly1.setPoly(coeff,mp);
poly1.dispPoly();
	

setPoly accepts an input vector that corresponds to the coefficients of the Poynomial and a maximum degree integer that corresponds to the maximum power of the polynomial. The code above uses dispPoly() to output the following polynomial.

1*z^(2)-0.5*z^(1)
	

getPoly returns the coefficient vector from a Laurent class object.

vector<double> get_coeff;
poly1.getPoly(get_coeff);
	

The two functions degree() and highdeg() return the degree of the Laurent Polynomial( size of coefficient vector - 1) and the highest power of the polynomial. In this case, the degree is 1 while the highest power is 2.

One() and Zero() set the value of Laurent Polynomial to one( 1*z^(0)) and zero ( 0*z^(0)).

LaurentAdd, LaurentSub and LaurentMult add subtract and multiply two Laurent Polynomials respectively and store the value in a third polynomial.

        double re_array[]= {-0.125,0.75,-0.125};
        double re_array2[]= {0.25,0.25};

        vector<double> a(re_array, re_array + sizeof(re_array)/sizeof(double));
        vector<double> b(re_array2, re_array2 + sizeof(re_array2)/sizeof(double));

        int low=1;
        int low2=1;
        Laurent<double> lp1,lp2,lp3,lp4,lp5,lp6;
        lp1.setPoly(a,low);
        lp2.setPoly(b,low2);
        cout << lp1.degree()+1 << " " << lp2.degree()+1 << endl; // prints Laurent Test

        vector<double> newvec;
        lp1.getPoly(newvec);
        cout << newvec.size() << endl;

        cout << "A : ";
        lp1.dispPoly();
        cout << "B : ";
        lp2.dispPoly();
        lp3.LaurentAdd(lp1,lp2);
        cout << "A+B : ";
        lp3.dispPoly();
        lp3.LaurentSub(lp1,lp2);
        cout << "A-B : ";
        lp3.dispPoly();

        lp4.LaurentMult(lp1,lp2);
        cout << "A*B : ";
        lp4.dispPoly();

	

This code has the following output :

3 2
3
A : -0.125*z^(1)+0.75*z^(0)-0.125*z^(-1)
B : 0.25*z^(1)+0.25*z^(0)
A+B : 0.125*z^(1)+1*z^(0)-0.125*z^(-1)
A-B : -0.375*z^(1)+0.5*z^(0)-0.125*z^(-1)
A*B : -0.03125*z^(2)+0.15625*z^(1)+0.15625*z^(0)-0.03125*z^(-1)

	

zinv inverts the power of the polynomial while scale(T s) scales the coefficients by a scalar s.

Long Division Using Div

The function Div is not part of the class. It is a stand alone function that divides two Laurent Polynomials and stores the values in a vector of Laurent Polynomials such that the every even term (starting from index zero) contains the quotient while every odd term contains the remainder polynomial. This is a very basic long division algorithm (as the solution is non-unique) and may not return all quotient/remainder combinations for very large polynomials. Improving this function is on my TO-DO list. For more information see the Sweldens/Daubechies paper as well as Mladen Victor Wickerhauser's Survey Of Wavelet Algorithms 2001/2002 and Wavelet Toolbox user's guide (Michel Misiti, Yves Misiti, Georges Oppenheim and Jean-Michel Poggi) .

void Div(Laurent &A, Laurent &B, vector > &lcont) 

A is divided by B and the results are stored in a Container lcont.

    vector lout;
    Div(lp1,lp2,lout);

    for (unsigned int i=0; i < lout.size()/2; i++) {
        cout << "Q" << i << ": ";
        lout[2*i].dispPoly();
        cout << endl;
        cout << "R" << i << ": " ;
        lout[2*i+1].dispPoly();
        cout << endl;

    }

The Output is

Q0: -0.5*z^(0)+3.5*z^(-1)

R0: -1*z^(-1)

Q1: -0.5*z^(0)-0.5*z^(-1)

R1: 1*z^(0)

Q2: 3.5*z^(0)-0.5*z^(-1)

R2: -1*z^(1)

Q3: -0.5*z^(0)-0.5*z^(-1)

R3: 1*z^(0)

Splitting A Laurent Polynomial Into Polyphase Components

Only single level splitting (Even and Odd) is available in this implementation.

void EvenOdd(Laurent &A,Laurent &even,Laurent &odd)

Example : In the following example you will have to include "filter.h" header file.

#include <iostream>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include "lwave.h"
#include "filter.h"


using namespace std;

int main()
{
        string name="db2";
        Laurent<double> lpd,hpd,lpr,hpr;
        lpoly(name,lpd,hpd,lpr,hpr);
        Laurent<double> leven,lodd;
        EvenOdd(lpr,leven,lodd);
        cout << "Polynomial 1 : ";
        lpr.dispPoly();
        cout << "Polynomial 1 Even Component : ";
        leven.dispPoly();
        cout << "Polynomial 1 Odd Component : ";
        lodd.dispPoly();
        
        Laurent<double> out;
        out.merge(leven,lodd);
        cout << "Merging Even and Odd Components : ";
        out.dispPoly();
        
        return 0;
}
	

The Output is

Polynomial 1 : 0.482963*z^(0)+0.836516*z^(-1)+0.224144*z^(-2)-0.12941*z^(-3)
Polynomial 1 Even Component : 0.482963*z^(0)+0.224144*z^(-1)
Polynomial 1 Odd Component : 0.836516*z^(0)-0.12941*z^(-1)
Merging Even and Odd Components : 0.482963*z^(0)+0.836516*z^(-1)+0.224144*z^(-2)
-0.12941*z^(-3)

Press any key to continue.

A Simple Example demonstrating the use of Laurent class

#include <iostream>
#include <vector>

#include "lwave.h"


using namespace std;

int main() {
//    double re_array[]= {5.0,2.0,4.0,3.0};
//      double re_array2[]= {2.0,2.0,-1.0,9.0};
    double re_array[]= {-0.125,0.75,-0.125};
        double re_array2[]= {0.25,0.25};

        vector<double> a(re_array, re_array + sizeof(re_array)/sizeof(double));
        vector<double> b(re_array2, re_array2 + sizeof(re_array2)/sizeof(double));
//      int low=-2;
//      int low2=2;
    int low=1;
        int low2=1;
        Laurent<double> lp1,lp2,lp3,lp4,lp5,lp6;
        lp1.setPoly(a,low);
        lp2.setPoly(b,low2);
        cout << lp1.degree()+1 << " " << lp2.degree()+1 << endl; // prints Laurent Test

    vector<double> newvec;
    lp1.getPoly(newvec);
    cout << newvec.size() << endl;

    cout << "A : ";
        lp1.dispPoly();
        cout << "B : ";
        lp2.dispPoly();
        lp3.LaurentAdd(lp1,lp2);
        cout << "A+B : ";
        lp3.dispPoly();
        lp3.LaurentSub(lp1,lp2);
        cout << "A-B : ";
    lp3.dispPoly();

    lp4.LaurentMult(lp1,lp2);
    cout << "A*B : ";
    lp4.dispPoly();

    lp5.zinv(lp1);
    cout << "A(1/z) : ";
    lp5.dispPoly();

    //cout << lp5.isMono() << endl;

    LaurentMat<double> Mat1;
    Mat1.setMat(lp1,lp1,lp2,lp2);
    Laurent<double> det1;
    Mat1.Det(det1);
    cout << "Determinant : ";
    det1.dispPoly();

    cout << "Mono : " << det1.isMono() << endl;
        vector lout;
    Div(lp1,lp2,lout);

    for (unsigned int i=0; i < lout.size()/2; i++) {
        cout << "Q" << i << ": ";
        lout[2*i].dispPoly();
        cout << endl;
        cout << "R" << i << ": " ;
        lout[2*i+1].dispPoly();
        cout << endl;

    }
        
        return 0;
}

	

The Output Follows

3 2
3
A : -0.125*z^(1)+0.75*z^(0)-0.125*z^(-1)
B : 0.25*z^(1)+0.25*z^(0)
A+B : 0.125*z^(1)+1*z^(0)-0.125*z^(-1)
A-B : -0.375*z^(1)+0.5*z^(0)-0.125*z^(-1)
A*B : -0.03125*z^(2)+0.15625*z^(1)+0.15625*z^(0)-0.03125*z^(-1)
A(1/z) : -0.125*z^(1)+0.75*z^(0)-0.125*z^(-1)
Determinant : 0*z^(-1)
Mono : 1
Q0: -0.5*z^(0)+3.5*z^(-1)

R0: -1*z^(-1)

Q1: -0.5*z^(0)-0.5*z^(-1)

R1: 1*z^(0)

Q2: 3.5*z^(0)-0.5*z^(-1)

R2: -1*z^(1)

Q3: -0.5*z^(0)-0.5*z^(-1)

R3: 1*z^(0)


Press any key to continue.