BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/Polynomial_type.h
Go to the documentation of this file.
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany)
00002 //
00003 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public License as
00005 // published by the Free Software Foundation; version 2.1 of the License.
00006 // See the file LICENSE.LGPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polynomial/include/CGAL/Polynomial/Polynomial_type.h $
00015 // $Id: Polynomial_type.h 49007 2009-04-29 13:55:06Z hemmer $
00016 //
00017 //
00018 // Author(s)     : Michael Hemmer <hemmer@informatik.uni-mainz.de> 
00019 //                 Arno Eigenwillig <arno@mpi-inf.mpg.de>
00020 //                 Michael Seel <seel@mpi-inf.mpg.de>
00021 //                 
00022 // ============================================================================
00023 
00024 // TODO: The comments are all original EXACUS comments and aren't adapted. So
00025 //         they may be wrong now.
00026 
00033 #ifndef CGAL_POLYNOMIAL_POLYNOMIAL_TYPE_H
00034 #define CGAL_POLYNOMIAL_POLYNOMIAL_TYPE_H
00035 
00036 #define CGAL_icoeff(T) typename CGAL::First_if_different<       \
00037 typename CGAL::CGALi::Innermost_coefficient_type<T>::Type, T, 1>::Type  
00038 
00039 #define CGAL_int(T) typename CGAL::First_if_different< int,   \
00040 typename CGAL::CGALi::Innermost_coefficient_type<T>::Type , 2>::Type 
00041 
00042 
00043 #include <CGAL/ipower.h>
00044 #include <sstream>
00045 #include <CGAL/Polynomial/misc.h>
00046 
00047 CGAL_BEGIN_NAMESPACE
00048 
00049 template <class NT> class Polynomial;
00050 template <class NT> class Scalar_factor_traits;
00051 template <class NT> Polynomial<NT> operator - (const Polynomial<NT>& p);
00052 
00053 namespace CGALi {
00054 
00055 template <class NT> class Polynomial_rep;
00056 
00057 // \brief tag type to distinguish a certain constructor of \c CGAL::Polynomial
00058 class Creation_tag {};
00059 
00060 //
00061 // The internal representation class Polynomial_rep<NT>
00062 //
00063 
00064 // \brief  internal representation class for \c CGAL::Polynomial
00065 template <class NT_> class Polynomial_rep 
00066 { 
00067   typedef NT_ NT;
00068   typedef std::vector<NT> Vector;
00069   typedef typename Vector::size_type      size_type;
00070   typedef typename Vector::iterator       iterator;
00071   typedef typename Vector::const_iterator const_iterator;
00072   Vector coeff;
00073 
00074   Polynomial_rep() : coeff() {}
00075   Polynomial_rep(Creation_tag, size_type s) : coeff(s,NT(0)) {}
00076 
00077   Polynomial_rep(size_type n, ...);
00078 
00079 #ifdef CGAL_USE_LEDA
00080   Polynomial_rep(const LEDA::array<NT>& coeff_)
00081     : coeff(coeff_.size())
00082   {
00083     for (int i = 0; i < coeff_.size(); i++) {
00084       coeff[i] = coeff_[i + coeff_.low()];
00085     }
00086   }
00087 #endif // CGAL_USE_LEDA
00088 
00089   template <class Forward_iterator>
00090   Polynomial_rep(Forward_iterator first, Forward_iterator last) 
00091     : coeff(first,last)
00092   {}
00093 
00094   void reduce() {
00095     while ( coeff.size()>1 && CGAL::is_zero(coeff.back())) coeff.pop_back();
00096   }
00097 
00098   void simplify_coefficients() {
00099     typename Algebraic_structure_traits<NT>::Simplify simplify;
00100     for (iterator i = coeff.begin(); i != coeff.end(); i++) {
00101       simplify(*i);
00102     }
00103   }
00104 
00105   friend class Polynomial<NT>;
00106 };  // class Polynomial_rep<NT_>
00107 
00108 template <class NT>
00109 Polynomial_rep<NT>::Polynomial_rep(size_type n, ...)
00110   : coeff(n)
00111 {
00112   // varargs, hence not inline, otherwise g++-3.1 -O2 makes trouble
00113   va_list ap; va_start(ap, n);
00114   for (size_type i = 0; i < n; i++) {
00115     coeff[i] = *(va_arg(ap, const NT*));
00116   }
00117   va_end(ap);
00118 }
00119 
00120 }// namespace CGALi
00121 
00122 //
00123 // The actual class Polynomial<NT>
00124 //
00125 
00192 template <class NT_>
00193 class Polynomial 
00194   : public Handle_with_policy< CGALi::Polynomial_rep<NT_> >,
00195     public boost::ordered_field_operators1< Polynomial<NT_> , 
00196            boost::ordered_field_operators2< Polynomial<NT_> , NT_ ,  
00197            boost::ordered_field_operators2< Polynomial<NT_> , CGAL_icoeff(NT_),
00198            boost::ordered_field_operators2< Polynomial<NT_> , CGAL_int(NT_)  > > > > 
00199 {
00200   typedef typename CGALi::Innermost_coefficient_type<NT_>::Type Innermost_coefficient_type; 
00201 public: 
00202 
00204 
00205 
00206   typedef NT_ NT; 
00208   typedef CGALi::Polynomial_rep<NT> Rep;
00210   typedef Handle_with_policy< Rep > Base;
00212   typedef typename Rep::Vector    Vector;
00214   typedef typename Rep::size_type size_type;
00216   typedef typename Rep::iterator  iterator;
00218   typedef typename Rep::const_iterator const_iterator;
00220 
00221 protected:
00223 
00224 
00225   Vector& coeffs() { return this->ptr()->coeff; }
00227   const Vector& coeffs() const { return this->ptr()->coeff; }
00229   Polynomial(CGALi::Creation_tag f, size_type s)
00230     : Base(CGALi::Polynomial_rep<NT>(f,s) )
00231     {}
00233 
00239     NT& coeff(unsigned int i) {
00240       CGAL_precondition(!this->is_shared() && i<(this->ptr()->coeff.size()));
00241       return this->ptr()->coeff[i]; 
00242     }
00243 
00245     void reduce() { this->ptr()->reduce(); }
00247     void reduce_warn() {
00248       CGAL_precondition( this->ptr()->coeff.size() > 0 );
00249       if (this->ptr()->coeff.back() == NT(0)) {
00250         CGAL_warning_msg(false, "unexpected degree loss (zero divisor?)");
00251         this->ptr()->reduce();
00252       }
00253     }
00255 
00256 //
00257 // Constructors of Polynomial<NT>
00258 //
00259 
00260 public:
00263     Polynomial() 
00264       : Base( Rep(CGALi::Creation_tag(), 1) ) { 
00265       coeff(0) = NT(0); 
00266     }
00267       
00268      
00270     Polynomial(const Polynomial<NT>& p) : Base(static_cast<const Base&>(p)) {}
00271         
00273     template <class T>
00274       explicit Polynomial(const T& a0)
00275       : Base(Rep(CGALi::Creation_tag(), 1))
00276       { coeff(0) = NT(a0); reduce(); simplify_coefficients(); } 
00277           
00279     Polynomial(const NT& a0)
00280       : Base(Rep(1, &a0))
00281       { reduce(); simplify_coefficients(); }
00282       
00284     Polynomial(const NT& a0, const NT& a1)
00285       : Base(Rep(2, &a0,&a1))
00286       { reduce(); simplify_coefficients(); }
00287 
00289     Polynomial(const NT& a0,const NT& a1,const NT& a2)
00290       : Base(Rep(3, &a0,&a1,&a2))
00291       { reduce(); simplify_coefficients(); }
00292       
00294     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3)
00295       : Base(Rep(4, &a0,&a1,&a2,&a3))
00296       { reduce(); simplify_coefficients(); }
00297 
00299     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3,
00300         const NT& a4)
00301       : Base(Rep(5, &a0,&a1,&a2,&a3,&a4))
00302       { reduce(); simplify_coefficients(); }
00303       
00305     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3,
00306         const NT& a4, const NT& a5)
00307       : Base(Rep(6, &a0,&a1,&a2,&a3,&a4,&a5))
00308       { reduce(); simplify_coefficients(); }
00309 
00311     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3,
00312         const NT& a4, const NT& a5, const NT& a6)
00313       : Base(Rep(7, &a0,&a1,&a2,&a3,&a4,&a5,&a6))
00314       { reduce(); simplify_coefficients(); }
00315 
00317     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3,
00318         const NT& a4, const NT& a5, const NT& a6, const NT& a7)
00319       : Base(Rep(8, &a0,&a1,&a2,&a3,&a4,&a5,&a6,&a7))
00320       { reduce(); simplify_coefficients(); }
00321       
00323     Polynomial(const NT& a0,const NT& a1,const NT& a2, const NT& a3,
00324         const NT& a4, const NT& a5, const NT& a6, const NT& a7,
00325         const NT& a8)
00326       : Base(Rep(9, &a0,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8))
00327       { reduce(); simplify_coefficients(); }
00328       
00336     template <class Forward_iterator>
00337     Polynomial(Forward_iterator first, Forward_iterator last)
00338       : Base(Rep(first,last)) 
00339       { reduce(); simplify_coefficients(); }
00340                               
00341 #if defined(CGAL_USE_LEDA) || defined(DOXYGEN_RUNNING)
00342 
00349     Polynomial(const LEDA::array<NT>& c)
00350       : Base(Rep(c))
00351       { reduce(); simplify_coefficients(); }
00352 #endif // defined(CGAL_USE_LEDA) || defined(DOXYGEN_RUNNING)
00353                                 
00354 //
00355 // Public member functions
00356 //
00357 
00358 public:
00360 
00361 
00363     const_iterator begin() const { return this->ptr()->coeff.begin(); }
00365     const_iterator end()   const { return this->ptr()->coeff.end(); }
00366 
00368 
00371     int degree() const { return this->ptr()->coeff.size()-1; } 
00372 
00374     const NT& operator[](unsigned int i) const {
00375       CGAL_precondition( i<(this->ptr()->coeff.size()) );
00376       return this->ptr()->coeff[i];
00377     }
00378 
00380 
00381     int number_of_terms() const {
00382       int terms = 0;
00383       if (degree() < 0) return -1;
00384       for (int i = 0; i <= degree(); i++) {
00385         if ((*this)[i] != NT(0)) terms++;
00386       }
00387       return terms;
00388     }
00389 
00391     const NT& lcoeff() const {
00392       CGAL_precondition( this->ptr()->coeff.size() > 0 );
00393       return this->ptr()->coeff.back();
00394     }
00395     
00396 
00402     // Note that there is no need to provide a special version for intervals.
00403     // This was shown by some benchmarks of George Tzoumas, for the 
00404     // Interval Newton method used in the Voronoi Diagram of Ellipses
00405     template <class NTX>
00406       typename Coercion_traits<NTX,NT>::Type 
00407       evaluate(const NTX& x_) const {
00408       typedef Coercion_traits<NTX,NT> CT;
00409       typename CT::Cast cast;
00410         
00411       CGAL_precondition( degree() >= 0 );
00412       int d = degree();
00413       typename CT::Type x = cast(x_);
00414       typename CT::Type y=cast(this->ptr()->coeff[d]);
00415       while (--d >= 0){
00416         //    y = y*x + cast(this->ptr()->coeff[d]);
00417         y *= x;
00418         y += cast(this->ptr()->coeff[d]);
00419       }
00420       return y; 
00421     }
00422 public:
00425    
00426     template <class NTX>
00427       typename Coercion_traits<NTX,NT>::Type 
00428       evaluate_homogeneous(const NTX& u_, 
00429           const NTX& v_,
00430           int hom_degree = -1) const {
00431       if(hom_degree == -1 ) hom_degree = degree();
00432       CGAL_precondition( hom_degree >= degree());
00433       CGAL_precondition( hom_degree >= 0 );
00434       typedef Coercion_traits<NTX,NT> CT;
00435       typedef typename CT::Type Type;
00436       typename CT::Cast cast;
00437 
00438       Type u = cast(u_);
00439       Type v = cast(v_);
00440       Type monom;
00441       Type y(0);
00442       for(int i = 0; i <= hom_degree; i++){
00443         monom = CGAL::ipower(v,hom_degree-i)*CGAL::ipower(u,i);
00444         if(i <= degree())
00445           y += monom * cast(this->ptr()->coeff[i]);  
00446       }
00447       return y;
00448     }
00449 
00450 private:
00451     // NTX not decomposable
00452     template <class NTX, class TAG >
00453       CGAL::Sign sign_at_(const NTX& x, TAG) const{
00454       CGAL_precondition(degree()>=0);
00455       return CGAL::sign(evaluate(x));
00456     }
00457     // NTX decomposable
00458     
00459     template <class NTX>
00460       CGAL::Sign sign_at_(const NTX& x, CGAL::Tag_true) const{
00461       CGAL_precondition(degree()>=0);
00462       typedef Fraction_traits<NTX> FT;
00463       typedef typename FT::Numerator_type Numerator_type;
00464       typedef typename FT::Denominator_type Denominator_type;
00465       Numerator_type num;
00466       Denominator_type den;
00467       typename FT::Decompose decompose;
00468       decompose(x,num,den);
00469       CGAL_precondition(CGAL::sign(den) == CGAL::POSITIVE);
00470 
00471       typedef Coercion_traits< Numerator_type , Denominator_type > CT;
00472       typename CT::Cast cast;
00473       return CGAL::sign(evaluate_homogeneous(cast(num),cast(den)));
00474     }
00475 public:
00477     template <class NTX>
00478       CGAL::Sign sign_at(const NTX& x) const{
00479       // the sign with evaluate_homogeneous is called
00480       // if NTX is decaomposable
00481       // and NT would be changed by NTX 
00482       typedef typename Fraction_traits<NTX>::Is_fraction Is_fraction;
00483       typedef typename Coercion_traits<NT,NTX>::Type Type;
00484       typedef typename ::boost::mpl::if_c<
00485       ::boost::is_same<Type,NT>::value, Is_fraction, CGAL::Tag_false
00486         >::type If_decomposable_AND_Type_equals_NT;
00487             
00488       return sign_at_(x,If_decomposable_AND_Type_equals_NT());
00489     }
00490     
00491     
00492     // for the benefit of mem_fun1 & friends who don't like const ref args
00493     template <class NTX>
00494       typename CGAL::Coercion_traits<NT,NTX>::Type 
00495       evaluate_arg_by_value(NTX x) const { return evaluate(x); } 
00496 
00506     template <class NTX> 
00507       typename Coercion_traits<NTX,NT>::Type 
00508       evaluate_absolute(const NTX& x) const {
00509       typedef typename Coercion_traits<NTX,NT>::Type Type;
00510       typedef typename Coercion_traits<NTX,NT>::Cast Cast;
00511       Type xx(Cast()(x));
00512       CGAL_precondition( degree() >= 0 );
00513       typename Real_embeddable_traits<Type>::Abs abs;
00514       int d = degree();
00515       Type y(abs(Cast()(this->ptr()->coeff[d])));
00516       while (--d >= 0) y = y*xx + abs(Cast()(this->ptr()->coeff[d]));
00517       return y;
00518     } 
00519 
00525     // TODO: Interval isn't available either!!
00526 /*    Interval evaluate_absolute(const Interval& x) const {
00527       CGAL_precondition( degree() >= 0 );
00528       typename Algebraic_structure_traits<Interval>::Abs abs;
00529       typename Algebraic_structure_traits<NT>::To_Interval to_Interval;
00530       int d = 0;
00531       Interval y(to_Interval(this->ptr()->coeff[d]));
00532       while (++d <= degree()) 
00533       y+=abs(pow(x,d)*to_Interval(this->ptr()->coeff[d]));
00534       return y;
00535       } */
00542     CGAL::Sign sign() const {
00543 //        BOOST_STATIC_ASSERT( (boost::is_same< typename Real_embeddable_traits<NT>::Is_real_embeddable,
00544 //                              CGAL::Tag_true>::value) );
00545       return CGAL::sign(lcoeff());
00546     }
00547 
00549     CGAL::Comparison_result compare(const Polynomial& p2) const {
00550       typename Real_embeddable_traits<NT>::Compare compare;
00551       typename Real_embeddable_traits<NT>::Sgn sign;
00552       CGAL_precondition(degree() >= 0);
00553       CGAL_precondition(p2.degree() >= 0);
00554 
00555       if (is_identical(p2)) return CGAL::EQUAL;
00556 
00557       int d1 = degree();
00558       int d2 = p2.degree();
00559       if (d1 > d2) {
00560         return sign((*this)[d1]);
00561       } else if (d1 < d2) {
00562         return -sign(p2[d2]);
00563       }
00564 
00565       for (int i = d1; i >= 0; i--) {
00566         CGAL::Comparison_result s = compare((*this)[i], p2[i]);
00567         if (s != CGAL::EQUAL) return s;
00568       }
00569       return CGAL::EQUAL;
00570     }
00571 
00573     CGAL::Comparison_result compare(const NT& p2) const {
00574       typename Real_embeddable_traits<NT>::Compare compare;
00575       typename Real_embeddable_traits<NT>::Sgn sign;
00576       CGAL_precondition(degree() >= 0);
00577 
00578       if (degree() > 0) {
00579         return sign(lcoeff());
00580       } else {
00581         return compare((*this)[0], p2);
00582       }
00583     }
00584 
00586     bool is_zero() const
00587     { return degree()==0 && this->ptr()->coeff[0]==NT(0); }
00588 
00590     Polynomial<NT> abs() const
00591     { if ( sign()<0 ) return -*this; return *this; }
00592 
00594 
00595     NT content() const {
00596       CGAL_precondition(degree() >= 0);
00597       if (is_zero()) return NT(0);
00598         
00599       return content_( typename Algebraic_structure_traits< NT >::Algebraic_category() );
00600     }
00601 
00602 private:
00603     NT content_( Unique_factorization_domain_tag ) const {
00604       typename Algebraic_structure_traits<NT>::Integral_division idiv;
00605       typename Algebraic_structure_traits<NT>::Unit_part    upart;
00606       typename Algebraic_structure_traits<NT>::Gcd          gcd;
00607       const_iterator it = this->ptr()->coeff.begin(), ite = this->ptr()->coeff.end();
00608       while (*it == NT(0)) it++;
00609       NT d = idiv(*it, upart(*it));
00610       for( ; it != ite; it++) {
00611         if (d == NT(1)) return d;
00612         if (*it != NT(0)) d = gcd(d, *it);
00613       }
00614       return d;
00615     }
00616 
00617     NT content_( Field_tag ) const {
00618       return NT(1);
00619     }
00620 
00621 public:
00622     
00624 
00625     NT unit_part() const {
00626       typename Algebraic_structure_traits<NT>::Unit_part upart;
00627       return upart(lcoeff());
00628     }
00629 
00631 
00633     void diff() {
00634       CGAL_precondition( degree() >= 0 );
00635       if (is_zero()) return;
00636       this->copy_on_write();
00637       if (degree() == 0) { coeff(0) = NT(0); return; }
00638       coeff(0) = coeff(1); // avoid redundant multiplication by NT(1)
00639       for (int i = 2; i <= degree(); i++) coeff(i-1) = coeff(i) * NT(i);
00640       this->ptr()->coeff.pop_back();
00641       reduce(); // in case NT has positive characteristic
00642     }
00643 
00645 
00647     void scale_up(const NT& a) {
00648       CGAL_precondition( degree() >= 0 );
00649       if (degree() == 0) return;
00650       this->copy_on_write();
00651       NT a_to_j = a;
00652       for (int j = 1; j <= degree(); j++) {
00653         coeff(j) *= a_to_j; 
00654         a_to_j *= a;
00655       }
00656       reduce_warn();
00657     }
00658 
00660 
00662     void scale_down(const NT& b)
00663     {
00664       CGAL_precondition( degree() >= 0 );
00665       if (degree() == 0) return;
00666       this->copy_on_write();
00667       NT b_to_n_minus_j = b;
00668       for (int j = degree() - 1; j >= 0; j--) {
00669         coeff(j) *= b_to_n_minus_j; 
00670         b_to_n_minus_j *= b;
00671       }
00672       reduce_warn();
00673     }
00674 
00676 
00678     void scale(const NT& a, const NT& b) { scale_up(a); scale_down(b); }
00679 
00681 
00683     void translate_by_one()
00684     {   // implemented using Ruffini-Horner, see [Akritas, 1989]
00685       CGAL_precondition( degree() >= 0 );
00686       this->copy_on_write();
00687       const int n = degree();
00688       for (int j = n-1; j >= 0; j--) {
00689         for (int i = j; i < n; i++) coeff(i) += coeff(i+1); 
00690       }
00691     }
00692 
00694 
00696     void translate(const NT& c)
00697     {   // implemented using Ruffini-Horner, see [Akritas, 1989]
00698       CGAL_precondition( degree() >= 0 );
00699       this->copy_on_write();
00700       const int n = degree();
00701       for (int j = n-1; j >= 0; j--) {
00702         for (int i = j; i < n; i++) coeff(i) += c*coeff(i+1);
00703       }
00704     }
00705 
00707 
00709     void translate(const NT& a, const NT& b) 
00710     {   // implemented using Mehlhorn's variant of Ruffini-Horner
00711       CGAL_precondition( degree() >= 0 );
00712       this->copy_on_write();
00713       const int n = degree();
00714 
00715       NT b_to_n_minus_j = b;
00716       for (int j = n-1; j >= 0; j--) {
00717         coeff(j) *= b_to_n_minus_j;
00718         b_to_n_minus_j *= b;
00719       }
00720 
00721       for (int j = n-1; j >= 0; j--) {
00722         coeff(j) += a*coeff(j+1);
00723         for (int i = j+1; i < n; i++) {
00724           coeff(i) = b*coeff(i) + a*coeff(i+1); 
00725         }
00726         coeff(n) *= b;
00727       }
00728       reduce_warn();
00729     }
00730 
00732 
00734     void reversal() {
00735       CGAL_precondition( degree() >= 0 );
00736       this->copy_on_write();
00737       NT t;
00738       for (int l = 0, r = degree(); l < r; l++, r--) {
00739         t = coeff(l); coeff(l) = coeff(r); coeff(r) = t;
00740       }
00741       reduce();
00742     }
00743 
00745     void divide_by_x() {
00746       CGAL_precondition(degree() >= 0);
00747       if (is_zero()) return;
00748       this->copy_on_write();
00749       for (int i = 0; i < degree(); i++) {
00750         coeff(i) = coeff(i+1);
00751       }
00752       coeffs().pop_back();
00753     }
00754 
00756     void simplify_coefficients() { this->ptr()->simplify_coefficients(); }
00757 
00759 
00766     void output_maple(std::ostream& os) const;
00768     void output_ascii(std::ostream& os) const;
00770     void output_benchmark(std::ostream& os) const;
00771 
00773     void scalar_div(const typename
00774         Scalar_factor_traits< Polynomial<NT> >::Scalar& b) {
00775       typename Scalar_factor_traits<NT>::Scalar_div sdiv;
00776       this->copy_on_write();
00777       for (int i = degree(); i >= 0; --i) {
00778         sdiv(coeff(i), b);
00779       }
00780     };
00781 
00783 
00784 //
00785 // Static member functions
00786 //
00787 
00789 
00790 
00799     static void euclidean_division (const Polynomial<NT>& f,
00800         const Polynomial<NT>& g,
00801         Polynomial<NT>& q, Polynomial<NT>& r);
00802 
00812     static void pseudo_division(const Polynomial<NT>& f,
00813         const Polynomial<NT>& g, 
00814         Polynomial<NT>& q, Polynomial<NT>& r, NT& D);
00815 
00816 
00834     static Polynomial<NT> input_ascii(std::istream& is);
00835 
00837 
00838 //
00839 // Arithmetic Operations, Part II:
00840 // implementing two-address arithmetic (incl. mixed-mode) by member functions
00841 //
00842 
00843 // ...for polynomials
00844     Polynomial<NT>& operator += (const Polynomial<NT>& p1) {
00845       this->copy_on_write();
00846       int d = std::min(degree(),p1.degree()), i;
00847       for(i=0; i<=d; ++i) coeff(i) += p1[i];
00848       while (i<=p1.degree()) this->ptr()->coeff.push_back(p1[i++]);
00849       reduce(); return (*this);
00850     }
00851 
00852     Polynomial<NT>& operator -= (const Polynomial<NT>& p1) 
00853       {
00854         this->copy_on_write();
00855         int d = std::min(degree(),p1.degree()), i;
00856         for(i=0; i<=d; ++i) coeff(i) -= p1[i];
00857         while (i<=p1.degree()) this->ptr()->coeff.push_back(-p1[i++]);
00858         reduce(); return (*this);
00859       }
00860 
00861     Polynomial<NT>& operator *= (const Polynomial<NT>& p2)
00862       { 
00863         // TODO: use copy on write 
00864         Polynomial<NT> p1 = (*this);
00865         typedef typename Polynomial<NT>::size_type size_type;
00866         CGAL_precondition(p1.degree()>=0 && p2.degree()>=0);
00867         CGALi::Creation_tag TAG;
00868         Polynomial<NT>  p(TAG, size_type(p1.degree()+p2.degree()+1) ); 
00869         // initialized with zeros
00870         for (int i=0; i <= p1.degree(); ++i)
00871           for (int j=0; j <= p2.degree(); ++j)
00872             p.coeff(i+j) += (p1[i]*p2[j]); 
00873         p.reduce();
00874         return (*this) = p ;
00875       }
00876 
00877     Polynomial<NT>& operator /= (const Polynomial<NT>& p2)
00878       { 
00879         // TODO: use copy on write 
00880         CGAL_precondition(!p2.is_zero());
00881         if ((*this).is_zero()) return (*this);
00882 
00883         Polynomial<NT> p1 = (*this);
00884         typedef Algebraic_structure_traits< Polynomial<NT> > AST; 
00885         // Precondition: q with p1 == p2 * q must exist within NT[x].
00886         // If this holds, we can perform Euclidean division even over a ring NT
00887         // Proof: The quotients of each division that occurs are precisely
00888         //   the terms of q and hence in NT.
00889         Polynomial<NT> q, r;
00890         Polynomial<NT>::euclidean_division(p1, p2, q, r);
00891         CGAL_postcondition( !AST::Is_exact::value || p2 * q == p1);
00892         return (*this) = q;
00893       }
00894 
00895 
00896     // ...and in mixed-mode arithmetic
00897     Polynomial<NT>& operator += (const NT& num)
00898       { this->copy_on_write(); coeff(0) += (NT)num; return *this; }
00899 
00900     Polynomial<NT>& operator -= (const NT& num)
00901       { this->copy_on_write(); coeff(0) -= (NT)num; return *this; }
00902 
00903     Polynomial<NT>& operator *= (const NT& num) {
00904       CGAL_precondition(degree() >= 0);
00905       this->copy_on_write();
00906       for(int i=0; i<=degree(); ++i) coeff(i) *= (NT)num; 
00907       reduce();
00908       return *this;
00909     }
00910 
00911     Polynomial<NT>& operator /= (const NT& num)
00912       {
00913         CGAL_precondition(num != NT(0));
00914         CGAL_precondition(degree() >= 0);
00915         if (is_zero()) return *this;
00916         this->copy_on_write();
00917         typename Algebraic_structure_traits<NT>::Integral_division idiv;
00918         for(int i = 0; i <= degree(); ++i) coeff(i) = idiv(coeff(i), num);
00919         reduce_warn();
00920         return *this;
00921       }// ...and in mixed-mode arithmetic
00922                               
00923     // TODO: avoid  NT(num)
00924     Polynomial<NT>& operator += (CGAL_int(NT) num)
00925       { return *this += NT(num); } 
00926     Polynomial<NT>& operator -= (CGAL_int(NT) num)
00927       { return *this -= NT(num); } 
00928     Polynomial<NT>& operator *= (CGAL_int(NT) num)
00929       { return *this *= NT(num); } 
00930     Polynomial<NT>& operator /= (CGAL_int(NT) num)
00931       { return *this /= NT(num); }  
00932                               
00933     // TODO: avoid  NT(num)
00934     Polynomial<NT>& operator += (const CGAL_icoeff(NT)& num)
00935       { return *this += NT(num); } 
00936     Polynomial<NT>& operator -= (const CGAL_icoeff(NT)& num)
00937       { return *this -= NT(num); } 
00938     Polynomial<NT>& operator *= (const CGAL_icoeff(NT)& num)
00939       { return *this *= NT(num); } 
00940     Polynomial<NT>& operator /= (const CGAL_icoeff(NT)& num)
00941       { return *this /= NT(num); }
00942 
00943     // special operation to implement (pseudo-)division and the like
00944     void minus_offsetmult(const Polynomial<NT>& p, const NT& b, int k)
00945     {
00946       CGAL_precondition(!this->is_shared());
00947       int pd = p.degree();
00948       CGAL_precondition(degree() >= pd+k);
00949       for (int i = 0; i <= pd; i++) coeff(i+k) -= b*p[i];
00950       reduce();
00951     }
00952     
00953     friend Polynomial<NT> operator - <> (const Polynomial<NT>&);   
00954 }; // class Polynomial<NT_>
00955 
00956 // Arithmetic Operators, Part III:
00957 // implementation of unary operators and three-address arithmetic
00958 // by friend functions
00959 //
00960 
00961 template <class NT> inline
00962 Polynomial<NT> operator + (const Polynomial<NT>& p) {
00963   CGAL_precondition(p.degree() >= 0);
00964   return p;
00965 }
00966 
00967 template <class NT> inline
00968 Polynomial<NT> operator - (const Polynomial<NT>& p) {
00969   CGAL_precondition(p.degree()>=0);
00970   Polynomial<NT> res(p.coeffs().begin(),p.coeffs().end());
00971   typename Polynomial<NT>::iterator it, ite=res.coeffs().end();
00972   for(it=res.coeffs().begin(); it!=ite; ++it) *it = -*it;
00973   return res;
00974 }
00975 
00976 
00977 
00978 
00979 template <class NT> inline
00980 Polynomial<NT> operator * (const Polynomial<NT>& p1, 
00981     const Polynomial<NT>& p2)
00982 {
00983   typedef typename Polynomial<NT>::size_type size_type;
00984   CGAL_precondition(p1.degree()>=0 && p2.degree()>=0);
00985   CGALi::Creation_tag TAG;
00986   Polynomial<NT>  p(TAG, size_type(p1.degree()+p2.degree()+1) ); 
00987   // initialized with zeros
00988   for (int i=0; i <= p1.degree(); ++i)
00989     for (int j=0; j <= p2.degree(); ++j)
00990       p.coeff(i+j) += (p1[i]*p2[j]); 
00991   p.reduce();
00992   return p;
00993 }
00994 
00995 
00996 //
00997 // Comparison Operators
00998 //
00999 
01000 // polynomials only
01001 template <class NT> inline
01002 bool operator == (const Polynomial<NT>& p1, const Polynomial<NT>& p2) {
01003   CGAL_precondition(p1.degree() >= 0);
01004   CGAL_precondition(p2.degree() >= 0);
01005   if (p1.is_identical(p2)) return true;
01006   if (p1.degree() != p2.degree()) return false;
01007   for (int i = p1.degree(); i >= 0; i--) if (p1[i] != p2[i]) return false;
01008   return true;
01009 }
01010 template <class NT> inline
01011 bool operator < (const Polynomial<NT>& p1, const Polynomial<NT>& p2)
01012 { return ( p1.compare(p2) < 0 ); } 
01013 template <class NT> inline
01014 bool operator > (const Polynomial<NT>& p1, const Polynomial<NT>& p2)
01015 { return ( p1.compare(p2) > 0 ); } 
01016 
01017 // operators NT
01018 template <class NT> inline 
01019 bool operator == (const NT& num, const Polynomial<NT>& p) {
01020   CGAL_precondition(p.degree() >= 0);
01021   return p.degree() == 0 && p[0] == num;
01022 }
01023 template <class NT> inline
01024 bool operator == (const Polynomial<NT>& p, const NT& num)  {
01025   CGAL_precondition(p.degree() >= 0);
01026   return p.degree() == 0 && p[0] == num;
01027 }
01028 template <class NT> inline
01029 bool operator < (const NT& num, const Polynomial<NT>& p) 
01030 { return ( p.compare(num) > 0 );}
01031 template <class NT> inline
01032 bool operator < (const Polynomial<NT>& p,const NT& num) 
01033 { return ( p.compare(num) < 0 );}
01034 template <class NT> inline
01035 bool operator > (const NT& num, const Polynomial<NT>& p) 
01036 { return ( p.compare(num) < 0 );}
01037 template <class NT> inline
01038 bool operator > (const Polynomial<NT>& p,const NT& num) 
01039 { return ( p.compare(num) > 0 );}
01040 
01041 
01042 // compare int #################################
01043 template <class NT> inline
01044 bool operator == (const CGAL_int(NT)& num, const Polynomial<NT>& p)  {
01045   CGAL_precondition(p.degree() >= 0);
01046   return p.degree() == 0 && p[0] == NT(num);
01047 }
01048 template <class NT> inline
01049 bool operator == (const Polynomial<NT>& p, const CGAL_int(NT)& num)  {
01050   CGAL_precondition(p.degree() >= 0);
01051   return p.degree() == 0 && p[0] == NT(num);
01052 }
01053 template <class NT> inline
01054 bool operator < (const CGAL_int(NT)& num, const Polynomial<NT>& p) 
01055 { return ( p.compare(NT(num)) > 0 );}
01056 template <class NT> inline
01057 bool operator < (const Polynomial<NT>& p, const CGAL_int(NT)& num) 
01058 { return ( p.compare(NT(num)) < 0 );}
01059 template <class NT> inline
01060 bool operator > (const CGAL_int(NT)& num, const Polynomial<NT>& p) 
01061 { return ( p.compare(NT(num)) < 0 );}
01062 template <class NT> inline
01063 bool operator > (const Polynomial<NT>& p, const CGAL_int(NT)& num) 
01064 { return ( p.compare(NT(num)) > 0 );}
01065 
01066 // compare icoeff ###################################
01067 template <class NT> inline
01068 bool operator == (const CGAL_icoeff(NT)& num, const Polynomial<NT>& p)  {
01069   CGAL_precondition(p.degree() >= 0);
01070   return p.degree() == 0 && p[0] == NT(num);
01071 }
01072 template <class NT> inline
01073 bool operator == (const Polynomial<NT>& p, const CGAL_icoeff(NT)& num)  {
01074   CGAL_precondition(p.degree() >= 0);
01075   return p.degree() == 0 && p[0] == NT(num);
01076 }
01077 template <class NT> inline
01078 bool operator < (const CGAL_icoeff(NT)& num, const Polynomial<NT>& p) 
01079 { return ( p.compare(NT(num)) > 0 );}
01080 template <class NT> inline
01081 bool operator < (const Polynomial<NT>& p, const CGAL_icoeff(NT)& num) 
01082 { return ( p.compare(NT(num)) < 0 );}
01083 
01084 
01085 template <class NT> inline
01086 bool operator > (const CGAL_icoeff(NT)& num, const Polynomial<NT>& p) 
01087 { return ( p.compare(NT(num)) < 0 );}
01088 template <class NT> inline
01089 bool operator > (const Polynomial<NT>& p, const CGAL_icoeff(NT)& num) 
01090 { return ( p.compare(NT(num)) > 0 );}
01091 
01092 //
01093 // Algebraically non-trivial operations
01094 //
01095 
01096 // 1) Euclidean and pseudo-division of polynomials
01097 // (implementation of static member functions)
01098 
01099 template <class NT>
01100 void Polynomial<NT>::euclidean_division(
01101     const Polynomial<NT>& f, const Polynomial<NT>& g,
01102     Polynomial<NT>& q, Polynomial<NT>& r)
01103 {
01104   typedef Algebraic_structure_traits<NT> AST;
01105   typename AST::Integral_division idiv;
01106   int fd = f.degree(), gd = g.degree();
01107   if ( fd < gd ) {
01108     q = Polynomial<NT>(NT(0)); r = f;
01109 
01110     CGAL_postcondition( !AST::Is_exact::value || f == q*g + r); 
01111     return;
01112   }
01113   // now we know fd >= gd 
01114   int qd = fd-gd, delta = qd+1, rd = fd;
01115 
01116   CGALi::Creation_tag TAG;    
01117   q = Polynomial<NT>(TAG, delta ); 
01118   r = f; r.copy_on_write();
01119   while ( qd >= 0 ) {
01120     NT Q = idiv(r[rd], g[gd]);
01121     q.coeff(qd) += Q;
01122     r.minus_offsetmult(g,Q,qd);
01123     r.simplify_coefficients();
01124     if (r.is_zero()) break;
01125     rd = r.degree();
01126     qd = rd - gd;
01127   }
01128   q.simplify_coefficients();
01129 
01130   CGAL_postcondition( !AST::Is_exact::value || f == q*g + r);
01131 }
01132 
01133 #ifndef CGAL_POLY_USE_OLD_PSEUDODIV
01134 
01135 template <class NT>
01136 void Polynomial<NT>::pseudo_division(
01137     const Polynomial<NT>& A, const Polynomial<NT>& B,
01138     Polynomial<NT>& Q, Polynomial<NT>& R, NT& D)
01139 {
01140   typedef Algebraic_structure_traits<NT> AST;
01141   // pseudo-division with incremental multiplication by lcoeff(B)
01142   // see [Cohen, 1993], algorithm 3.1.2
01143 
01144   CGAL_precondition(!B.is_zero());
01145   int delta = A.degree() - B.degree();
01146 
01147   if (delta < 0 || A.is_zero()) {
01148     Q = Polynomial<NT>(NT(0)); R = A; D = NT(1);
01149        
01150     CGAL_postcondition( !AST::Is_exact::value || Polynomial<NT>(D)*A == Q*B + R);
01151     return;
01152   }
01153   const NT d = B.lcoeff();
01154   int e = delta + 1;
01155   D = CGAL::ipower(d, e);
01156   CGALi::Creation_tag TAG;
01157   Q = Polynomial<NT>(TAG, e);
01158   R = A; R.copy_on_write(); R.simplify_coefficients();
01159 
01160   // invariant: d^(deg(A)-deg(B)+1 - e) * A == Q*B + R
01161   do { // here we have delta == R.degree() - B.degree() >= 0 && R != 0
01162     NT lR = R.lcoeff();
01163     for (int i = delta+1; i <= Q.degree(); i++) Q.coeff(i) *= d;
01164     Q.coeff(delta) = lR;              // Q = d*Q + lR * X^delta
01165     for (int i = 0; i <= R.degree(); i++) R.coeff(i) *= d;
01166     R.minus_offsetmult(B, lR, delta); // R = d*R - lR * X^delta * B
01167     R.simplify_coefficients();
01168     e--;
01169     delta = R.degree() - B.degree();
01170   } while (delta > 0 || (delta == 0 && !R.is_zero()));
01171   // funny termination condition because deg(0) = 0, not -\infty
01172 
01173   NT q = CGAL::ipower(d, e);
01174   Q *= q; Q.simplify_coefficients();
01175   R *= q; R.simplify_coefficients();
01176 
01177   CGAL_postcondition( !AST::Is_exact::value || Polynomial<NT>(D)*A == Q*B + R);
01178 }
01179 
01180 #else
01181 
01182 template <class NT>
01183 void Polynomial<NT>::pseudo_division(
01184     const Polynomial<NT>& f, const Polynomial<NT>& g, 
01185     Polynomial<NT>& q, Polynomial<NT>& r, NT& D)
01186 {
01187   typedef Algebraic_structure_traits<NT> AST;
01188   // pseudo-division with one big multiplication with lcoeff(g)^{...}
01189   typename Algebraic_structure_traits<NT>::Integral_division idiv;
01190 
01191   int fd=f.degree(), gd=g.degree();
01192   if ( fd < gd ) {
01193     q = Polynomial<NT>(NT(0)); r = f; D = NT(1); 
01194 
01195     CGAL_postcondition( !AST::Is_exact::value  || Polynomial<NT>(D)*f==q*g+r);
01196     return;
01197   }
01198   // now we know rd >= gd 
01199   int qd = fd-gd, delta = qd+1, rd = fd;
01200   CGALi::Creation_tag TAG;
01201   q = Polynomial<NT>(TAG, delta );
01202   NT G = g[gd]; // highest order coeff of g
01203   D = CGAL::ipower(G, delta);
01204   Polynomial<NT> res = D*f;
01205   res.simplify_coefficients();
01206   while ( qd >= 0 ) {
01207     NT F = res[rd];    // highest order coeff of res
01208     NT t = idiv(F, G); // sure to be integral by multiplication of D
01209     q.coeff(qd) = t;   // store q coeff
01210     res.minus_offsetmult(g,t,qd); 
01211     res.simplify_coefficients();
01212     if (res.is_zero()) break;
01213     rd = res.degree();
01214     qd = rd - gd;
01215   }
01216   r = res; // already simplified
01217   q.simplify_coefficients();
01218 
01219   CGAL_postcondition( !AST::Is_exact::value  || Polynomial<NT>(D)*f==q*g+r);
01220 }
01221 
01222 template <class NT> inline
01223 Polynomial<NT> division(const Polynomial<NT>& p1, 
01224     const Polynomial<NT>& p2,
01225     Integral_domain_tag)
01226 {
01227   typedef Algebraic_structure_traits<NT> AST;
01228   CGAL_precondition(!p2.is_zero());
01229   if ( p1.is_zero() ) return p1;
01230   Polynomial<NT> q,r; NT D;
01231   Polynomial<NT>::pseudo_division(p1,p2,q,r,D);
01232   q/=D;
01233 
01234   CGAL_postcondition( !AST::Is_exact::value || p2 * q == p1);
01235   return q;
01236 }
01237 
01238 template <class NT> inline
01239 Polynomial<NT> division(const Polynomial<NT>& p1, 
01240     const Polynomial<NT>& p2,
01241     Field_tag)
01242 {
01243   typedef Algebraic_structure_traits<NT> AST;
01244   CGAL_precondition(!p2.is_zero());
01245   if (p1.is_zero()) return p1;
01246   Polynomial<NT> q,r;
01247   Polynomial<NT>::euclidean_division(p1,p2,q,r);
01248   CGAL_postcondition( !AST::Is_exact::value  || p2 * q == p1);
01249   return q;
01250 }
01251 
01252 #endif // CGAL_POLY_USE_OLD_PSEUDODIV
01253 
01254 //
01255 // I/O Operations
01256 //
01257 
01267 template <class NT>
01268 std::ostream& operator << (std::ostream& os, const Polynomial<NT>& p) {
01269   switch(CGAL::get_mode(os)) {
01270   case CGAL::IO::PRETTY:
01271     p.output_maple(os); break;
01272   default:
01273     p.output_ascii(os); break;
01274   }
01275   return os;
01276 }
01277 
01286 template <class NT>
01287 std::istream& operator >> (std::istream& is, Polynomial<NT>& p) {
01288   CGAL_precondition(!CGAL::is_pretty(is));
01289   p = Polynomial<NT>::input_ascii(is);
01290   return is;
01291 }
01292 
01293 
01294 template <class NT> inline
01295 void print_maple_monomial(std::ostream& os, const NT& coeff,
01296     const char *var, int expn)
01297 {
01298   if (expn == 0 || coeff != NT(1)) {
01299     os << CGAL::oformat(coeff, Parens_as_product_tag());
01300     if (expn >= 1) os << "*";
01301   }
01302   if (expn >= 1) {
01303     os << var;
01304     if (expn > 1) os << "^" << CGAL::oformat(expn);
01305   }
01306 }
01307 
01308 // fwd declaration of Polynomial_traits_d
01309 template <typename Polynomial_d> class Polynomial_traits_d;
01310 
01311 template <class NT>
01312 void Polynomial<NT>::output_maple(std::ostream& os) const {
01313   const Polynomial<NT>& p = *this;
01314   const char *varname;
01315   char vnbuf[42];
01316     
01317   // use variable names x, y, z, w1, w2, w3, ...
01318   if (Polynomial_traits_d<NT>::d < 3) {
01319     static const char *varnames[] = { "x", "y", "z" };
01320     varname = varnames[Polynomial_traits_d<NT>::d];
01321   } else {
01322     sprintf(vnbuf, "w%d", Polynomial_traits_d<NT>::d - 2);
01323     varname = vnbuf;
01324   }
01325     
01326   int i = p.degree();
01327   CGAL::print_maple_monomial(os, p[i], varname, i);
01328   while (--i >= 0) {
01329     if (p[i] != NT(0)) {
01330       os << " + ";
01331       CGAL::print_maple_monomial(os, p[i], varname, i);
01332     }
01333   }
01334 }
01335 
01336 template <class NT>
01337 void Polynomial<NT>::output_ascii(std::ostream &os) const {
01338   const Polynomial<NT> &p = *this;
01339   if (p.is_zero()) { os << "P[0 (0," << oformat(NT(0)) << ")]"; return; }
01340 
01341   os << "P[" << oformat(p.degree());
01342   for (int i = 0; i <= p.degree(); i++) {
01343     if (p[i] != NT(0)) os << "(" << CGAL::oformat(i) << ","
01344                           << CGAL::oformat(p[i]) << ")";
01345   }
01346   os << "]";
01347 }
01348 
01349 template <class NT>
01350 void Polynomial<NT>::output_benchmark(std::ostream &os) const {
01351   typedef typename Polynomial_traits_d< Polynomial<NT> >::Innermost_coefficient_type 
01352     Innermost_coefficient_type;
01353   typedef std::pair< Exponent_vector, Innermost_coefficient_type >
01354     Exponents_coeff_pair;
01355   typedef typename Polynomial_traits_d< Polynomial<NT> >::Monomial_representation Gmr;
01356     
01357   std::vector< Exponents_coeff_pair > monom_rep;
01358   Gmr gmr;
01359   gmr( *this, std::back_inserter( monom_rep ) );
01360     
01361   os << Benchmark_rep< Polynomial< NT > >::get_benchmark_name() << "( ";
01362     
01363   for( typename std::vector< Exponents_coeff_pair >::iterator it = monom_rep.begin();
01364        it != monom_rep.end(); ++it ) {
01365     if( it != monom_rep.begin() )
01366       os << ", ";
01367     os << "( " << bmformat( it->second ) << ", ";
01368     it->first.output_benchmark(os);
01369     os << " )";        
01370   }
01371   os << " )";
01372 }
01373 
01374 // Benchmark_rep specialization 
01375 template < class NT >
01376 class Benchmark_rep< CGAL::Polynomial< NT > > {
01377   const CGAL::Polynomial< NT >& t;
01378 public:
01380   Benchmark_rep( const CGAL::Polynomial< NT >& tt) : t(tt) {}
01382   std::ostream& operator()( std::ostream& out) const { 
01383     t.output_benchmark( out );
01384     return out;
01385   }
01386     
01387   static std::string get_benchmark_name() {
01388     std::stringstream ss;
01389     ss << "Polynomial< " << Polynomial_traits_d< Polynomial< NT > >::d;
01390         
01391     std::string coeff_name = Benchmark_rep< NT >::get_benchmark_name();
01392         
01393     if( coeff_name != "" )
01394       ss << ", " << coeff_name;
01395         
01396     ss << " >";
01397     return ss.str();
01398   }
01399 };
01400 
01401 // Moved to internal namespace because of name clashes
01402 // TODO: Is this OK?
01403 namespace CGALi {
01404 
01405 inline static void swallow(std::istream &is, char d) {
01406   char c;
01407   do c = is.get(); while (isspace(c));
01408   if (c != d) CGAL_error_msg( "input error: unexpected character in polynomial");
01409 }
01410 } // namespace CGALi
01411 
01412 template <class NT>
01413 Polynomial<NT> Polynomial<NT>::input_ascii(std::istream &is) {
01414   char c;
01415   int degr = -1, i;
01416 
01417   CGALi::swallow(is, 'P');
01418   CGALi::swallow(is, '[');
01419   is >> CGAL::iformat(degr);
01420   if (degr < 0) {
01421     CGAL_error_msg( "input error: negative degree of polynomial specified");
01422   }
01423   CGALi::Creation_tag TAG;
01424   Polynomial<NT> p(TAG, degr+1);
01425 
01426   do c = is.get(); while (isspace(c));
01427   do {
01428     if (c != '(') CGAL_error_msg( "input error: ( expected");
01429     is >> CGAL::iformat(i);
01430     if (!(i >= 0 && i <= degr && p[i] == NT(0))) {
01431       CGAL_error_msg( "input error: invalid exponent in polynomial");
01432     };
01433     CGALi::swallow(is, ',');
01434     is >> CGAL::iformat(p.coeff(i));
01435     CGALi::swallow(is, ')');
01436     do c = is.get(); while (isspace(c));
01437   } while (c != ']');
01438 
01439   p.reduce();
01440   p.simplify_coefficients();
01441   return p;
01442 }
01443 
01444 template <class COEFF>
01445 struct Needs_parens_as_product<Polynomial<COEFF> >{
01446   typedef Polynomial<COEFF> Poly;
01447   bool operator()(const Poly& x){ return (x.degree() > 0); }
01448 };
01449 
01450 
01451 
01452 CGAL_END_NAMESPACE
01453 
01454 #undef CGAL_icoeff
01455 #undef CGAL_int
01456 
01457 #endif // CGAL_POLYNOMIAL_POLYNOMIAL_TYPE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines