diff --git a/polynomial.cc b/polynomial.cc index 1b14230..5e0630d 100644 --- a/polynomial.cc +++ b/polynomial.cc @@ -56,6 +56,94 @@ r.resize(rhs.degree()-1,true); } +template +NRMat Sylvester(const Polynomial &p, const Polynomial &q) +{ +int nm=p.degree()+q.degree(); +NRMat a(nm,nm); +a.clear(); +for(int i=0; i=0; --j) + a(i,i+p.degree()-j)=p[j]; +for(int i=0; i=0; --j) + a(q.degree()+i,i+q.degree()-j)=q[j]; +return a; +} + +template +NRMat Polynomial::companion() const +{ +if((*this)[degree()]==(T)0) laerror("zero coefficient at highest degree - simplify first"); +NRMat a(degree(),degree()); +a.clear(); +for(int i=0; i +NRVec::complextype> Polynomial::roots() const +{ +laerror("roots not implemented for integer polynomials"); +return NRVec::complextype>(1); +} + +template +NRVec::complextype> Polynomial::roots() const +{ +NRMat a=this->companion(); +NRVec::complextype> r(degree()); +gdiagonalize(a,r,NULL,NULL); +return r; +} + +template +NRVec Polynomial::realroots(const typename LA_traits::normtype thr) const +{ +NRVec::complextype> r = roots(); +NRVec rr(degree()); +int nr=0; +for(int i=0; i +Polynomial lagrange_interpolation(const NRVec &x, const NRVec &y) +{ +if(x.size()!=y.size()) laerror("vectors of different length in lagrange_interpolation"); +if(x.size()<1) laerror("empty vector in lagrange_interpolation"); +if(x.size()==1) + { + Polynomial p(0); + p[0]=y[0]; + return p; + } +int n=x.size()-1; +Polynomial p(n); +p.clear(); +for(int i=0; i<=n; ++i) + { + T prod=(T)1; + for(int j=0; j<=n; ++j) if(j!=i) prod *= (x[i]-x[j]); + if(prod==(T)0) laerror("repeated x-value in lagrange_interpolation"); + Polynomial tmp=polyfromroots(x,i); + p += tmp * y[i] / prod; + } +return p; +} + + + + /***************************************************************************//** * forced instantization in the corresponding object file ******************************************************************************/ @@ -64,10 +152,13 @@ template class Polynomial; template class Polynomial >; #define INSTANTIZE(T) \ +template NRMat Sylvester(const Polynomial &p, const Polynomial &q); \ +template Polynomial lagrange_interpolation(const NRVec &x, const NRVec &y); \ - -//INSTANTIZE(double) +INSTANTIZE(int) +INSTANTIZE(double) +INSTANTIZE(std::complex) diff --git a/polynomial.h b/polynomial.h index 40a8d7e..c97346d 100644 --- a/polynomial.h +++ b/polynomial.h @@ -22,6 +22,7 @@ #include "la_traits.h" #include "vec.h" +#include "nonclass.h" namespace LA { @@ -78,6 +79,7 @@ public: while(n>0 && abs((*this)[n]) companion() const; //matrix which has this characteristic polynomial + NRVec::complextype> roots() const; //implemented for complex and double only + NRVec realroots(const typename LA_traits::normtype thr) const; - //gcd, lcm - //roots, interpolation ... special only for real->complex - declare only and implent only template specialization in .cc + //@@@gcd, lcm euler and svd }; @@ -148,12 +152,43 @@ sum += p[0]; return sum; } +template +NRVec values(const Polynomial &p, const NRVec &x) +{ +NRVec r(x.size()); +for(int i=0; i inline Polynomial operator+(const T &a, const Polynomial &rhs) {return Polynomial(rhs)+=a;} template inline Polynomial operator-(const T &a, const Polynomial &rhs) {return Polynomial(rhs)-=a;} +//Sylvester matrix +template +extern NRMat Sylvester(const Polynomial &p, const Polynomial &q); + +//polynomial from given roots +template +Polynomial polyfromroots(const NRVec &roots, const int skip= -1) +{ +Polynomial p(0); +p[0]=(T)1; +for(int i=0; i +extern Polynomial lagrange_interpolation(const NRVec &x, const NRVec &y); + + + }//namespace #endif diff --git a/t.cc b/t.cc index a490521..70ae1e5 100644 --- a/t.cc +++ b/t.cc @@ -2167,7 +2167,7 @@ cout < z=value(p,q); //p(q(x)) Polynomial y=value(q,p); cout <>n ; +NRVec r(n); +r.randomize(1.); +r.sort(0); +Polynomial p=polyfromroots(r); +cout <>n ; +NRVec x(n+1),y(n+1); +x.randomize(1.); +y.randomize(1.); +Polynomial p=lagrange_interpolation(x,y); +cout < yy=values(p,x); +cout<<"interpolation error= "<<(y-yy).norm()<