00001
00002
00003
00004
00005
00006
00007
00008
00009
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;
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
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
00117 res = lcm(res, i->denominator());
00118
00119 return res;
00120 }
00121
00122
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
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 ;
00158 return;
00159 }
00160 else
00161 ;
00162
00163 typedef typename P1::coef_type P1coef;
00164 typedef typename P1coef::value_type P1int;
00165
00166
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
00174
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
00181 polynom_pseudodivide_simple(p1i, p2i, pqi, pri, multiplier);
00182
00183
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
00223
00224
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
00314
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
00347
00348 return res;
00349 }
00350
00351
00352
00353
00354 }
00355
00356
00357 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00358 #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYALG
00359
00360 #undef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYALG
00361 #endif
00362
00363
00364 #endif // #ifndef _ARAGELI_polyalg_hpp_