// Copyright (c) 2006-2010 Inria Lorraine (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. // // 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$ // // Author: Luis PeƱaranda #ifndef CGAL_RS_FUNCTORS_H #define CGAL_RS_FUNCTORS_H #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IEEE_DBL_MANT_DIG # define CGAL_RS_FUNCTORS_DBL_PREC IEEE_DBL_MANT_DIG #else # define CGAL_RS_FUNCTORS_DBL_PREC 53 #endif namespace RSFunctors{ typedef CGAL::RS_polynomial_1 Polynomial; typedef CGAL::Algebraic_1 Algebraic; typedef CGAL::Gmpfr Bound; typedef int Multiplicity; template struct Compute_polynomial_1: public std::unary_function{ typedef _P P; typedef CGAL::from_rs_poly

back; P operator()(const Algebraic &a)const{ return back()(a.pol()); } }; // Compute_polynomial_1 template struct Is_square_free_1: public std::unary_function<_P,bool>{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef _Gcd_policy Gcd; bool operator()(const P &p)const{ Polynomial rsp=convert()(p); return(!(Gcd()(rsp,rsp.derive()).get_degree_static())); } }; // Is_square_free_1 template struct Make_square_free_1: public std::unary_function<_P,_P>{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef CGAL::from_rs_poly

back; typedef _Gcd_policy Gcd; P operator()(const P &p)const{ return back()(CGAL::sfpart_1()(convert()(p))); } }; // Make_square_free_1 template struct Square_free_factorize_1{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef CGAL::from_rs_poly

back; typedef _Gcd_policy Gcd; template OutputIterator operator()(const P &p,OutputIterator oi)const{ Polynomial rsp=convert()(p); CGAL::sqfrvec factorization(CGAL::sqfr_1()(rsp)); for(CGAL::sqfrvec::iterator i=factorization.begin(); i!=factorization.end(); ++i){ *oi++=std::make_pair(back()((*i).first),(*i).second); } return oi; } }; // Square_free_factorize_1 template struct Is_coprime_1: public std::binary_function<_P,_P,bool>{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef _Gcd_policy Gcd; bool operator()(const P &p1,const P &p2)const{ CGAL::RS_polynomial_1 rsp1=convert()(p1); CGAL::RS_polynomial_1 rsp2=convert()(p2); return(!Gcd()(rsp1,rsp2).get_degree_static()); } }; // Is_coprime_1 template struct Make_coprime_1{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef CGAL::from_rs_poly

back; typedef _Gcd_policy Gcd; bool operator()(const P &p1,const P &p2,P &g,P &q1,P &q2)const{ typedef _Gcd_policy Gcd; CGAL::RS_polynomial_1 rsp1=convert()(p1); CGAL::RS_polynomial_1 rsp2=convert()(p2); CGAL::RS_polynomial_1 rsg=convert()(g); rsg=Gcd()(rsp1,rsp2); g=back()(rsg); // even when g==1, we calculate q1 and q2 q1=back()(*CGAL::Ediv_1()(rsp1,rsg)); q2=back()(*CGAL::Ediv_1()(rsp2,rsg)); return rsg.get_degree_static()?false:true; } }; // Make_coprime_1 template struct Solve_RS_1{ typedef _Gcd_policy Gcd; typedef CGAL::sfpart_1 Sfpart; typedef CGAL::sqfr_1 Sqfr; template OutputIterator operator()(const Polynomial &p,OutputIterator res)const{ int nr,*m; mpfi_ptr *x; CGAL::sqfrvec sfv=Sqfr()(p); x=(mpfi_ptr*)malloc(Sfpart()(p).get_degree()*sizeof(mpfi_ptr)); m=(int*)calloc(Sfpart()(p).get_degree(),sizeof(int)); nr=solve_1(x,Sfpart()(p)); CGAL_assertion_msg(nr>=0,"error in resolution"); for(CGAL::sqfrvec::size_type i=0;ileft)); CGAL::Sign sg_r= CGAL::RSSign::signat(sfv[i].first,&(x[j]->right)); if((sg_l!=sg_r)||((sg_l==CGAL::ZERO)&&(sg_r==CGAL::ZERO))){ m[j]=sfv[i].second; --k; } } } } for(int i=0;i OutputIterator operator()(const Polynomial &p, bool known_to_be_square_free, OutputIterator res)const{ int nr,m; mpfi_ptr *x; if(known_to_be_square_free){ p.set_sf(); x=(mpfi_ptr*)malloc(p.get_degree()*sizeof(mpfi_ptr)); nr=solve_1(x,p); CGAL_assertion_msg(nr>=0,"error in resolution"); m=1; // we know in this case that multiplicity is 1 }else{ x=(mpfi_ptr*)malloc(Sfpart()(p).get_degree()*sizeof(mpfi_ptr)); nr=solve_1(x,Sfpart()(p)); CGAL_assertion_msg(nr>=0,"error in resolution"); m=0; // we won't calculate multiplicities } for(int i=0;i struct Solve_1{ typedef _P P; typedef CGAL::to_rs_poly

convert; typedef _Gcd_policy Gcd; typedef Solve_RS_1 Solve_RS; template OutputIterator operator()(const P &p,OutputIterator res)const{ return Solve_RS()(convert()(p),res); } template OutputIterator operator()(const P &p, bool known_to_be_square_free, OutputIterator res)const{ return Solve_RS()(convert()(p),known_to_be_square_free,res); } template OutputIterator operator()(const P &p, const Bound& lower, const Bound& upper, OutputIterator res)const{ typedef std::vector > RMV; RMV roots; this->operator()(p,std::back_inserter(roots)); for(typename RMV::iterator it = roots.begin(); it != roots.end();it++){ if(lower <= it->first && it->first <= upper) *res++=*it; } return res; } template OutputIterator operator()(const P &p, bool known_to_be_square_free, const Bound& lower, const Bound& upper, OutputIterator res)const{ typedef std::vector< Algebraic > RV; RV roots; this->operator()(p,known_to_be_square_free,std::back_inserter(roots)); for(typename RV::iterator it = roots.begin(); it != roots.end();it++){ if(lower <= *it && *it <= upper) *res++=*it; } return res; } }; // Solve_1 template struct Construct_alg_1{ typedef _P Poly; typedef _Coeff_type Coeff; typedef _Gcd Gcd; typedef CGAL::to_rs_poly convert; typedef Solve_1 Solve; Algebraic operator()(int a) const { return Algebraic(a); } Algebraic operator()(const Bound a) const { return Algebraic(a); } Algebraic operator()(const Coeff a) const { return Algebraic(a); } Algebraic operator()(const Poly &p,int i) const { CGAL_precondition(CGAL::is_square_free(p)); std::vector roots; std::back_insert_iterator > rootsit(roots); Solve()(p,true,rootsit); return roots[i]; } Algebraic operator()(const Poly &p,Bound l,Bound u) const { mpfi_t i; mpfi_init(i); mpfr_set(&i->left,l.fr(),GMP_RNDD); mpfr_set(&i->right,u.fr(),GMP_RNDU); return Algebraic(i,convert()(p),0,0 //,NULL,NULL ); } }; // Construct_alg_1 template struct Number_of_solutions_1: public std::unary_function<_P,int>{ typedef _P P; typedef CGAL::to_rs_poly

convert; int operator()(const P &p)const{ int nr; mpfi_ptr *x; CGAL::RS_polynomial_1 rspoly=convert()(p); x=(mpfi_ptr*)malloc(rspoly.get_degree()*sizeof(mpfi_ptr)); nr=solve_1(x,rspoly); CGAL_assertion_msg(nr>=0,"error in resolution"); free(x); return nr; } }; // Number_of_solutions_1 template struct Sign_at_1: public std::binary_function<_P,Algebraic,CGAL::Sign>{ typedef _P P; typedef _Gcd_policy Gcd; typedef CGAL::to_rs_poly

convert; CGAL::Sign operator()(const P &p,const Algebraic &a)const{ return RS3::sign_1(convert()(p),a); } }; // Sign_at_1 template struct Is_zero_at_1: public std::binary_function<_P,Algebraic,bool>{ typedef _P P; typedef _Gcd_policy Gcd; typedef Sign_at_1 Sign_at; bool operator()(const P &p,const Algebraic &a)const{ return (Sign_at()(p,a)==CGAL::ZERO); } }; // Is_zero_at_1 template struct Compare_1: public std::binary_function{ typedef _Gcd_policy Gcd; typedef CGAL::Comparison_result Comparison_result; typedef CGAL::Gmpz Gmpz; typedef CGAL::Gmpq Gmpq; Comparison_result operator()(const Algebraic &r1,const Algebraic &r2)const{ return CGAL::RS_COMPARE::compare_1(r1,r2); } Comparison_result operator()(const int &r1, const Algebraic &r2)const{ return this->operator()(Algebraic(r1),r2);} Comparison_result operator()(const Bound &r1,const Algebraic &r2)const{ return this->operator()(Algebraic(r1),r2);} Comparison_result operator()(const Gmpz &r1, const Algebraic &r2)const{ return this->operator()(Algebraic(r1),r2);} Comparison_result operator()(const Gmpq &r1, const Algebraic &r2)const{ return this->operator()(Algebraic(r1),r2);} Comparison_result operator()(const Algebraic &r1,const int &r2)const{ return this->operator()(r1,Algebraic(r2));} Comparison_result operator()(const Algebraic &r1,const Bound &r2)const{ return this->operator()(r1,Algebraic(r2));} Comparison_result operator()(const Algebraic &r1,const Gmpz &r2)const{ return this->operator()(r1,Algebraic(r2));} Comparison_result operator()(const Algebraic &r1,const Gmpq &r2)const{ return this->operator()(r1,Algebraic(r2));} }; // Compare_1 template struct Isolate_1: public std::binary_function >{ typedef _P Poly; typedef _Gcd Gcd; typedef CGAL::to_rs_poly convert; typedef Solve_1 Solve; typedef Compare_1 Compare; std::pair operator()(const Algebraic &a,const Poly &p)const{ std::vector roots; std::back_insert_iterator > rootsit(roots); Solve()(p,true,rootsit); for(std::vector::size_type i=0;i struct Bound_between_1: public std::binary_function{ typedef _Gcd_policy Gcd; Bound operator()(const Algebraic &x1,const Algebraic &x2)const{ double l,r,m; switch(CGAL::RS_COMPARE::compare_1(x1,x2)){ case CGAL::LARGER: CGAL_assertion(x2.sup() x1.inf().get_precision()? 1+x2.sup().get_precision(): 1+x1.inf().get_precision()))/2; break; case CGAL::SMALLER: CGAL_assertion(x1.sup() x2.inf().get_precision()? 1+x1.sup().get_precision(): 1+x2.inf().get_precision()))/2; break; default: CGAL_error_msg("bound between two equal numbers"); } } }; // Bound_between_1 struct Approximate_absolute_1: public std::binary_function >{ std::pair operator()(const Algebraic& x, int prec) const { RS3::refine_1(x,CGAL::abs(prec)); CGAL_postcondition_code( CGAL::Gmpfr::Precision_type subprec=1+ std::max(x.inf().get_precision(), x.sup().get_precision()); CGAL::Gmpfr width=CGAL::Gmpfr::sub(x.sup(),x.inf(),subprec); ) CGAL_postcondition_code(if(prec>0)) CGAL_postcondition(width*CGAL::ipower(Bound(2),prec)<=Bound(1)); CGAL_postcondition_code(else) CGAL_postcondition(width<=CGAL::ipower(Bound(2),-prec)); return std::make_pair(x.inf(),x.sup()); } }; struct Approximate_relative_1 :public std::binary_function >{ std::pair operator()(const Algebraic &x, int prec) const { if(CGAL::is_zero(x)) return std::make_pair(Bound(0),Bound(0)); Bound error=CGAL::ipower(Bound(2),CGAL::abs(prec)); Bound max_b=(CGAL::max)(CGAL::abs(x.sup()),CGAL::abs(x.inf())); while(prec>0? (x.sup()-x.inf())*error>max_b: (x.sup()-x.inf())>error*max_b){ RS3::refine_1(x,mpfi_get_prec(x.mpfi())+CGAL::abs(prec)); max_b=(CGAL::max)(CGAL::abs(x.sup()),CGAL::abs(x.inf())); } CGAL_postcondition_code(if(prec>0)) CGAL_postcondition((x.sup()-x.inf())*CGAL::ipower(Bound(2),prec)<=max_b); CGAL_postcondition_code(else) CGAL_postcondition((x.sup()-x.inf())<=CGAL::ipower(Bound(2),-prec)*max_b); return std::make_pair(x.inf(),x.sup()); } }; } // namespace RSFunctors #undef CGAL_RS_FUNCTORS_DBL_PREC #endif // CGAL_RS_FUNCTORS_H