diff --git a/contfrac.cc b/contfrac.cc index 6c7eed1..565820f 100644 --- a/contfrac.cc +++ b/contfrac.cc @@ -20,6 +20,7 @@ #include #include #include +#include namespace LA { @@ -132,6 +133,67 @@ for(int i=1; i<=n; ++i) //truncate if possible } +template +ContFrac Homographic::value(const ContFrac&x) const +{ +Homographic h(*this); + +std::list l; +for(int i=0; i<=x.length()+1; ++i) //scan all input + { + //digest next input term + Homographic hnew; + if(i>x.length()||i!=0&&x[i]==0) //input is infinity + { + hnew.x[0][0]=hnew.x[0][1]=h.x[0][1]; + hnew.x[1][0]=hnew.x[1][1]=h.x[1][1]; + } + else + { + hnew.x[0][0]=h.x[0][1]; + hnew.x[1][0]=h.x[1][1]; + hnew.x[0][1]=h.x[0][0]+h.x[0][1]*x[i]; + hnew.x[1][1]=h.x[1][0]+h.x[1][1]*x[i]; + } + + //std::cout<<"hnew\n"<< hnew.x[0][0]<<" "<< hnew.x[0][1]<<"\n"<< hnew.x[1][0]<<" "<< hnew.x[1][1]<<"\n"; + + //check if we are ready to output + bool inf=0; + T q0,q1; + if(hnew.x[1][0]==0) inf=1; else q0=hnew.x[0][0]/hnew.x[1][0]; + if(hnew.x[1][1]==0) inf=1; else q1=hnew.x[0][1]/hnew.x[1][1]; + while(!inf && q0==q1) //ready to output + { + l.push_back(q0); + //std::cout <<"out "< hnew2; + hnew2.x[0][0]=hnew.x[1][0]; + hnew2.x[0][1]=hnew.x[1][1]; + hnew2.x[1][0]=hnew.x[0][0]-hnew.x[1][0]*q0; + hnew2.x[1][1]=hnew.x[0][1]-hnew.x[1][1]*q0; + //std::cout<<"hnew2\n"<< hnew2.x[0][0]<<" "<< hnew2.x[0][1]<<"\n"<< hnew2.x[1][0]<<" "<< hnew2.x[1][1]<<"\n"; + hnew=hnew2; + inf=0; + if(hnew.x[1][0]==0) inf=1; else q0=hnew.x[0][0]/hnew.x[1][0]; + if(hnew.x[1][1]==0) inf=1; else q1=hnew.x[0][1]/hnew.x[1][1]; + } + //termination + if(hnew.x[1][0]==0&&hnew.x[1][1]==0) //terminate + { + //std::cout<<"terminate at "< +class Homographic; + +template +class BiHomographic; + + +//@@@implement iterator and rewrite Homographic::value + template class ContFrac : public NRVec { private: @@ -50,7 +73,7 @@ public: ContFrac(const int n) : NRVec(n+1) {}; ContFrac(double x, const int n, const T thres=0); //might yield a non-canonical form ContFrac(const T p, const T q); //should yield a canonical form - ContFrac(const Rational r) : ContFrac(r.num,r.den) {}; + ContFrac(const Rational &r) : ContFrac(r.num,r.den) {}; void canonicalize(); void convergent(T *p, T*q, const int trunc= -1) const; @@ -64,9 +87,39 @@ public: NRVec::resize(n+1,preserve); if(preserve) for(int i=nold+1; i<=n;++i) (*this)[i]=0; } + + ContFrac operator+(const Rational &rhs) const {Homographic h({{rhs.num,rhs.den},{rhs.den,0}}); return h.value(*this);}; + ContFrac operator-(const Rational &rhs) const {Homographic h({{-rhs.num,rhs.den},{rhs.den,0}}); return h.value(*this);}; + ContFrac operator*(const Rational &rhs) const {Homographic h({{0,rhs.num},{rhs.den,0}}); return h.value(*this);}; + ContFrac operator/(const Rational &rhs) const {Homographic h({{0,rhs.den},{rhs.num,0}}); return h.value(*this);}; + }; +//for Gosper's arithmetic + +template +class Homographic { +public: +T x[2][2]; //{{a,b},{c,d}} for (a+b.z)/(c+d.z) + + Homographic(){}; + explicit Homographic(const T (&a)[2][2]) {memcpy(x,a,2*2*sizeof(T));}; + ContFrac value(const ContFrac&x) const; + +}; + + +template +class BiHomographic { +public: +T x[2][2][2]; + + BiHomographic(){}; + explicit BiHomographic(const T (&a)[2][2][2]) {memcpy(x,a,2*2*2*sizeof(T));}; + ContFrac value(const ContFrac&x, const ContFrac&y) const; +}; + }//namespace diff --git a/permutation.cc b/permutation.cc index 4b0c4a7..b83b455 100644 --- a/permutation.cc +++ b/permutation.cc @@ -19,6 +19,7 @@ #include "permutation.h" #include #include +#include namespace LA { diff --git a/t.cc b/t.cc index fc48b46..d9d61b0 100644 --- a/t.cc +++ b/t.cc @@ -2431,7 +2431,7 @@ NRMat mm=m.permuted_rows(p); cout <>x; @@ -2463,5 +2463,15 @@ double zzz=zz.value(); cout < r({11,101}); +ContFrac x(r); +ContFrac y= x+Rational({2,3}); +cout<(y)< z= x*Rational({2,3}); +cout<(z)< -NRVec::NRVec(const std::list l) +NRVec::NRVec(const std::list l) : NRVec(l.size()) { -resize(l.size()); int ii=0; for(typename std::list::const_iterator i=l.begin(); i!=l.end(); ++i) (*this)[ii++] = *i; }