mirror of https://github.com/CGAL/cgal
Moved code to compute subresultants and sturm-habicht-sequences into Polynomial-package
This commit is contained in:
parent
6794adacb8
commit
5af98f25dc
|
|
@ -3145,7 +3145,11 @@ Polynomial/include/CGAL/Polynomial/may_have_common_factor.h -text
|
|||
Polynomial/include/CGAL/Polynomial/modular_filter.h -text
|
||||
Polynomial/include/CGAL/Polynomial/resultant.h -text
|
||||
Polynomial/include/CGAL/Polynomial/square_free_factorization.h -text
|
||||
Polynomial/include/CGAL/Polynomial/sturm_habicht_sequence.h -text
|
||||
Polynomial/include/CGAL/Polynomial/subresultants.h -text
|
||||
Polynomial/include/CGAL/Polynomial/univariate_polynomial_utils.h -text
|
||||
Polynomial/test/Polynomial/sturm_habicht_sequence.cpp -text
|
||||
Polynomial/test/Polynomial/subresultants.cpp -text
|
||||
Polytope_distance_d/doc_tex/Polytope_distance_d/dist.png -text
|
||||
Polytope_distance_d/doc_tex/Polytope_distance_d/polydist.eps -text svneol=unset#application/postscript
|
||||
Polytope_distance_d/doc_tex/Polytope_distance_d/polydist.gif -text svneol=unset#image/gif
|
||||
|
|
|
|||
|
|
@ -452,8 +452,6 @@ namespace CGALi {
|
|||
}
|
||||
return it;
|
||||
}
|
||||
}// namespace CGALi
|
||||
|
||||
|
||||
/*! \ingroup CGAL_resultant_matrix
|
||||
* \brief computes the coefficients of the polynomial subresultant sequence
|
||||
|
|
@ -554,6 +552,7 @@ typename CGALi::Simple_matrix< NT> polynomial_subresultant_matrix(
|
|||
return Ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -73,8 +73,35 @@ inline int square_free_factorization_for_regular_polynomial(const Polynomial<Coe
|
|||
template <class NT> inline bool may_have_multiple_factor( const Polynomial<NT>&);
|
||||
template <class NT> inline bool may_have_common_factor(const Polynomial<NT>&,const Polynomial<NT>&);
|
||||
|
||||
template< class Coeff >
|
||||
struct Simple_matrix;
|
||||
|
||||
template<class NT>
|
||||
CGALi::Simple_matrix<NT> polynomial_subresultant_matrix(
|
||||
CGAL::Polynomial<NT> f,
|
||||
CGAL::Polynomial<NT> g,
|
||||
int d=0);
|
||||
|
||||
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator polynomial_subresultants(CGAL::Polynomial<NT> A, CGAL::Polynomial<NT> B,
|
||||
OutputIterator out);
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator principal_subresultants(CGAL::Polynomial<NT> A, CGAL::Polynomial<NT> B,
|
||||
OutputIterator out);
|
||||
|
||||
template <typename OutputIterator, typename NT > inline
|
||||
OutputIterator principal_sturm_habicht_sequence(CGAL::Polynomial<NT> A,
|
||||
OutputIterator out);
|
||||
|
||||
template<typename OutputIterator, typename NT> OutputIterator
|
||||
sturm_habicht_sequence(CGAL::Polynomial<NT> P, OutputIterator out);
|
||||
|
||||
|
||||
} // namespace CGALi
|
||||
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,396 @@
|
|||
// TODO: Add licence
|
||||
//
|
||||
// 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: $
|
||||
//
|
||||
//
|
||||
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
#ifndef CGAL_ACK_STURM_HABICHT
|
||||
#define CGAL_ACK_STURM_HABICHT 1
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <CGAL/Polynomial/bezout_matrix.h>
|
||||
#include <CGAL/Polynomial/subresultants.h>
|
||||
|
||||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
namespace CGALi {
|
||||
|
||||
/*!
|
||||
* \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 NT,typename OutputIterator>
|
||||
OutputIterator prs_principal_sturm_habicht_sequence(CGAL::Polynomial<NT> P,
|
||||
OutputIterator out) {
|
||||
std::vector<CGAL::Polynomial<NT> > stha;
|
||||
CGAL::CGALi::sturm_habicht_sequence(P,std::back_inserter(stha));
|
||||
for(int i=0; i<static_cast<int>(stha.size()); i++) {
|
||||
int d = stha[i].degree();
|
||||
CGAL_assertion(d<=i);
|
||||
if(d<i) {
|
||||
*out++ = NT(0);
|
||||
} else {
|
||||
*out++ = 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 NT,typename OutputIterator>
|
||||
OutputIterator bezout_principal_sturm_habicht_sequence
|
||||
(CGAL::Polynomial<NT> P,
|
||||
OutputIterator out) {
|
||||
|
||||
CGAL::Polynomial<NT> Px(P);
|
||||
Px.diff();
|
||||
CGAL::CGALi::Simple_matrix<NT> M
|
||||
= CGAL::CGALi::polynomial_subresultant_matrix(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++=Px.lcoeff();
|
||||
*out++=P.lcoeff();
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*! \ingroup NiX_resultant_matrix
|
||||
* \brief compute the principal and coprincipal Sturm-Habicht sequence
|
||||
*/
|
||||
template<typename NT,typename OutputIterator1,typename OutputIterator2>
|
||||
void prs_first_two_sturm_habicht_coefficients(CGAL::Polynomial<NT> P,
|
||||
OutputIterator1 pstha,
|
||||
OutputIterator2 copstha) {
|
||||
|
||||
std::vector<CGAL::Polynomial<NT> > stha;
|
||||
int n = P.degree();
|
||||
|
||||
sturm_habicht_sequence(P,std::back_inserter(stha));
|
||||
CGAL_assertion(static_cast<int>(stha.size())==n+1);
|
||||
for(int i=0;i<=n;i++) {
|
||||
int d = stha[i].degree();
|
||||
CGAL_assertion(d<=i);
|
||||
if(d<i) {
|
||||
*pstha++ = NT(0);
|
||||
} else {
|
||||
*pstha++ = stha[i][i];
|
||||
}
|
||||
}
|
||||
for(int i=1;i<=n;i++) {
|
||||
int d = stha[i].degree();
|
||||
CGAL_assertion(d<=i);
|
||||
if(d<i-1) {
|
||||
*copstha++ = NT(0);
|
||||
} else {
|
||||
*copstha++ = stha[i][i-1];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*! \brief compute the principal and coprincipal Sturm-Habicht sequence
|
||||
*/
|
||||
template<typename NT,typename OutputIterator1,typename OutputIterator2>
|
||||
void bezout_first_two_sturm_habicht_coefficients(CGAL::Polynomial<NT> P,
|
||||
OutputIterator1 pstha,
|
||||
OutputIterator2 copstha) {
|
||||
CGAL::Polynomial<NT> Px(P);
|
||||
Px.diff();
|
||||
CGAL::CGALi::Simple_matrix<NT> M
|
||||
= CGAL::CGALi::polynomial_subresultant_matrix(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++ = Px.lcoeff();
|
||||
*pstha++ = P.lcoeff();
|
||||
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++ = Px[Px.degree()-1];
|
||||
*copstha++ = P[P.degree()-1];
|
||||
}
|
||||
|
||||
|
||||
// the general function for CGAL::Integral_domain_without_division_tag
|
||||
template <typename OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename NT> inline
|
||||
void
|
||||
first_two_sturm_habicht_coefficients_
|
||||
(CGAL::Polynomial<NT> 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::Unique_factorization_domain_tag
|
||||
template <typename OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename NT> inline
|
||||
void
|
||||
first_two_sturm_habicht_coefficients_
|
||||
(CGAL::Polynomial<NT> A,
|
||||
OutputIterator1 pstha,
|
||||
OutputIterator2 copstha,
|
||||
CGAL::Unique_factorization_domain_tag) {
|
||||
|
||||
return prs_first_two_sturm_habicht_coefficients(A,pstha,copstha);
|
||||
|
||||
}
|
||||
|
||||
template <typename OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename NT > inline
|
||||
void
|
||||
first_two_sturm_habicht_coefficients_(CGAL::Polynomial<NT> A,
|
||||
OutputIterator1 pstha,
|
||||
OutputIterator2 copstha) {
|
||||
typedef typename
|
||||
CGAL::Algebraic_structure_traits<NT>::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 <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
principal_sturm_habicht_sequence_
|
||||
(CGAL::Polynomial<NT> A,
|
||||
OutputIterator out,
|
||||
CGAL::Integral_domain_without_division_tag) {
|
||||
|
||||
return bezout_principal_sturm_babicht_sequence(A,out);
|
||||
}
|
||||
|
||||
// the specialization for CGAL::Unique_factorization_domain_tag
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
principal_sturm_habicht_sequence_
|
||||
(CGAL::Polynomial<NT> A,
|
||||
OutputIterator out,
|
||||
CGAL::Unique_factorization_domain_tag) {
|
||||
|
||||
return prs_principal_sturm_habicht_sequence(A,out);
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename NT > inline
|
||||
OutputIterator principal_sturm_habicht_sequence_(CGAL::Polynomial<NT> A,
|
||||
OutputIterator out) {
|
||||
typedef typename
|
||||
CGAL::Algebraic_structure_traits<NT>::Algebraic_category
|
||||
Algebraic_category;
|
||||
return principal_sturm_habicht_sequence_(A,out,Algebraic_category());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! \ingroup NiX_resultant_matrix
|
||||
* \brief compute the sequence of
|
||||
* principal Sturm-Habicht coefficients
|
||||
*/
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
principal_sturm_habicht_sequence(CGAL::Polynomial<NT> A,
|
||||
OutputIterator out){
|
||||
|
||||
return CGAL::CGALi::principal_sturm_habicht_sequence_(A,out);
|
||||
}
|
||||
|
||||
/*! \ingroup NiX_resultant_matrix
|
||||
* \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 OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename NT> inline
|
||||
void first_two_sturm_habicht_coefficients(CGAL::Polynomial<NT> A,
|
||||
OutputIterator1 pstha,
|
||||
OutputIterator2 copstha){
|
||||
|
||||
return CGAL::CGALi::first_two_sturm_habicht_coefficients_
|
||||
(A,pstha,copstha);
|
||||
}
|
||||
|
||||
/*! \ingroup NiX_resultant_matrix
|
||||
* \brief compute the Sturm-Habicht sequence
|
||||
*/
|
||||
template<typename OutputIterator, typename NT> OutputIterator
|
||||
sturm_habicht_sequence(CGAL::Polynomial<NT> P, OutputIterator out) {
|
||||
int p = P.degree();
|
||||
|
||||
CGAL::Polynomial<NT> P_x(P);
|
||||
P_x.diff();
|
||||
|
||||
std::vector<CGAL::Polynomial<NT> > stha;
|
||||
|
||||
CGAL::CGALi::polynomial_subresultants(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;
|
||||
}
|
||||
|
||||
/*! \ingroup NiX_resultant_matrix
|
||||
* \brief compute the Sturm-Habicht sequence with cofactors
|
||||
*/
|
||||
template<typename OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename OutputIterator3,
|
||||
typename NT> OutputIterator1
|
||||
sturm_habicht_sequence_with_cofactors(CGAL::Polynomial<NT> P,
|
||||
OutputIterator1 out_stha,
|
||||
OutputIterator2 out_f,
|
||||
OutputIterator3 out_fx) {
|
||||
int p = P.degree();
|
||||
|
||||
CGAL::Polynomial<NT> P_x(P);
|
||||
P_x.diff();
|
||||
|
||||
std::vector<CGAL::Polynomial<NT> > stha,co_f,co_fx;
|
||||
|
||||
CGAL::CGALi::prs_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(CGAL::Polynomial<NT>(1));
|
||||
co_fx.push_back(CGAL::Polynomial<NT>(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) {
|
||||
*out_stha++ = stha[i];
|
||||
*out_f++ = co_f[i];
|
||||
*out_fx++ = co_fx[i];
|
||||
} else {
|
||||
*out_stha++ = -stha[i];
|
||||
*out_f++ = -co_f[i];
|
||||
*out_fx++ = -co_fx[i];
|
||||
}
|
||||
}
|
||||
|
||||
return out_stha;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief returns the number of roots of a polynomial with given
|
||||
* principal Sturm-Habicht sequence (counted without multiplicity)
|
||||
*/
|
||||
template<typename NT,typename InputIterator>
|
||||
int stha_count_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;
|
||||
}
|
||||
|
||||
} // namespace CGALi
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
|
||||
#endif // CGAL_ACK_STURM_HABICHT
|
||||
|
|
@ -0,0 +1,560 @@
|
|||
// TODO: Add licence
|
||||
//
|
||||
// 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: $
|
||||
//
|
||||
//
|
||||
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
|
||||
//
|
||||
// ============================================================================
|
||||
#ifndef CGAL_ACK_SUBRESULTANTS_H
|
||||
#define CGAL_ACK_SUBRESULTANTS_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <CGAL/Polynomial.h>
|
||||
#include <CGAL/Polynomial/bezout_matrix.h>
|
||||
|
||||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
namespace CGALi {
|
||||
|
||||
// Intern function needed for Ducos algorithm
|
||||
|
||||
template<typename NT> void lazard_optimization(NT y,
|
||||
double n,
|
||||
CGAL::Polynomial<NT> B,
|
||||
CGAL::Polynomial<NT>& C) {
|
||||
CGAL_precondition(n>0);
|
||||
NT x = B.lcoeff();
|
||||
double a = pow(2.,std::floor(log(n)/log(2.)));
|
||||
NT c = x;
|
||||
n -= a;
|
||||
while(a!=1) {
|
||||
a/=2;
|
||||
c=CGAL::integral_division(c*c,y);
|
||||
if(n>=a) {
|
||||
c=CGAL::integral_division(c*x,y);
|
||||
n-=a;
|
||||
}
|
||||
}
|
||||
C=c*B/y;
|
||||
}
|
||||
|
||||
template<typename NT>
|
||||
void lickteig_roy_optimization(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
CGAL::Polynomial<NT> C,
|
||||
NT s,
|
||||
CGAL::Polynomial<NT>& D) {
|
||||
typedef CGAL::Polynomial<NT> Poly; // for convenience
|
||||
int d = A.degree(), e = B.degree();
|
||||
CGAL_precondition(d>=e);
|
||||
std::vector<Poly> H(d+1);
|
||||
std::list<NT> initial;
|
||||
initial.push_front(C.lcoeff());
|
||||
for(int i=0;i<e;i++) {
|
||||
H[i] = Poly(initial.begin(),initial.end());
|
||||
initial.push_front(NT(0));
|
||||
}
|
||||
H[e]=Poly(initial.begin(),initial.end())-C;
|
||||
CGAL_assertion(H[e].degree()<e);
|
||||
initial.clear();
|
||||
std::copy(H[e].begin(),H[e].end(),std::back_inserter(initial));
|
||||
initial.push_front(NT(0));
|
||||
for(int i=e+1;i<d;i++) {
|
||||
H[i]=Poly(initial.begin(),initial.end());
|
||||
NT h_i_e=H[i].degree()>=e ? H[i][e] : NT(0);
|
||||
H[i]-=(h_i_e*B)/B.lcoeff();
|
||||
initial.clear();
|
||||
std::copy(H[i].begin(),H[i].end(),std::back_inserter(initial));
|
||||
initial.push_front(NT(0));
|
||||
}
|
||||
H[d]=Poly(initial.begin(),initial.end());
|
||||
D=Poly(0);
|
||||
for(int i=0;i<d;i++) {
|
||||
D+=A[i]*H[i];
|
||||
}
|
||||
D/=A.lcoeff();
|
||||
NT Hde = H[d].degree()>=e ? H[d][e] : NT(0);
|
||||
D=(B.lcoeff()*(H[d]+D)-Hde*B)/s;
|
||||
if((d-e)%2==0) {
|
||||
D=-D;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename NT> NT resultant_for_constant_polynomial
|
||||
(CGAL::Polynomial<NT> P, CGAL::Polynomial<NT> Q) {
|
||||
CGAL_assertion(P.degree() < 1 || Q.degree() < 1);
|
||||
if(P.is_zero() || Q.is_zero() ) {
|
||||
return NT(0);
|
||||
}
|
||||
if(P.degree()==0) {
|
||||
return CGAL::ipower(P.lcoeff(),Q.degree());
|
||||
} else {
|
||||
return CGAL::ipower(Q.lcoeff(),P.degree());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Compute the sequence of subresultants with pseudo-division
|
||||
*
|
||||
* This is an implementation of Ducos' algorithm. It improves on the
|
||||
* classical methods for subresultant computation by reducing the
|
||||
* swell-up of intermediate results. For all details, see
|
||||
* L.Ducos: Optimazations of the Subresultant algorithm. <i>Journal of Pure
|
||||
* and Applied Algebra</i> <b>145</b> (2000) 149--163
|
||||
*/
|
||||
template <typename NT,typename OutputIterator> inline
|
||||
OutputIterator prs_polynomial_subresultants(CGAL::Polynomial<NT> P,
|
||||
CGAL::Polynomial<NT> Q,
|
||||
OutputIterator out) {
|
||||
|
||||
if(P.degree() < 1 || Q.degree() < 1) {
|
||||
*out++ = CGAL::CGALi::resultant_for_constant_polynomial(P,Q);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool poly_swapped = (P.degree() < Q.degree());
|
||||
|
||||
if(poly_swapped) {
|
||||
std::swap(P,Q);
|
||||
}
|
||||
|
||||
CGAL::Polynomial<NT> zero_pol(NT(0));
|
||||
std::vector<CGAL::Polynomial<NT> > sres;
|
||||
|
||||
int deg_diff=P.degree()-Q.degree();
|
||||
|
||||
if(deg_diff==0) {
|
||||
sres.push_back(Q);
|
||||
} else {
|
||||
sres.push_back(CGAL::ipower(Q.lcoeff(),deg_diff-1)*Q);
|
||||
}
|
||||
|
||||
CGAL::Polynomial<NT> A,B,C,D,dummy_pol;
|
||||
NT s,dummy_nt;
|
||||
int delta,d,e;
|
||||
|
||||
A=Q;
|
||||
|
||||
s=CGAL::ipower(Q.lcoeff(),deg_diff);
|
||||
|
||||
CGAL::Polynomial<NT>::pseudo_division(P, -Q, dummy_pol, B, dummy_nt);
|
||||
|
||||
while(true) {
|
||||
d=A.degree();
|
||||
e=B.degree();
|
||||
if(B.is_zero()) {
|
||||
for(int i=0;i<d;i++) {
|
||||
sres.push_back(zero_pol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sres.push_back(B);
|
||||
delta=d-e;
|
||||
if(delta>1) {
|
||||
CGAL::CGALi::lazard_optimization(s,double(delta-1),B,C);
|
||||
//C=CGAL::ipower(CGAL::integral_division(B.lcoeff(),s),delta-1)*B;
|
||||
for(int i=0;i<delta-2;i++) {
|
||||
sres.push_back(zero_pol);
|
||||
}
|
||||
sres.push_back(C);
|
||||
}
|
||||
else {
|
||||
C=B;
|
||||
}
|
||||
if(e==0) {
|
||||
break;
|
||||
}
|
||||
CGAL::CGALi::lickteig_roy_optimization(A,B,C,s,D);
|
||||
B=D;
|
||||
//CGAL::Polynomial<NT>::pseudo_division(A, -B, dummy_pol, D, dummy_nt);
|
||||
//B= D / (CGAL::ipower(s,delta)*A.lcoeff());
|
||||
A=C;
|
||||
s=A.lcoeff();
|
||||
}
|
||||
|
||||
CGAL_assertion(static_cast<int>(sres.size())
|
||||
== Q.degree()+1);
|
||||
|
||||
// If P and Q were swapped, correct the signs
|
||||
if(poly_swapped) {
|
||||
int p = P.degree();
|
||||
int q = Q.degree();
|
||||
for(int i=0;i<=q;i++) {
|
||||
if((p-i)*(q-i) % 2 == 1) {
|
||||
sres[q-i]=-sres[q-i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, reverse the entries
|
||||
return std::copy(sres.rbegin(),sres.rend(),out);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Computes the polynomial subresultants
|
||||
* as minors of the Bezout matrix
|
||||
*/
|
||||
template <typename NT,typename OutputIterator> inline
|
||||
OutputIterator bezout_polynomial_subresultants(CGAL::Polynomial<NT> P,
|
||||
CGAL::Polynomial<NT> Q,
|
||||
OutputIterator out) {
|
||||
if(P.degree() < 1 || Q.degree() < 1) {
|
||||
*out++ = CGAL::CGALi::resultant_for_constant_polynomial(P,Q);
|
||||
return out;
|
||||
}
|
||||
|
||||
typedef CGAL::CGALi::Simple_matrix<NT> Matrix;
|
||||
Matrix M = CGAL::CGALi::polynomial_subresultant_matrix(P,Q);
|
||||
|
||||
int r = static_cast<int>(M.row_dimension());
|
||||
|
||||
for(int i = 0;i < r; i++) {
|
||||
std::vector<NT> curr_row;
|
||||
std::copy(M[r-1-i].begin(),
|
||||
M[r-1-i].end(),
|
||||
std::back_inserter(curr_row));
|
||||
//std::reverse(curr_row.begin(),curr_row.end());
|
||||
*out++=CGAL::Polynomial<NT>(curr_row.rbegin(),curr_row.rend());
|
||||
}
|
||||
int deg_diff=P.degree()-Q.degree();
|
||||
if(deg_diff==0) {
|
||||
*out++=Q;
|
||||
} else if(deg_diff>0) {
|
||||
*out++=CGAL::ipower(Q.lcoeff(),deg_diff-1)*Q;
|
||||
} else {
|
||||
*out++=CGAL::ipower(P.lcoeff(),-deg_diff-1)*P;
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compute the sequence of principal subresultants
|
||||
* with pseudo-division
|
||||
*
|
||||
* Uses Ducos algorithm for the polynomial subresultant, and
|
||||
* returns the formal leading coefficients.
|
||||
*/
|
||||
template <typename NT,typename OutputIterator> inline
|
||||
OutputIterator prs_principal_subresultants(CGAL::Polynomial<NT> P,
|
||||
CGAL::Polynomial<NT> Q,
|
||||
OutputIterator out) {
|
||||
|
||||
std::vector<CGAL::Polynomial<NT> > sres;
|
||||
int q = std::min(Q.degree(),P.degree());
|
||||
|
||||
CGAL::CGALi::prs_polynomial_subresultants(P,Q,std::back_inserter(sres));
|
||||
CGAL_assertion(static_cast<int>(sres.size()) == q+1);
|
||||
for(int i=0; i <= q; i++) {
|
||||
int d = sres[i].degree();
|
||||
CGAL_assertion(d<=i);
|
||||
if(d<i) {
|
||||
*out++ = NT(0);
|
||||
} else {
|
||||
*out++ = sres[i][i];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compute the sequence of principal subresultants
|
||||
* with minors of the Bezout matrix
|
||||
*
|
||||
*/
|
||||
template <typename NT,typename OutputIterator> inline
|
||||
OutputIterator bezout_principal_subresultants(CGAL::Polynomial<NT> P,
|
||||
CGAL::Polynomial<NT> Q,
|
||||
OutputIterator out) {
|
||||
if(P.degree() < 1 || Q.degree() < 1) {
|
||||
*out++ = CGAL::CGALi::resultant_for_constant_polynomial(P,Q);
|
||||
return out;
|
||||
}
|
||||
|
||||
typedef CGAL::CGALi::Simple_matrix<NT> Matrix;
|
||||
Matrix M = CGAL::CGALi::polynomial_subresultant_matrix(P,Q,1);
|
||||
|
||||
int r = static_cast<int>(M.row_dimension());
|
||||
|
||||
for(int i = r - 1;i >=0; i--) {
|
||||
*out++=M[i][i];
|
||||
}
|
||||
int deg_diff=P.degree()-Q.degree();
|
||||
if(deg_diff==0) {
|
||||
*out++=NT(1);
|
||||
} else if(deg_diff>0) {
|
||||
*out++=CGAL::ipower(Q.lcoeff(),deg_diff);
|
||||
} else {
|
||||
*out++=CGAL::ipower(P.lcoeff(),-deg_diff);
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the subresultants together with the according cofactors
|
||||
*/
|
||||
template<typename NT,
|
||||
typename OutputIterator1,
|
||||
typename OutputIterator2,
|
||||
typename OutputIterator3>
|
||||
OutputIterator1 prs_subresultants_with_cofactors(CGAL::Polynomial<NT> P,
|
||||
CGAL::Polynomial<NT> Q,
|
||||
OutputIterator1 sres_out,
|
||||
OutputIterator2 coP_out,
|
||||
OutputIterator3 coQ_out) {
|
||||
|
||||
|
||||
if(P.degree() < 1 || Q.degree() < 1) {
|
||||
*sres_out++ = CGAL::CGALi::resultant_for_constant_polynomial(P,Q);
|
||||
*coP_out++ = Q.lcoeff();
|
||||
*coQ_out++ = P.lcoeff();
|
||||
return sres_out;
|
||||
}
|
||||
|
||||
bool poly_swapped = (P.degree() < Q.degree());
|
||||
|
||||
if(poly_swapped) {
|
||||
std::swap(P,Q);
|
||||
}
|
||||
|
||||
CGAL::Polynomial<NT> zero_pol(NT(0));
|
||||
std::vector<CGAL::Polynomial<NT> > sres, coP, coQ;
|
||||
|
||||
int deg_diff=P.degree()-Q.degree();
|
||||
|
||||
if(deg_diff==0) {
|
||||
sres.push_back(Q);
|
||||
} else {
|
||||
sres.push_back(CGAL::ipower(Q.lcoeff(),deg_diff-1)*Q);
|
||||
}
|
||||
|
||||
|
||||
CGAL::Polynomial<NT> A,B,C,D,Quo, coPA, coPB, coQA, coQB, coPC, coQC;
|
||||
NT s,m;
|
||||
int delta,d,e;
|
||||
|
||||
coPA = CGAL::Polynomial<NT>(NT(0));
|
||||
coQA = CGAL::Polynomial<NT>(CGAL::ipower(Q.lcoeff(),deg_diff-1));
|
||||
|
||||
coP.push_back(coPA);
|
||||
coQ.push_back(coQA);
|
||||
|
||||
A=Q;
|
||||
|
||||
s=CGAL::ipower(Q.lcoeff(),deg_diff);
|
||||
|
||||
CGAL::Polynomial<NT>::pseudo_division(P, -Q, Quo, B, m);
|
||||
|
||||
coPB = CGAL::Polynomial<NT>(m);
|
||||
coQB = Quo;
|
||||
|
||||
|
||||
while(true) {
|
||||
d=A.degree();
|
||||
e=B.degree();
|
||||
if(B.is_zero()) {
|
||||
for(int i=0;i<d;i++) {
|
||||
sres.push_back(zero_pol);
|
||||
coP.push_back(zero_pol);
|
||||
coQ.push_back(zero_pol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
sres.push_back(B);
|
||||
coP.push_back(coPB);
|
||||
coQ.push_back(coQB);
|
||||
|
||||
delta=d-e;
|
||||
if(delta>1) {
|
||||
C=CGAL::ipower(B.lcoeff(),delta-1)*B / CGAL::ipower(s,delta-1);
|
||||
|
||||
coPC = CGAL::ipower(B.lcoeff(),delta-1)*coPB /
|
||||
CGAL::ipower(s,delta-1);
|
||||
coQC = CGAL::ipower(B.lcoeff(),delta-1)*coQB /
|
||||
CGAL::ipower(s,delta-1);
|
||||
for(int i=0;i<delta-2;i++) {
|
||||
sres.push_back(zero_pol);
|
||||
coP.push_back(zero_pol);
|
||||
coQ.push_back(zero_pol);
|
||||
}
|
||||
sres.push_back(C);
|
||||
coP.push_back(coPC);
|
||||
coQ.push_back(coQC);
|
||||
|
||||
}
|
||||
else {
|
||||
C=B;
|
||||
coPC = coPB;
|
||||
coQC = coQB;
|
||||
}
|
||||
if(e==0) {
|
||||
break;
|
||||
}
|
||||
NT denominator = CGAL::ipower(s,delta)*A.lcoeff();
|
||||
CGAL::Polynomial<NT>::pseudo_division(A, -B, Quo, D, m);
|
||||
coPB = (m*coPA + Quo*coPB) / denominator;
|
||||
coQB = (m*coQA + Quo*coQB) / denominator;
|
||||
B = D / denominator;
|
||||
A = C;
|
||||
coPA = coPC;
|
||||
coQA = coQC;
|
||||
s = A.lcoeff();
|
||||
}
|
||||
|
||||
CGAL_assertion(static_cast<int>(sres.size())
|
||||
== Q.degree()+1);
|
||||
|
||||
// If P and Q were swapped, correct the signs
|
||||
if(poly_swapped) {
|
||||
int p = P.degree();
|
||||
int q = Q.degree();
|
||||
for(int i=0;i<=q;i++) {
|
||||
if((p-i)*(q-i) % 2 == 1) {
|
||||
sres[q-i] = -sres[q-i];
|
||||
coP[q-i] = -coP[q-i];
|
||||
coQ[q-i] = -coQ[q-i];
|
||||
}
|
||||
}
|
||||
for(int i=0;i<=q;i++) {
|
||||
// Swap coP and coQ:
|
||||
CGAL::Polynomial<NT> help = coP[i];
|
||||
coP[i] = coQ[i];
|
||||
coQ[i] = help;
|
||||
}
|
||||
}
|
||||
|
||||
// Now, reverse the entries
|
||||
std::copy(coP.rbegin(),coP.rend(),coP_out);
|
||||
std::copy(coQ.rbegin(),coQ.rend(),coQ_out);
|
||||
return std::copy(sres.rbegin(),sres.rend(),sres_out);
|
||||
|
||||
}
|
||||
|
||||
// the general function for CGAL::Integral_domain_without_division_tag
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
polynomial_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out,
|
||||
CGAL::Integral_domain_without_division_tag){
|
||||
|
||||
return bezout_polynomial_subresultants(A,B,out);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// the specialization for CGAL::Unique_factorization_domain_tag
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
polynomial_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out,
|
||||
CGAL::Unique_factorization_domain_tag){
|
||||
|
||||
return prs_polynomial_subresultants(A,B,out);
|
||||
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename NT > inline
|
||||
OutputIterator polynomial_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out) {
|
||||
typedef typename
|
||||
CGAL::Algebraic_structure_traits<NT>::Algebraic_category
|
||||
Algebraic_category;
|
||||
return polynomial_subresultants_(A,B,out,Algebraic_category());
|
||||
}
|
||||
|
||||
// the general function for CGAL::Integral_domain_without_division_tag
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
principal_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out,
|
||||
CGAL::Integral_domain_without_division_tag){
|
||||
|
||||
return bezout_principal_subresultants(A,B,out);
|
||||
|
||||
}
|
||||
|
||||
// the specialization for CGAL::Unique_factorization_domain_tag
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator
|
||||
principal_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out,
|
||||
CGAL::Unique_factorization_domain_tag){
|
||||
|
||||
return prs_principal_subresultants(A,B,out);
|
||||
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename NT > inline
|
||||
OutputIterator principal_subresultants_(CGAL::Polynomial<NT> A,
|
||||
CGAL::Polynomial<NT> B,
|
||||
OutputIterator out) {
|
||||
typedef typename
|
||||
CGAL::Algebraic_structure_traits<NT>::Algebraic_category
|
||||
Algebraic_category;
|
||||
return principal_subresultants_(A,B,out,Algebraic_category());
|
||||
}
|
||||
|
||||
|
||||
/*! \relates CGAL::Polynomial
|
||||
* \brief compute the polynomial subresultants of the polynomials
|
||||
* \c A and \c B
|
||||
*
|
||||
* If \c n is the degree of A, the routine returns a sequence
|
||||
* of length n+1, the (polynomial) subresultants of \c A and \c B.
|
||||
* It starts with the resultant of \c A and \c B.
|
||||
* The <tt>i</tt>th polynomial has degree
|
||||
* at most i, and the last polynomial is \c A itself.
|
||||
*
|
||||
* The way the subresultants are computed depends on the Algebra_type.
|
||||
* In general the subresultant will be computed by the function
|
||||
* CGAL::bezout_polynomial_subresultants, but if possible the function
|
||||
* CGAL::prs_polynomial_subresultants is used.
|
||||
*/
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator polynomial_subresultants(CGAL::Polynomial<NT> A, CGAL::Polynomial<NT> B,
|
||||
OutputIterator out) {
|
||||
return CGAL::CGALi::polynomial_subresultants_(A, B, out);
|
||||
}
|
||||
|
||||
/*! \relates CGAL::Polynomial
|
||||
* \brief compute the principal subresultants of the polynomials
|
||||
* \c A and \c B
|
||||
*
|
||||
* If \c q is the degree of B, the routine returns a sequence
|
||||
* of length q+1, the (principal) subresultants of \c A and \c B.
|
||||
* It starts with the resultant of \c A and \c B,
|
||||
* and ends with the leading coefficient of \c B.
|
||||
*
|
||||
* The way the subresultants are computed depends on the Algebra_type.
|
||||
* In general the subresultant will be computed by the function
|
||||
* CGAL::bezout_principal_subresultants, but if possible the function
|
||||
* CGAL::prs_principal_subresultants is used.
|
||||
*/
|
||||
template <typename OutputIterator, typename NT> inline
|
||||
OutputIterator principal_subresultants(CGAL::Polynomial<NT> A, CGAL::Polynomial<NT> B,
|
||||
OutputIterator out) {
|
||||
return CGAL::CGALi::principal_subresultants_(A, B, out);
|
||||
}
|
||||
|
||||
} // namespace CGALi
|
||||
|
||||
CGAL_END_NAMESPACE
|
||||
#endif// CGAL_ACK_SUBRESULTANTS_H
|
||||
|
|
@ -0,0 +1,347 @@
|
|||
// TODO: Add licence
|
||||
//
|
||||
// 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: $
|
||||
//
|
||||
//
|
||||
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <cstddef>
|
||||
|
||||
#include <CGAL/Polynomial/sturm_habicht_sequence.h>
|
||||
#include <CGAL/Arithmetic_kernel.h>
|
||||
|
||||
|
||||
template<typename ArithmeticKernel> void test_routine() {
|
||||
|
||||
// All results are computed with the sres_stha.mpl worksheet
|
||||
typedef typename ArithmeticKernel::Integer NT;
|
||||
typedef CGAL::Polynomial<NT> PNT_1;
|
||||
typedef CGAL::Polynomial<PNT_1> PNT_2;
|
||||
|
||||
{ // test for the principal Sturm-Habicht sequence
|
||||
// f=x^3*(x+1)*(x-1)*(x-2)^2
|
||||
PNT_1 f(NT(0),NT(0),NT(0),NT(-4),NT(4),NT(3),NT(-4),NT(1));
|
||||
std::vector<NT> stha;
|
||||
CGAL::CGALi::principal_sturm_habicht_sequence(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==8);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(0));
|
||||
assert(stha[2] == NT(0));
|
||||
assert(stha[3] == NT(864));
|
||||
assert(stha[4] == NT(324));
|
||||
assert(stha[5] == NT(54));
|
||||
assert(stha[6] == NT(7));
|
||||
assert(stha[7] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>
|
||||
(stha.begin(),stha.end()) == 4);
|
||||
|
||||
stha.clear();
|
||||
|
||||
CGAL::CGALi::prs_principal_sturm_habicht_sequence(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==8);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(0));
|
||||
assert(stha[2] == NT(0));
|
||||
assert(stha[3] == NT(864));
|
||||
assert(stha[4] == NT(324));
|
||||
assert(stha[5] == NT(54));
|
||||
assert(stha[6] == NT(7));
|
||||
assert(stha[7] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>
|
||||
(stha.begin(),stha.end()) == 4);
|
||||
|
||||
stha.clear();
|
||||
|
||||
CGAL::CGALi::bezout_principal_sturm_habicht_sequence(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==8);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(0));
|
||||
assert(stha[2] == NT(0));
|
||||
assert(stha[3] == NT(864));
|
||||
assert(stha[4] == NT(324));
|
||||
assert(stha[5] == NT(54));
|
||||
assert(stha[6] == NT(7));
|
||||
assert(stha[7] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>
|
||||
(stha.begin(),stha.end()) == 4);
|
||||
|
||||
stha.clear();
|
||||
|
||||
typename
|
||||
CGAL::Polynomial_traits_d<PNT_1>::Principal_sturm_habicht_sequence()
|
||||
(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==8);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(0));
|
||||
assert(stha[2] == NT(0));
|
||||
assert(stha[3] == NT(864));
|
||||
assert(stha[4] == NT(324));
|
||||
assert(stha[5] == NT(54));
|
||||
assert(stha[6] == NT(7));
|
||||
assert(stha[7] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>
|
||||
(stha.begin(),stha.end()) == 4);
|
||||
}
|
||||
|
||||
{ // Example for the defective case
|
||||
// f:=x^8+x^2
|
||||
PNT_1 f(NT(0),NT(0),NT(1),NT(0),NT(0),NT(0),NT(0),NT(0),NT(1));
|
||||
|
||||
std::vector<NT> stha;
|
||||
CGAL::CGALi::principal_sturm_habicht_sequence (f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==9);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(-93312));
|
||||
assert(stha[2] == NT(-62208));
|
||||
assert(stha[3] == NT(0));
|
||||
assert(stha[4] == NT(0));
|
||||
assert(stha[5] == NT(0));
|
||||
assert(stha[6] == NT(0));
|
||||
assert(stha[7] == NT(8));
|
||||
assert(stha[8] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>(stha.begin(),stha.end()) == 1);
|
||||
|
||||
stha.clear();
|
||||
|
||||
CGAL::CGALi::prs_principal_sturm_habicht_sequence (f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==9);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(-93312));
|
||||
assert(stha[2] == NT(-62208));
|
||||
assert(stha[3] == NT(0));
|
||||
assert(stha[4] == NT(0));
|
||||
assert(stha[5] == NT(0));
|
||||
assert(stha[6] == NT(0));
|
||||
assert(stha[7] == NT(8));
|
||||
assert(stha[8] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>(stha.begin(),stha.end()) == 1);
|
||||
|
||||
stha.clear();
|
||||
|
||||
CGAL::CGALi::bezout_principal_sturm_habicht_sequence (f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==9);
|
||||
assert(stha[0] == NT(0));
|
||||
assert(stha[1] == NT(-93312));
|
||||
assert(stha[2] == NT(-62208));
|
||||
assert(stha[3] == NT(0));
|
||||
assert(stha[4] == NT(0));
|
||||
assert(stha[5] == NT(0));
|
||||
assert(stha[6] == NT(0));
|
||||
assert(stha[7] == NT(8));
|
||||
assert(stha[8] == NT(1));
|
||||
assert(CGAL::CGALi::stha_count_number_of_real_roots<NT>(stha.begin(),stha.end()) == 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
{ // test for the complete Sturm-Habicht sequence
|
||||
// f:=(2*x+1)^3*(x+1)*(x-1)
|
||||
PNT_1 f(NT(-1),NT(-6),NT(-11),NT(-2),NT(12),NT(8));
|
||||
PNT_1 fx(f);
|
||||
fx.diff();
|
||||
|
||||
std::vector<PNT_1> stha;
|
||||
|
||||
CGAL::CGALi::sturm_habicht_sequence(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==6);
|
||||
|
||||
assert(stha[5]==f);
|
||||
assert(stha[4]==fx);
|
||||
assert(stha[3]==PNT_1(NT(1024),NT(5568),NT(9984),NT(5888)));
|
||||
assert(stha[2]==PNT_1(NT(55296),NT(221184),NT(221184)));
|
||||
assert(stha[1].is_zero());
|
||||
assert(stha[0].is_zero());
|
||||
|
||||
stha.clear();
|
||||
|
||||
typename CGAL::Polynomial_traits_d<PNT_1>::Sturm_habicht_sequence()
|
||||
(f,std::back_inserter(stha));
|
||||
|
||||
assert(stha.size()==6);
|
||||
|
||||
assert(stha[5]==f);
|
||||
assert(stha[4]==fx);
|
||||
assert(stha[3]==PNT_1(NT(1024),NT(5568),NT(9984),NT(5888)));
|
||||
assert(stha[2]==PNT_1(NT(55296),NT(221184),NT(221184)));
|
||||
assert(stha[1].is_zero());
|
||||
assert(stha[0].is_zero());
|
||||
|
||||
}
|
||||
|
||||
{ // test for cofactors
|
||||
// f:=(2*x+1)^3*(x+1)*(x-1)
|
||||
PNT_1 f(NT(-1),NT(-6),NT(-11),NT(-2),NT(12),NT(8));
|
||||
PNT_1 fx = CGAL::diff(f);
|
||||
|
||||
std::vector<PNT_1> stha_check,stha,co_f,co_fx;
|
||||
|
||||
CGAL::CGALi::sturm_habicht_sequence(f,std::back_inserter(stha_check));
|
||||
CGAL::CGALi::sturm_habicht_sequence_with_cofactors(f,
|
||||
std::back_inserter(stha),
|
||||
std::back_inserter(co_f),
|
||||
std::back_inserter(co_fx)
|
||||
);
|
||||
|
||||
int n = static_cast<int>(stha.size());
|
||||
assert(n == static_cast<int>(stha_check.size()));
|
||||
for(int i = 0; i < n; i++) {
|
||||
assert(stha[i]==stha_check[i]);
|
||||
assert(stha[i]==co_f[i]*f + co_fx[i]*fx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{ // Cofactors, defective case
|
||||
// f:=x^8+x^2
|
||||
PNT_1 f(NT(0),NT(0),NT(1),NT(0),NT(0),NT(0),NT(0),NT(0),NT(1));
|
||||
PNT_1 fx = CGAL::diff(f);
|
||||
|
||||
std::vector<PNT_1> stha_check,stha,co_f,co_fx;
|
||||
|
||||
|
||||
CGAL::CGALi::sturm_habicht_sequence(f,std::back_inserter(stha_check));
|
||||
CGAL::CGALi::sturm_habicht_sequence_with_cofactors(f,
|
||||
std::back_inserter(stha),
|
||||
std::back_inserter(co_f),
|
||||
std::back_inserter(co_fx)
|
||||
);
|
||||
|
||||
int n = static_cast<int>(stha.size());
|
||||
assert(n == static_cast<int>(stha_check.size()));
|
||||
for(int i = 0; i < n; i++) {
|
||||
assert(stha[i]==stha_check[i]);
|
||||
assert(stha[i]==co_f[i]*f + co_fx[i]*fx);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
{ // Test for bivariate polynomials
|
||||
// f:=y^4 + 6*y^3 + 9*y^2 + (9*x^3 + 3*x^2 + 2*x + 5)*y + (2*x^2 + 5*x + 7)
|
||||
std::stringstream ss("P[4(0,P[2(0,7)(1,5)(2,2)])(1,P[3(0,5)(1,2)(2,3)(3,9)])(2,P[0(0,9)])(3,P[0(0,6)])(4,P[0(0,1)])]");
|
||||
PNT_2 f;
|
||||
ss >> f;
|
||||
|
||||
{
|
||||
std::vector<PNT_1> stha,costha;
|
||||
CGAL::CGALi::first_two_sturm_habicht_coefficients(f,std::back_inserter(stha),
|
||||
std::back_inserter(costha));
|
||||
|
||||
assert(stha.size()==5);
|
||||
assert(costha.size()==4);
|
||||
|
||||
NT c1[13] = { NT(-81383),NT(-113448),NT(-123840),NT(-223936),NT(-272142),
|
||||
NT(-14700),NT(419954),NT(156816),NT(-247131),NT(-498636),
|
||||
NT(-275562),NT(-236196),NT(-177147) };
|
||||
PNT_1 p1(c1,c1+13);
|
||||
assert(stha[0] == p1);
|
||||
assert(stha[1] == PNT_1(NT(-828),NT(-1008),NT(-864),NT(-1728),NT(-1620),
|
||||
NT(-1944),NT(-2916)) );
|
||||
assert(stha[2] == PNT_1(NT(36)) );
|
||||
assert(stha[3] == PNT_1(NT(4)) );
|
||||
assert(stha[4] == PNT_1(NT(1)) );
|
||||
|
||||
|
||||
|
||||
assert(costha[0] == PNT_1(NT(-2742),NT(-2592),NT(-1788),NT(-2100),
|
||||
NT(-1638),NT(108),NT(1458)) );
|
||||
assert(costha[1] == PNT_1(NT(48),NT(-24),NT(-36),NT(-108)) );
|
||||
assert(costha[2] == PNT_1(NT(18)) );
|
||||
assert(costha[3] == PNT_1(NT(6)) );
|
||||
}
|
||||
{
|
||||
std::vector<PNT_1> stha,costha;
|
||||
CGAL::CGALi::prs_first_two_sturm_habicht_coefficients(f,std::back_inserter(stha),
|
||||
std::back_inserter(costha));
|
||||
|
||||
assert(stha.size()==5);
|
||||
assert(costha.size()==4);
|
||||
|
||||
NT c1[13] = { NT(-81383),NT(-113448),NT(-123840),NT(-223936),NT(-272142),
|
||||
NT(-14700),NT(419954),NT(156816),NT(-247131),NT(-498636),
|
||||
NT(-275562),NT(-236196),NT(-177147) };
|
||||
PNT_1 p1(c1,c1+13);
|
||||
assert(stha[0] == p1);
|
||||
assert(stha[1] == PNT_1(NT(-828),NT(-1008),NT(-864),NT(-1728),NT(-1620),
|
||||
NT(-1944),NT(-2916)) );
|
||||
assert(stha[2] == PNT_1(NT(36)) );
|
||||
assert(stha[3] == PNT_1(NT(4)) );
|
||||
assert(stha[4] == PNT_1(NT(1)) );
|
||||
|
||||
|
||||
|
||||
assert(costha[0] == PNT_1(NT(-2742),NT(-2592),NT(-1788),NT(-2100),
|
||||
NT(-1638),NT(108),NT(1458)) );
|
||||
assert(costha[1] == PNT_1(NT(48),NT(-24),NT(-36),NT(-108)) );
|
||||
assert(costha[2] == PNT_1(NT(18)) );
|
||||
assert(costha[3] == PNT_1(NT(6)) );
|
||||
}
|
||||
{
|
||||
std::vector<PNT_1> stha,costha;
|
||||
CGAL::CGALi::bezout_first_two_sturm_habicht_coefficients
|
||||
(f,std::back_inserter(stha),
|
||||
std::back_inserter(costha));
|
||||
|
||||
assert(stha.size()==5);
|
||||
assert(costha.size()==4);
|
||||
|
||||
NT c1[13] = { NT(-81383),NT(-113448),NT(-123840),NT(-223936),NT(-272142),
|
||||
NT(-14700),NT(419954),NT(156816),NT(-247131),NT(-498636),
|
||||
NT(-275562),NT(-236196),NT(-177147) };
|
||||
PNT_1 p1(c1,c1+13);
|
||||
assert(stha[0] == p1);
|
||||
assert(stha[1] == PNT_1(NT(-828),NT(-1008),NT(-864),NT(-1728),NT(-1620),
|
||||
NT(-1944),NT(-2916)) );
|
||||
assert(stha[2] == PNT_1(NT(36)) );
|
||||
assert(stha[3] == PNT_1(NT(4)) );
|
||||
assert(stha[4] == PNT_1(NT(1)) );
|
||||
|
||||
|
||||
|
||||
assert(costha[0] == PNT_1(NT(-2742),NT(-2592),NT(-1788),NT(-2100),
|
||||
NT(-1638),NT(108),NT(1458)) );
|
||||
assert(costha[1] == PNT_1(NT(48),NT(-24),NT(-36),NT(-108)) );
|
||||
assert(costha[2] == PNT_1(NT(18)) );
|
||||
assert(costha[3] == PNT_1(NT(6)) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
#ifdef CGAL_USE_LEDA
|
||||
test_routine<CGAL::LEDA_arithmetic_kernel>();
|
||||
#else
|
||||
std::cout << "LEDA tests skipped" << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_USE_CORE
|
||||
test_routine<CGAL::CORE_arithmetic_kernel>();
|
||||
#else
|
||||
std::cout << "CORE tests skipped" << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,472 @@
|
|||
// TODO: Add licence
|
||||
//
|
||||
// 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: $
|
||||
//
|
||||
//
|
||||
// Author(s) : Michael Kerber <mkerber@mpi-inf.mpg.de>
|
||||
//
|
||||
// ============================================================================
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Polynomial/subresultants.h>
|
||||
#include <CGAL/Arithmetic_kernel.h>
|
||||
|
||||
template<typename Poly_> Poly_ from_string(const char* s) {
|
||||
std::stringstream ss(s);
|
||||
Poly_ f;
|
||||
ss >> f;
|
||||
return f;
|
||||
}
|
||||
|
||||
template<typename ArithmeticKernel>
|
||||
void test_routine() {
|
||||
typedef ArithmeticKernel Arithmetic_kernel;
|
||||
|
||||
typedef typename Arithmetic_kernel::Rational Rational;
|
||||
typedef typename Arithmetic_kernel::Integer Integer;
|
||||
|
||||
typedef CGAL::Polynomial<Integer> Poly_int1;
|
||||
typedef CGAL::Polynomial<Poly_int1> Poly_int2;
|
||||
|
||||
typedef CGAL::Polynomial<Rational> Poly_rat1;
|
||||
{
|
||||
//Example for the regular case:
|
||||
Poly_int1 f(-5,-2,3,-6,-7,3,-2,4);
|
||||
Poly_int1 g(0,-1,5,-7,5);
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Integer(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_int1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_int1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(602925),Integer(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(4474810)));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Integer(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_int1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_int1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(602925),Integer(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(4474810)));
|
||||
sres.clear();
|
||||
CGAL::CGALi::polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Integer(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_int1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_int1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(602925),Integer(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(4474810)));
|
||||
sres.clear();
|
||||
typename CGAL::Polynomial_traits_d<Poly_int1>::Polynomial_subresultants()
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Integer(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_int1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_int1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(602925),Integer(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(4474810)));
|
||||
std::vector<Integer> psres;
|
||||
CGAL::CGALi::prs_principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
CGAL::CGALi::bezout_principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
CGAL::CGALi::principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
typename CGAL::Polynomial_traits_d<Poly_int1>::Principal_subresultants()
|
||||
(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
}
|
||||
|
||||
{
|
||||
// Defective exampke
|
||||
Poly_int1 f(1,-2,0,0,0,0,1);
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,CGAL::diff(f),std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==6);
|
||||
CGAL_assertion(sres[5]==CGAL::diff(f));
|
||||
CGAL_assertion(sres[4]==Poly_int1(Integer(36),Integer(-60)));
|
||||
CGAL_assertion(sres[3]==Poly_int1(0));
|
||||
CGAL_assertion(sres[2]==Poly_int1(0));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(-36000),Integer(60000)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(-153344)));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,CGAL::diff(f),std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==6);
|
||||
CGAL_assertion(sres[5]==CGAL::diff(f));
|
||||
CGAL_assertion(sres[4]==Poly_int1(Integer(36),Integer(-60)));
|
||||
CGAL_assertion(sres[3]==Poly_int1(0));
|
||||
CGAL_assertion(sres[2]==Poly_int1(0));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(-36000),Integer(60000)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(-153344)));
|
||||
std::vector<Integer> psres;
|
||||
CGAL::CGALi::prs_principal_subresultants(f,CGAL::diff(f),
|
||||
std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==6);
|
||||
CGAL_assertion(psres[5]==6);
|
||||
CGAL_assertion(psres[4]==0);
|
||||
CGAL_assertion(psres[3]==0);
|
||||
CGAL_assertion(psres[2]==0);
|
||||
CGAL_assertion(psres[1]==60000);
|
||||
CGAL_assertion(psres[0]==-153344);
|
||||
psres.clear();
|
||||
CGAL::CGALi::bezout_principal_subresultants(f,CGAL::diff(f),
|
||||
std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==6);
|
||||
CGAL_assertion(psres[5]==6);
|
||||
CGAL_assertion(psres[4]==0);
|
||||
CGAL_assertion(psres[3]==0);
|
||||
CGAL_assertion(psres[2]==0);
|
||||
CGAL_assertion(psres[1]==60000);
|
||||
CGAL_assertion(psres[0]==-153344);
|
||||
|
||||
|
||||
}
|
||||
{
|
||||
//Example for rational values:
|
||||
Poly_rat1 f(-5,-2,3,-6,-7,3,-2,4);
|
||||
Poly_rat1 g(0,-1,5,-7,5);
|
||||
std::vector<Poly_rat1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Rational(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_rat1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_rat1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_rat1(Rational(602925),Rational(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_rat1(Rational(4474810)));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Rational(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_rat1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_rat1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_rat1(Rational(602925),Rational(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_rat1(Rational(4474810)));
|
||||
sres.clear();
|
||||
CGAL::CGALi::polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
CGAL_assertion(sres[4]==Rational(25)*g);
|
||||
CGAL_assertion(sres[3]==Poly_rat1(-3125,-1768,4970,-9451));
|
||||
CGAL_assertion(sres[2]==Poly_rat1(206535,-262340,252423));
|
||||
CGAL_assertion(sres[1]==Poly_rat1(Rational(602925),Rational(657683)));
|
||||
CGAL_assertion(sres[0]==Poly_rat1(Rational(4474810)));
|
||||
std::vector<Rational> psres;
|
||||
CGAL::CGALi::prs_principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
CGAL::CGALi::bezout_principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
CGAL::CGALi::principal_subresultants(f,g,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==5);
|
||||
CGAL_assertion(psres[4]==125);
|
||||
CGAL_assertion(psres[3]==-9451);
|
||||
CGAL_assertion(psres[2]==252423);
|
||||
CGAL_assertion(psres[1]==657683);
|
||||
CGAL_assertion(psres[0]==4474810);
|
||||
psres.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// Another test included on 10 Jan 2007 - situation comes from arrangement
|
||||
// computation of curves:
|
||||
|
||||
// f:=y^4 + (x)*y^2 + (2*x^4 + (-1)*x^3);
|
||||
Poly_int2 f=from_string<Poly_int2>("P[4(0,P[4(3,-1)(4,2)])(2,P[1(1,1)])(4,P[0(0,1)])]");
|
||||
// g:=g:=eval(10000*f,[y=2*y,x=x-1/10]);
|
||||
Poly_int2 g=from_string<Poly_int2>("P[4(0,P[4(0,12)(1,-380)(2,4200)(3,-18000)(4,20000)])(2,P[1(0,-4000)(1,40000)])(4,P[0(0,160000)])]");
|
||||
std::vector<Poly_int2> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
// Computed with MAPLE
|
||||
CGAL_assertion(sres[4]==g);
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int2>("P[2(0,P[4(0,12)(1,-380)(2,4200)(3,142000)(4,-300000)])(2,P[1(0,-4000)(1,-120000)])]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int2>("P[2(0,P[5(0,-48000)(1,80000)(2,28800000)(3,-1072000000)(4,-15840000000)(5,36000000000)])(2,P[2(0,16000000)(1,960000000)(2,14400000000)])]"));
|
||||
CGAL_assertion(sres[1]==from_string<Poly_int2>("P[0(0,P[9(0,576000)(1,172800000)(2,5326400000)(3,-158512000000)(4,-5164000000000)(5,24705600000000)(6,615472000000000)(7,912480000000000)(8,-9864000000000000)(9,10800000000000000)])]"));
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int2>("P[0(0,P[16(0,20736)(1,11197440)(2,1559232000)(3,5760000)(4,-3426163040000)(5,-9736288000000)(6,2377866144000000)(7,-1780931200000000)(8,-427278798400000000)(9,-507616640000000000)(10,31454608000000000000)(11,83909222400000000000)(12,-697197584000000000000)(13,-919113600000000000000)(14,9138960000000000000000)(15,-15336000000000000000000)(16,8100000000000000000000)])]"));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
// Computed with MAPLE
|
||||
CGAL_assertion(sres[4]==g);
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int2>("P[2(0,P[4(0,12)(1,-380)(2,4200)(3,142000)(4,-300000)])(2,P[1(0,-4000)(1,-120000)])]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int2>("P[2(0,P[5(0,-48000)(1,80000)(2,28800000)(3,-1072000000)(4,-15840000000)(5,36000000000)])(2,P[2(0,16000000)(1,960000000)(2,14400000000)])]"));
|
||||
CGAL_assertion(sres[1]==from_string<Poly_int2>("P[0(0,P[9(0,576000)(1,172800000)(2,5326400000)(3,-158512000000)(4,-5164000000000)(5,24705600000000)(6,615472000000000)(7,912480000000000)(8,-9864000000000000)(9,10800000000000000)])]"));
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int2>("P[0(0,P[16(0,20736)(1,11197440)(2,1559232000)(3,5760000)(4,-3426163040000)(5,-9736288000000)(6,2377866144000000)(7,-1780931200000000)(8,-427278798400000000)(9,-507616640000000000)(10,31454608000000000000)(11,83909222400000000000)(12,-697197584000000000000)(13,-919113600000000000000)(14,9138960000000000000000)(15,-15336000000000000000000)(16,8100000000000000000000)])]"));
|
||||
sres.clear();
|
||||
CGAL::CGALi::polynomial_subresultants(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==5);
|
||||
// Computed with MAPLE
|
||||
CGAL_assertion(sres[4]==g);
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int2>("P[2(0,P[4(0,12)(1,-380)(2,4200)(3,142000)(4,-300000)])(2,P[1(0,-4000)(1,-120000)])]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int2>("P[2(0,P[5(0,-48000)(1,80000)(2,28800000)(3,-1072000000)(4,-15840000000)(5,36000000000)])(2,P[2(0,16000000)(1,960000000)(2,14400000000)])]"));
|
||||
CGAL_assertion(sres[1]==from_string<Poly_int2>("P[0(0,P[9(0,576000)(1,172800000)(2,5326400000)(3,-158512000000)(4,-5164000000000)(5,24705600000000)(6,615472000000000)(7,912480000000000)(8,-9864000000000000)(9,10800000000000000)])]"));
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int2>("P[0(0,P[16(0,20736)(1,11197440)(2,1559232000)(3,5760000)(4,-3426163040000)(5,-9736288000000)(6,2377866144000000)(7,-1780931200000000)(8,-427278798400000000)(9,-507616640000000000)(10,31454608000000000000)(11,83909222400000000000)(12,-697197584000000000000)(13,-919113600000000000000)(14,9138960000000000000000)(15,-15336000000000000000000)(16,8100000000000000000000)])]"));
|
||||
}
|
||||
|
||||
{ // Test for f.degree() < g.degree()
|
||||
Poly_int1 f = from_string<Poly_int1>("P[10(2,-4)(3,-73)(6,97)(7,-62)(10,-56)]");
|
||||
Poly_int1 g = from_string<Poly_int1>("P[15(5,-75)(6,-17)(8,71)(11,-44)(14,80)(15,-82)]");
|
||||
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==11);
|
||||
CGAL_assertion(sres[10]==from_string<Poly_int1>("P[10(2,-39337984)(3,-717918208)(6,953946112)(7,-609738752)(10,-550731776)]"));
|
||||
CGAL_assertion(sres[9]==from_string<Poly_int1>("P[9(2,-305262755840)(3,-4966105776128)(4,10840151891968)(5,-5962969628672)(6,6702091010048)(7,-22436989575168)(8,19712814514176)(9,-3099911815168)]"));
|
||||
CGAL_assertion(sres[8]==from_string<Poly_int1>("P[8(2,9680208765108224)(3,156728928112275456)(4,-360058057701515264)(5,152421565222248448)(6,-176106510157656064)(7,746064242175737856)(8,-579306262853885952)]"));
|
||||
CGAL_assertion(sres[7]==from_string<Poly_int1>("P[7(2,-1486764415342623952896)(3,-26708453688140199103488)(4,8054371431842323176960)(5,3491478546579489027072)(6,38677404054075120663552)(7,-43611415672712033527296)]"));
|
||||
CGAL_assertion(sres[6]==from_string<Poly_int1>("P[6(2,9979660953345863413381568)(3,193906324691706110661441648)(4,213219021894852075965695648)(5,362883385829743140658019008)(6,-93331232763027671680558576)]"));
|
||||
CGAL_assertion(sres[5]==from_string<Poly_int1>("P[5(2,-70907443741718133356344565824)(3,-1389117178389007568663227054224)(4,-1747565962047585993090805107776)(5,-2771071359404167222865326731904)]"));
|
||||
CGAL_assertion(sres[4]==from_string<Poly_int1>("P[4(2,-715876861001937085090535662991104)(3,-13330409138559036348802401660667328)(4,-5258395198219675575175450753910144)]"));
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int1>("P[3(2,-2842398393513781389004679512270277696)(3,-51817649494648561412362002061296745104)]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int1>("P[2(2,-46088453959546967380998470482217286656)]"));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(0)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(0)));
|
||||
sres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==11);
|
||||
CGAL_assertion(sres[10]==from_string<Poly_int1>("P[10(2,-39337984)(3,-717918208)(6,953946112)(7,-609738752)(10,-550731776)]"));
|
||||
CGAL_assertion(sres[9]==from_string<Poly_int1>("P[9(2,-305262755840)(3,-4966105776128)(4,10840151891968)(5,-5962969628672)(6,6702091010048)(7,-22436989575168)(8,19712814514176)(9,-3099911815168)]"));
|
||||
CGAL_assertion(sres[8]==from_string<Poly_int1>("P[8(2,9680208765108224)(3,156728928112275456)(4,-360058057701515264)(5,152421565222248448)(6,-176106510157656064)(7,746064242175737856)(8,-579306262853885952)]"));
|
||||
CGAL_assertion(sres[7]==from_string<Poly_int1>("P[7(2,-1486764415342623952896)(3,-26708453688140199103488)(4,8054371431842323176960)(5,3491478546579489027072)(6,38677404054075120663552)(7,-43611415672712033527296)]"));
|
||||
CGAL_assertion(sres[6]==from_string<Poly_int1>("P[6(2,9979660953345863413381568)(3,193906324691706110661441648)(4,213219021894852075965695648)(5,362883385829743140658019008)(6,-93331232763027671680558576)]"));
|
||||
CGAL_assertion(sres[5]==from_string<Poly_int1>("P[5(2,-70907443741718133356344565824)(3,-1389117178389007568663227054224)(4,-1747565962047585993090805107776)(5,-2771071359404167222865326731904)]"));
|
||||
CGAL_assertion(sres[4]==from_string<Poly_int1>("P[4(2,-715876861001937085090535662991104)(3,-13330409138559036348802401660667328)(4,-5258395198219675575175450753910144)]"));
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int1>("P[3(2,-2842398393513781389004679512270277696)(3,-51817649494648561412362002061296745104)]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int1>("P[2(2,-46088453959546967380998470482217286656)]"));
|
||||
CGAL_assertion(sres[1]==Poly_int1(Integer(0)));
|
||||
CGAL_assertion(sres[0]==Poly_int1(Integer(0)));
|
||||
sres.clear();
|
||||
}
|
||||
{ // Another example where sign switches are necessary
|
||||
Poly_int1 f = from_string<Poly_int1>("P[3(0,42)(1,-40)(2,-7)(3,-10)]");
|
||||
Poly_int1 g = from_string<Poly_int1>("P[5(0,74)(1,6)(2,-92)(3,75)(4,23)(5,-50)]");
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==4);
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int1>("P[3(0,-420)(1,400)(2,70)(3,100)]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int1>("P[2(0,-1058480)(1,688000)(2,698080)]"));
|
||||
CGAL_assertion(sres[1]==from_string<Poly_int1>("P[1(0,-22577275200)(1,28253151360)]"));
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int1>("P[0(0,-103066942158720)]"));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==4);
|
||||
CGAL_assertion(sres[3]==from_string<Poly_int1>("P[3(0,-420)(1,400)(2,70)(3,100)]"));
|
||||
CGAL_assertion(sres[2]==from_string<Poly_int1>("P[2(0,-1058480)(1,688000)(2,698080)]"));
|
||||
CGAL_assertion(sres[1]==from_string<Poly_int1>("P[1(0,-22577275200)(1,28253151360)]"));
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int1>("P[0(0,-103066942158720)]"));
|
||||
}
|
||||
{ // Test cases with constant polynomials
|
||||
{
|
||||
Poly_int1 f(Integer(8));
|
||||
Poly_int1 g=from_string<Poly_int1>("P[3(0,43)(1,40)(2,-19)(3,2)]");
|
||||
std::vector<Poly_int1> sres;
|
||||
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].degree()==0);
|
||||
CGAL_assertion(sres[0][0]==Integer(8*8*8));
|
||||
sres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].degree()==0);
|
||||
CGAL_assertion(sres[0][0]==Integer(8*8*8));
|
||||
std::vector<Integer> psres;
|
||||
|
||||
CGAL::CGALi::prs_principal_subresultants
|
||||
(g,f,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==1);
|
||||
CGAL_assertion(psres[0]==Integer(8*8*8));
|
||||
psres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_principal_subresultants
|
||||
(g,f,std::back_inserter(psres));
|
||||
CGAL_assertion(psres.size()==1);
|
||||
CGAL_assertion(psres[0]==Integer(8*8*8));
|
||||
}
|
||||
{
|
||||
Poly_int1 f(Integer(0));
|
||||
Poly_int1 g=from_string<Poly_int1>("P[1(0,1)(1,1)]");
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].is_zero());
|
||||
sres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].is_zero());
|
||||
}
|
||||
{
|
||||
Poly_int1 f(Integer(7));
|
||||
Poly_int1 g(Integer(-12));
|
||||
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_principal_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0]==Integer(1));
|
||||
sres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_principal_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0]==Integer(1));
|
||||
}
|
||||
{
|
||||
Poly_int2 f=from_string<Poly_int2>("P[0(0,P[0(0,122)])]");
|
||||
Poly_int2 g=from_string<Poly_int2>("P[0(0,P[0(0,0)])]");
|
||||
std::vector<Poly_int2> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].is_zero());
|
||||
sres.clear();
|
||||
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==1);
|
||||
CGAL_assertion(sres[0].is_zero());
|
||||
}
|
||||
|
||||
}
|
||||
{ // Test for two linear polynomials:
|
||||
Poly_int1 f = from_string<Poly_int1>("P[1(0,-5)(1,6)]");
|
||||
Poly_int1 g = from_string<Poly_int1>("P[1(0,-3)(1,4)]");
|
||||
std::vector<Poly_int1> sres;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==2);
|
||||
CGAL_assertion(sres[1]==g);
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int1>("P[0(0,2)]"));
|
||||
sres.clear();
|
||||
CGAL::CGALi::bezout_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres));
|
||||
CGAL_assertion(sres.size()==2);
|
||||
CGAL_assertion(sres[1]==g);
|
||||
CGAL_assertion(sres[0]==from_string<Poly_int1>("P[0(0,2)]"));
|
||||
}
|
||||
{ // Test for cofactors, univariate
|
||||
Poly_int1 f = from_string<Poly_int1>("P[6(0,246)(1,100)(2,197)(3,14)(4,136)(5,191)(6,207)]");
|
||||
Poly_int1 g = from_string<Poly_int1>("P[5(0,100)(1,394)(2,42)(3,544)(4,955)(5,1242)]");
|
||||
std::vector<Poly_int1> sres_check,sres,coP,coQ;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres_check));
|
||||
CGAL::CGALi::prs_subresultants_with_cofactors
|
||||
(f,g,
|
||||
std::back_inserter(sres),
|
||||
std::back_inserter(coP),
|
||||
std::back_inserter(coQ));
|
||||
CGAL_assertion(sres.size()==sres_check.size());
|
||||
CGAL_assertion(sres.size()==coP.size());
|
||||
CGAL_assertion(sres.size()==coQ.size());
|
||||
for(int i=0;i < static_cast<int>(sres.size()); i++) {
|
||||
CGAL_assertion(sres[i]==sres_check[i]);
|
||||
CGAL_assertion(sres[i]==coP[i]*f + coQ[i]*g);
|
||||
}
|
||||
}
|
||||
{ // Test for trivariate
|
||||
typedef CGAL::Polynomial<Poly_int2> Poly_int3;
|
||||
Poly_int3 f = from_string<Poly_int3>("P[6(0,P[6(0,P[6(2,3)(4,-3)(6,1)])(1,P[1(1,-2)])(2,P[4(0,3)(2,-5)(4,3)])(4,P[2(0,-3)(2,3)])(6,P[0(0,1)])])(3,P[1(0,P[0(0,2)])(1,P[1(1,-2)])])(6,P[0(0,P[0(0,1)])])]");
|
||||
Poly_int3 g = CGAL::diff(f);
|
||||
std::vector<Poly_int3> sres_check,sres,coP,coQ;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres_check));
|
||||
CGAL::CGALi::prs_subresultants_with_cofactors
|
||||
(f,g,
|
||||
std::back_inserter(sres),
|
||||
std::back_inserter(coP),
|
||||
std::back_inserter(coQ));
|
||||
CGAL_assertion(sres.size()==sres_check.size());
|
||||
CGAL_assertion(sres.size()==coP.size());
|
||||
CGAL_assertion(sres.size()==coQ.size());
|
||||
for(int i=0;i < static_cast<int>(sres.size()); i++) {
|
||||
CGAL_assertion(sres[i]==sres_check[i]);
|
||||
CGAL_assertion(sres[i]==coP[i]*f + coQ[i]*g);
|
||||
}
|
||||
}
|
||||
{ // Test for cofactors, bivariate
|
||||
Poly_int2 f = from_string<Poly_int2>("P[7(0,P[7(0,72)(1,113)(2,238)(3,75)(4,77)(5,149)(6,34)(7,75)])(1,P[6(0,113)(1,69)(2,94)(3,171)(4,148)(5,103)(6,42)])(2,P[5(0,103)(1,233)(2,16)(3,131)(4,2)(5,156)])(3,P[4(0,249)(1,194)(2,156)(3,81)(4,176)])(4,P[3(0,39)(1,140)(2,134)(3,190)])(5,P[2(0,117)(1,249)(2,158)])(6,P[1(0,109)(1,46)])(7,P[0(0,236)])]");
|
||||
Poly_int2 g = from_string<Poly_int2>("P[6(0,P[6(0,113)(1,69)(2,94)(3,171)(4,148)(5,103)(6,42)])(1,P[5(0,206)(1,466)(2,32)(3,262)(4,4)(5,312)])(2,P[4(0,747)(1,582)(2,468)(3,243)(4,528)])(3,P[3(0,156)(1,560)(2,536)(3,760)])(4,P[2(0,585)(1,1245)(2,790)])(5,P[1(0,654)(1,276)])(6,P[0(0,1652)])]");
|
||||
std::vector<Poly_int2> sres_check,sres,coP,coQ;
|
||||
CGAL::CGALi::prs_polynomial_subresultants
|
||||
(f,g,std::back_inserter(sres_check));
|
||||
CGAL::CGALi::prs_subresultants_with_cofactors
|
||||
(f,g,
|
||||
std::back_inserter(sres),
|
||||
std::back_inserter(coP),
|
||||
std::back_inserter(coQ));
|
||||
CGAL_assertion(sres.size()==sres_check.size());
|
||||
CGAL_assertion(sres.size()==coP.size());
|
||||
CGAL_assertion(sres.size()==coQ.size());
|
||||
for(int i=0;i < static_cast<int>(sres.size()); i++) {
|
||||
CGAL_assertion(sres[i]==sres_check[i]);
|
||||
CGAL_assertion(sres[i]==coP[i]*f + coQ[i]*g);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int main(){
|
||||
|
||||
#ifdef CGAL_USE_LEDA
|
||||
test_routine<CGAL::LEDA_arithmetic_kernel>();
|
||||
#else
|
||||
std::cerr << "LEDA tests skipped!" << std::endl;
|
||||
#endif
|
||||
#ifdef CGAL_USE_CORE
|
||||
test_routine<CGAL::CORE_arithmetic_kernel>();
|
||||
#else
|
||||
std::cerr << "CORE tests skipped!" << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue