/* LA: linear algebra C++ interface library Copyright (C) 2021 Jiri Pittner or This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "polynomial.h" #include #include namespace LA { template void Polynomial::polydiv(const Polynomial &rhs, Polynomial &q, Polynomial &r) const { if(rhs[rhs.degree()]==(T)0) laerror("division by a polynomial with zero leading coefficient - simplify it first"); if(rhs.degree()==0) //scalar division { q= *this/rhs[0]; r.resize(0,false); r[0]=0; return; } int rdegree= rhs.degree(); int qdegree= degree()-rdegree; if(qdegree<0) { q.resize(0,false); q[0]=0; r= *this; return; } //general case q.resize(qdegree,false); r= *this; r.copyonwrite(); for(int i=degree(); i>=rdegree; --i) { T tmp= r[i]/rhs[rdegree]; q[i-rdegree]= tmp; r -= rhs.shifted(i-rdegree)*tmp; } 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 ******************************************************************************/ template class Polynomial; 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(int) INSTANTIZE(double) INSTANTIZE(std::complex) }//namespace