dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/Polynomial/sturm_habicht_sequence.h

489 lines
14 KiB
C++
Executable File

// 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 <mkerber@mpi-inf.mpg.de>
//
// ============================================================================
#ifndef CGAL_POLYNOMIAL_STURM_HABICHT
#define CGAL_POLYNOMIAL_STURM_HABICHT 1
#include <vector>
#include <algorithm>
#include <CGAL/Polynomial/bezout_matrix.h>
#include <CGAL/Polynomial/subresultants.h>
namespace CGAL {
namespace internal {
/*!
* \brief compute the leading coefficients of the Sturm-Habicht sequence of
* the polynomial <I>P</I>
*
* The principal Sturm-Habicht sequence is obtained by computing the scalar
* subresultant sequence of <I>P</I> and its derivative, extended
* by <I>P</I> and <I>P'</I> 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<typename Polynomial_traits_d,typename OutputIterator>
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<typename Polynomial_traits_d::Polynomial_d> stha;
CGAL::internal::sturm_habicht_sequence<Polynomial_traits_d>
(P,std::back_inserter(stha));
for(int i=0; i<static_cast<int>(stha.size()); i++) {
int d = degree(stha[i]);
CGAL_assertion(d<=i);
if(d<i) {
*out++ = NT(0);
} else {
*out++ = coeff(stha[i],i);
}
}
return out;
}
/*!
* \brief compute the leading coefficients of the Sturm-Habicht sequence of
* the polynomial <I>P</I>
*
* The principal Sturm-Habicht sequence is obtained by computing the scalar
* subresultant sequence of <I>P</I> and its derivative, extended
* by <I>P</I> and <I>P'</I> 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<typename Polynomial_traits_d,typename OutputIterator>
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<NT> M
= CGAL::internal::polynomial_subresultant_matrix<Polynomial_traits_d>
(P,Px,1);
int n = static_cast<int>(M.row_dimension());
for(int i=0; i<n; i++) {
if((n-1-i)%4==0 || (n-1-i)%4==1) {
*out++ = -M[n-1-i][n-1-i];
} else {
*out++ = M[n-1-i][n-1-i];
}
}
*out++=lcoeff(Px);
*out++=lcoeff(P);
return out;
}
/*!
* \brief compute the principal and coprincipal Sturm-Habicht sequence
*/
template<typename Polynomial_traits_d,
typename OutputIterator1,
typename OutputIterator2>
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<Polynomial> stha;
int n = degree(P);
sturm_habicht_sequence<Polynomial_traits_d>(P,std::back_inserter(stha));
CGAL_assertion(static_cast<int>(stha.size())==n+1);
for(int i=0;i<=n;i++) {
int d = degree(stha[i]);
CGAL_assertion(d<=i);
if(d<i) {
*pstha++ = NT(0);
} else {
*pstha++ = coeff(stha[i],i);
}
}
for(int i=1;i<=n;i++) {
int d = degree(stha[i]);
CGAL_assertion(d<=i);
if(d<i-1) {
*copstha++ = NT(0);
} else {
*copstha++ = coeff(stha[i],i-1);
}
}
return;
}
/*! \brief compute the principal and coprincipal Sturm-Habicht sequence
*/
template<typename Polynomial_traits_d,
typename OutputIterator1,
typename OutputIterator2>
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<NT> M
= CGAL::internal::polynomial_subresultant_matrix<Polynomial_traits_d>
(P,Px,2);
int n = static_cast<int>(M.row_dimension());
for(int i=0; i<n; i++) {
if((n-1-i)%4==0 || (n-1-i)%4==1) {
*pstha++ = -M[n-1-i][n-1-i];
} else {
*pstha++ = M[n-1-i][n-1-i];
}
}
*pstha++ = lcoeff(Px);
*pstha++ = lcoeff(P);
for(int i=1; i<n; i++) {
if(n-i-1%4==0 || n-i-1%4==1) {
*copstha++ = -M[n-i-1][n-i];
} else {
*copstha++ = M[n-1-i][n-i];
}
}
*copstha++ = coeff(Px,degree(Px)-1);
*copstha++ = coeff(P,degree(P)-1);
}
// the general function for CGAL::Integral_domain_without_division_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_without_division_tag){
bezout_first_two_sturm_habicht_coefficients<Polynomial_traits_d>
(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<Polynomial_traits_d>
(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<NT>::Algebraic_category
Algebraic_category;
first_two_sturm_habicht_coefficients_<Polynomial_traits_d>
(A,pstha,copstha,Algebraic_category());
}
// the general function for CGAL::Integral_domain_without_division_tag
template <typename Polynomial_traits_d,typename OutputIterator> 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<Polynomial_traits_d>
(A,out);
}
// the specialization for CGAL::Integral_domain_tag
template <typename Polynomial_traits_d,typename OutputIterator> 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<Polynomial_traits_d>(A,out);
}
template <typename Polynomial_traits_d,typename OutputIterator> 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<NT>::Algebraic_category
Algebraic_category;
return principal_sturm_habicht_sequence_<Polynomial_traits_d>
(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_
<Polynomial_traits_d> (A,pstha,copstha);
}
/*!
* \brief compute the sequence of
* principal Sturm-Habicht coefficients
*/
template <typename Polynomial_traits_d,typename OutputIterator> inline
OutputIterator
principal_sturm_habicht_sequence
(typename Polynomial_traits_d::Polynomial_d A,
OutputIterator out){
return CGAL::internal::principal_sturm_habicht_sequence_
<Polynomial_traits_d>(A,out);
}
/*!
* \brief compute the Sturm-Habicht sequence
*/
template<typename Polynomial_traits_d,typename OutputIterator> 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<Polynomial> stha;
CGAL::internal::polynomial_subresultants<Polynomial_traits_d>
(P,P_x,std::back_inserter(stha));
stha.push_back(P);
CGAL_assertion(static_cast<int>(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<typename Polynomial_traits_d,
typename OutputIterator1,
typename OutputIterator2,
typename OutputIterator3>
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<Polynomial> stha,co_f,co_fx;
CGAL::internal::polynomial_subresultants_with_cofactors<Polynomial_traits_d>
(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<int>(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<typename InputIterator>
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<typename Polynomial_d>
int number_of_real_roots(Polynomial_d f) {
typedef CGAL::Polynomial_traits_d<Polynomial_d> Poly_traits_d;
typedef typename Poly_traits_d::Coefficient_type Coeff;
std::vector<Coeff> 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