// -*- mode:C++ -*- /* Class for fractions. The base class must provide arithmetic operations +,-,*, pow for positive powers void simplify( T & a, T & b) to simplify a and b bool is_one(const T & a) returns true if a==1 T(1) returns the 1 polynomial */ /* * Copyright (C) 2000, 2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _GIAC_FRACTION_H_ #define _GIAC_FRACTION_H_ #include "first.h" #include #ifndef NO_NAMESPACE_GIAC namespace giac { #endif // ndef NO_NAMESPACE_GIAC template class Tfraction { public: T num; T den; Tfraction (const T & n,const T & d) : num(n),den(d) {}; Tfraction (const T & n) : num(n),den(T(1)) {}; // does not work properly?? Tfraction (const Tfraction & f) : num(f.num), den(f.den) {}; Tfraction normal() const; void dbgprint(); }; template class Tref_fraction { public: ref_count_t ref_count; Tfraction f; Tref_fraction(const Tfraction & F):ref_count(1),f(F) {} }; template Tfraction Tfraction::normal() const { T n(num),d(den); simplify(n,d); if (is_minus_one(d)){ n=-n; d=-d; } if (is_sq_minus_one(d)){ n=-d*n; d=1; } return Tfraction(n,d); } template Tfraction operator + (const Tfraction & a,const Tfraction & b){ if (is_one(a.den)) return(Tfraction (a.num+b)); if (is_one(b.den)) return(Tfraction (b.num+a)); T da(a.den),db(b.den); T den=simplify3(da,db); T num=(a.num*db+b.num*da); if (is_zero(num)) return Tfraction(num,1); simplify3(num,den); den=den*da*db; return Tfraction (num,den); } template Tfraction operator + (const Tfraction & a,const T & b){ return Tfraction(a.num+a.den*b,a.den); } template Tfraction operator + (const T & a,const Tfraction & b){ return Tfraction(a*b.den+b.num,b.den); } template Tfraction operator - (const Tfraction & a,const Tfraction & b){ if (is_one(a.den)) return(Tfraction (a.num-b)); if (is_one(b.den)) return(Tfraction (-b.num+a)); T da(a.den),db(b.den); T den=simplify3(da,db); T num=(a.num*db-b.num*da); if (is_zero(num)) return Tfraction(num,1); simplify3(num,den); den=den*da*db; return Tfraction (num,den); } template Tfraction operator - (const Tfraction & a,const T & b){ return Tfraction(a.num-a.den*b,a.den); } template Tfraction operator - (const T & a,const Tfraction & b){ return Tfraction(a*b.den-b.num,b.den); } template Tfraction operator * (const Tfraction & a,const Tfraction & b) { if (is_one(a.den)) return(Tfraction (a.num*b)); if (is_one(b.den)) return(Tfraction (b.num*a)); Tfraction f1(a.num,b.den); simplify(f1.num,f1.den); Tfraction f2(b.num,a.den); simplify(f2.num,f2.den); return Tfraction(f1.num*f2.num,f1.den*f2.den); } template Tfraction operator * (const Tfraction & a,const T & b){ if (is_one(a.den)) return Tfraction(a.num*b,a.den); T nume(b),deno(a.den); simplify(nume,deno); return Tfraction(a.num*nume,deno); /* Tfraction f2(b,a.den); simplify(f2.num,f2.den); return Tfraction(a.num*f2.num,f2.den); */ } template Tfraction operator * (const T & a,const Tfraction & b){ if (is_one(b.den)) return Tfraction(a*b.num,b.den); T nume(a),deno(b.den); simplify(nume,deno); return Tfraction(nume*b.num,deno); /* Tfraction f1(a,b.den); simplify(f1.num,f1.den); return Tfraction(f1.num*b.num,f1.den); */ } template Tfraction operator / (const Tfraction & a,const Tfraction & b){ if (is_one(a.den)) return(Tfraction (a.num/b)); if (is_one(b.den)){ // std::cerr << "fraction code change"< (a/b.num)); } Tfraction f1(a.num,b.num); simplify(f1.num,f1.den); Tfraction f2(b.den,a.den); simplify(f2.num,f2.den); return Tfraction(f1.num*f2.num,f1.den*f2.den); } template Tfraction operator / (const Tfraction & a,const T & b){ Tfraction f2(a.num,b); simplify(f2.num,f2.den); return Tfraction(f2.num,f2.den*a.den); } template Tfraction operator / (const T & a,const Tfraction & b){ Tfraction f2(a,b.num); simplify(f2.num,f2.den); return Tfraction(f2.num*b.den,f2.den); } template Tfraction pow (const Tfraction & p,int n){ if (!n) return Tfraction(T(1),T(1)); if (n>0){ if (is_one(p.den)) return Tfraction(pow(p.num,n),p.den); else return Tfraction(pow(p.num,n),pow(p.den,n)); } return Tfraction(pow(Tfraction(p.den,p.num),-n)); } #ifdef NSPIRE template nio::ios_base & operator << (nio::ios_base & os, const Tfraction & f ){ os << f.num << "/" << f.den << " " ; return os; } #else template std::ostream & operator << (std::ostream & os, const Tfraction & f ){ os << f.num << "/" << f.den << " " ; return os; } #endif template void Tfraction::dbgprint() { COUT << num << "/" << den << " " ; } // factorization will be a std::vector of facteur, // each facteur being a polynomial // and it's multiplicity template class facteur { public: T fact; int mult; facteur():fact(1),mult(0) {} facteur(const facteur & f) : fact(f.fact), mult(f.mult) {} facteur(const T & f, int m) : fact(f),mult(m) {} #ifdef NSPIRE template friend nio::ios_base & operator << (nio::ios_base & os, const facteur & m ){ return os << ":facteur:!" << m.fact << "!" << "^" << m.mult ; } #else friend std::ostream & operator << (std::ostream & os, const facteur & m ){ return os << ":facteur:!" << m.fact << "!" << "^" << m.mult ; } #endif void dbgprint() const { COUT << *this << std::endl; } }; #ifndef NO_NAMESPACE_GIAC } // namespace giac #endif // ndef NO_NAMESPACE_GIAC #endif // ndef _GIAC_FRACTION_H_