From b4aaa77da4590feb35157b9db870560843763ee1 Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Sat, 19 Feb 2022 19:10:24 +0100 Subject: [PATCH] working on contfrac --- contfrac.cc | 114 +++++++++++++++++++++++++++++++++++++++++++++++--- contfrac.h | 72 ++++++++++++++++++++++++++++--- permutation.h | 2 +- t.cc | 12 +++++- 4 files changed, 186 insertions(+), 14 deletions(-) diff --git a/contfrac.cc b/contfrac.cc index 565820f..94eaa5c 100644 --- a/contfrac.cc +++ b/contfrac.cc @@ -17,6 +17,7 @@ */ #include "contfrac.h" +#include "permutation.h" #include #include #include @@ -121,6 +122,7 @@ void ContFrac::canonicalize() { int n=this->length(); if(n==0) return; +this->copyonwrite(); if((*this)[n]==1) {(*this)[n]=0; ++(*this)[n-1];} //avoid deepest 1/1 for(int i=1; i<=n; ++i) //truncate if possible { @@ -139,11 +141,13 @@ 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 +typename ContFrac::iterator px=x.begin(); + +do //scan all input { //digest next input term Homographic hnew; - if(i>x.length()||i!=0&&x[i]==0) //input is infinity + if(px==x.end()|| px!=x.begin()&& *px==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]; @@ -152,8 +156,8 @@ for(int i=0; i<=x.length()+1; ++i) //scan all input { 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]; + 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; } //std::cout<<"hnew\n"<< hnew.x[0][0]<<" "<< hnew.x[0][1]<<"\n"<< hnew.x[1][0]<<" "<< hnew.x[1][1]<<"\n"; @@ -182,21 +186,119 @@ for(int i=0; i<=x.length()+1; ++i) //scan all input if(hnew.x[1][0]==0&&hnew.x[1][1]==0) //terminate { //std::cout<<"terminate at "< +std::istream & operator>>(std::istream &s, Rational &x) +{ +char c; +s>>x.num>>c>>x.den; +return s; +} + + + template class Homographic; @@ -60,7 +92,6 @@ template class BiHomographic; -//@@@implement iterator and rewrite Homographic::value template class ContFrac : public NRVec { @@ -71,14 +102,15 @@ public: template ContFrac(const T (&a)[SIZE]) : NRVec(a) {}; ContFrac(const NRVec &v) : NRVec(v) {}; //allow implicit conversion from NRVec ContFrac(const int n) : NRVec(n+1) {}; - ContFrac(double x, const int n, const T thres=0); //might yield a non-canonical form + ContFrac(double x, const int n, const T thres=0); //might yield a non-canonical form + //we could make a template for analogous conversion from an arbitrary-precision type ContFrac(const T p, const T q); //should yield a canonical form ContFrac(const Rational &r) : ContFrac(r.num,r.den) {}; void canonicalize(); void convergent(T *p, T*q, const int trunc= -1) const; Rational rational(const int trunc= -1) const {T p,q; convergent(&p,&q,trunc); return Rational(p,q);}; - double value(const int trunc= -1) const; + double value(const int trunc= -1) const; //we could make also a template usable with an arbitrary-precision type ContFrac reciprocal() const; int length() const {return NRVec::size()-1;}; void resize(const int n, const bool preserve=true) @@ -87,13 +119,41 @@ public: NRVec::resize(n+1,preserve); if(preserve) for(int i=nold+1; i<=n;++i) (*this)[i]=0; } - + //arithmetics with a single ContFrac operand 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);}; - + ContFrac & operator+=(const T &rhs) {this->copyonwrite(); (*this)[0]+=rhs; return *this;}; + ContFrac & operator-=(const T &rhs) {this->copyonwrite(); (*this)[0]-=rhs; return *this;}; + ContFrac operator+(const T &rhs) const {ContFrac r(*this); r+=rhs; return r;}; + ContFrac operator-(const T &rhs) const {ContFrac r(*this); r-=rhs; return r;}; + ContFrac operator*(const T &rhs) const {Homographic h({{0,rhs},{1,0}}); return h.value(*this);}; + ContFrac operator/(const T &rhs) const {Homographic h({{0,1},{rhs,0}}); return h.value(*this);}; + + //arithmetics with two ContFrac operands + //@@@ + + //iterator + class iterator { + private: + T *p; + public: + iterator() {}; + ~iterator() {}; + iterator(T *v): p(v) {}; + bool operator==(const iterator rhs) const {return p==rhs.p;} + bool operator!=(const iterator rhs) const {return p!=rhs.p;} + iterator operator++() {return ++p;} + iterator operator++(int) {return p++;} + T& operator*() const {return *p;} + T *operator->() const {return p;} + }; + iterator begin() const {return NRVec::v;} + iterator end() const {return NRVec::v+NRVec::nn;} + iterator beyondend() const {return NRVec::v+NRVec::nn+1;} + }; //for Gosper's arithmetic diff --git a/permutation.h b/permutation.h index fb69c5a..52f76ad 100644 --- a/permutation.h +++ b/permutation.h @@ -119,7 +119,7 @@ return big; template inline T lcm(T a, T b) { -return (a*b)/gcd(a,b); +return (a/gcd(a,b))*b; } diff --git a/t.cc b/t.cc index d9d61b0..d8a1df6 100644 --- a/t.cc +++ b/t.cc @@ -2431,6 +2431,16 @@ NRMat mm=m.permuted_rows(p); cout < p,q; +cin>>p>>q; +cout < r({11,101}); ContFrac x(r);