diff --git a/polynomial.cc b/polynomial.cc index c9c09e5..5fd52f8 100644 --- a/polynomial.cc +++ b/polynomial.cc @@ -23,19 +23,49 @@ namespace LA { +template +void Polynomial::polydiv(const Polynomial &rhs, Polynomial &q, Polynomial &r) const +{ +if(rhs[rhs.degree()]==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); +} /***************************************************************************//** * forced instantization in the corresponding object file ******************************************************************************/ template class Polynomial; -template class Polynomial; template class Polynomial; +template class Polynomial >; #define INSTANTIZE(T) \ -//INSTANTIZE(float) //INSTANTIZE(double) diff --git a/polynomial.h b/polynomial.h index fbdca35..40a8d7e 100644 --- a/polynomial.h +++ b/polynomial.h @@ -29,6 +29,7 @@ template class Polynomial : public NRVec { public: Polynomial(): NRVec() {}; + Polynomial(const NRVec &v) : NRVec(v) {}; //allow implicit conversion from NRVec Polynomial(const int n) : NRVec(n+1) {}; Polynomial(const T &a, const int n) : NRVec(n+1) {NRVec::clear(); (*this)[0]=a;}; @@ -39,13 +40,16 @@ public: Polynomial& operator-=(const T &a) {NOT_GPU(*this); NRVec::copyonwrite(); (*this)[0]-=a; return *this;} Polynomial operator+(const T &a) const {return Polynomial(*this) += a;}; Polynomial operator-(const T &a) const {return Polynomial(*this) -= a;}; - //operator *= and * by a scalar inherited - //unary- inherited + Polynomial operator-() const {return NRVec::operator-();} + Polynomial operator*(const T &a) const {return NRVec::operator*(a);} + Polynomial operator/(const T &a) const {return NRVec::operator/(a);} + Polynomial& operator*=(const T &a) {NRVec::operator*=(a); return *this;} + Polynomial& operator/=(const T &a) {NRVec::operator/=(a); return *this;} Polynomial& operator+=(const Polynomial &rhs) { NOT_GPU(*this); NRVec::copyonwrite(); - if(rhs.degree()>degree()) resize(rhs.degree()); + if(rhs.degree()>degree()) resize(rhs.degree(),true); for(int i=0; i<=rhs.degree(); ++i) (*this)[i] += rhs[i]; return *this; } @@ -53,7 +57,7 @@ public: Polynomial& operator-=(const Polynomial &rhs) { NOT_GPU(*this); NRVec::copyonwrite(); - if(rhs.degree()>degree()) resize(rhs.degree()); + if(rhs.degree()>degree()) resize(rhs.degree(),true); for(int i=0; i<=rhs.degree(); ++i) (*this)[i] -= rhs[i]; return *this; } @@ -61,16 +65,69 @@ public: Polynomial operator-(const Polynomial &rhs) const {return Polynomial(*this) -= rhs;}; Polynomial operator*(const Polynomial &rhs) const //for very long polynomials FFT should be used { + NOT_GPU(*this); Polynomial r(degree()+rhs.degree()); r.clear(); for(int i=0; i<=rhs.degree(); ++i) for(int j=0; j<=degree(); ++j) r[i+j] += rhs[i]*(*this)[j]; return r; }; + void simplify(const typename LA_traits::normtype thr) + { + NOT_GPU(*this); + int n=degree(); + while(n>0 && abs((*this)[n])0) + { + Polynomial r(degree()+shift); + for(int i=0; icomplex - declare only and implent only template specialization in .cc diff --git a/t.cc b/t.cc index 45b4bdb..a490521 100644 --- a/t.cc +++ b/t.cc @@ -2172,23 +2172,33 @@ if(1) int n,m; double x; cin >>n >>m >>x; +if(n p(n),q(m); p.randomize(1.); q.randomize(1.); +NRVec qq(q); +Polynomial qqq(qq); +Polynomial pp(n); pp.randomize(1.); p*=10.; +Polynomial a,b; +p.polydiv(q,a,b); Polynomial r=p*q; Polynomial z=value(p,q); //p(q(x)) Polynomial y=value(q,p); cout < u(5,5); u.randomize(1.); cout << (value(p,u)*value(q,u) -value(r,u)).norm()< NRVec::operator-() const { #ifdef CUDALA if(location == cpu){ #endif - cblas_dscal(nn, -1.0, v, 1); + cblas_dscal(nn, -1.0, result.v, 1); #ifdef CUDALA }else{ - cublasDscal(nn, -1.0, v, 1); + cublasDscal(nn, -1.0, result.v, 1); TEST_CUBLAS("cublasDscal"); } #endif @@ -174,10 +174,10 @@ const NRVec > NRVec >::operator-() con #ifdef CUDALA if(location == cpu){ #endif - cblas_zdscal(nn, -1.0, v, 1); + cblas_zdscal(nn, -1.0, result.v, 1); #ifdef CUDALA }else{ - cublasZdscal(nn, -1.0, (cuDoubleComplex*)v, 1); + cublasZdscal(nn, -1.0, (cuDoubleComplex*)result.v, 1); TEST_CUBLAS("cublasZdscal"); } #endif diff --git a/vec.h b/vec.h index 646f332..70e0651 100644 --- a/vec.h +++ b/vec.h @@ -193,10 +193,12 @@ public: inline NRVec& operator+=(const T &a); inline NRVec& operator-=(const T &a); inline NRVec& operator*=(const T &a); + inline NRVec& operator/=(const T &a); inline const NRVec operator+(const T &a) const; inline const NRVec operator-(const T &a) const; inline const NRVec operator*(const T &a) const; + inline const NRVec operator/(const T &a) const; //! determine the actual value of the reference counter @@ -753,6 +755,16 @@ inline NRVec & NRVec::operator*=(const T &a) { return *this; } +template +inline NRVec & NRVec::operator/=(const T &a) { + NOT_GPU(*this); + copyonwrite(); + + for(register int i=0; iT * with given vector \f$\vec{y}\f$ of type T and order \f$N\f$ @@ -858,6 +870,7 @@ inline const NRVec NRVec::unitvector() const { NRVECMAT_OPER(Vec,+) NRVECMAT_OPER(Vec,-) NRVECMAT_OPER(Vec,*) +NRVECMAT_OPER(Vec,/) /***************************************************************************//** * generate operators involving vector and vector @@ -1035,13 +1048,13 @@ nn = n; if(location == cpu) { #endif - if(preserve) {vold=v; do_delete=true;} else delete[] v; + if(preserve) {vold=v; preserved= do_delete=true;} else delete[] v; v = new T[nn]; #ifdef CUDALA } else { - if(preserve) {vold=v; do_delete=true;} else gpufree(v); + if(preserve) {vold=v; d preserved= o_delete=true;} else gpufree(v); v = (T*) gpualloc(nn*sizeof(T)); } #endif @@ -1374,6 +1387,9 @@ inline NRVec& NRVec::operator*=(const double &a) { return *this; } +template<> +inline NRVec& NRVec::operator/=(const double &a) {return *this *= (1./a);} + /***************************************************************************//** * multiplies this complex vector \f$\vec{x}\f$ by a complex scalar value \f$\alpha\f$ * \f[\vec{x}_i\leftarrow\alpha\vec{x}_i\f] @@ -1397,6 +1413,9 @@ inline NRVec >& NRVec >::operator*=(co return *this; } +template<> +inline NRVec >& NRVec >::operator/=(const std::complex &a) {return *this *= (1./a);} + /***************************************************************************//** * computes the inner product of this real vector \f$\vec{x}\f$ with given real vector \f$\vec{y]\f$ * @param[in] rhs real vector \f$\vec{y}\f$