diff --git a/.gitattributes b/.gitattributes index ffb0c4c872c..eeb54099388 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2885,6 +2885,7 @@ Polynomial/examples/Polynomial/coefficient_access.cpp -text Polynomial/examples/Polynomial/construction.cpp -text Polynomial/examples/Polynomial/degree.cpp -text Polynomial/examples/Polynomial/gcd_up_to_constant_factor.cpp -text +Polynomial/examples/Polynomial/subresultants.cpp -text Polynomial/examples/Polynomial/substitute.cpp -text Polynomial/examples/Polynomial/swap_move.cpp -text Polynomial/include/CGAL/Polynomial/Coercion_traits.h -text diff --git a/Polynomial/doc_tex/Polynomial/intro.tex b/Polynomial/doc_tex/Polynomial/intro.tex index f7e50a08ffe..4b1032a565f 100644 --- a/Polynomial/doc_tex/Polynomial/intro.tex +++ b/Polynomial/doc_tex/Polynomial/intro.tex @@ -361,6 +361,83 @@ The following example illustrates the application of some functors discussed above: \ccIncludeExampleCode{Polynomial/substitute.cpp} +\section{Resultants, Subresultants and Sturm-Habicht sequences} + +The \ccc{PolynomialTraits_d} concept also provides more sophisitcated functors +for computations with polynomials -- +computing the resultant of two polynomials, +their polynomial subresultant sequence, with or without cofactors, +and their principal subresultant coefficients. +% +\begin{itemize} +\item \ccc{PolynomialTraits_d::Resultant}\ccGlue +\item \ccc{PolynomialTraits_d::PolynomialSubresultants}\ccGlue +\item \ccc{PolynomialTraits_d::PolynomialSubresultantsWithCofactors}\ccGlue +\item \ccc{PolynomialTraits_d::PrincipalSubresultants} +\end{itemize} +% +Moreover, functors to compute the Sturm-Habicht sequence, with or without +cofactors, and for the principal Sturm-Habicht coefficients exist. +% +\begin{itemize} +\item \ccc{PolynomialTraits_d::SturmHabichtSequence}\ccGlue +\item \ccc{PolynomialTraits_d::SturmHabichtSequenceWithCofactors}\ccGlue +\item \ccc{PolynomialTraits_d::PrincipalSturmHabichtSequence} +\end{itemize} +% +With the exception of \ccc{PolynomialTraits_d::Resultant}, +all these functors are only optional -- however, if the coefficient type +is at least a model of \ccc{Integral_domain_without_division}, +one can simply call the corresponding functions +\begin{itemize} +\item \ccc{CGAL::polynomial_subresultants}\ccGlue +\item \ccc{CGAL::principal_subresultants}\ccGlue +\item \ccc{CGAL::sturm_habicht_sequence}\ccGlue +\item \ccc{CGAL::principal_sturm_habicht_sequence} +\end{itemize} +to obtain valid models. If the coefficient type models \ccc{Integral_domain}, +the functions +\begin{itemize} +\item \ccc{CGAL::polynomial_subresultants_with_cofactors}\ccGlue +\item \ccc{CGAL::sturm_habicht_sequence_with_cofactors} +\end{itemize} +also yield models for the remaining functors. + +The principal Sturm-Habicht coefficients allow to count the number of +real roots of a polynomial using the function +\begin{itemize} +\item \ccc{CGAL::stha_count_number_of_real_roots}. +\end{itemize} +As input, this function requires an iterator range that represents +the principal Sturm-Habicht coefficients. +This might look circumstantially at a first sight, +as one has to store the principal Sturm-Habicht sequence temporarily. +However, we remark an important property of the (principal) Sturm-Habicht +sequence. Having a polynomial $f_t(x)$ that depends on a parameter $t$, +and its (principal) Sturm-Habicht coefficients +$\mathrm{stha}_0(f_t),\ldots,\mathrm{stha}_n(f_t)$, evaluating +$\mathrm{stha}_0(f_t)$ for $t=t_0$ yields a valid (principal) +Sturm-Habicht sequence for $f_{t_0}$. The same holds for (principal) +subresultants. Thus, it is enough in such situations to compute +the sequence once for the parameter $t$, and call +\ccc{CGAL::stha_count_number_of_real_roots} for each specialized parameter +value. + +We finally remark that computing subresultants and Sturm-Habicht sequences +introduces an enormous coefficient swell-up. +An applications of the functors therefore does not make sense +for built-in integers except for toy examples as below. +To avoid overflows, one should pass to arbitrary size integer types +in real applications. + +\subsection{Examples} + +The following example illustrates how two compute resultants of two +polynomials, and how to count the number of distinct real roots +of a polynomial using its principal Sturm-Habicht coefficients. + +\ccIncludeExampleCode{Polynomial/subresultants.cpp} + \section{Design and Implementation History} This package is the result of the integration process of the NumeriX library diff --git a/Polynomial/examples/Polynomial/subresultants.cpp b/Polynomial/examples/Polynomial/subresultants.cpp new file mode 100644 index 00000000000..41690c5cfde --- /dev/null +++ b/Polynomial/examples/Polynomial/subresultants.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +int main(){ + CGAL::set_pretty_mode(std::cout); + + typedef CGAL::Polynomial_type_generator::Type Poly_1; + typedef CGAL::Polynomial_traits_d PT_1; + + //construction using shift + Poly_1 x = PT_1::Shift()(Poly_1(1),1); // x^1 + + Poly_1 F // = (x+1)^2*(x-1)*(2x-1)=2x^4+x^3-3x^2-x+1 + = 2 * CGAL::ipower(x,4) + 1 * CGAL::ipower(x,3) + - 3 * CGAL::ipower(x,2) - 1 * CGAL::ipower(x,1) + + 1 * CGAL::ipower(x,0); + std::cout << "F=" << F << std::endl; + + Poly_1 G // = (x+1)*(x+3)=x^2+4*x+3 + = 1 * CGAL::ipower(x,2) + 4 * CGAL::ipower(x,1) + 3 * CGAL::ipower(x,0); + std::cout << "G=" << G << std::endl; + + // Resultant computation: + PT_1::Resultant resultant; + + std::cout << "The resultant of F and G is: " << resultant(F,G) << std::endl; + // It is zero, because F and G have a common factor + + // Real root counting: + PT_1::Principal_sturm_habicht_sequence stha; + std::vector psc; + + stha(F,std::back_inserter(psc)); + + int roots = CGAL::stha_count_number_of_real_roots(psc.begin(),psc.end()); + + std::cout << "The number of real roots of F is: " << roots << std::endl; // 3 + + return 0; + +}