660 lines
30 KiB
C++
Executable File
660 lines
30 KiB
C++
Executable File
// Copyright (c) 2006-2013 INRIA Nancy-Grand Est (France). All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public License as
|
|
// published by the Free Software Foundation; either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
|
|
// See the file LICENSE.LGPL distributed with CGAL.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
// SPDX-License-Identifier: LGPL-3.0+
|
|
//
|
|
// Author: Luis Peñaranda <luis.penaranda@gmx.com>
|
|
|
|
#ifndef CGAL_RS_FUNCTORS_1_H
|
|
#define CGAL_RS_FUNCTORS_1_H
|
|
|
|
#include <vector>
|
|
#include <CGAL/Gmpfi.h>
|
|
|
|
namespace CGAL{
|
|
namespace RS_AK1{
|
|
|
|
template <class Polynomial_,
|
|
class Algebraic_,
|
|
class Bound_,
|
|
class Coefficient_,
|
|
class Isolator_>
|
|
struct Construct_algebraic_real_1{
|
|
typedef Polynomial_ Polynomial;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Bound_ Bound;
|
|
typedef Coefficient_ Coefficient;
|
|
typedef Isolator_ Isolator;
|
|
typedef Algebraic result_type;
|
|
|
|
template <class T>
|
|
Algebraic operator()(const T &a)const{
|
|
return Algebraic(a);
|
|
}
|
|
|
|
Algebraic operator()(const Polynomial &p,size_t i)const{
|
|
Isolator isol(p);
|
|
return Algebraic(p,isol.left_bound(i),isol.right_bound(i));
|
|
}
|
|
|
|
Algebraic operator()(const Polynomial &p,
|
|
const Bound &l,
|
|
const Bound &r)const{
|
|
return Algebraic(p,l,r);
|
|
}
|
|
|
|
}; // struct Construct_algebraic_1
|
|
|
|
template <class Polynomial_,class Algebraic_>
|
|
struct Compute_polynomial_1:
|
|
public CGAL::cpp98::unary_function<Algebraic_,Polynomial_>{
|
|
typedef Polynomial_ Polynomial;
|
|
typedef Algebraic_ Algebraic;
|
|
Polynomial operator()(const Algebraic &x)const{
|
|
return x.get_pol();
|
|
}
|
|
}; // struct Compute_polynomial_1
|
|
|
|
template <class Polynomial_,class Ptraits_>
|
|
struct Is_coprime_1:
|
|
public CGAL::cpp98::binary_function<Polynomial_,Polynomial_,bool>{
|
|
typedef Polynomial_ Polynomial;
|
|
typedef Ptraits_ Ptraits;
|
|
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
|
|
typedef typename Ptraits::Degree Degree;
|
|
inline bool operator()(const Polynomial &p1,const Polynomial &p2)const{
|
|
return Degree()(Gcd()(p1,p2))==0;
|
|
}
|
|
}; // struct Is_coprime_1
|
|
|
|
template <class Polynomial_,class Ptraits_>
|
|
struct Make_coprime_1{
|
|
typedef Polynomial_ Polynomial;
|
|
typedef Ptraits_ Ptraits;
|
|
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
|
|
typedef typename Ptraits::Degree Degree;
|
|
typedef typename Ptraits::Integral_division_up_to_constant_factor
|
|
IDiv;
|
|
bool operator()(const Polynomial &p1,
|
|
const Polynomial &p2,
|
|
Polynomial &g,
|
|
Polynomial &q1,
|
|
Polynomial &q2)const{
|
|
g=Gcd()(p1,p2);
|
|
q1=IDiv()(p1,g);
|
|
q2=IDiv()(p2,g);
|
|
return Degree()(Gcd()(p1,p2))==0;
|
|
}
|
|
}; // struct Make_coprime_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Isolator_,
|
|
class Signat_,
|
|
class Ptraits_>
|
|
struct Solve_1{
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Isolator_ Isolator;
|
|
typedef Signat_ Signat;
|
|
typedef Ptraits_ Ptraits;
|
|
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
|
|
typedef typename Ptraits::Square_free_factorize_up_to_constant_factor
|
|
Sqfr;
|
|
typedef typename Ptraits::Degree Degree;
|
|
typedef typename Ptraits::Make_square_free Sfpart;
|
|
|
|
template <class OutputIterator>
|
|
OutputIterator operator()(const Polynomial_1 &p,
|
|
OutputIterator res)const{
|
|
typedef std::pair<Polynomial_1,int> polmult;
|
|
typedef std::vector<polmult> sqvec;
|
|
|
|
Polynomial_1 sfp=Sfpart()(p);
|
|
sqvec sfv;
|
|
Sqfr()(p,std::back_inserter(sfv));
|
|
Isolator isol(sfp);
|
|
int *m=(int*)calloc(isol.number_of_real_roots(),sizeof(int));
|
|
for(typename sqvec::iterator i=sfv.begin();i!=sfv.end();++i){
|
|
int k=Degree()(i->first);
|
|
Signat signof(i->first);
|
|
for(int j=0;k&&j<isol.number_of_real_roots();++j){
|
|
if(!m[j]){
|
|
CGAL::Sign sg_l=
|
|
signof(isol.left_bound(j));
|
|
CGAL::Sign sg_r=
|
|
signof(isol.right_bound(j));
|
|
if((sg_l!=sg_r)||
|
|
((sg_l==CGAL::ZERO)&&
|
|
(sg_r==CGAL::ZERO))){
|
|
m[j]=i->second;
|
|
--k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(int l=0;l<isol.number_of_real_roots();++l)
|
|
*res++=std::make_pair(Algebraic(p,
|
|
isol.left_bound(l),
|
|
isol.right_bound(l)),
|
|
m[l]);
|
|
free(m);
|
|
return res;
|
|
}
|
|
|
|
template <class OutputIterator>
|
|
OutputIterator operator()(const Polynomial_1 &p,
|
|
bool known_to_be_square_free,
|
|
OutputIterator res)const{
|
|
Isolator isol(p);
|
|
for(int l=0;l<isol.number_of_real_roots();++l)
|
|
*res++=Algebraic(p,
|
|
isol.left_bound(l),
|
|
isol.right_bound(l));
|
|
return res;
|
|
}
|
|
|
|
template <class OutputIterator>
|
|
OutputIterator operator()(const Polynomial_1 &p,
|
|
const Bound &l,
|
|
const Bound &u,
|
|
OutputIterator res)const{
|
|
typedef std::vector<Algebraic> RV;
|
|
typedef std::pair<Polynomial_1,int> PM;
|
|
typedef std::vector<PM> PMV;
|
|
typedef typename PMV::iterator PMVI;
|
|
CGAL_precondition_msg(l<=u,
|
|
"left bound must be <= right bound");
|
|
RV roots; // all roots of the polynomial
|
|
this->operator()(p,false,std::back_inserter(roots));
|
|
size_t nb_roots=roots.size();
|
|
// indices of the first and last roots to be reported:
|
|
size_t index_l=0,index_u;
|
|
while(index_l<nb_roots&&roots[index_l]<l)
|
|
++index_l;
|
|
CGAL_assertion(index_l<=nb_roots);
|
|
if(index_l==nb_roots)
|
|
return res;
|
|
index_u=index_l;
|
|
while(index_u<nb_roots&&roots[index_u]<u)
|
|
++index_u;
|
|
CGAL_assertion(index_u<=nb_roots);
|
|
if(index_u==index_l)
|
|
return res;
|
|
// now, we have to return roots in [index_l,index_u)
|
|
PMV sfv;
|
|
Sqfr()(p,std::back_inserter(sfv)); // square-free fact. of p
|
|
// array to store the multiplicities
|
|
int *m=(int*)calloc(nb_roots,sizeof(int));
|
|
// we iterate over all the pairs <root,mult> and match the
|
|
// roots in the interval [index_l,index_u)
|
|
for(PMVI i=sfv.begin();i!=sfv.end();++i){
|
|
int k=Degree()(i->first);
|
|
Signat signof(i->first);
|
|
for(size_t j=index_l;k&&j<index_u;++j){
|
|
if(!m[j]){
|
|
CGAL::Sign sg_l=
|
|
signof(roots[j].get_left());
|
|
CGAL::Sign sg_r=
|
|
signof(roots[j].get_right());
|
|
if((sg_l!=sg_r)||
|
|
((sg_l==CGAL::ZERO)&&
|
|
(sg_r==CGAL::ZERO))){
|
|
m[j]=i->second;
|
|
--k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(size_t l=index_l;l<index_u;++l)
|
|
*res++=std::make_pair(roots[l],m[l]);
|
|
free(m);
|
|
return res;
|
|
}
|
|
|
|
template <class OutputIterator>
|
|
OutputIterator operator()(const Polynomial_1 &p,
|
|
bool known_to_be_square_free,
|
|
const Bound &l,
|
|
const Bound &u,
|
|
OutputIterator res)const{
|
|
typedef std::vector<Algebraic> RV;
|
|
typedef typename RV::iterator RVI;
|
|
CGAL_precondition_msg(l<=u,
|
|
"left bound must be <= right bound");
|
|
RV roots;
|
|
this->operator()(p,
|
|
known_to_be_square_free,
|
|
std::back_inserter(roots));
|
|
for(RVI it=roots.begin();it!=roots.end();it++)
|
|
if(*it>=l&&*it<=u)
|
|
*res++=*it;
|
|
return res;
|
|
}
|
|
|
|
}; // struct Solve_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Refiner_,
|
|
class Signat_,
|
|
class Ptraits_>
|
|
class Sign_at_1:
|
|
public CGAL::cpp98::binary_function<Polynomial_,Algebraic_,CGAL::Sign>{
|
|
// This implementation will work with any polynomial type whose
|
|
// coefficient type is explicit interoperable with Gmpfi.
|
|
// TODO: Make this function generic.
|
|
public:
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Refiner_ Refiner;
|
|
typedef Signat_ Signat;
|
|
typedef Ptraits_ Ptraits;
|
|
|
|
private:
|
|
CGAL::Uncertain<CGAL::Sign> eval_interv(const Polynomial_1 &p,
|
|
const Bound &l,
|
|
const Bound &r)const{
|
|
typedef typename Ptraits::Substitute Subst;
|
|
std::vector<CGAL::Gmpfi> substitutions;
|
|
substitutions.push_back(CGAL::Gmpfi(l,r));
|
|
CGAL::Gmpfi eval=Subst()(p,
|
|
substitutions.begin(),
|
|
substitutions.end());
|
|
return eval.sign();
|
|
}
|
|
|
|
// This function assumes that the sign of the evaluation is not zero,
|
|
// it just refines x until having the correct sign.
|
|
CGAL::Sign refine_and_return(const Polynomial_1 &p,Algebraic x)const{
|
|
CGAL::Gmpfr xl(x.get_left());
|
|
CGAL::Gmpfr xr(x.get_right());
|
|
CGAL::Uncertain<CGAL::Sign> s;
|
|
for(;;){
|
|
Refiner()(x.get_pol(),
|
|
xl,
|
|
xr,
|
|
2*CGAL::max(xl.get_precision(),
|
|
xr.get_precision()));
|
|
s=eval_interv(p,xl,xr);
|
|
if(!s.is_same(Uncertain<CGAL::Sign>::indeterminate())){
|
|
x.set_left(xl);
|
|
x.set_right(xr);
|
|
return s;
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
CGAL::Sign operator()(const Polynomial_1 &p,Algebraic x)const{
|
|
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
|
|
typedef typename Ptraits::Make_square_free Sfpart;
|
|
typedef typename Ptraits::Degree Degree;
|
|
typedef typename Ptraits::Differentiate Deriv;
|
|
CGAL::Uncertain<CGAL::Sign> unknown=
|
|
Uncertain<CGAL::Sign>::indeterminate();
|
|
CGAL::Uncertain<CGAL::Sign> s=eval_interv(p,
|
|
x.get_left(),
|
|
x.get_right());
|
|
if(!s.is_same(unknown))
|
|
return s;
|
|
// We are not sure about the sign. We calculate the gcd in
|
|
// order to know if both polynomials have common roots.
|
|
Polynomial_1 sfpp=Sfpart()(p);
|
|
Polynomial_1 gcd=Gcd()(sfpp,Sfpart()(x.get_pol()));
|
|
if(Degree()(gcd)==0)
|
|
return refine_and_return(p,x);
|
|
|
|
// At this point, gcd is not 1; we proceed as follows:
|
|
// -we refine x until having p monotonic in x's interval (to be
|
|
// sure that p has at most one root on that interval),
|
|
// -if the gcd has a root on this interval, both roots are
|
|
// equal (we return 0), otherwise, we refine until having a
|
|
// result.
|
|
|
|
// How to assure that p is monotonic in an interval: when its
|
|
// derivative is never zero in that interval.
|
|
Polynomial_1 dsfpp=Deriv()(sfpp);
|
|
CGAL::Gmpfr xl(x.get_left());
|
|
CGAL::Gmpfr xr(x.get_right());
|
|
while(eval_interv(dsfpp,xl,xr).is_same(unknown)){
|
|
Refiner()(x.get_pol(),
|
|
xl,
|
|
xr,
|
|
2*CGAL::max(xl.get_precision(),
|
|
xr.get_precision()));
|
|
}
|
|
x.set_left(xl);
|
|
x.set_right(xr);
|
|
|
|
// How to know that the gcd has a root: evaluate endpoints.
|
|
CGAL::Sign sleft,sright;
|
|
Signat sign_at_gcd(gcd);
|
|
if((sleft=sign_at_gcd(x.get_left()))==CGAL::ZERO||
|
|
(sright=sign_at_gcd(x.get_right()))==CGAL::ZERO||
|
|
(sleft!=sright))
|
|
return CGAL::ZERO;
|
|
return refine_and_return(p,x);
|
|
}
|
|
}; // struct Sign_at_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Refiner_,
|
|
class Signat_,
|
|
class Ptraits_>
|
|
class Is_zero_at_1:
|
|
public CGAL::cpp98::binary_function<Polynomial_,Algebraic_,bool>{
|
|
// This implementation will work with any polynomial type whose
|
|
// coefficient type is explicit interoperable with Gmpfi.
|
|
// TODO: Make this function generic.
|
|
public:
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Refiner_ Refiner;
|
|
typedef Signat_ Signat;
|
|
typedef Ptraits_ Ptraits;
|
|
|
|
private:
|
|
CGAL::Uncertain<CGAL::Sign> eval_interv(const Polynomial_1 &p,
|
|
const Bound &l,
|
|
const Bound &r)const{
|
|
typedef typename Ptraits::Substitute Subst;
|
|
std::vector<CGAL::Gmpfi> substitutions;
|
|
substitutions.push_back(CGAL::Gmpfi(l,r));
|
|
CGAL::Gmpfi eval=Subst()(p,
|
|
substitutions.begin(),
|
|
substitutions.end());
|
|
return eval.sign();
|
|
}
|
|
|
|
public:
|
|
bool operator()(const Polynomial_1 &p,Algebraic x)const{
|
|
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
|
|
typedef typename Ptraits::Make_square_free Sfpart;
|
|
typedef typename Ptraits::Degree Degree;
|
|
typedef typename Ptraits::Differentiate Deriv;
|
|
CGAL::Uncertain<CGAL::Sign> unknown=
|
|
Uncertain<CGAL::Sign>::indeterminate();
|
|
CGAL::Uncertain<CGAL::Sign> s=eval_interv(p,
|
|
x.get_left(),
|
|
x.get_right());
|
|
if(!s.is_same(unknown))
|
|
return (s==CGAL::ZERO);
|
|
// We are not sure about the sign. We calculate the gcd in
|
|
// order to know if both polynomials have common roots.
|
|
Polynomial_1 sfpp=Sfpart()(p);
|
|
Polynomial_1 gcd=Gcd()(sfpp,Sfpart()(x.get_pol()));
|
|
if(Degree()(gcd)==0)
|
|
return false;
|
|
|
|
// At this point, gcd is not 1; we proceed as follows:
|
|
// -we refine x until having p monotonic in x's interval (to be
|
|
// sure that p has at most one root on that interval),
|
|
// -if the gcd has a root on this interval, both roots are
|
|
// equal (we return 0), otherwise, we refine until having a
|
|
// result.
|
|
|
|
// How to assure that p is monotonic in an interval: when its
|
|
// derivative is never zero in that interval.
|
|
Polynomial_1 dsfpp=Deriv()(sfpp);
|
|
CGAL::Gmpfr xl(x.get_left());
|
|
CGAL::Gmpfr xr(x.get_right());
|
|
while(eval_interv(dsfpp,xl,xr).is_same(unknown)){
|
|
Refiner()(x.get_pol(),
|
|
xl,
|
|
xr,
|
|
2*CGAL::max(xl.get_precision(),
|
|
xr.get_precision()));
|
|
}
|
|
x.set_left(xl);
|
|
x.set_right(xr);
|
|
|
|
// How to know that the gcd has a root: evaluate endpoints.
|
|
CGAL::Sign sleft,sright;
|
|
Signat sign_at_gcd(gcd);
|
|
return((sleft=sign_at_gcd(x.get_left()))==CGAL::ZERO||
|
|
(sright=sign_at_gcd(x.get_right()))==CGAL::ZERO||
|
|
(sleft!=sright));
|
|
}
|
|
}; // class Is_zero_at_1
|
|
|
|
// TODO: it says in the manual that this should return a size_type, but test
|
|
// programs assume that this is equal to int
|
|
template <class Polynomial_,class Isolator_>
|
|
struct Number_of_solutions_1:
|
|
public CGAL::cpp98::unary_function<Polynomial_,int>{
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Isolator_ Isolator;
|
|
size_t operator()(const Polynomial_1 &p)const{
|
|
// TODO: make sure that p is square free (precondition)
|
|
Isolator isol(p);
|
|
return isol.number_of_real_roots();
|
|
}
|
|
}; // struct Number_of_solutions_1
|
|
|
|
// This functor not only compares two algebraic numbers. In case they are
|
|
// different, it refines them until they do not overlap.
|
|
template <class Algebraic_,
|
|
class Bound_,
|
|
class Comparator_>
|
|
struct Compare_1:
|
|
public CGAL::cpp98::binary_function<Algebraic_,Algebraic_,CGAL::Comparison_result>{
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Bound_ Bound;
|
|
typedef Comparator_ Comparator;
|
|
|
|
CGAL::Comparison_result operator()(Algebraic a,Algebraic b)const{
|
|
Bound al=a.get_left();
|
|
Bound ar=a.get_right();
|
|
Bound bl=b.get_left();
|
|
Bound br=b.get_right();
|
|
CGAL::Comparison_result c=Comparator()(a.get_pol(),al,ar,
|
|
b.get_pol(),bl,br);
|
|
a.set_left(al);
|
|
a.set_right(ar);
|
|
b.set_left(bl);
|
|
b.set_right(br);
|
|
return c;
|
|
}
|
|
|
|
CGAL::Comparison_result operator()(Algebraic a,const Bound &b)const{
|
|
Bound al=a.get_left();
|
|
Bound ar=a.get_right();
|
|
Algebraic balg(b);
|
|
CGAL::Comparison_result c=Comparator()(a.get_pol(),al,ar,
|
|
balg.get_pol(),b,b);
|
|
a.set_left(al);
|
|
a.set_right(ar);
|
|
return c;
|
|
}
|
|
|
|
template <class T>
|
|
CGAL::Comparison_result operator()(Algebraic a,const T &b)const{
|
|
Bound al=a.get_left();
|
|
Bound ar=a.get_right();
|
|
Algebraic balg(b);
|
|
CGAL::Comparison_result c=Comparator()(a.get_pol(),
|
|
al,
|
|
ar,
|
|
balg.get_pol(),
|
|
balg.get_left(),
|
|
balg.get_right());
|
|
a.set_left(al);
|
|
a.set_right(ar);
|
|
return c;
|
|
}
|
|
|
|
}; // class Compare_1
|
|
|
|
template <class Algebraic_,
|
|
class Bound_,
|
|
class Comparator_>
|
|
struct Bound_between_1:
|
|
public CGAL::cpp98::binary_function<Algebraic_,Algebraic_,Bound_>{
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Bound_ Bound;
|
|
typedef Comparator_ Comparator;
|
|
|
|
Bound operator()(Algebraic a,Algebraic b)const{
|
|
typedef Compare_1<Algebraic,Bound,Comparator> Compare;
|
|
typename Bound::Precision_type prec;
|
|
switch(Compare()(a,b)){
|
|
case CGAL::LARGER:
|
|
CGAL_assertion(b.get_right()<a.get_left());
|
|
prec=CGAL::max(b.get_right().get_precision(),
|
|
a.get_left().get_precision());
|
|
return Bound::add(b.get_right(),
|
|
a.get_left(),
|
|
1+prec)/2;
|
|
break;
|
|
case CGAL::SMALLER:
|
|
CGAL_assertion(a.get_right()<b.get_left());
|
|
prec=CGAL::max(a.get_right().get_precision(),
|
|
b.get_left().get_precision());
|
|
return Bound::add(a.get_right(),
|
|
b.get_left(),
|
|
1+prec)/2;
|
|
break;
|
|
default:
|
|
CGAL_error_msg(
|
|
"bound between two equal numbers");
|
|
}
|
|
}
|
|
}; // struct Bound_between_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Isolator_,
|
|
class Comparator_,
|
|
class Signat_,
|
|
class Ptraits_>
|
|
struct Isolate_1:
|
|
public CGAL::cpp98::binary_function<Algebraic_,Polynomial_,std::pair<Bound_,Bound_> >{
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Isolator_ Isolator;
|
|
typedef Comparator_ Comparator;
|
|
typedef Signat_ Signat;
|
|
typedef Ptraits_ Ptraits;
|
|
|
|
std::pair<Bound,Bound>
|
|
operator()(const Algebraic &a,const Polynomial_1 &p)const{
|
|
std::vector<Algebraic> roots;
|
|
std::back_insert_iterator<std::vector<Algebraic> > rit(roots);
|
|
typedef Solve_1<Polynomial_1,
|
|
Bound,
|
|
Algebraic,
|
|
Isolator,
|
|
Signat,
|
|
Ptraits> Solve;
|
|
typedef Compare_1<Algebraic,Bound,Comparator> Compare;
|
|
Solve()(p,false,rit);
|
|
for(typename std::vector<Algebraic>::size_type i=0;
|
|
i<roots.size();
|
|
++i){
|
|
// we use the comparison functor, that makes both
|
|
// intervals disjoint iff the algebraic numbers they
|
|
// represent are not equal
|
|
Compare()(a,roots[i]);
|
|
}
|
|
return std::make_pair(a.left(),a.right());
|
|
}
|
|
}; // Isolate_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Refiner_>
|
|
struct Approximate_absolute_1:
|
|
public CGAL::cpp98::binary_function<Algebraic_,int,std::pair<Bound_,Bound_> >{
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Refiner_ Refiner;
|
|
|
|
// This implementation assumes that Bound is Gmpfr.
|
|
// TODO: make generic.
|
|
std::pair<Bound,Bound> operator()(const Algebraic &x,const int &a)const{
|
|
Bound xl(x.get_left()),xr(x.get_right());
|
|
// refsteps=log2(xl-xr)
|
|
mpfr_t temp;
|
|
mpfr_init(temp);
|
|
mpfr_sub(temp,xr.fr(),xl.fr(),GMP_RNDU);
|
|
mpfr_log2(temp,temp,GMP_RNDU);
|
|
long refsteps=mpfr_get_si(temp,GMP_RNDU);
|
|
mpfr_clear(temp);
|
|
Refiner()(x.get_pol(),xl,xr,CGAL::abs(refsteps+a));
|
|
x.set_left(xl);
|
|
x.set_right(xr);
|
|
CGAL_assertion(a>0?
|
|
(xr-xl)*CGAL::ipower(Bound(2),a)<=Bound(1):
|
|
(xr-xl)<=CGAL::ipower(Bound(2),-a));
|
|
return std::make_pair(xl,xr);
|
|
}
|
|
}; // struct Approximate_absolute_1
|
|
|
|
template <class Polynomial_,
|
|
class Bound_,
|
|
class Algebraic_,
|
|
class Refiner_>
|
|
struct Approximate_relative_1:
|
|
public CGAL::cpp98::binary_function<Algebraic_,int,std::pair<Bound_,Bound_> >{
|
|
typedef Polynomial_ Polynomial_1;
|
|
typedef Bound_ Bound;
|
|
typedef Algebraic_ Algebraic;
|
|
typedef Refiner_ Refiner;
|
|
|
|
std::pair<Bound,Bound> operator()(const Algebraic &x,const int &a)const{
|
|
if(CGAL::is_zero(x))
|
|
return std::make_pair(Bound(0),Bound(0));
|
|
Bound error=CGAL::ipower(Bound(2),CGAL::abs(a));
|
|
Bound xl(x.get_left()),xr(x.get_right());
|
|
Bound max_b=(CGAL::max)(CGAL::abs(xr),CGAL::abs(xl));
|
|
while(a>0?(xr-xl)*error>max_b:(xr-xl)>error*max_b){
|
|
Refiner()(x.get_pol(),
|
|
xl,
|
|
xr,
|
|
std::max<unsigned>(
|
|
CGAL::abs(a),
|
|
CGAL::max(xl.get_precision(),
|
|
xr.get_precision())));
|
|
max_b=(CGAL::max)(CGAL::abs(xr),CGAL::abs(xl));
|
|
}
|
|
x.set_left(xl);
|
|
x.set_right(xr);
|
|
CGAL_assertion(
|
|
a>0?
|
|
(xr-xl)*CGAL::ipower(Bound(2),a)<=max_b:
|
|
(xr-xl)<=CGAL::ipower(Bound(2),-a)*max_b);
|
|
return std::make_pair(xl,xr);
|
|
}
|
|
}; // struct Approximate_relative_1
|
|
|
|
} // namespace RS_AK1
|
|
} // namespace CGAL
|
|
|
|
#endif // CGAL_RS_FUNCTORS_1_H
|