diff --git a/contfrac.cc b/contfrac.cc index 7f49c9b..74dfcd5 100644 --- a/contfrac.cc +++ b/contfrac.cc @@ -144,13 +144,14 @@ void ContFrac::canonicalize() { int n=this->length(); if(n==0) return; +this->copyonwrite(); if(n>0 && (*this)[1]<0) //handle negative a_i i>0 { - for(int i=0; i<=n; ++i) (*this[i]) = -(*this[i]); + for(int i=0; i<=n; ++i) (*this)[i] = -(*this)[i]; *this = -(*this); + n=this->length(); //unary minus changes the length } -this->copyonwrite(); -if((*this)[n]==1) {(*this)[n]=0; ++(*this)[n-1];} //avoid deepest 1/1 +if(n>0 && (*this)[n]==1) {(*this)[n]=0; ++(*this)[n-1];} //avoid deepest 1/1 for(int i=1; i<=n; ++i) //truncate if possible { if((*this)[i]==0) //convention for infinity @@ -393,6 +394,7 @@ if(den<0) den= -den; } T g=gcd(num,den); +if(g<0) g= -g; //gcd may be negative for negative num if(g>1) { num/=g; @@ -405,7 +407,8 @@ Rational & Rational::operator*=(const T &rhs) { T r=rhs; T g=gcd(r,den); -if(MYABS(g)>1) +if(g<0) g= -g; //keep den positive +if(g>1) { r/=g; den/=g; @@ -420,12 +423,14 @@ Rational & Rational::operator/=(const T &rhs) { T r=rhs; T g=gcd(r,num); -if(MYABS(g)>1) +if(g<0) g= -g; +if(g>1) { r/=g; num/=g; } den*=r; +if(den<0) {num= -num; den= -den;} //keep den positive return *this; } diff --git a/contfrac.h b/contfrac.h index c8ee819..8e0e5ae 100644 --- a/contfrac.h +++ b/contfrac.h @@ -124,7 +124,7 @@ public: ContFrac(T p, T q); //should yield a canonical form explicit ContFrac(const Rational &r) : ContFrac(r.num,r.den) {}; - void canonicalize(); + void canonicalize(); //requires a_1..a_n of the same sign (works on the terms, no overflow for fixed-size T) 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; //we could make also a template usable with an arbitrary-precision type diff --git a/polynomial.cc b/polynomial.cc index 00a5d40..ab3ae59 100644 --- a/polynomial.cc +++ b/polynomial.cc @@ -177,7 +177,7 @@ Polynomial poly_gcd(const Polynomial &p, const Polynomial &q, const typ Polynomial big,small; if(p.degree() < q.degree()) {big=q; small=p;} else {big=p; small=q;} small.simplify(thr); -if(small.degree()==0) return small; +if(small.degree()==0) return MYABS(small[0])<=thr ? big : small; //gcd(p,0)=p, gcd(p,const)=const Polynomial help; do { help=small; @@ -185,7 +185,7 @@ do { big=help; small.simplify(thr); } -while((d<0 && small.degree() != 0) || (d>=0 && small.degree()>=d)); +while(!(small.degree()==0 && MYABS(small[0])<=thr) && (d<0 || small.degree()>=d)); //stop at zero remainder or below the expected degree return big; } diff --git a/polynomial.h b/polynomial.h index 8b5e24a..17ce948 100644 --- a/polynomial.h +++ b/polynomial.h @@ -213,7 +213,7 @@ for(int i=d; i>2; i-=2) sum= sum*x2; //not *= for matrices } sum += p[1]; -sum *= x; +sum= sum*x; //not *= for matrices return sum; }