// Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : Michael Kerber // // ============================================================================ #ifndef CGAL_POLYNOMIAL_STURM_HABICHT #define CGAL_POLYNOMIAL_STURM_HABICHT 1 #include #include #include #include namespace CGAL { namespace internal { /*! * \brief compute the leading coefficients of the Sturm-Habicht sequence of * the polynomial P * * The principal Sturm-Habicht sequence is obtained by computing the scalar * subresultant sequence of P and its derivative, extended * by P and P' and some sign changes. * * For details, see: Gonzalez-Vega,Lombardi,Recio,Roy: Determinants and Real * Roots of Univariate Polynomials. Texts and Monographs in Symbolic * Computation. Springer (1999) 300-316. * Only the special case Q=1 is implemented */ template OutputIterator prs_principal_sturm_habicht_sequence (typename Polynomial_traits_d::Polynomial_d P, OutputIterator out) { typedef typename Polynomial_traits_d::Coefficient_type NT; typename Polynomial_traits_d::Get_coefficient coeff; typename Polynomial_traits_d::Degree degree; std::vector stha; CGAL::internal::sturm_habicht_sequence (P,std::back_inserter(stha)); for(int i=0; i(stha.size()); i++) { int d = degree(stha[i]); CGAL_assertion(d<=i); if(dP * * The principal Sturm-Habicht sequence is obtained by computing the scalar * subresultant sequence of P and its derivative, extended * by P and P' and some sign changes. * * For details, see: Gonzalez-Vega,Lombardi,Recio,Roy: Determinants and Real * Roots of Univariate Polynomials. Texts and Monographs in Symbolic * Computation. Springer (1999) 300-316. * Only the special case Q=1 is implemented */ template OutputIterator bezout_principal_sturm_habicht_sequence (typename Polynomial_traits_d::Polynomial_d P, OutputIterator out) { typedef typename Polynomial_traits_d::Polynomial_d Polynomial; typedef typename Polynomial_traits_d::Coefficient_type NT; typename Polynomial_traits_d::Leading_coefficient lcoeff; typename Polynomial_traits_d::Differentiate diff; Polynomial Px = diff(P); CGAL::internal::Simple_matrix M = CGAL::internal::polynomial_subresultant_matrix (P,Px,1); int n = static_cast(M.row_dimension()); for(int i=0; i void prs_first_two_sturm_habicht_coefficients (typename Polynomial_traits_d::Polynomial_d P, OutputIterator1 pstha, OutputIterator2 copstha) { typedef typename Polynomial_traits_d::Polynomial_d Polynomial; typedef typename Polynomial_traits_d::Coefficient_type NT; typename Polynomial_traits_d::Get_coefficient coeff; typename Polynomial_traits_d::Degree degree; std::vector stha; int n = degree(P); sturm_habicht_sequence(P,std::back_inserter(stha)); CGAL_assertion(static_cast(stha.size())==n+1); for(int i=0;i<=n;i++) { int d = degree(stha[i]); CGAL_assertion(d<=i); if(d void bezout_first_two_sturm_habicht_coefficients (typename Polynomial_traits_d::Polynomial_d P, OutputIterator1 pstha, OutputIterator2 copstha) { typedef typename Polynomial_traits_d::Polynomial_d Polynomial; typedef typename Polynomial_traits_d::Coefficient_type NT; typename Polynomial_traits_d::Get_coefficient coeff; typename Polynomial_traits_d::Degree degree; typename Polynomial_traits_d::Leading_coefficient lcoeff; typename Polynomial_traits_d::Differentiate diff; Polynomial Px=diff(P); CGAL::internal::Simple_matrix M = CGAL::internal::polynomial_subresultant_matrix (P,Px,2); int n = static_cast(M.row_dimension()); for(int i=0; i inline void first_two_sturm_habicht_coefficients_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator1 pstha, OutputIterator2 copstha, CGAL::Integral_domain_without_division_tag){ bezout_first_two_sturm_habicht_coefficients (A,pstha,copstha); } // the general function for CGAL::Integral_domain_tag template < typename Polynomial_traits_d, typename OutputIterator1, typename OutputIterator2 > inline void first_two_sturm_habicht_coefficients_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator1 pstha, OutputIterator2 copstha, CGAL::Integral_domain_tag) { return prs_first_two_sturm_habicht_coefficients (A,pstha,copstha); } template < typename Polynomial_traits_d, typename OutputIterator1, typename OutputIterator2 > inline void first_two_sturm_habicht_coefficients_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator1 pstha, OutputIterator2 copstha) { typedef typename Polynomial_traits_d::Coefficient_type NT; typedef typename CGAL::Algebraic_structure_traits::Algebraic_category Algebraic_category; first_two_sturm_habicht_coefficients_ (A,pstha,copstha,Algebraic_category()); } // the general function for CGAL::Integral_domain_without_division_tag template inline OutputIterator principal_sturm_habicht_sequence_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator out, CGAL::Integral_domain_without_division_tag) { return bezout_principal_sturm_habicht_sequence (A,out); } // the specialization for CGAL::Integral_domain_tag template inline OutputIterator principal_sturm_habicht_sequence_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator out, CGAL::Integral_domain_tag) { return prs_principal_sturm_habicht_sequence(A,out); } template inline OutputIterator principal_sturm_habicht_sequence_ (typename Polynomial_traits_d::Polynomial_d A, OutputIterator out) { typedef typename Polynomial_traits_d::Coefficient_type NT; typedef typename CGAL::Algebraic_structure_traits::Algebraic_category Algebraic_category; return principal_sturm_habicht_sequence_ (A,out,Algebraic_category()); } /*! * \brief computes the first two coefficients of each polynomial of * the Sturm-Habicht sequence. * * This function is needed in Curve_analysis_2 for certain genericity checks */ template < typename Polynomial_traits_d, typename OutputIterator1, typename OutputIterator2 > inline void first_two_sturm_habicht_coefficients (typename Polynomial_traits_d::Polynomial_d A, OutputIterator1 pstha, OutputIterator2 copstha){ return CGAL::internal::first_two_sturm_habicht_coefficients_ (A,pstha,copstha); } /*! * \brief compute the sequence of * principal Sturm-Habicht coefficients */ template inline OutputIterator principal_sturm_habicht_sequence (typename Polynomial_traits_d::Polynomial_d A, OutputIterator out){ return CGAL::internal::principal_sturm_habicht_sequence_ (A,out); } /*! * \brief compute the Sturm-Habicht sequence */ template OutputIterator sturm_habicht_sequence(typename Polynomial_traits_d::Polynomial_d P, OutputIterator out) { typedef typename Polynomial_traits_d::Polynomial_d Polynomial; typename Polynomial_traits_d::Degree degree; typename Polynomial_traits_d::Differentiate diff; int p = degree(P); Polynomial P_x = diff(P); std::vector stha; CGAL::internal::polynomial_subresultants (P,P_x,std::back_inserter(stha)); stha.push_back(P); CGAL_assertion(static_cast(stha.size())==p+1); for(int i=0;i<=p; i++) { if((p-i)%4==0 || (p-i)%4==1) { *out++ = stha[i]; } else { *out++ = -stha[i]; } } return out; } /*! * \brief compute the Sturm-Habicht sequence with cofactors */ template OutputIterator1 sturm_habicht_sequence_with_cofactors (typename Polynomial_traits_d::Polynomial_d P, OutputIterator1 stha_out, OutputIterator2 cof_out, OutputIterator3 cofx_out) { typedef typename Polynomial_traits_d::Polynomial_d Polynomial; typename Polynomial_traits_d::Degree degree; typename Polynomial_traits_d::Differentiate diff; typename Polynomial_traits_d::Construct_polynomial construct; int p = degree(P); Polynomial P_x = diff(P); std::vector stha,co_f,co_fx; CGAL::internal::polynomial_subresultants_with_cofactors (P,P_x, std::back_inserter(stha), std::back_inserter(co_f), std::back_inserter(co_fx)); stha.push_back(P); co_f.push_back(construct(1)); co_fx.push_back(construct(0)); CGAL_assertion(static_cast(stha.size())==p+1); for(int i=0;i<=p; i++) { if((p-i)%4==0 || (p-i)%4==1) { *stha_out++ = stha[i]; *cof_out++ = co_f[i]; *cofx_out++ = co_fx[i]; } else { *stha_out++ = -stha[i]; *cof_out++ = -co_f[i]; *cofx_out++ = -co_fx[i]; } } return stha_out; } } // namespace internal /*! * \brief returns the number of roots of a polynomial with given * principal Sturm-Habicht sequence (counted without multiplicity) */ template int number_of_real_roots(InputIterator start,InputIterator end) { if(start==end) { return 0; } int m = 0; CGAL::Sign last_non_zero=CGAL::ZERO; //marks the starting point CGAL::Sign curr_sign; int k; InputIterator el=start; //std::cout << "Sign of." << (*el) << std::endl; curr_sign=CGAL::sign(*el); while(curr_sign==CGAL::ZERO && el!=end) { el++; curr_sign=CGAL::sign(*el); } if(el==end) return 0; last_non_zero=curr_sign; k=0; el++; while(el!=end) { curr_sign=CGAL::sign(*el); el++; if(curr_sign==CGAL::ZERO) { k++; } else { if(k%2==0) { // k is even k=k/2; int pm_one = (curr_sign==last_non_zero ? 1 : -1); pm_one = (k%2==1) ? -pm_one : pm_one; m+=pm_one; } k=0; last_non_zero=curr_sign; } } return m; } /*! * \brief returns the number of roots of a polynomial */ template int number_of_real_roots(Polynomial_d f) { typedef CGAL::Polynomial_traits_d Poly_traits_d; typedef typename Poly_traits_d::Coefficient_type Coeff; std::vector stha; typename Poly_traits_d::Principal_sturm_habicht_sequence() (f,std::back_inserter(stha)); return CGAL::number_of_real_roots(stha.begin(),stha.end()); } } //namespace CGAL #endif // CGAL_POLYNOMIAL_STURM_HABICHT