1964 lines
68 KiB
C
1964 lines
68 KiB
C
|
// Copyright (c) 2000 Max-Planck-Institute Saarbruecken (Germany).
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// This file is part of CGAL (www.cgal.org)
|
||
|
//
|
||
|
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Nef_2/include/CGAL/Nef_2/Polynomial.h $
|
||
|
// $Id: Polynomial.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
|
||
|
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||
|
//
|
||
|
//
|
||
|
// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
|
||
|
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||
|
|
||
|
#ifndef CGAL_NEF_2_POLYNOMIAL_H
|
||
|
#define CGAL_NEF_2_POLYNOMIAL_H
|
||
|
|
||
|
#include <CGAL/basic.h>
|
||
|
#include <CGAL/kernel_assertions.h>
|
||
|
#include <CGAL/Handle_for.h>
|
||
|
#include <CGAL/number_type_basic.h>
|
||
|
#include <CGAL/number_utils.h>
|
||
|
#include <CGAL/IO/io.h>
|
||
|
#include <cstddef>
|
||
|
#undef CGAL_NEF_DEBUG
|
||
|
#define CGAL_NEF_DEBUG 3
|
||
|
#include <CGAL/Nef_2/debug.h>
|
||
|
#include <vector>
|
||
|
|
||
|
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
namespace Nef {
|
||
|
|
||
|
template <class NT> class Polynomial_rep;
|
||
|
|
||
|
// SPECIALIZE_CLASS(NT,int double) START
|
||
|
// CLASS TEMPLATE NT:
|
||
|
template <class NT> class Polynomial;
|
||
|
// CLASS TEMPLATE int:
|
||
|
template <> class Polynomial<int> ;
|
||
|
// CLASS TEMPLATE double:
|
||
|
template <> class Polynomial<double> ;
|
||
|
// SPECIALIZE_CLASS(NT,int double) END
|
||
|
|
||
|
|
||
|
|
||
|
/*{\Mtext \headerline{Range template}}*/
|
||
|
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
typename std::iterator_traits<Forward_iterator>::value_type
|
||
|
gcd_of_range(Forward_iterator its, Forward_iterator ite, Unique_factorization_domain_tag)
|
||
|
/*{\Mfunc calculates the greates common divisor of the
|
||
|
set of numbers $\{ |*its|, |*++its|, \ldots, |*it| \}$ of type |NT|,
|
||
|
where |++it == ite| and |NT| is the value type of |Forward_iterator|.
|
||
|
\precond there exists a pairwise gcd operation |NT gcd(NT,NT)| and
|
||
|
|its!=ite|.}*/
|
||
|
{ CGAL_assertion(its!=ite);
|
||
|
typedef typename std::iterator_traits<Forward_iterator>::value_type NT;
|
||
|
NT res = *its++;
|
||
|
for(; its!=ite; ++its) res =
|
||
|
(*its==0 ? res : CGAL_NTS gcd(res, *its));
|
||
|
if (res==0) res = 1;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
typename std::iterator_traits<Forward_iterator>::value_type
|
||
|
gcd_of_range(Forward_iterator its, Forward_iterator ite, Integral_domain_without_division_tag)
|
||
|
/*{\Mfunc calculates the greates common divisor of the
|
||
|
set of numbers $\{ |*its|, |*++its|, \ldots, |*it| \}$ of type |NT|,
|
||
|
where |++it == ite| and |NT| is the value type of |Forward_iterator|.
|
||
|
\precond |its!=ite|.}*/
|
||
|
{ CGAL_assertion(its!=ite);
|
||
|
typedef typename std::iterator_traits<Forward_iterator>::value_type NT;
|
||
|
NT res = *its++;
|
||
|
for(; its!=ite; ++its) res =
|
||
|
(*its==0 ? res : 1);
|
||
|
if (res==0) res = 1;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
typename std::iterator_traits<Forward_iterator>::value_type
|
||
|
gcd_of_range(Forward_iterator its, Forward_iterator ite)
|
||
|
{
|
||
|
|
||
|
typedef typename std::iterator_traits<Forward_iterator>::value_type NT;
|
||
|
typedef CGAL::Algebraic_structure_traits<NT> AST;
|
||
|
return gcd_of_range(its,ite,typename AST::Algebraic_category());
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT> inline Polynomial<NT>
|
||
|
operator - (const Polynomial<NT>&);
|
||
|
template <class NT> Polynomial<NT>
|
||
|
operator + (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
template <class NT> Polynomial<NT>
|
||
|
operator - (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
template <class NT> Polynomial<NT>
|
||
|
operator * (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
template <class NT> Polynomial<NT>
|
||
|
operator / (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
template <class NT> Polynomial<NT>
|
||
|
operator % (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
|
||
|
template<class NT> CGAL::Sign
|
||
|
sign(const Polynomial<NT>& p);
|
||
|
|
||
|
template <class NT> double
|
||
|
to_double(const Polynomial<NT>& p) ;
|
||
|
template <class NT> bool
|
||
|
is_valid(const Polynomial<NT>& p) ;
|
||
|
template <class NT> bool
|
||
|
is_finite(const Polynomial<NT>& p) ;
|
||
|
|
||
|
template<class NT>
|
||
|
std::ostream& operator << (std::ostream& os, const Polynomial<NT>& p);
|
||
|
template <class NT>
|
||
|
std::istream& operator >> (std::istream& is, Polynomial<NT>& p);
|
||
|
|
||
|
|
||
|
// lefthand side
|
||
|
template<class NT> inline Polynomial<NT> operator +
|
||
|
(const NT& num, const Polynomial<NT>& p2);
|
||
|
template<class NT> inline Polynomial<NT> operator -
|
||
|
(const NT& num, const Polynomial<NT>& p2);
|
||
|
template<class NT> inline Polynomial<NT> operator *
|
||
|
(const NT& num, const Polynomial<NT>& p2);
|
||
|
template<class NT> inline Polynomial<NT> operator /
|
||
|
(const NT& num, const Polynomial<NT>& p2);
|
||
|
template<class NT> inline Polynomial<NT> operator %
|
||
|
(const NT& num, const Polynomial<NT>& p2);
|
||
|
|
||
|
// righthand side
|
||
|
template<class NT> inline Polynomial<NT> operator +
|
||
|
(const Polynomial<NT>& p1, const NT& num);
|
||
|
template<class NT> inline Polynomial<NT> operator -
|
||
|
(const Polynomial<NT>& p1, const NT& num);
|
||
|
template<class NT> inline Polynomial<NT> operator *
|
||
|
(const Polynomial<NT>& p1, const NT& num);
|
||
|
template<class NT> inline Polynomial<NT> operator /
|
||
|
(const Polynomial<NT>& p1, const NT& num);
|
||
|
template<class NT> inline Polynomial<NT> operator %
|
||
|
(const Polynomial<NT>& p1, const NT& num);
|
||
|
|
||
|
|
||
|
// lefthand side
|
||
|
template<class NT> inline bool operator ==
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
template<class NT> inline bool operator !=
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
template<class NT> inline bool operator <
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
template<class NT> inline bool operator <=
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
template<class NT> inline bool operator >
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
template<class NT> inline bool operator >=
|
||
|
(const NT& num, const Polynomial<NT>& p);
|
||
|
|
||
|
// righthand side
|
||
|
template<class NT> inline bool operator ==
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
template<class NT> inline bool operator !=
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
template<class NT> inline bool operator <
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
template<class NT> inline bool operator <=
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
template<class NT> inline bool operator >
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
template<class NT> inline bool operator >=
|
||
|
(const Polynomial<NT>& p, const NT& num);
|
||
|
|
||
|
|
||
|
|
||
|
template <class pNT> class Polynomial_rep {
|
||
|
typedef pNT NT;
|
||
|
|
||
|
typedef std::vector<NT> Vector;
|
||
|
|
||
|
|
||
|
typedef typename Vector::size_type size_type;
|
||
|
typedef typename Vector::iterator iterator;
|
||
|
typedef typename Vector::const_iterator const_iterator;
|
||
|
Vector coeff;
|
||
|
|
||
|
Polynomial_rep() : coeff(0) {}
|
||
|
Polynomial_rep(const NT& n) : coeff(1) { coeff[0]=n; }
|
||
|
Polynomial_rep(const NT& n, const NT& m) : coeff(2)
|
||
|
{ coeff[0]=n; coeff[1]=m; }
|
||
|
Polynomial_rep(const NT& a, const NT& b, const NT& c) : coeff(3)
|
||
|
{ coeff[0]=a; coeff[1]=b; coeff[2]=c; }
|
||
|
Polynomial_rep(size_type s) : coeff(s,NT(0)) {}
|
||
|
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
Polynomial_rep(std::pair<Forward_iterator,Forward_iterator> poly)
|
||
|
: coeff(poly.first,poly.second) {}
|
||
|
|
||
|
|
||
|
void reduce()
|
||
|
{ while ( coeff.size()>1 && coeff.back()==NT(0) ) coeff.pop_back(); }
|
||
|
|
||
|
friend class Polynomial<pNT>;
|
||
|
friend class Polynomial<int>;
|
||
|
friend class Polynomial<double>;
|
||
|
friend std::istream& operator >> <> (std::istream&, Polynomial<NT>&);
|
||
|
|
||
|
};
|
||
|
|
||
|
// SPECIALIZE_CLASS(NT,int double) START
|
||
|
// CLASS TEMPLATE NT:
|
||
|
/*{\Msubst
|
||
|
typename iterator_traits<Forward_iterator>::value_type#NT
|
||
|
<>#
|
||
|
}*/
|
||
|
|
||
|
/*{\Manpage{Polynomial}{NT}{Polynomials in one variable}{p}}*/
|
||
|
|
||
|
template <class pNT> class Polynomial :
|
||
|
public Handle_for< Polynomial_rep<pNT> >
|
||
|
{
|
||
|
/* {\Mdefinition An instance |\Mvar| of the data type |\Mname| represents
|
||
|
a polynomial $p = a_0 + a_1 x + \ldots a_d x^d $ from the ring |NT[x]|.
|
||
|
The data type offers standard ring operations and a sign operation which
|
||
|
determines the sign for the limit process $x \rightarrow \infty$.
|
||
|
|
||
|
|NT[x]| becomes a unique factorization domain, if the number type
|
||
|
|NT| is either a field type (1) or a unique factorization domain
|
||
|
(2). In both cases there's a polynomial division operation defined.}
|
||
|
*/
|
||
|
|
||
|
/*{\Mtypes 5}*/
|
||
|
public:
|
||
|
typedef pNT NT;
|
||
|
|
||
|
typedef Handle_for< Polynomial_rep<NT> > Base;
|
||
|
typedef Polynomial_rep<NT> Rep;
|
||
|
typedef typename Rep::Vector Vector;
|
||
|
typedef typename Rep::size_type size_type;
|
||
|
typedef typename Rep::iterator iterator;
|
||
|
|
||
|
typedef typename Rep::const_iterator const_iterator;
|
||
|
/*{\Mtypemember a random access iterator for read-only access to the
|
||
|
coefficient vector.}*/
|
||
|
|
||
|
//protected:
|
||
|
void reduce() { this->ptr()->reduce(); }
|
||
|
Vector& coeffs() { return this->ptr()->coeff; }
|
||
|
const Vector& coeffs() const { return this->ptr()->coeff; }
|
||
|
Polynomial(size_type s) : Base( Polynomial_rep<NT>(s) ) {}
|
||
|
// creates a polynomial of degree s-1
|
||
|
|
||
|
|
||
|
/*{\Mcreation 3}*/
|
||
|
public:
|
||
|
|
||
|
Polynomial()
|
||
|
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| of undefined
|
||
|
value. }*/
|
||
|
: Base( Polynomial_rep<NT>() ) {}
|
||
|
|
||
|
Polynomial(const NT& a0)
|
||
|
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the constant polynomial $a_0$.}*/
|
||
|
: Base(Polynomial_rep<NT>(a0)) { reduce(); }
|
||
|
|
||
|
Polynomial(NT a0, NT a1)
|
||
|
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x$. }*/
|
||
|
: Base(Polynomial_rep<NT>(a0,a1)) { reduce(); }
|
||
|
|
||
|
Polynomial(const NT& a0, const NT& a1,const NT& a2)
|
||
|
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x + a_2 x^2$. }*/
|
||
|
: Base(Polynomial_rep<NT>(a0,a1,a2)) { reduce(); }
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
Polynomial(std::pair<Forward_iterator, Forward_iterator> poly)
|
||
|
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial whose coefficients are determined by the iterator range,
|
||
|
i.e. let $(a_0 = |*first|, a_1 = |*++first|, \ldots a_d = |*it|)$,
|
||
|
where |++it == last| then |\Mvar| stores the polynomial $a_1 + a_2 x +
|
||
|
\ldots a_d x^d$.}*/
|
||
|
: Base(Polynomial_rep<NT>(poly)) { reduce(); }
|
||
|
|
||
|
|
||
|
// KILL double START
|
||
|
Polynomial(double n) : Base(Polynomial_rep<NT>(NT(n))) { reduce(); }
|
||
|
Polynomial(double n1, double n2)
|
||
|
: Base(Polynomial_rep<NT>(NT(n1),NT(n2))) { reduce(); }
|
||
|
// KILL double END
|
||
|
|
||
|
// KILL int START
|
||
|
Polynomial(int n) : Base(Polynomial_rep<NT>(NT(n))) { reduce(); }
|
||
|
Polynomial(int n1, int n2)
|
||
|
: Base(Polynomial_rep<NT>(NT(n1),NT(n2))) { reduce(); }
|
||
|
// KILL int END
|
||
|
|
||
|
//protected: // accessing coefficients internally:
|
||
|
NT& coeff(unsigned int i)
|
||
|
{ CGAL_assertion(!this->is_shared() && i<(this->ptr()->coeff.size()));
|
||
|
return this->ptr()->coeff[i];
|
||
|
}
|
||
|
public:
|
||
|
|
||
|
/*{\Moperations 3 3 }*/
|
||
|
const_iterator begin() const { return this->ptr()->coeff.begin(); }
|
||
|
/*{\Mop a random access iterator pointing to $a_0$.}*/
|
||
|
const_iterator end() const { return this->ptr()->coeff.end(); }
|
||
|
/*{\Mop a random access iterator pointing beyond $a_d$.}*/
|
||
|
|
||
|
int degree() const
|
||
|
{ return static_cast<int>(this->ptr()->coeff.size())-1; }
|
||
|
/*{\Mop the degree of the polynomial.}*/
|
||
|
|
||
|
const NT& operator[](unsigned int i) const
|
||
|
{ CGAL_assertion( i<(this->ptr()->coeff.size()) );
|
||
|
return this->ptr()->coeff[i]; }
|
||
|
//{\Marrop the coefficient $a_i$ of the polynomial.}
|
||
|
|
||
|
NT operator()(unsigned int i) const
|
||
|
{
|
||
|
if(i<(this->ptr()->coeff.size()))
|
||
|
return this->ptr()->coeff[i];
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
NT eval_at(const NT& r) const
|
||
|
/*{\Mop evaluates the polynomial at |r|.}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
NT res = this->ptr()->coeff[0], x = r;
|
||
|
for(int i=1; i<=degree(); ++i)
|
||
|
{ res += this->ptr()->coeff[i]*x; x*=r; }
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
CGAL::Sign sign() const
|
||
|
/*{\Mop returns the sign of the limit process for $x \rightarrow \infty$
|
||
|
(the sign of the leading coefficient).}*/
|
||
|
{ const NT& leading_coeff = this->ptr()->coeff.back();
|
||
|
if (degree() < 0) return CGAL::ZERO;
|
||
|
if (leading_coeff < NT(0)) return (CGAL::NEGATIVE);
|
||
|
if (leading_coeff > NT(0)) return (CGAL::POSITIVE);
|
||
|
return CGAL::ZERO;
|
||
|
}
|
||
|
|
||
|
bool is_zero() const
|
||
|
/*{\Mop returns true iff |\Mvar| is the zero polynomial.}*/
|
||
|
{ return degree()==0 && this->ptr()->coeff[0]==NT(0); }
|
||
|
|
||
|
Polynomial<NT> abs() const
|
||
|
/*{\Mop returns |-\Mvar| if |\Mvar.sign()==NEGATIVE| and |\Mvar|
|
||
|
otherwise.}*/
|
||
|
{ return ( sign()==CGAL::NEGATIVE ) ? - *this : *this; }
|
||
|
|
||
|
|
||
|
NT content() const
|
||
|
/*{\Mop returns the content of |\Mvar| (the gcd of its coefficients).}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
return gcd_of_range(this->ptr()->coeff.begin(),this->ptr()->coeff.end());
|
||
|
}
|
||
|
|
||
|
|
||
|
/*{\Mtext Additionally |\Mname| offers standard arithmetic ring
|
||
|
opertions like |+,-,*,+=,-=,*=|. By means of the sign operation we can
|
||
|
also offer comparison predicates as $<,>,\leq,\geq$. Where $p_1 < p_2$
|
||
|
holds iff $|sign|(p_1 - p_2) < 0$. This data type is fully compliant
|
||
|
to the requirements of CGAL number types. \setopdims{3cm}{2cm}}*/
|
||
|
|
||
|
friend Polynomial<NT>
|
||
|
operator - <> (const Polynomial<NT>&);
|
||
|
|
||
|
friend Polynomial<NT>
|
||
|
operator + <> (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
|
||
|
friend Polynomial<NT>
|
||
|
operator - <> (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
|
||
|
friend Polynomial<NT>
|
||
|
operator * <> (const Polynomial<NT>&, const Polynomial<NT>&);
|
||
|
|
||
|
friend
|
||
|
Polynomial<NT> operator / <>
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2);
|
||
|
|
||
|
/*{\Mbinopfunc implements polynomial division of |p1| and |p2|. if
|
||
|
|p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3|
|
||
|
does not exist in |NT[x]|. The correct division algorithm is chosen
|
||
|
according to a number type traits class.
|
||
|
If |Number_type_traits<NT>::Has_gcd == Tag_true| then the division is
|
||
|
done by \emph{pseudo division} based on a |gcd| operation of |NT|. If
|
||
|
|Number_type_traits<NT>::Has_gcd == Tag_false| then the division is done
|
||
|
by \emph{euclidean division} based on the division operation of the
|
||
|
field |NT|.
|
||
|
|
||
|
\textbf{Note} that |NT=int| quickly leads to overflow
|
||
|
errors when using this operation.}*/
|
||
|
|
||
|
/*{\Mtext \headerline{Static member functions}}*/
|
||
|
|
||
|
static Polynomial<NT> gcd
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2);
|
||
|
/*{\Mstatic returns the greatest common divisor of |p1| and |p2|.
|
||
|
\textbf{Note} that |NT=int| quickly leads to overflow errors when
|
||
|
using this operation. \precond Requires |NT| to be a unique
|
||
|
factorization domain, i.e. to provide a |gcd| operation.}*/
|
||
|
|
||
|
static void pseudo_div
|
||
|
(const Polynomial<NT>& f, const Polynomial<NT>& g,
|
||
|
Polynomial<NT>& q, Polynomial<NT>& r, NT& D);
|
||
|
/*{\Mstatic implements division with remainder on polynomials of
|
||
|
the ring |NT[x]|: $D*f = g*q + r$. \precond |NT| is a unique
|
||
|
factorization domain, i.e., there exists a |gcd| operation and an
|
||
|
integral division operation on |NT|.}*/
|
||
|
|
||
|
static void euclidean_div
|
||
|
(const Polynomial<NT>& f, const Polynomial<NT>& g,
|
||
|
Polynomial<NT>& q, Polynomial<NT>& r);
|
||
|
/*{\Mstatic implements division with remainder on polynomials of
|
||
|
the ring |NT[x]|: $f = g*q + r$. \precond |NT| is a field, i.e.,
|
||
|
there exists a division operation on |NT|. }*/
|
||
|
|
||
|
friend double to_double <> (const Polynomial<NT>& p);
|
||
|
|
||
|
|
||
|
Polynomial<NT>& operator += (const Polynomial<NT>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) += p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<NT>& operator -= (const Polynomial<NT>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) -= p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(-p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<NT>& operator *= (const Polynomial<NT>& p1)
|
||
|
{ (*this)=(*this)*p1; return (*this); }
|
||
|
|
||
|
Polynomial<NT>& operator /= (const Polynomial<NT>& p1)
|
||
|
{ (*this)=(*this)/p1; return (*this); }
|
||
|
|
||
|
Polynomial<NT>& operator %= (const Polynomial<NT>& p1)
|
||
|
{ (*this)=(*this)%p1; return (*this); }
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------
|
||
|
// SPECIALIZE_MEMBERS(int double) START
|
||
|
|
||
|
Polynomial<NT>& operator += (const NT& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator -= (const NT& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator *= (const NT& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator /= (const NT& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator %= (const NT& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
// SPECIALIZING_MEMBERS FOR const int&
|
||
|
|
||
|
Polynomial<NT>& operator += (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator -= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator *= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator /= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator %= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
// SPECIALIZING_MEMBERS FOR const double&
|
||
|
|
||
|
Polynomial<NT>& operator += (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator -= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (NT)num; return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator *= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator /= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<NT>& operator %= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (NT)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
// SPECIALIZE_MEMBERS(int double) END
|
||
|
//------------------------------------------------------------------
|
||
|
|
||
|
void minus_offsetmult(const Polynomial<NT>& p, const NT& b, int k)
|
||
|
{ CGAL_assertion(!this->is_shared());
|
||
|
Polynomial<NT> s(size_type(p.degree()+k+1)); // zero entries
|
||
|
for (int i=k; i <= s.degree(); ++i) s.coeff(i) = b*p[i-k];
|
||
|
operator-=(s);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/*{\Mimplementation This data type is implemented as an item type
|
||
|
via a smart pointer scheme. The coefficients are stored in a vector of
|
||
|
|NT| entries. The simple arithmetic operations $+,-$ take time
|
||
|
$O(d*T(NT))$, multiplication is quadratic in the maximal degree of the
|
||
|
arguments times $T(NT)$, where $T(NT)$ is the time for a corresponding
|
||
|
operation on two instances of the ring type.}*/
|
||
|
|
||
|
//############ POLYNOMIAL< INT > ###################################
|
||
|
// CLASS TEMPLATE int:
|
||
|
/*{\Xsubst
|
||
|
iterator_traits<Forward_iterator>::value_type#int
|
||
|
<>#
|
||
|
}*/
|
||
|
|
||
|
/*{\Xanpage{Polynomial}{int}{Polynomials in one variable}{p}}*/
|
||
|
|
||
|
template <>
|
||
|
class Polynomial<int> :
|
||
|
public Handle_for< Polynomial_rep<int> >
|
||
|
{
|
||
|
/*{\Xdefinition An instance |\Mvar| of the data type |\Mname| represents
|
||
|
a polynomial $p = a_0 + a_1 x + \ldots a_d x^d $ from the ring |int[x]|.
|
||
|
The data type offers standard ring operations and a sign operation which
|
||
|
determines the sign for the limit process $x \rightarrow \infty$.
|
||
|
|
||
|
|int[x]| becomes a unique factorization domain, if the number type
|
||
|
|int| is either a field type (1) or a unique factorization domain
|
||
|
(2). In both cases there's a polynomial division operation defined.}*/
|
||
|
|
||
|
/*{\Xtypes 5}*/
|
||
|
public:
|
||
|
typedef int NT;
|
||
|
/*{\Xtypemember the component type representing the coefficients.}*/
|
||
|
|
||
|
typedef Handle_for< Polynomial_rep<int> > Base;
|
||
|
typedef Polynomial_rep<int> Rep;
|
||
|
typedef Rep::Vector Vector;
|
||
|
typedef Rep::size_type size_type;
|
||
|
typedef Rep::iterator iterator;
|
||
|
|
||
|
typedef Rep::const_iterator const_iterator;
|
||
|
/*{\Xtypemember a random access iterator for read-only access to the
|
||
|
coefficient vector.}*/
|
||
|
|
||
|
//protected:
|
||
|
void reduce() { this->ptr()->reduce(); }
|
||
|
Vector& coeffs() { return this->ptr()->coeff; }
|
||
|
const Vector& coeffs() const { return this->ptr()->coeff; }
|
||
|
Polynomial(size_type s) : Base( Polynomial_rep<int>(s) ) {}
|
||
|
// creates a polynomial of degree s-1
|
||
|
|
||
|
|
||
|
/*{\Xcreation 3}*/
|
||
|
public:
|
||
|
|
||
|
Polynomial()
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| of undefined
|
||
|
value. }*/
|
||
|
: Base( Polynomial_rep<int>() ) {}
|
||
|
|
||
|
Polynomial(const int& a0)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the constant polynomial $a_0$.}*/
|
||
|
: Base(Polynomial_rep<int>(a0)) { reduce(); }
|
||
|
|
||
|
|
||
|
Polynomial(int a0, int a1)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x$. }*/
|
||
|
: Base(Polynomial_rep<int>(a0,a1)) { reduce(); }
|
||
|
|
||
|
Polynomial(const int& a0, const int& a1,const int& a2)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x + a_2 x^2$. }*/
|
||
|
: Base(Polynomial_rep<int>(a0,a1,a2)) { reduce(); }
|
||
|
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
Polynomial(std::pair<Forward_iterator, Forward_iterator> poly)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial whose coefficients are determined by the iterator range,
|
||
|
i.e. let $(a_0 = |*first|, a_1 = |*++first|, \ldots a_d = |*it|)$,
|
||
|
where |++it == last| then |\Mvar| stores the polynomial $a_1 + a_2 x +
|
||
|
\ldots a_d x^d$.}*/
|
||
|
: Base(Polynomial_rep<int>(poly)) { reduce(); }
|
||
|
|
||
|
|
||
|
|
||
|
// KILL double START
|
||
|
Polynomial(double n) : Base(Polynomial_rep<int>(int(n))) { reduce(); }
|
||
|
Polynomial(double n1, double n2)
|
||
|
: Base(Polynomial_rep<int>(int(n1),int(n2))) { reduce(); }
|
||
|
// KILL double END
|
||
|
|
||
|
//protected: // accessing coefficients internally:
|
||
|
int& coeff(unsigned int i)
|
||
|
{ CGAL_assertion(!this->is_shared() && i<(this->ptr()->coeff.size()));
|
||
|
return this->ptr()->coeff[i];
|
||
|
}
|
||
|
public:
|
||
|
|
||
|
/*{\Xoperations 3 3 }*/
|
||
|
const_iterator begin() const { return this->ptr()->coeff.begin(); }
|
||
|
/*{\Xop a random access iterator pointing to $a_0$.}*/
|
||
|
const_iterator end() const { return this->ptr()->coeff.end(); }
|
||
|
/*{\Xop a random access iterator pointing beyond $a_d$.}*/
|
||
|
|
||
|
int degree() const
|
||
|
{ return static_cast<int>(this->ptr()->coeff.size())-1; }
|
||
|
/*{\Xop the degree of the polynomial.}*/
|
||
|
|
||
|
const int& operator[](unsigned int i) const
|
||
|
{ CGAL_assertion( i<(this->ptr()->coeff.size()) );
|
||
|
return this->ptr()->coeff[i]; }
|
||
|
/*{\Xarrop the coefficient $a_i$ of the polynomial.}*/
|
||
|
|
||
|
int eval_at(const int& r) const
|
||
|
/*{\Xop evaluates the polynomial at |r|.}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
int res = this->ptr()->coeff[0], x = r;
|
||
|
for(int i=1; i<=degree(); ++i)
|
||
|
{ res += this->ptr()->coeff[i]*x; x*=r; }
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
CGAL::Sign sign() const
|
||
|
/*{\Xop returns the sign of the limit process for $x \rightarrow \infty$
|
||
|
(the sign of the leading coefficient).}*/
|
||
|
{ const int& leading_coeff = this->ptr()->coeff.back();
|
||
|
if (leading_coeff < int(0)) return (CGAL::NEGATIVE);
|
||
|
if (leading_coeff > int(0)) return (CGAL::POSITIVE);
|
||
|
return CGAL::ZERO;
|
||
|
}
|
||
|
|
||
|
bool is_zero() const
|
||
|
/*{\Xop returns true iff |\Mvar| is the zero polynomial.}*/
|
||
|
{ return degree()==0 && this->ptr()->coeff[0]==int(0); }
|
||
|
|
||
|
Polynomial<int> abs() const
|
||
|
/*{\Xop returns |-\Mvar| if |\Mvar.sign()==NEGATIVE| and |\Mvar|
|
||
|
otherwise.}*/
|
||
|
{ return ( sign()==CGAL::NEGATIVE ) ? - *this : *this; }
|
||
|
|
||
|
int content() const
|
||
|
/*{\Xop returns the content of |\Mvar| (the gcd of its coefficients).
|
||
|
\precond Requires |int| to provide a |gcd| operation.}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
return gcd_of_range(this->ptr()->coeff.begin(),this->ptr()->coeff.end());
|
||
|
}
|
||
|
|
||
|
/*{\Xtext Additionally |\Mname| offers standard arithmetic ring
|
||
|
opertions like |+,-,*,+=,-=,*=|. By means of the sign operation we can
|
||
|
also offer comparison predicates as $<,>,\leq,\geq$. Where $p_1 < p_2$
|
||
|
holds iff $|sign|(p_1 - p_2) < 0$. This data type is fully compliant
|
||
|
to the requirements of CGAL number types. \setopdims{3cm}{2cm}}*/
|
||
|
|
||
|
|
||
|
friend Polynomial<int>
|
||
|
operator + <> (const Polynomial<int>&, const Polynomial<int>&);
|
||
|
|
||
|
friend Polynomial<int>
|
||
|
operator - <> (const Polynomial<int>&, const Polynomial<int>&);
|
||
|
|
||
|
friend Polynomial<int>
|
||
|
operator * <> (const Polynomial<int>&, const Polynomial<int>&);
|
||
|
|
||
|
friend
|
||
|
Polynomial<int> operator / <>
|
||
|
(const Polynomial<int>& p1, const Polynomial<int>& p2);
|
||
|
/*{\Xbinopfunc implements polynomial division of |p1| and |p2|. if
|
||
|
|p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3|
|
||
|
does not exist in |int[x]|. The correct division algorithm is chosen
|
||
|
according to a number type traits class.
|
||
|
If |Number_type_traits<int>::Has_gcd == Tag_true| then the division is
|
||
|
done by \emph{pseudo division} based on a |gcd| operation of |int|. If
|
||
|
|Number_type_traits<int>::Has_gcd == Tag_false| then the division is done
|
||
|
by \emph{euclidean division} based on the division operation of the
|
||
|
field |int|.
|
||
|
|
||
|
\textbf{Note} that |int=int| quickly leads to overflow
|
||
|
errors when using this operation.}*/
|
||
|
|
||
|
/*{\Xtext \headerline{Static member functions}}*/
|
||
|
|
||
|
static Polynomial<int> gcd
|
||
|
(const Polynomial<int>& p1, const Polynomial<int>& p2);
|
||
|
/*{\Xstatic returns the greatest common divisor of |p1| and |p2|.
|
||
|
\textbf{Note} that |int=int| quickly leads to overflow errors when
|
||
|
using this operation. \precond Requires |int| to be a unique
|
||
|
factorization domain, i.e. to provide a |gcd| operation.}*/
|
||
|
|
||
|
static void pseudo_div
|
||
|
(const Polynomial<int>& f, const Polynomial<int>& g,
|
||
|
Polynomial<int>& q, Polynomial<int>& r, int& D);
|
||
|
/*{\Xstatic implements division with remainder on polynomials of
|
||
|
the ring |int[x]|: $D*f = g*q + r$. \precond |int| is a unique
|
||
|
factorization domain, i.e., there exists a |gcd| operation and an
|
||
|
integral division operation on |int|.}*/
|
||
|
|
||
|
static void euclidean_div
|
||
|
(const Polynomial<int>& f, const Polynomial<int>& g,
|
||
|
Polynomial<int>& q, Polynomial<int>& r);
|
||
|
/*{\Xstatic implements division with remainder on polynomials of
|
||
|
the ring |int[x]|: $f = g*q + r$. \precond |int| is a field, i.e.,
|
||
|
there exists a division operation on |int|. }*/
|
||
|
|
||
|
friend double to_double <> (const Polynomial<int>& p);
|
||
|
|
||
|
|
||
|
Polynomial<int>& operator += (const Polynomial<int>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) += p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<int>& operator -= (const Polynomial<int>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) -= p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(-p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<int>& operator *= (const Polynomial<int>& p1)
|
||
|
{ (*this)=(*this)*p1; return (*this); }
|
||
|
|
||
|
Polynomial<int>& operator /= (const Polynomial<int>& p1)
|
||
|
{ (*this)=(*this)/p1; return (*this); }
|
||
|
|
||
|
Polynomial<int>& operator %= (const Polynomial<int>& p1)
|
||
|
{ (*this)=(*this)%p1; return (*this); }
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------
|
||
|
// SPECIALIZE_MEMBERS(int double) START
|
||
|
|
||
|
Polynomial<int>& operator += (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (int)num; return *this; }
|
||
|
|
||
|
Polynomial<int>& operator -= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (int)num; return *this; }
|
||
|
|
||
|
Polynomial<int>& operator *= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<int>& operator /= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<int>& operator %= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
// SPECIALIZING_MEMBERS FOR const double&
|
||
|
|
||
|
Polynomial<int>& operator += (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (int)num; return *this; }
|
||
|
|
||
|
Polynomial<int>& operator -= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (int)num; return *this; }
|
||
|
|
||
|
Polynomial<int>& operator *= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<int>& operator /= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<int>& operator %= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (int)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
// SPECIALIZE_MEMBERS(int double) END
|
||
|
//------------------------------------------------------------------
|
||
|
|
||
|
void minus_offsetmult(const Polynomial<int>& p, const int& b, int k)
|
||
|
{ CGAL_assertion(!is_shared());
|
||
|
Polynomial<int> s(size_type(p.degree()+k+1)); // zero entries
|
||
|
for (int i=k; i <= s.degree(); ++i) s.coeff(i) = b*p[i-k];
|
||
|
operator-=(s);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/*{\Ximplementation This data type is implemented as an item type
|
||
|
via a smart pointer scheme. The coefficients are stored in a vector of
|
||
|
|int| entries. The simple arithmetic operations $+,-$ take time
|
||
|
$O(d*T(int))$, multiplication is quadratic in the maximal degree of the
|
||
|
arguments times $T(int)$, where $T(int)$ is the time for a corresponding
|
||
|
operation on two instances of the ring type.}*/
|
||
|
|
||
|
|
||
|
//############ POLYNOMIAL< INT > ###################################
|
||
|
|
||
|
//############ POLYNOMIAL< DOUBLE > ################################
|
||
|
|
||
|
|
||
|
// CLASS TEMPLATE double:
|
||
|
/*{\Xsubst
|
||
|
iterator_traits<Forward_iterator>::value_type#double
|
||
|
<>#
|
||
|
}*/
|
||
|
|
||
|
/*{\Xanpage{Polynomial}{double}{Polynomials in one variable}{p}}*/
|
||
|
|
||
|
template <>
|
||
|
class Polynomial<double> :
|
||
|
public Handle_for< Polynomial_rep<double> >
|
||
|
{
|
||
|
/*{\Xdefinition An instance |\Mvar| of the data type |\Mname| represents
|
||
|
a polynomial $p = a_0 + a_1 x + \ldots a_d x^d $ from the ring |double[x]|.
|
||
|
The data type offers standard ring operations and a sign operation which
|
||
|
determines the sign for the limit process $x \rightarrow \infty$.
|
||
|
|
||
|
|double[x]| becomes a unique factorization domain, if the number type
|
||
|
|double| is either a field type (1) or a unique factorization domain
|
||
|
(2). In both cases there's a polynomial division operation defined.}*/
|
||
|
|
||
|
/*{\Xtypes 5}*/
|
||
|
public:
|
||
|
typedef double NT;
|
||
|
/*{\Xtypemember the component type representing the coefficients.}*/
|
||
|
|
||
|
typedef Handle_for< Polynomial_rep<double> > Base;
|
||
|
typedef Polynomial_rep<double> Rep;
|
||
|
typedef Rep::Vector Vector;
|
||
|
typedef Rep::size_type size_type;
|
||
|
typedef Rep::iterator iterator;
|
||
|
|
||
|
typedef Rep::const_iterator const_iterator;
|
||
|
/*{\Xtypemember a random access iterator for read-only access to the
|
||
|
coefficient vector.}*/
|
||
|
|
||
|
//protected:
|
||
|
void reduce() { this->ptr()->reduce(); }
|
||
|
Vector& coeffs() { return this->ptr()->coeff; }
|
||
|
const Vector& coeffs() const { return this->ptr()->coeff; }
|
||
|
Polynomial(size_type s) : Base( Polynomial_rep<double>(s) ) {}
|
||
|
// creates a polynomial of degree s-1
|
||
|
|
||
|
|
||
|
/*{\Xcreation 3}*/
|
||
|
public:
|
||
|
|
||
|
Polynomial()
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| of undefined
|
||
|
value. }*/
|
||
|
: Base( Polynomial_rep<double>() ) {}
|
||
|
|
||
|
Polynomial(const double& a0)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the constant polynomial $a_0$.}*/
|
||
|
: Base(Polynomial_rep<double>(a0)) { reduce(); }
|
||
|
|
||
|
Polynomial(const double a0, const double a1)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x$. }*/
|
||
|
: Base(Polynomial_rep<double>(a0,a1)) { reduce(); }
|
||
|
|
||
|
Polynomial(const double& a0, const double& a1,const double& a2)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial $a_0 + a_1 x + a_2 x^2$. }*/
|
||
|
: Base(Polynomial_rep<double>(a0,a1,a2)) { reduce(); }
|
||
|
|
||
|
template <class Forward_iterator>
|
||
|
Polynomial(std::pair<Forward_iterator, Forward_iterator> poly)
|
||
|
/*{\Xcreate introduces a variable |\Mvar| of type |\Mname| representing
|
||
|
the polynomial whose coefficients are determined by the iterator range,
|
||
|
i.e. let $(a_0 = |*first|, a_1 = |*++first|, \ldots a_d = |*it|)$,
|
||
|
where |++it == last| then |\Mvar| stores the polynomial $a_1 + a_2 x +
|
||
|
\ldots a_d x^d$.}*/
|
||
|
: Base(Polynomial_rep<double>(poly)) { reduce(); }
|
||
|
|
||
|
|
||
|
|
||
|
// KILL int START
|
||
|
Polynomial(int n) : Base(Polynomial_rep<double>(double(n))) { reduce(); }
|
||
|
Polynomial(int n1, int n2)
|
||
|
: Base(Polynomial_rep<double>(double(n1),double(n2))) { reduce(); }
|
||
|
// KILL int END
|
||
|
|
||
|
//protected: // accessing coefficients internally:
|
||
|
double& coeff(unsigned int i)
|
||
|
{ CGAL_assertion(!this->is_shared() && i<(this->ptr()->coeff.size()));
|
||
|
return this->ptr()->coeff[i];
|
||
|
}
|
||
|
public:
|
||
|
|
||
|
/*{\Xoperations 3 3 }*/
|
||
|
const_iterator begin() const { return this->ptr()->coeff.begin(); }
|
||
|
/*{\Xop a random access iterator pointing to $a_0$.}*/
|
||
|
const_iterator end() const { return this->ptr()->coeff.end(); }
|
||
|
/*{\Xop a random access iterator pointing beyond $a_d$.}*/
|
||
|
|
||
|
int degree() const
|
||
|
{ return static_cast<int>(this->ptr()->coeff.size())-1; }
|
||
|
/*{\Xop the degree of the polynomial.}*/
|
||
|
|
||
|
const double& operator[](unsigned int i) const
|
||
|
{ CGAL_assertion( i<(this->ptr()->coeff.size()) );
|
||
|
return this->ptr()->coeff[i]; }
|
||
|
/*{\Xarrop the coefficient $a_i$ of the polynomial.}*/
|
||
|
|
||
|
double eval_at(const double& r) const
|
||
|
/*{\Xop evaluates the polynomial at |r|.}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
double res = this->ptr()->coeff[0], x = r;
|
||
|
for(int i=1; i<=degree(); ++i)
|
||
|
{ res += this->ptr()->coeff[i]*x; x*=r; }
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
CGAL::Sign sign() const
|
||
|
/*{\Xop returns the sign of the limit process for $x \rightarrow \infty$
|
||
|
(the sign of the leading coefficient).}*/
|
||
|
{ const double& leading_coeff = this->ptr()->coeff.back();
|
||
|
if (leading_coeff < double(0)) return (CGAL::NEGATIVE);
|
||
|
if (leading_coeff > double(0)) return (CGAL::POSITIVE);
|
||
|
return CGAL::ZERO;
|
||
|
}
|
||
|
|
||
|
bool is_zero() const
|
||
|
/*{\Xop returns true iff |\Mvar| is the zero polynomial.}*/
|
||
|
{ return degree()==0 && this->ptr()->coeff[0]==double(0); }
|
||
|
|
||
|
Polynomial<double> abs() const
|
||
|
/*{\Xop returns |-\Mvar| if |\Mvar.sign()==NEGATIVE| and |\Mvar|
|
||
|
otherwise.}*/
|
||
|
{ return ( sign()==CGAL::NEGATIVE ) ? - *this : *this; }
|
||
|
|
||
|
|
||
|
double content() const
|
||
|
/*{\Xop returns the content of |\Mvar| (the gcd of its coefficients).
|
||
|
\precond Requires |double| to provide a |gdc| operation.}*/
|
||
|
{ CGAL_assertion( degree()>=0 );
|
||
|
return gcd_of_range(this->ptr()->coeff.begin(),this->ptr()->coeff.end());
|
||
|
}
|
||
|
|
||
|
|
||
|
/*{\Xtext Additionally |\Mname| offers standard arithmetic ring
|
||
|
opertions like |+,-,*,+=,-=,*=|. By means of the sign operation we can
|
||
|
also offer comparison predicates as $<,>,\leq,\geq$. Where $p_1 < p_2$
|
||
|
holds iff $|sign|(p_1 - p_2) < 0$. This data type is fully compliant
|
||
|
to the requirements of CGAL number types. \setopdims{3cm}{2cm}}*/
|
||
|
|
||
|
friend Polynomial<double>
|
||
|
operator + <> (const Polynomial<double>&, const Polynomial<double>&);
|
||
|
|
||
|
friend Polynomial<double>
|
||
|
operator - <> (const Polynomial<double>&, const Polynomial<double>&);
|
||
|
|
||
|
friend Polynomial<double>
|
||
|
operator * <> (const Polynomial<double>&, const Polynomial<double>&);
|
||
|
|
||
|
friend
|
||
|
Polynomial<double> operator / <>
|
||
|
(const Polynomial<double>& p1, const Polynomial<double>& p2);
|
||
|
/*{\Xbinopfunc implements polynomial division of |p1| and |p2|. if
|
||
|
|p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3|
|
||
|
does not exist in |double[x]|. The correct division algorithm is chosen
|
||
|
according to the number type traits class.
|
||
|
If |Number_type_traits<double>::Has_gcd == Tag_true| then the division is
|
||
|
done by \emph{pseudo division} based on a |gcd| operation of |double|. If
|
||
|
|Number_type_traits<double>::Has_gcd == Tag_false| then the division is done
|
||
|
by \emph{euclidean division} based on the division operation of the
|
||
|
field |double|.
|
||
|
|
||
|
\textbf{Note} that |double=int| quickly leads to overflow
|
||
|
errors when using this operation.}*/
|
||
|
|
||
|
/*{\Xtext \headerline{Static member functions}}*/
|
||
|
|
||
|
static Polynomial<double> gcd
|
||
|
(const Polynomial<double>& p1, const Polynomial<double>& p2);
|
||
|
/*{\Xstatic returns the greatest common divisor of |p1| and |p2|.
|
||
|
\textbf{Note} that |double=int| quickly leads to overflow errors when
|
||
|
using this operation. \precond Requires |double| to be a unique
|
||
|
factorization domain, i.e. to provide a |gdc| operation.}*/
|
||
|
|
||
|
static void pseudo_div
|
||
|
(const Polynomial<double>& f, const Polynomial<double>& g,
|
||
|
Polynomial<double>& q, Polynomial<double>& r, double& D);
|
||
|
/*{\Xstatic implements division with remainder on polynomials of
|
||
|
the ring |double[x]|: $D*f = g*q + r$. \precond |double| is a unique
|
||
|
factorization domain, i.e., there exists a |gcd| operation and an
|
||
|
integral division operation on |double|.}*/
|
||
|
|
||
|
static void euclidean_div
|
||
|
(const Polynomial<double>& f, const Polynomial<double>& g,
|
||
|
Polynomial<double>& q, Polynomial<double>& r);
|
||
|
/*{\Xstatic implements division with remainder on polynomials of
|
||
|
the ring |double[x]|: $f = g*q + r$. \precond |double| is a field, i.e.,
|
||
|
there exists a division operation on |double|. }*/
|
||
|
|
||
|
friend double to_double <> (const Polynomial<double>& p);
|
||
|
|
||
|
|
||
|
Polynomial<double>& operator += (const Polynomial<double>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) += p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<double>& operator -= (const Polynomial<double>& p1)
|
||
|
{ this->copy_on_write();
|
||
|
int d = (std::min)(degree(),p1.degree()), i;
|
||
|
for(i=0; i<=d; ++i) coeff(i) -= p1[i];
|
||
|
while (i<=p1.degree()) this->ptr()->coeff.push_back(-p1[i++]);
|
||
|
reduce(); return (*this); }
|
||
|
|
||
|
Polynomial<double>& operator *= (const Polynomial<double>& p1)
|
||
|
{ (*this)=(*this)*p1; return (*this); }
|
||
|
|
||
|
Polynomial<double>& operator /= (const Polynomial<double>& p1)
|
||
|
{ (*this)=(*this)/p1; return (*this); }
|
||
|
|
||
|
Polynomial<double>& operator %= (const Polynomial<double>& p1)
|
||
|
{ (*this)=(*this)%p1; return (*this); }
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------
|
||
|
// SPECIALIZE_MEMBERS(int double) START
|
||
|
|
||
|
Polynomial<double>& operator += (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (double)num; return *this; }
|
||
|
|
||
|
Polynomial<double>& operator -= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (double)num; return *this; }
|
||
|
|
||
|
Polynomial<double>& operator *= (const double& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<double>& operator /= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
/*
|
||
|
Polynomial<double>& operator %= (const double& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
*/
|
||
|
|
||
|
// SPECIALIZING_MEMBERS FOR const int&
|
||
|
|
||
|
Polynomial<double>& operator += (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) += (double)num; return *this; }
|
||
|
|
||
|
Polynomial<double>& operator -= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
coeff(0) -= (double)num; return *this; }
|
||
|
|
||
|
Polynomial<double>& operator *= (const int& num)
|
||
|
{ this->copy_on_write();
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) *= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
Polynomial<double>& operator /= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) /= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
|
||
|
/*
|
||
|
Polynomial<double>& operator %= (const int& num)
|
||
|
{ this->copy_on_write(); CGAL_assertion(num!=0);
|
||
|
for(int i=0; i<=degree(); ++i) coeff(i) %= (double)num;
|
||
|
reduce(); return *this; }
|
||
|
*/
|
||
|
|
||
|
// SPECIALIZE_MEMBERS(int double) END
|
||
|
//------------------------------------------------------------------
|
||
|
|
||
|
void minus_offsetmult(const Polynomial<double>& p, const double& b, int k)
|
||
|
{ CGAL_assertion(!this->is_shared());
|
||
|
Polynomial<double> s(size_type(p.degree()+k+1)); // zero entries
|
||
|
for (int i=k; i <= s.degree(); ++i) s.coeff(i) = b*p[i-k];
|
||
|
operator-=(s);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/*{\Ximplementation This data type is implemented as an item type
|
||
|
via a smart pointer scheme. The coefficients are stored in a vector of
|
||
|
|double| entries. The simple arithmetic operations $+,-$ take time
|
||
|
$O(d*T(double))$, multiplication is quadratic in the maximal degree of the
|
||
|
arguments times $T(double)$, where $T(double)$ is the time for a corresponding
|
||
|
operation on two instances of the ring type.}*/
|
||
|
|
||
|
|
||
|
//############ POLYNOMIAL< DOUBLE > ################################
|
||
|
|
||
|
|
||
|
|
||
|
// SPECIALIZE_CLASS(NT,int double) END
|
||
|
|
||
|
template <class NT> double to_double
|
||
|
(const Polynomial<NT>&)
|
||
|
{ return 0; }
|
||
|
|
||
|
template <class NT> bool is_valid
|
||
|
(const Polynomial<NT>& p)
|
||
|
{ return (CGAL::is_valid(p[0])); }
|
||
|
|
||
|
template <class NT> bool is_finite
|
||
|
(const Polynomial<NT>& p)
|
||
|
{ return CGAL::is_finite(p[0]); }
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> operator - (const Polynomial<NT>& p)
|
||
|
{
|
||
|
CGAL_assertion(p.degree()>=0);
|
||
|
Polynomial<NT> res(std::make_pair(p.coeffs().begin(),p.coeffs().end()));
|
||
|
typename Polynomial<NT>::iterator it, ite=res.coeffs().end();
|
||
|
for(it=res.coeffs().begin(); it!=ite; ++it) *it = -*it;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> operator + (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2)
|
||
|
{
|
||
|
typedef typename Polynomial<NT>::size_type size_type;
|
||
|
CGAL_assertion(p1.degree()>=0 && p2.degree()>=0);
|
||
|
bool p1d_smaller_p2d = p1.degree() < p2.degree();
|
||
|
int min,max,i;
|
||
|
if (p1d_smaller_p2d) { min = p1.degree(); max = p2.degree(); }
|
||
|
else { max = p1.degree(); min = p2.degree(); }
|
||
|
Polynomial<NT> p( size_type(max + 1));
|
||
|
for (i = 0; i <= min; ++i ) p.coeff(i) = p1[i]+p2[i];
|
||
|
if (p1d_smaller_p2d) for (; i <= max; ++i ) p.coeff(i)=p2[i];
|
||
|
else /* p1d >= p2d */ for (; i <= max; ++i ) p.coeff(i)=p1[i];
|
||
|
p.reduce();
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> operator - (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2)
|
||
|
{
|
||
|
typedef typename Polynomial<NT>::size_type size_type;
|
||
|
CGAL_assertion(p1.degree()>=0 && p2.degree()>=0);
|
||
|
bool p1d_smaller_p2d = p1.degree() < p2.degree();
|
||
|
int min,max,i;
|
||
|
if (p1d_smaller_p2d) { min = p1.degree(); max = p2.degree(); }
|
||
|
else { max = p1.degree(); min = p2.degree(); }
|
||
|
Polynomial<NT> p( size_type(max+1) );
|
||
|
for (i = 0; i <= min; ++i ) p.coeff(i)=p1[i]-p2[i];
|
||
|
if (p1d_smaller_p2d) for (; i <= max; ++i ) p.coeff(i)= -p2[i];
|
||
|
else /* p1d >= p2d */ for (; i <= max; ++i ) p.coeff(i)= p1[i];
|
||
|
p.reduce();
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> operator * (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2)
|
||
|
{
|
||
|
typedef typename Polynomial<NT>::size_type size_type;
|
||
|
if (p1.degree()<0 || p2.degree()<0) return p1;
|
||
|
CGAL_assertion(p1.degree()>=0 && p2.degree()>=0);
|
||
|
Polynomial<NT> p( size_type(p1.degree()+p2.degree()+1) );
|
||
|
// initialized with zeros
|
||
|
for (int i=0; i <= p1.degree(); ++i)
|
||
|
for (int j=0; j <= p2.degree(); ++j)
|
||
|
p.coeff(i+j) += (p1[i]*p2[j]);
|
||
|
p.reduce();
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> operator / (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2)
|
||
|
{
|
||
|
typedef Algebraic_structure_traits<NT> AST;
|
||
|
return divop(p1,p2, typename AST::Algebraic_category());
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT> inline
|
||
|
Polynomial<NT> operator % (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2)
|
||
|
{
|
||
|
typedef Algebraic_structure_traits<NT> AST;
|
||
|
return modop(p1,p2, typename AST::Algebraic_category());
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> divop (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2,
|
||
|
Integral_domain_without_division_tag)
|
||
|
{ CGAL_assertion(!p2.is_zero());
|
||
|
if (p1.is_zero()) {
|
||
|
return 0;
|
||
|
}
|
||
|
Polynomial<NT> q;
|
||
|
Polynomial<NT> r;
|
||
|
Polynomial<NT>::euclidean_div(p1,p2,q,r);
|
||
|
CGAL_postcondition( (p2*q+r==p1) );
|
||
|
return q;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> divop (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2,
|
||
|
Unique_factorization_domain_tag)
|
||
|
{ CGAL_assertion(!p2.is_zero());
|
||
|
if (p1.is_zero()) return 0;
|
||
|
Polynomial<NT> q,r; NT D;
|
||
|
Polynomial<NT>::pseudo_div(p1,p2,q,r,D);
|
||
|
CGAL_postcondition( (p2*q+r==p1*Polynomial<NT>(D)) );
|
||
|
return q/=D;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> modop (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2,
|
||
|
Integral_domain_without_division_tag)
|
||
|
{ CGAL_assertion(!p2.is_zero());
|
||
|
if (p1.is_zero()) return 0;
|
||
|
Polynomial<NT> q,r;
|
||
|
Polynomial<NT>::euclidean_div(p1,p2,q,r);
|
||
|
CGAL_postcondition( (p2*q+r==p1) );
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> modop (const Polynomial<NT>& p1,
|
||
|
const Polynomial<NT>& p2,
|
||
|
Unique_factorization_domain_tag)
|
||
|
{ CGAL_assertion(!p2.is_zero());
|
||
|
if (p1.is_zero()) return 0;
|
||
|
Polynomial<NT> q,r; NT D;
|
||
|
Polynomial<NT>::pseudo_div(p1,p2,q,r,D);
|
||
|
CGAL_postcondition( (p2*q+r==p1*Polynomial<NT>(D)) );
|
||
|
return q/=D;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
inline Polynomial<NT>
|
||
|
gcd(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return Polynomial<NT>::gcd(p1,p2); }
|
||
|
|
||
|
|
||
|
template <class NT> bool operator ==
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() == CGAL::ZERO ); }
|
||
|
|
||
|
template <class NT> bool operator !=
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() != CGAL::ZERO ); }
|
||
|
|
||
|
template <class NT> bool operator <
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() == CGAL::NEGATIVE ); }
|
||
|
|
||
|
template <class NT> bool operator <=
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() != CGAL::POSITIVE ); }
|
||
|
|
||
|
template <class NT> bool operator >
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() == CGAL::POSITIVE ); }
|
||
|
|
||
|
template <class NT> bool operator >=
|
||
|
(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ return ( (p1-p2).sign() != CGAL::NEGATIVE ); }
|
||
|
|
||
|
template <class NT> CGAL::Sign
|
||
|
sign(const Polynomial<NT>& p)
|
||
|
{ return p.sign(); }
|
||
|
|
||
|
//------------------------------------------------------------------
|
||
|
// SPECIALIZE_FUNCTION(NT,int double) START
|
||
|
// SPECIALIZING inline to :
|
||
|
|
||
|
// lefthand side
|
||
|
inline Polynomial<int> operator +
|
||
|
(const int& num, const Polynomial<int>& p2)
|
||
|
{ return (Polynomial<int>(num) + p2); }
|
||
|
inline Polynomial<int> operator -
|
||
|
(const int& num, const Polynomial<int>& p2)
|
||
|
{ return (Polynomial<int>(num) - p2); }
|
||
|
inline Polynomial<int> operator *
|
||
|
(const int& num, const Polynomial<int>& p2)
|
||
|
{ return (Polynomial<int>(num) * p2); }
|
||
|
inline Polynomial<int> operator /
|
||
|
(const int& num, const Polynomial<int>& p2)
|
||
|
{ return (Polynomial<int>(num)/p2); }
|
||
|
inline Polynomial<int> operator %
|
||
|
(const int& num, const Polynomial<int>& p2)
|
||
|
{ return (Polynomial<int>(num)%p2); }
|
||
|
|
||
|
// righthand side
|
||
|
inline Polynomial<int> operator +
|
||
|
(const Polynomial<int>& p1, const int& num)
|
||
|
{ return (p1 + Polynomial<int>(num)); }
|
||
|
inline Polynomial<int> operator -
|
||
|
(const Polynomial<int>& p1, const int& num)
|
||
|
{ return (p1 - Polynomial<int>(num)); }
|
||
|
inline Polynomial<int> operator *
|
||
|
(const Polynomial<int>& p1, const int& num)
|
||
|
{ return (p1 * Polynomial<int>(num)); }
|
||
|
inline Polynomial<int> operator /
|
||
|
(const Polynomial<int>& p1, const int& num)
|
||
|
{ return (p1 / Polynomial<int>(num)); }
|
||
|
inline Polynomial<int> operator %
|
||
|
(const Polynomial<int>& p1, const int& num)
|
||
|
{ return (p1 % Polynomial<int>(num)); }
|
||
|
|
||
|
// lefthand side
|
||
|
inline bool operator ==
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() == CGAL::ZERO );}
|
||
|
inline bool operator !=
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() != CGAL::ZERO );}
|
||
|
inline bool operator <
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() == CGAL::NEGATIVE );}
|
||
|
inline bool operator <=
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() != CGAL::POSITIVE );}
|
||
|
inline bool operator >
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() == CGAL::POSITIVE );}
|
||
|
inline bool operator >=
|
||
|
(const int& num, const Polynomial<int>& p)
|
||
|
{ return ( (Polynomial<int>(num)-p).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// righthand side
|
||
|
inline bool operator ==
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() == CGAL::ZERO );}
|
||
|
inline bool operator !=
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() != CGAL::ZERO );}
|
||
|
inline bool operator <
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() == CGAL::NEGATIVE );}
|
||
|
inline bool operator <=
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() != CGAL::POSITIVE );}
|
||
|
inline bool operator >
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() == CGAL::POSITIVE );}
|
||
|
inline bool operator >=
|
||
|
(const Polynomial<int>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<int>(num)).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// SPECIALIZING pure int params:
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const int& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) + p2); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const int& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) - p2); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const int& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) * p2); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const int& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)/p2); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const int& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)%p2); }
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const Polynomial<NT>& p1, const int& num)
|
||
|
{ return (p1 + Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const Polynomial<NT>& p1, const int& num)
|
||
|
{ return (p1 - Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const Polynomial<NT>& p1, const int& num)
|
||
|
{ return (p1 * Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const Polynomial<NT>& p1, const int& num)
|
||
|
{ return (p1 / Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const Polynomial<NT>& p1, const int& num)
|
||
|
{ return (p1 % Polynomial<NT>(num)); }
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const int& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const Polynomial<NT>& p, const int& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// SPECIALIZING inline to :
|
||
|
|
||
|
// lefthand side
|
||
|
inline Polynomial<double> operator +
|
||
|
(const double& num, const Polynomial<double>& p2)
|
||
|
{ return (Polynomial<double>(num) + p2); }
|
||
|
inline Polynomial<double> operator -
|
||
|
(const double& num, const Polynomial<double>& p2)
|
||
|
{ return (Polynomial<double>(num) - p2); }
|
||
|
inline Polynomial<double> operator *
|
||
|
(const double& num, const Polynomial<double>& p2)
|
||
|
{ return (Polynomial<double>(num) * p2); }
|
||
|
inline Polynomial<double> operator /
|
||
|
(const double& num, const Polynomial<double>& p2)
|
||
|
{ return (Polynomial<double>(num)/p2); }
|
||
|
inline Polynomial<double> operator %
|
||
|
(const double& num, const Polynomial<double>& p2)
|
||
|
{ return (Polynomial<double>(num)%p2); }
|
||
|
|
||
|
// righthand side
|
||
|
inline Polynomial<double> operator +
|
||
|
(const Polynomial<double>& p1, const double& num)
|
||
|
{ return (p1 + Polynomial<double>(num)); }
|
||
|
inline Polynomial<double> operator -
|
||
|
(const Polynomial<double>& p1, const double& num)
|
||
|
{ return (p1 - Polynomial<double>(num)); }
|
||
|
inline Polynomial<double> operator *
|
||
|
(const Polynomial<double>& p1, const double& num)
|
||
|
{ return (p1 * Polynomial<double>(num)); }
|
||
|
inline Polynomial<double> operator /
|
||
|
(const Polynomial<double>& p1, const double& num)
|
||
|
{ return (p1 / Polynomial<double>(num)); }
|
||
|
inline Polynomial<double> operator %
|
||
|
(const Polynomial<double>& p1, const double& num)
|
||
|
{ return (p1 % Polynomial<double>(num)); }
|
||
|
|
||
|
// lefthand side
|
||
|
inline bool operator ==
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() == CGAL::ZERO );}
|
||
|
inline bool operator !=
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() != CGAL::ZERO );}
|
||
|
inline bool operator <
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() == CGAL::NEGATIVE );}
|
||
|
inline bool operator <=
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() != CGAL::POSITIVE );}
|
||
|
inline bool operator >
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() == CGAL::POSITIVE );}
|
||
|
inline bool operator >=
|
||
|
(const double& num, const Polynomial<double>& p)
|
||
|
{ return ( (Polynomial<double>(num)-p).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// righthand side
|
||
|
inline bool operator ==
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() == CGAL::ZERO );}
|
||
|
inline bool operator !=
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() != CGAL::ZERO );}
|
||
|
inline bool operator <
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() == CGAL::NEGATIVE );}
|
||
|
inline bool operator <=
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() != CGAL::POSITIVE );}
|
||
|
inline bool operator >
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() == CGAL::POSITIVE );}
|
||
|
inline bool operator >=
|
||
|
(const Polynomial<double>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<double>(num)).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// SPECIALIZING pure double params:
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const double& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) + p2); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const double& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) - p2); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const double& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) * p2); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const double& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)/p2); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const double& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)%p2); }
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const Polynomial<NT>& p1, const double& num)
|
||
|
{ return (p1 + Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const Polynomial<NT>& p1, const double& num)
|
||
|
{ return (p1 - Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const Polynomial<NT>& p1, const double& num)
|
||
|
{ return (p1 * Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const Polynomial<NT>& p1, const double& num)
|
||
|
{ return (p1 / Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const Polynomial<NT>& p1, const double& num)
|
||
|
{ return (p1 % Polynomial<NT>(num)); }
|
||
|
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const double& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const Polynomial<NT>& p, const double& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// SPECIALIZE_FUNCTION ORIGINAL
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const NT& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) + p2); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const NT& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) - p2); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const NT& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num) * p2); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const NT& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)/p2); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const NT& num, const Polynomial<NT>& p2)
|
||
|
{ return (Polynomial<NT>(num)%p2); }
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> Polynomial<NT> operator +
|
||
|
(const Polynomial<NT>& p1, const NT& num)
|
||
|
{ return (p1 + Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator -
|
||
|
(const Polynomial<NT>& p1, const NT& num)
|
||
|
{ return (p1 - Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator *
|
||
|
(const Polynomial<NT>& p1, const NT& num)
|
||
|
{ return (p1 * Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator /
|
||
|
(const Polynomial<NT>& p1, const NT& num)
|
||
|
{ return (p1 / Polynomial<NT>(num)); }
|
||
|
template <class NT> Polynomial<NT> operator %
|
||
|
(const Polynomial<NT>& p1, const NT& num)
|
||
|
{ return (p1 % Polynomial<NT>(num)); }
|
||
|
|
||
|
|
||
|
// lefthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const NT& num, const Polynomial<NT>& p)
|
||
|
{ return ( (Polynomial<NT>(num)-p).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// righthand side
|
||
|
template <class NT> bool operator ==
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::ZERO );}
|
||
|
template <class NT> bool operator !=
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::ZERO );}
|
||
|
template <class NT> bool operator <
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::NEGATIVE );}
|
||
|
template <class NT> bool operator <=
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() == CGAL::POSITIVE );}
|
||
|
template <class NT> bool operator >=
|
||
|
(const Polynomial<NT>& p, const NT& num)
|
||
|
{ return ( (p-Polynomial<NT>(num)).sign() != CGAL::NEGATIVE );}
|
||
|
|
||
|
// SPECIALIZE_FUNCTION(NT,int double) END
|
||
|
//------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
void print_monomial(std::ostream& os, const NT& n, int i)
|
||
|
{
|
||
|
if (i==0) os << n;
|
||
|
if (i==1) os << n << "R";
|
||
|
if (i>1) os << n << "R^" << i;
|
||
|
}
|
||
|
|
||
|
// I/O
|
||
|
template <class NT>
|
||
|
std::ostream& operator << (std::ostream& os, const Polynomial<NT>& p)
|
||
|
{
|
||
|
int i;
|
||
|
switch( get_mode(os) )
|
||
|
{
|
||
|
case CGAL::IO::ASCII :
|
||
|
os << p.degree() << ' ';
|
||
|
for(i=0; i<=p.degree(); ++i)
|
||
|
os << p[i] << ' ';
|
||
|
break;
|
||
|
case CGAL::IO::BINARY :
|
||
|
CGAL::write(os, p.degree());
|
||
|
for( i=0; i <= p.degree(); ++i)
|
||
|
CGAL::write(os, p[i]);
|
||
|
break;
|
||
|
default: // i.e. PRETTY
|
||
|
os << "Polynomial(" << p.degree() << ", ";
|
||
|
for( i=0; i <= p.degree(); ++i) {
|
||
|
os << p[i];
|
||
|
if (i < p.degree())
|
||
|
os << ", ";
|
||
|
}
|
||
|
os << ")";
|
||
|
// Alternative pretty format
|
||
|
//print_monomial(os,p[p.degree()],p.degree());
|
||
|
//for(i=p.degree()-1; i>=0; --i) {
|
||
|
// if (p[i]!=NT(0)) { os << " + "; print_monomial(os,p[i],i); }
|
||
|
//}
|
||
|
break;
|
||
|
}
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
template <class NT>
|
||
|
std::istream& operator >> (std::istream& is, Polynomial<NT>& p) {
|
||
|
int i,d;
|
||
|
char ch;
|
||
|
NT c;
|
||
|
bool pretty = false;
|
||
|
switch( get_mode(is) ) {
|
||
|
case CGAL::IO::ASCII :
|
||
|
case CGAL::IO::PRETTY :
|
||
|
is >> ch;
|
||
|
if ( ch == 'P') {
|
||
|
pretty = true;
|
||
|
// Parse rest of "olynomial("
|
||
|
const char buffer[11] = "olynomial(";
|
||
|
const char* p = buffer;
|
||
|
is >> ch;
|
||
|
while ( is && *p != '\0' && *p == ch) {
|
||
|
is >> ch;
|
||
|
++p;
|
||
|
}
|
||
|
if ( *p != '\0')
|
||
|
is.clear( std::ios::badbit);
|
||
|
if ( ! is)
|
||
|
return is;
|
||
|
is.putback(ch);
|
||
|
} else {
|
||
|
is.putback(ch);
|
||
|
}
|
||
|
is >> d;
|
||
|
if ( pretty) {
|
||
|
is >> ch;
|
||
|
if ( ch != ',') {
|
||
|
is.clear( std::ios::badbit);
|
||
|
return is;
|
||
|
}
|
||
|
}
|
||
|
if (d < 0) {
|
||
|
if ( pretty) {
|
||
|
is >> ch;
|
||
|
if ( ch != ')') {
|
||
|
is.clear( std::ios::badbit);
|
||
|
return is;
|
||
|
}
|
||
|
}
|
||
|
if ( is)
|
||
|
p = Polynomial<NT>();
|
||
|
} else {
|
||
|
typename Polynomial<NT>::Vector coeffs(d+1);
|
||
|
for( i = 0; i <= d; ++i) {
|
||
|
is >> coeffs[i];
|
||
|
if ( pretty && i < d) {
|
||
|
is >> ch;
|
||
|
if ( ch != ',') {
|
||
|
is.clear( std::ios::badbit);
|
||
|
return is;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( pretty) {
|
||
|
is >> ch;
|
||
|
if ( ch != ')') {
|
||
|
is.clear( std::ios::badbit);
|
||
|
return is;
|
||
|
}
|
||
|
}
|
||
|
if ( is)
|
||
|
p = Polynomial<NT>(std::make_pair( coeffs.begin(),
|
||
|
coeffs.end()));
|
||
|
}
|
||
|
break;
|
||
|
case CGAL::IO::BINARY :
|
||
|
CGAL::read(is, d);
|
||
|
if (d < 0)
|
||
|
p = Polynomial<NT>();
|
||
|
else {
|
||
|
typename Polynomial<NT>::Vector coeffs(d+1);
|
||
|
for(i=0; i<=d; ++i) {
|
||
|
CGAL::read(is,c);
|
||
|
coeffs[i]=c;
|
||
|
}
|
||
|
p = Polynomial<NT>(std::make_pair( coeffs.begin(), coeffs.end()));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
// SPECIALIZE_FUNCTION ORIGINAL
|
||
|
template <class NT>
|
||
|
void Polynomial<NT>::euclidean_div(
|
||
|
const Polynomial<NT>& f, const Polynomial<NT>& g,
|
||
|
Polynomial<NT>& q, Polynomial<NT>& r)
|
||
|
{
|
||
|
r = f;
|
||
|
r.copy_on_write();
|
||
|
int rd = r.degree();
|
||
|
int gd = g.degree(), qd;
|
||
|
if ( rd < gd ) {
|
||
|
q = Polynomial<NT>(NT(0));
|
||
|
} else {
|
||
|
qd = rd - gd + 1;
|
||
|
q = Polynomial<NT>(std::size_t(qd));
|
||
|
}
|
||
|
while ( rd >= gd && !(r.is_zero())) {
|
||
|
NT S = r[rd] / g[gd];
|
||
|
qd = rd-gd;
|
||
|
q.coeff(qd) += S;
|
||
|
r.minus_offsetmult(g,S,qd);
|
||
|
rd = r.degree();
|
||
|
}
|
||
|
CGAL_postcondition( f==q*g+r );
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
void Polynomial<NT>::pseudo_div(
|
||
|
const Polynomial<NT>& f, const Polynomial<NT>& g,
|
||
|
Polynomial<NT>& q, Polynomial<NT>& r, NT& D)
|
||
|
{
|
||
|
CGAL_NEF_TRACEN("pseudo_div "<<f<<" , "<< g);
|
||
|
int fd=f.degree(), gd=g.degree();
|
||
|
if ( fd<gd )
|
||
|
{ q = Polynomial<NT>(0); r = f; D = 1;
|
||
|
CGAL_postcondition(Polynomial<NT>(D)*f==q*g+r); return;
|
||
|
}
|
||
|
// now we know fd >= gd and f>=g
|
||
|
int qd=fd-gd, delta=qd+1, rd=fd;
|
||
|
{ q = Polynomial<NT>( std::size_t(delta) ); }; // workaround for SunPRO
|
||
|
NT G = g[gd]; // highest order coeff of g
|
||
|
D = G; while (--delta) D*=G; // D = G^delta
|
||
|
Polynomial<NT> res = Polynomial<NT>(D)*f;
|
||
|
CGAL_NEF_TRACEN(" pseudo_div start "<<res<<" "<<qd<<" "<<q.degree());
|
||
|
while (qd >= 0) {
|
||
|
NT F = res[rd]; // highest order coeff of res
|
||
|
NT t = F/G; // ensured to be integer by multiplication of D
|
||
|
q.coeff(qd) = t; // store q coeff
|
||
|
res.minus_offsetmult(g,t,qd);
|
||
|
if (res.is_zero()) break;
|
||
|
rd = res.degree();
|
||
|
qd = rd - gd;
|
||
|
}
|
||
|
r = res;
|
||
|
CGAL_postcondition(Polynomial<NT>(D)*f==q*g+r);
|
||
|
CGAL_NEF_TRACEN(" returning "<<q<<", "<<r<<", "<< D);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class NT>
|
||
|
Polynomial<NT> Polynomial<NT>::gcd(
|
||
|
const Polynomial<NT>& p1, const Polynomial<NT>& p2)
|
||
|
{ CGAL_NEF_TRACEN("gcd("<<p1<<" , "<<p2<<")");
|
||
|
if ( p1.is_zero() ) {
|
||
|
if ( p2.is_zero() ) return Polynomial<NT>(NT(1));
|
||
|
else return p2.abs();
|
||
|
}
|
||
|
if ( p2.is_zero() )
|
||
|
return p1.abs();
|
||
|
|
||
|
Polynomial<NT> f1 = p1.abs();
|
||
|
Polynomial<NT> f2 = p2.abs();
|
||
|
NT f1c = f1.content(), f2c = f2.content();
|
||
|
f1 /= f1c; f2 /= f2c;
|
||
|
NT F = CGAL_NTS gcd(f1c,f2c);
|
||
|
Polynomial<NT> q,r; NT M=1,D;
|
||
|
bool first = true;
|
||
|
while ( ! f2.is_zero() ) {
|
||
|
Polynomial<NT>::pseudo_div(f1,f2,q,r,D);
|
||
|
if (!first) M*=D;
|
||
|
CGAL_NEF_TRACEV(f1);CGAL_NEF_TRACEV(f2);CGAL_NEF_TRACEV(q);CGAL_NEF_TRACEV(r);CGAL_NEF_TRACEV(M);
|
||
|
r /= r.content();
|
||
|
f1=f2; f2=r;
|
||
|
first=false;
|
||
|
}
|
||
|
CGAL_NEF_TRACEV(f1.content());
|
||
|
return Polynomial<NT>(F)*f1.abs();
|
||
|
}
|
||
|
|
||
|
|
||
|
// SPECIALIZE_IMPLEMENTATION(NT,int double) END
|
||
|
|
||
|
} // namespace Nef
|
||
|
|
||
|
|
||
|
using Nef::to_double;
|
||
|
using Nef::sign;
|
||
|
using Nef::is_finite;
|
||
|
using Nef::is_valid;
|
||
|
using Nef::gcd;
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
#include <CGAL/Nef_2/Polynomial_impl.h>
|
||
|
|
||
|
#endif // CGAL_NEF_2_POLYNOMIAL_H
|