//Author(s) : Michael Hemmer /*! \file CGAL/modular_gcd.h provides gcd for Polynomials, based on Modular arithmetic. */ #ifndef CGAL_MODULAR_GCD_H #define CGAL_MODULAR_GCD_H 1 #include #include #include #include #include #include //#include namespace CGAL { template typename Scalar_factor_traits::Scalar scalar_factor(const NT& x){ typename Scalar_factor_traits::Scalar_factor scalar_factor; return scalar_factor(x); } template typename Scalar_factor_traits::Scalar scalar_factor(const NT& x,const typename Scalar_factor_traits::Scalar& d){ typename Scalar_factor_traits::Scalar_factor scalar_factor; return scalar_factor(x,d); } template typename Modular_traits::Modular_NT modular_image(const NT& x){ typename Modular_traits::Modular_image modular_image; return modular_image(x); } template class MY_INT_TAG{}; template bool operator < (const std::vector& a, const std::vector& b){ for(unsigned int i = 0; i < a.size(); i++){ if (a[i] < b[i]) return true; } return false; } template std::vector min(const std::vector& a, const std::vector& b){ return (a < b)?a:b; } //ALGORITHM P (TODO) template Polynomial algorithm_x( const Polynomial & p1, const Polynomial & p2, TAG){ CGAL_precondition(Polynomial_traits_d< Polynomial >::d > 1); typedef Polynomial Poly; typedef Polynomial_traits_d PT; typedef typename PT::Innermost_coefficient IC; const int num_of_vars = PT::d; typename PT::Innermost_leading_coefficient ilcoeff; typename PT::Degree_vector degree_vector; // will play the role of content typedef typename Scalar_factor_traits::Scalar Scalar; typedef typename Modular_traits::Modular_NT MPoly; typename Polynomial_traits_d::Degree_vector mdegree_vector; typedef typename Modular_traits::Modular_NT MScalar; typedef Chinese_remainder_traits CRT; typename CRT::Chinese_remainder chinese_remainder; typename Polynomial_traits_d::Canonicalize canonicalize; Poly F1 = canonicalize(p1); Poly F2 = canonicalize(p2); //std::cout <<" F1 : " << F1 <::Denominator_for_algebraic_integers dfai; typename Algebraic_extension_traits::Normalization_factor nfac; // in case IC is an algebriac extension it may happen, that // Fx=G*Hx is not possible if the coefficients are algebraic integers Poly tmp = F1+F2; IC denom = dfai(begin(tmp),end(tmp)); // TODO use this //IC denom = dfai(tmp.begin(),tmp.end()); denom *= nfac(denom); tmp = Poly(denom); F1 *=tmp; F2 *=tmp; } //std::cout <<" F1*denom*nafc: " << F1 < dv_F1 = degree_vector(F1); std::vector dv_F2 = degree_vector(F2); std::vector dv_e = min(dv_F1,dv_F2);; MScalar mg_; MPoly mF1,mF2,mG_,mH1,mH2; typename CRT::Scalar_type p,q,pq; Poly Gs,H1s,H2s; // s =^ star while(!solved){ do{ //--------------------------------------- //choose prime not deviding f1 or f2 do{ prime_index++; CGAL_precondition(0<= prime_index && prime_index < 64); int current_prime = primes[prime_index]; Modular::set_current_prime(current_prime); } while(!(( modular_image(f1) != 0 ) && ( modular_image(f2) != 0 ))); // -------------------------------------- // invoke gcd for current prime mg_ = CGAL::modular_image(g_); mF1 = CGAL::modular_image(F1_); mF2 = CGAL::modular_image(F2_); // replace mG_ = gcd (mF1,mF2)*MPoly(mg_); for multivariat mG_ = algorithm_x(mF1,mF2,MY_INT_TAG())*MPoly(mg_); mH1 = CGAL::integral_division(mF1,mG_); mH2 = CGAL::integral_division(mF2,mG_); //--------------------------------------- // return if G is constant if (mG_ == MPoly(1)) return Poly(1); // -------------------------------------- }// repeat until mG_ degree is less equal the known bound // check prime while( mdegree_vector(mG_) > dv_e); if(mdegree_vector(mG_) < dv_e ){ // restart chinese remainder // ignore previous unlucky primes n=1; dv_e= mdegree_vector(mG_); }else{ CGAL_postcondition( mdegree_vector(mG_)== dv_e); n++; // increase number of lucky primes } // -------------------------------------- // try chinese remainder //std::cout <<" chinese remainder round :" << n << std::endl; typename Modular_traits::Modular_image_inv inv_map; if(n == 1){ // init chinese remainder q = Modular::get_current_prime(); // implicit ! Gs = inv_map(mG_); H1s = inv_map(mH1); H2s = inv_map(mH2); }else{ // continue chinese remainder int p = Modular::get_current_prime(); // implicit! //std::cout <<" p: "<< p< Polynomial algorithm_x( const Polynomial & p1, const Polynomial & p2, MY_INT_TAG<1> ){ typedef Polynomial Poly; BOOST_STATIC_ASSERT(Polynomial_traits_d::d == 1); typedef Algebraic_structure_traits AST; typedef typename AST::Algebraic_category TAG; BOOST_STATIC_ASSERT((boost::is_same::value)); return gcd(p1,p2); } // TODO: ALGORITHM M template Polynomial modular_gcd_utcf( const Polynomial& FF1 , const Polynomial& FF2 ){ CGAL_precondition(Polynomial_traits_d >::d == 1); typedef Polynomial Poly; typedef Polynomial_traits_d PT; const int num_of_vars = PT::d; typedef typename PT::Innermost_coefficient IC; typename PT::Innermost_leading_coefficient ilcoeff; typename PT::Degree_vector degree_vector; // will paly the role of content typedef typename Scalar_factor_traits::Scalar Scalar; typedef typename Modular_traits::Modular_NT MPoly; typename Polynomial_traits_d::Degree_vector mdegree_vector; typedef typename Modular_traits::Modular_NT MScalar; typedef Chinese_remainder_traits CRT; typename CRT::Chinese_remainder chinese_remainder; typename Polynomial_traits_d::Canonicalize canonicalize; Poly F1 = canonicalize(FF1); Poly F2 = canonicalize(FF2); //std::cout <<" F1 : " << F1 < POLY; //typename Polynomial_traits_d::Innermost_coefficient_to_polynomial ictp; //typename Polynomial_traits_d::Innermost_coefficient_begin begin; //typename Polynomial_traits_d::Innermost_coefficient_end end; typename Algebraic_extension_traits::Denominator_for_algebraic_integers dfai; typename Algebraic_extension_traits::Normalization_factor nfac; // in case IC is an algebriac extension it may happen, that // Fx=G*Hx is not possible if the coefficients are algebraic integers Poly tmp = F1+F2; //IC denom = dfai(begin(tmp),end(tmp)); // TODO use this IC denom = dfai(tmp.begin(),tmp.end()); denom *= nfac(denom); tmp = Poly(denom); F1 *=tmp; F2 *=tmp; } //std::cout <<" F1*denom*nafc: " << F1 < dv_F1 = degree_vector(F1); std::vector dv_F2 = degree_vector(F1); std::vector dv_e = min(dv_F1,dv_F2);; MScalar mg_; MPoly mF1,mF2,mG_,mH1,mH2; typename CRT::Scalar_type p,q,pq; Poly Gs,H1s,H2s; // s =^ star while(!solved){ do{ //--------------------------------------- //choose prime not deviding f1 or f2 do{ prime_index++; CGAL_precondition(0<= prime_index && prime_index < 64); int current_prime = primes[prime_index]; Modular::set_current_prime(current_prime); } while(!(( modular_image(f1) != 0 ) && ( modular_image(f2) != 0 ))); // -------------------------------------- // invoke gcd for current prime mg_ = CGAL::modular_image(g_); mF1 = CGAL::modular_image(F1_); mF2 = CGAL::modular_image(F2_); // replace mG_ = gcd (mF1,mF2)*MPoly(mg_); for multivariat mG_ = algorithm_x(mF1,mF2,MY_INT_TAG())*MPoly(mg_); mH1 = CGAL::integral_division(mF1,mG_); mH2 = CGAL::integral_division(mF2,mG_); //--------------------------------------- // return if G is constant if (mG_ == MPoly(1)) return Poly(1); // -------------------------------------- }// repeat until mG_ degree is less equal the known bound // check prime while( mdegree_vector(mG_) > dv_e); if(mdegree_vector(mG_) < dv_e ){ // restart chinese remainder // ignore previous unlucky primes n=1; dv_e= mdegree_vector(mG_); }else{ CGAL_postcondition( mdegree_vector(mG_)== dv_e); n++; // increase number of lucky primes } // -------------------------------------- // try chinese remainder //std::cout <<" chinese remainder round :" << n << std::endl; typename Modular_traits::Modular_image_inv inv_map; if(n == 1){ // init chinese remainder q = Modular::get_current_prime(); // implicit ! Gs = inv_map(mG_); H1s = inv_map(mH1); H2s = inv_map(mH2); }else{ // continue chinese remainder int p = Modular::get_current_prime(); // implicit! //std::cout <<" p: "<< p<