From a032344c66fb1765e81af6010d5f6c5b10fe9ac5 Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Mon, 21 Feb 2022 16:45:44 +0100 Subject: [PATCH] ContFrac arithmetics --- contfrac.cc | 247 +++++++++++++++++++++++++++++++++++++++------------- contfrac.h | 32 +++++-- t.cc | 17 +++- 3 files changed, 229 insertions(+), 67 deletions(-) diff --git a/contfrac.cc b/contfrac.cc index 94eaa5c..50d505a 100644 --- a/contfrac.cc +++ b/contfrac.cc @@ -135,68 +135,206 @@ for(int i=1; i<=n; ++i) //truncate if possible } +template +Homographic Homographic::input(const T &z, const bool inf) const +{ +Homographic hnew; +if(inf) //effective infinity, end of input + { + hnew.v[0][0]=hnew.v[0][1]=v[0][1]; + hnew.v[1][0]=hnew.v[1][1]=v[1][1]; + } +else + { + hnew.v[0][0]=v[0][1]; + hnew.v[1][0]=v[1][1]; + hnew.v[0][1]=v[0][0]+v[0][1]* z; + hnew.v[1][1]=v[1][0]+v[1][1]* z; + } +return hnew; +} + +template +Homographic Homographic::output(const T &z) const +{ +Homographic hnew; + hnew.v[0][0]=v[1][0]; + hnew.v[0][1]=v[1][1]; + hnew.v[1][0]=v[0][0]-v[1][0]*z; + hnew.v[1][1]=v[0][1]-v[1][1]*z; +return hnew; +} + + +template +bool Homographic::outputready(T &z) const +{ +bool inf=0; +T q0,q1; +if(v[1][0]==0) inf=1; else q0=v[0][0]/v[1][0]; +if(v[1][1]==0) inf=1; else q1=v[0][1]/v[1][1]; +if(!inf && q0==q1) {z=q0; return true;} +return false; +} + +template +bool Homographic::terminate() const +{ +return v[1][0]==0&&v[1][1]==0; +} + + template ContFrac Homographic::value(const ContFrac&x) const { Homographic h(*this); std::list l; -typename ContFrac::iterator px=x.begin(); - -do //scan all input +for(typename ContFrac::iterator px=x.begin(); px!=x.beyondend(); ++px) { //digest next input term - Homographic hnew; - if(px==x.end()|| px!=x.begin()&& *px==0) //input is infinity + h=h.input(*px,px==x.end()|| px!=x.begin()&& *px==0); + + //output as much as possible + T out; + while(h.outputready(out)) { - 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]* *px; - hnew.x[1][1]=h.x[1][0]+h.x[1][1]* *px; + l.push_back(out); + h=h.output(out); } - //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 + //terminate if exhausted + if(h.terminate()) { - 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 "<(l); +} + + + template void Rational::simplify() { @@ -206,7 +344,7 @@ if(den<0) den= -den; } T g=gcd(num,den); -if(g>1) +if(MYABS(g)>1) { num/=g; den/=g; @@ -218,7 +356,7 @@ Rational & Rational::operator*=(const T &rhs) { T r=rhs; T g=gcd(r,den); -if(g>1) +if(MYABS(g)>1) { r/=g; den/=g; @@ -233,7 +371,7 @@ Rational & Rational::operator/=(const T &rhs) { T r=rhs; T g=gcd(r,num); -if(g>1) +if(MYABS(g)>1) { r/=g; num/=g; @@ -270,19 +408,20 @@ Rational & Rational::operator*=(const Rational &rhs) Rational r(rhs); T g; g=gcd(num,r.den); -if(g>1) +if(MYABS(g)>1) { num/=g; r.den/=g; } g=gcd(den,r.num); -if(g>1) +if(MYABS(g)>1) { den/=g; r.num/=g; } num*=r.num; den*=r.den; +if(den<0) {den= -den; num= -num;} return *this; } @@ -293,32 +432,20 @@ return *this; * forced instantization in the corresponding object file ******************************************************************************/ template class Rational; -template class Rational; template class Rational; -template class Rational; template class Rational; -template class Rational; template class ContFrac; -template class ContFrac; template class ContFrac; -template class ContFrac; template class ContFrac; -template class ContFrac; template class Homographic; -template class Homographic; template class Homographic; -template class Homographic; template class Homographic; -template class Homographic; template class BiHomographic; -template class BiHomographic; template class BiHomographic; -template class BiHomographic; template class BiHomographic; -template class BiHomographic; diff --git a/contfrac.h b/contfrac.h index 4cd2606..736ebd7 100644 --- a/contfrac.h +++ b/contfrac.h @@ -34,6 +34,8 @@ namespace LA { template class ContFrac; + +//@@@operator== > >= etc. template class Rational { public: @@ -93,6 +95,8 @@ class BiHomographic; + +//@@@operator== > >= etc. template class ContFrac : public NRVec { private: @@ -133,7 +137,10 @@ public: ContFrac operator/(const T &rhs) const {Homographic h({{0,1},{rhs,0}}); return h.value(*this);}; //arithmetics with two ContFrac operands - //@@@ + ContFrac operator+(const ContFrac &rhs) const {BiHomographic h({{{0,1},{1,0}},{{1,0},{0,0}}}); return h.value(*this,rhs);}; + ContFrac operator-(const ContFrac &rhs) const {BiHomographic h({{{0,1},{-1,0}},{{1,0},{0,0}}}); return h.value(*this,rhs);}; + ContFrac operator*(const ContFrac &rhs) const {BiHomographic h({{{0,0},{0,1}},{{1,0},{0,0}}}); return h.value(*this,rhs);}; + ContFrac operator/(const ContFrac &rhs) const {BiHomographic h({{{0,1},{0,0}},{{0,0},{1,0}}}); return h.value(*this,rhs);}; //iterator class iterator { @@ -161,11 +168,16 @@ public: template class Homographic { public: -T x[2][2]; //{{a,b},{c,d}} for (a+b.z)/(c+d.z) +T v[2][2]; //{{a,b},{c,d}} for (a+b.x)/(c+d.x) i.e. [denominator][power_x] Homographic(){}; - explicit Homographic(const T (&a)[2][2]) {memcpy(x,a,2*2*sizeof(T));}; - ContFrac value(const ContFrac&x) const; + explicit Homographic(const T (&a)[2][2]) {memcpy(v,a,2*2*sizeof(T));}; + ContFrac value(const ContFrac&z) const; + + Homographic input(const T &x, const bool inf) const; + Homographic output(const T &x) const; + bool outputready(T &x) const; + bool terminate() const; }; @@ -173,11 +185,19 @@ T x[2][2]; //{{a,b},{c,d}} for (a+b.z)/(c+d.z) template class BiHomographic { public: -T x[2][2][2]; +T v[2][2][2]; //{{{a,b},{c,d}},{{e,f},{g,h}}} i.e.[denominator][power_y][power_x] BiHomographic(){}; - explicit BiHomographic(const T (&a)[2][2][2]) {memcpy(x,a,2*2*2*sizeof(T));}; + explicit BiHomographic(const T (&a)[2][2][2]) {memcpy(v,a,2*2*2*sizeof(T));}; ContFrac value(const ContFrac&x, const ContFrac&y) const; + + BiHomographic inputx(const T &x, const bool inf) const; + BiHomographic inputy(const T &y, const bool inf) const; + BiHomographic output(const T &z) const; + int inputselect() const; + bool outputready(T &x) const; + bool terminate() const; + }; diff --git a/t.cc b/t.cc index d8a1df6..1a21e57 100644 --- a/t.cc +++ b/t.cc @@ -2431,7 +2431,7 @@ NRMat mm=m.permuted_rows(p); cout < p,q; cin>>p>>q; @@ -2483,5 +2483,20 @@ ContFrac z= x*Rational({2,3}); cout<(z)< x(11,101); +ContFrac v(3,7); +ContFrac y= x+v; +cout<(y)< z= x*v; +cout<(z)< h({{{12,4},{3,1}},{{0,1},{-1,0}}}); +ContFrac zz=h.value(x,v); +cout<(zz)<(x)+3)*(Rational(v)+4)/(Rational(x)-Rational(v))<