polyalg.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     polyalg.hpp
00004 
00005     This file is a part of Arageli library.
00006 
00007     Copyright (C) Nikolai Yu. Zolotykh, 1999--2006
00008     Copyright (C) Sergey S. Lyalin, 2005--2006
00009     University of Nizhni Novgorod, Russia
00010 
00011 *****************************************************************************/
00012 
00019 #ifndef _ARAGELI_polyalg_hpp_
00020 #define _ARAGELI_polyalg_hpp_
00021 
00022 #include "config.hpp"
00023 
00024 #include <cstddef>
00025 
00026 #include "type_traits.hpp"
00027 #include "factory.hpp"
00028 #include "_utility.hpp"
00029 #include "misc.hpp"
00030 
00031 
00032 #include "std_import.hpp"
00033 
00034 //****************************************************************************
00035 
00036 namespace Arageli
00037 {
00038 
00039 
00041 
00042 template <typename P1, typename P2, typename PQ, typename PR>
00043 void polynom_divide_simple
00044 (
00045     const P1& p1,
00046     const P2& p2,
00047     PQ& pq,
00048     PR& pr
00049 )
00050 {
00051     ARAGELI_ASSERT_0(!is_null(p2));
00052 
00053     pr = p1;
00054     pq = null(pq);
00055     const typename P2::monom& lmp2 = p2.leading_monom();
00056     typename PR::degree_type
00057         oldprdeg = pr.degree(),
00058         newprdeg = oldprdeg;
00059     const typename P2::degree_type p2deg = lmp2.degree();
00060     
00061     for(;;)
00062     {
00063         if(newprdeg < p2deg)break;
00064         ARAGELI_ASSERT_1(!is_null(pr));
00065         typename PR::monom mpr = pr.leading_monom();
00066         mpr /= lmp2;    // maybe integer division
00067         P2 tp2 = p2;
00068         oldprdeg = newprdeg;
00069         pr -= (tp2 *= mpr);
00070         newprdeg = pr.degree();
00071         ARAGELI_ASSERT_1(newprdeg <= oldprdeg);
00072         pq += mpr;
00073         if(newprdeg == oldprdeg)break;
00074     }
00075 }
00076 
00077 
00078 template <typename P1, typename P2, typename PQ, typename PR, typename T>
00079 void polynom_pseudodivide_simple
00080 (
00081     const P1& p1,
00082     const P2& p2,
00083     PQ& pq,
00084     PR& pr,
00085     T& multiplier
00086 )
00087 {
00088     ARAGELI_ASSERT_0(!is_null(p2));
00089 
00090     if(p1.degree() < p2.degree())
00091     {
00092         pq = null(pq);
00093         pr = p1;
00094         multiplier = unit(multiplier);
00095     }
00096     else
00097     {
00098         multiplier = power(p2.leading_coef(), p1.degree() - p2.degree() + 1);
00099         polynom_divide_simple(p1*multiplier, p2, pq, pr);
00100         //std::cout << "\npq = " << pq;
00101     }
00102 }
00103 
00104 
00105 template <typename P, typename T>
00106 T& polynom_rational_to_int_value (const P& p, T& res)
00107 {
00108     res = unit(res);
00109     
00110     for
00111     (
00112         typename P::coef_const_iterator i = p.coefs_begin();
00113         i != p.coefs_end();
00114         ++i
00115     )
00116         //res *= i->denominator();
00117         res = lcm(res, i->denominator());
00118 
00119     return res;
00120 }
00121 
00122 //extern int _my_counter_1, _my_counter_2;
00123 
00124 template <typename Pr, typename Pi, typename X>
00125 void polynom_rational_to_int (const Pr& pr, Pi& pi, const X& x)
00126 {
00127     pi = null(pi);
00128 
00129     typedef typename Pr::monom_const_iterator Pr_citer;
00130     typedef typename Pr::coef_type Pr_coef;
00131     typedef typename Pi::monom Pi_monom;
00132     Pr_citer pr_monoms_end = pr.monoms_end();
00133 
00134     // WARNING.  P1 and P1int, P2 and P2int should have the same monom order.
00135     
00136     for(Pr_citer i = pr.monoms_begin(); i != pr_monoms_end; ++i)
00137     {
00138         const Pr_coef& ic = i->coef();
00139         ARAGELI_ASSERT_0(is_divisible(x, ic.denominator()));
00140         
00141         pi.insert
00142         (
00143             pi.monoms_end(),
00144             Pi_monom(ic.numerator() * (x/ic.denominator()), i->degree())
00145         );
00146     }
00147 }
00148 
00149 
00150 template <typename P1, typename P2, typename PQ, typename PR>
00151 void polynom_divide_rational_simple
00152 (P1 p1, P2 p2, PQ& pq, PR& pr)
00153 {
00154     if(p1.degree() + p2.degree() <= 2 || p2.size() == 1)
00155     {
00156         polynom_divide_simple(p1, p2, pq, pr);
00157         /*_my_counter_1++*/;
00158         return;
00159     }
00160     else
00161         /*_my_counter_2++*/;
00162     
00163     typedef typename P1::coef_type P1coef;
00164     typedef typename P1coef::value_type P1int;
00165 
00166     // WARNING! Should other types (coef_type for P2, PQ and PR) be a rational too?
00167 
00168     typename P1::template other_coef<P1int>::type p1i;
00169     typename P2::template other_coef<P1int>::type p2i;
00170     typename PQ::template other_coef<P1int>::type pqi;
00171     typename PR::template other_coef<P1int>::type pri;
00172 
00173     // Compute normalization values.  After multiplication by them all coefficients
00174     // become integer.
00175 
00176     P1int m1, m2, multiplier;
00177     polynom_rational_to_int(p1, p1i, polynom_rational_to_int_value(p1, m1));
00178     polynom_rational_to_int(p2, p2i, polynom_rational_to_int_value(p2, m2));
00179 
00180     // perform pseudo division
00181     polynom_pseudodivide_simple(p1i, p2i, pqi, pri, multiplier);
00182 
00183     // restore correct quotient and remainder
00184 
00185     multiplier *= m1;
00186     pq = pqi; pr = pri;
00187     (pq *= m2) /= multiplier;
00188     pr /= multiplier;
00189 }
00190 
00191 
00192 template <typename P1, typename P2, typename PQ, typename PR>
00193 inline void polynom_divide
00194 (
00195     const P1& p1, const P2& p2, PQ& pq, PR& pr,
00196     const type_category::type&
00197 )
00198 { polynom_divide_simple(p1, p2, pq, pr); }
00199 
00200 
00201 template <typename P1, typename P2, typename PQ, typename PR>
00202 inline void polynom_divide
00203 (
00204     const P1& p1, const P2& p2, PQ& pq, PR& pr,
00205     const type_category::rational&
00206 )
00207 { polynom_divide_rational_simple(p1, p2, pq, pr); }
00208 
00209 
00210 template <typename P1, typename P2, typename PQ, typename PR>
00211 inline void polynom_divide
00212 (const P1& p1, const P2& p2, PQ& pq, PR& pr)
00213 {
00214     polynom_divide
00215     (
00216         p1, p2, pq, pr,
00217         type_traits<typename P1::coef_type>::category_value
00218     );
00219 }
00220 
00221 
00222 //template <typename P1, typename P2, typename PM>
00223 //void polynom_mult
00224 //(const P1& p1, const P2& p2, PM& pm)
00225 //{
00226 //  
00227 //}
00228 
00229 
00231 template <typename P, typename M>
00232 void sparse_polynom_reduction_mod (P& p, const M& m)
00233 {
00234     typedef typename P::coef_iterator Piter;
00235     Piter pend = p.coefs_end();
00236     for(Piter i = p.coefs_begin(); i != pend;)
00237         if(is_null(*i = prrem(*i, m)))
00238             i = Piter(p.erase(i.base()));
00239         else ++i;
00240 }
00241 
00242 
00244 template <typename P>
00245 typename P::coef_type max_abs_coef (const P& p)
00246 {
00247     ARAGELI_ASSERT_0(!p.is_null());
00248     typename P::coef_type res = null<typename P::coef_type>();
00249     
00250     for(typename P::coef_const_iterator i = p.coefs_begin(); i != p.coefs_end(); ++i)   
00251     {
00252         typename P::coef_type absval = abs(*i);
00253         if(absval > res)res = absval;
00254     }
00255 
00256     return res;
00257 }
00258 
00259 
00261 template <typename P>
00262 typename P::coef_type max_abs_coef_wo_leading (const P& p)
00263 {
00264     ARAGELI_ASSERT_0(p.degree() > 0);
00265     typename P::coef_const_iterator i = p.coefs_end();
00266     --i;
00267     typename P::coef_type res = null(*i);
00268     if(i == p.coefs_begin())return res;
00269 
00270     do
00271     {
00272         --i;
00273         typename P::coef_type absval = abs(*i);
00274         if(absval > res)res = absval;
00275     }while(i != p.coefs_begin());
00276 
00277     return res;
00278 }
00279 
00280 
00281 template <typename P>
00282 typename P::coef_type polynom_content (const P& x)
00283 {
00284     typedef big_int T;
00285     T res = null<T>();
00286     for(typename P::coef_const_iterator i = x.coefs_begin(); i != x.coefs_end(); ++i)
00287         res = gcd(res, big_int(*i));
00288     return res;
00289 }
00290 
00291 
00292 template <typename P>
00293 inline P polynom_primpart (const P& x)
00294 { return x/polynom_content(x); }
00295 
00296 
00297 template <typename T, typename P>
00298 T root_upper_bound_cauchy (const P& p)
00299 {
00300     ARAGELI_ASSERT_0(p.degree() > 0);
00301     
00302     if(p.size() == 1)return null(p.leading_coef());
00303     else
00304         return unit<T>() +
00305             T(max_abs_coef_wo_leading(p))/abs(T(p.leading_coef()));
00306 }
00307 
00308 
00309 
00310 template <typename P, typename V>
00311 V& squarefree_factorize_poly_rational (const P& h, V& res)
00312 {
00313     //TODO: Make it faster!
00314     //TODO: Resolve normalization of the gcd result.
00315     
00316     res.resize(0);
00317     P g = gcd(h, diff(h));
00318     g /= safe_reference(g.leading_coef());
00319     
00320     P c, d;
00321 
00322     c = h/g;
00323     d = diff(h)/g - diff(c);
00324 
00325     while(!c.is_unit())
00326     {
00327         res.push_back(gcd(c, d));
00328         res.back() /= safe_reference(res.back().leading_coef());
00329         c = c/res.back();
00330         d = d/res.back() - diff(c);
00331     }
00332 
00333     return res;
00334 }
00335 
00336 
00337 
00338 template <typename P>
00339 P reciprocal_poly (const P& p)
00340 {
00341     P res;
00342     typedef typename P::monom monom;
00343     for(typename P::monom_const_iterator i = p.monoms_begin(); i != p.monoms_end(); ++i)
00344         res += monom(i->coef(), p.degree() - i->degree());
00345 
00346     //std::cout << "\nreciprocal_poly(" << p << ") = " << res;
00347 
00348     return res;
00349 }
00350 
00351 
00352 
00353 
00354 } // namespace Arageli
00355 
00356 
00357 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00358     #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYALG
00359 //  #include "polyalg.cpp"
00360     #undef  ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYALG
00361 #endif
00362 
00363 
00364 #endif  //  #ifndef _ARAGELI_polyalg_hpp_

Generated on Thu Aug 31 17:38:08 2006 for Arageli by  doxygen 1.4.7