BWAPI
|
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