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.
vectorlout; 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; vectorlout; 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.