// Copyright (c) 2007-2009 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_POLYNOMIAL_1_UTILS_H #define CGAL_RS_POLYNOMIAL_1_UTILS_H #include #include #include #include #include #include #include #ifdef CGAL_USE_RS3 #include #endif namespace CGAL{ #ifdef CGAL_USE_RS3 // Fabrice's modular gcd algorithm struct Rsgcd_1: public std::binary_function{ RS_polynomial_1& operator()( const RS_polynomial_1 &p1, const RS_polynomial_1 &p2)const{ int dr,d1,d2; mpz_t * r_z; d1=p1.get_degree(); d2=p2.get_degree(); dr=rs3_up_mz_gcd( &r_z, (const mpz_t*)p1.get_coefs(), d1, (const mpz_t*)p2.get_coefs(), d2); RS_polynomial_1 *result=new RS_polynomial_1(&r_z,dr); return *result; } }; #endif struct Cgalgcd_1: public std::binary_function{ RS_polynomial_1& operator()( const RS_polynomial_1 &p1, const RS_polynomial_1 &p2)const{ typedef Polynomial P; typedef from_rs_poly

convert; typedef to_rs_poly

convertback; return convertback()(CGAL::gcd(convert()(p1),convert()(p2))); } }; // my modular gcd algorithm struct Modgcd_1: public std::binary_function{ RS_polynomial_1& operator()( const RS_polynomial_1 &u, const RS_polynomial_1 &v)const{ RS_polynomial_1 *result=new RS_polynomial_1( u.get_degree()get_coefs(), u.get_coefs(), u.get_degree_static(), v.get_coefs(), v.get_degree_static()); result->force_degree(dr); return *result; } }; // Cont()(c,u) stores in c the gcd of the coefficients of u struct Cont: public std::binary_function{ void operator()(mpz_ptr c,const RS_polynomial_1 &u){ mpz_set(c,u.coef(0)); for(int i=1;i{ RS_polynomial_1& operator()(const RS_polynomial_1 &u){ mpz_t c; mpz_init(c); Cont()(c,u); RS_polynomial_1 *res=new RS_polynomial_1(u/c); mpz_clear(c); return *res; } }; // pseudo division; returns , where: // d^l*f=qg+r, d=leadingcoef(f), l=max(deg(f)-deg(g)+1,0) struct Pdiv_1: public std::binary_function< RS_polynomial_1, RS_polynomial_1, std::pair >{ std::pair operator()(const RS_polynomial_1 &f,const RS_polynomial_1 &g){ int degf,degg,lambda,i; mpz_t d; mpz_ptr lcg; degf=f.get_degree(); degg=g.get_degree(); RS_polynomial_1 q(degf); RS_polynomial_1 r(f); lcg=g.leading_coefficient(); lambda=degf-degg+1; if(lambda>0){ mpz_init(d); mpz_pow_ui(d,g.leading_coefficient(),lambda); r*=d; mpz_clear(d); } if(!degg){ for(int i=0;i<=f.get_degree_static();++i) mpz_divexact(q.coef(i),r.coef(i),lcg); return std::make_pair(q,RS_polynomial_1()); } // don't use get_degree_static while((i=r.get_degree()-degg)>=0){ mpz_divexact(q.coef(i),r.leading_coefficient(),lcg); r-=g.times_monomial(q.coef(i),i); } return std::make_pair(q,r); } }; struct Pdivrem_1: public std::binary_function{ RS_polynomial_1 operator()(const RS_polynomial_1 &f,const RS_polynomial_1 &g){ return Pdiv_1()(f,g).second; } }; struct Pdivquo_1: public std::binary_function{ RS_polynomial_1 operator()(const RS_polynomial_1 &f,const RS_polynomial_1 &g){ return Pdiv_1()(f,g).first; } }; // subresultant GCD algorithm: // Knuth, TAOCP vol. 2, 2nd edition, section 4.6.1, algorithm C struct Gcd_1: public std::binary_function{ RS_polynomial_1& operator()( const RS_polynomial_1 &uu, const RS_polynomial_1 &vv)const{ RS_polynomial_1 u,r; RS_polynomial_1 *v=new RS_polynomial_1(vv.get_degree()); mpz_t contu,g,d,h,den_h; int delta; // C1. mpz_init(contu); Cont()(contu,uu); u=uu/contu; mpz_init(g); Cont()(g,vv); // g will store cont(v) *v=vv/g; mpz_init(d); mpz_gcd(d,contu,g); // we don't need cont(u) and cont(v) anymore; so we will use the // variables which stored them (we will use contu as a temp and g to // store the value g) mpz_set_ui(g,1); // now, g will store the g from the algorithm mpz_init_set_ui(h,1); mpz_init(den_h); // C2. while((r=Pdivrem_1()(u,*v)).get_degree_static()){ delta=u.get_degree()-v->get_degree(); // C3. u=*v; if(delta<0){ // v := r(x) * (gh^(-delta)) mpz_pow_ui(contu,h,(unsigned)(-delta)); mpz_mul(contu,g,contu); *v=r*contu; }else{ // v := r(x) / (gh^delta) mpz_pow_ui(contu,h,(unsigned)delta); mpz_mul(contu,g,contu); *v=r/contu; } mpz_set(g,u.leading_coefficient()); if(delta){ // if delta=0, h remains unchanged if(delta==1){ // if delta=1, h:=g mpz_set(h,g); }else{ // otherwise, h:=h^(1-delta)*g^delta if(delta>1){ mpz_pow_ui(den_h,h,(unsigned)(delta-1)); mpz_pow_ui(h,g,(unsigned)delta); mpz_divexact(h,h,den_h); }else{ // delta<0 mpz_pow_ui(h,h,(unsigned)(1-delta)); mpz_pow_ui(den_h,g,(unsigned)(-delta)); mpz_divexact(h,h,den_h); } } } } mpz_clear(contu); mpz_clear(g); mpz_clear(h); mpz_clear(den_h); if(mpz_sgn(r.coef(0))){ v->force_degree(0); // v(x)=1, so d*Pp()(v(x))=d v->set_coef(0,d); }else{ *v=Pp()(*v); *v*=d; } mpz_clear(d); return *v; } }; // exact division: the result is undefined when the division is not exact struct Ediv_1: public std::binary_function{ RS_polynomial_1* operator()(const RS_polynomial_1 &f,const RS_polynomial_1 &g){ /* int degf,degg,i; mpz_ptr lcg; mpz_t r; degf=f.get_degree(); degg=g.get_degree(); RS_polynomial_1 *q=new RS_polynomial_1(degf-degg); lcg=g.leading_coefficient(); if(!degg){ for(int i=0;i<=degf;++i) mpz_divexact(q->coef(i),f.coef(i),lcg); return q; } mpz_init(r); mpz_set(r,f.leading_coefficient()); std::cout<<"f="<