00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <lacunaryx/linear_factors_univariate.hpp>
00022 #include <factorix/irreducible_polynomial_polynomial.hpp>
00023
00024 namespace mmx {
00025
00026 #define Monomial monomial< vector<E> >
00027 #define Sparse_polynomial sparse_polynomial<C, Monomial, V>
00028 #define Univariate_polynomial polynomial<C>
00029 #define Bivariate_polynomial polynomial<polynomial<C> >
00030 #define Bivariate_factor irreducible_factor< polynomial <polynomial<rational> > >
00031 #define Bivariate_factors vector<Bivariate_factor>
00032 #define Sparse_factor irreducible_factor<Sparse_polynomial>
00033 #define Sparse_factors vector<Sparse_factor>
00034
00035 namespace lacunaryx {
00036 template<typename C, typename V1, typename V2, typename M, typename W>
00037 void set_as_bivariate_polynomial (polynomial<polynomial<C,V2>,V1>& p,
00038 const sparse_polynomial<C,M,W>& q) {
00039 nat n1= 1 + as<nat> (deg (q,0));
00040 vector<nat> n2 (0u, n1);
00041 for (nat i= 0; i < N(q); i++) {
00042 nat e1= as<nat> (deg (get_monomial (q, i),0));
00043 nat e2= as<nat> (deg (get_monomial (q, i),1));
00044 n2[e1]= max (n2[e1], e2);
00045 }
00046 n2= n2+1;
00047 vector<C*> buf ((C*) NULL,n1);
00048 vector<nat> l2 (0u, n1);
00049 for (nat i= 0; i < n1; i++) {
00050 l2[i]= aligned_size<C,V2> (n2[i]);
00051 buf[i]= mmx_new<C> (l2[i], promote (0,CF(q)));
00052 }
00053
00054 for (nat i= 0; i < N(q); i++) {
00055 nat e1= as<nat> (deg (get_monomial (q, i),0));
00056 nat e2= as<nat> (deg (get_monomial (q, i),1));
00057 buf[e1][e2]= get_coefficient (q, i);
00058 }
00059 nat l1= aligned_size<C,V2> (n1);
00060 polynomial<C,V2>* c1= mmx_new<polynomial<C,V2> > (l1);
00061 for (nat i= 0; i < n1; i++)
00062 c1[i]= polynomial<C,V2> (buf[i],n2[i],l2[i],CF(q));
00063 polynomial<C,V2> sample (CF(q));
00064 p= polynomial<polynomial<C,V2>,V1> (c1, n1, l1, get_format (sample));
00065
00066 }
00067
00068 template<typename C, typename M, typename W>
00069 polynomial<polynomial<C> > as_bivariate_polynomial (const sparse_polynomial<C,M,W> &q) {
00070 polynomial<C> sample (CF(q));
00071 polynomial<polynomial<C> > p (get_format (sample));
00072 set_as_bivariate_polynomial(p,q);
00073 return p;
00074 }
00075
00076 template<typename C, typename E, typename V>
00077 Sparse_polynomial
00078 as_sparse_polynomial (const polynomial< polynomial<rational> >& q) {
00079 vector< polynomial<rational> > v= coefficients(q);
00080 vector<C> coefficients;
00081 vector<Monomial> monomials;
00082 C lcm_den=1;
00083 for (nat i=0; i<N(v); i++) {
00084 for (nat j=0; j<N(v[i]); j++) {
00085 rational c= v[i][j];
00086 if (c != 0) lcm_den= lcm (lcm_den, as<C> (denominator (c)));
00087 }
00088 }
00089 for (nat i=0; i<N(v); i++) {
00090 for (nat j=0; j<N(v[i]); j++) {
00091 rational c= v[i][j];
00092 if (c != 0) {
00093 C num= as<C> (numerator (c));
00094 C den= as<C> (denominator (c));
00095 coefficients << num*lcm_den/den;
00096 monomials << Monomial (vec(i,j));
00097 }
00098 }
00099 }
00100 return Sparse_polynomial (coefficients, monomials, 2);
00101 }
00102
00103 template<typename C, typename E, typename V>
00104 Sparse_factor as_sparse_factor (const Bivariate_factor& f) {
00105 return Sparse_factor (as_sparse_polynomial<C,E,V> (f.f), f.m);
00106 }
00107
00108 template<typename C, typename E, typename V>
00109 Sparse_polynomial homogenize(const Sparse_polynomial& p) {
00110
00111 E d= deg(p);
00112 vector<Monomial> v= supp(p);
00113 for (nat i=0; i<N(v); i++) {
00114 E dm= deg (v[i],0);
00115 v[i]= Monomial (vec (dm,d-dm));
00116 }
00117 return Sparse_polynomial ( coefficients(p), v, 2);
00118 }
00119
00120 template<typename E, typename C, typename V>
00121 E w_deg (const Sparse_polynomial& p, vector<E> w) {
00122 return dot (multi_deg(p), w);
00123 }
00124
00125 template<typename E>
00126 E w_deg (const Monomial m, vector<E> w) {
00127 return dot (multi_deg(m),w);
00128 }
00129
00130
00131 template<typename E, typename C, typename V>
00132 vector<nat> sort_poly (const Sparse_polynomial& q, vector<E> w) {
00133 vector<E> degrees= fill<E>(0,N(q));
00134 vector<nat> order= fill<nat>(0,N(q));
00135
00136 for (nat i=0; i<N(q); i++) {
00137 Monomial m= get_monomial(q,i);
00138 degrees[i]= w_deg(m,w);
00139 }
00140
00141 sort (degrees, order);
00142 return order;
00143 }
00144
00145
00146 template<typename E, typename C, typename V>
00147 vector<nat> sort_poly (const Sparse_polynomial& q, nat var) {
00148 vector<E> degrees= fill<E>(0,N(q));
00149 vector<nat> order= fill<nat>(0,N(q));
00150
00151 for (nat i=0; i<N(q); i++) {
00152 Monomial m= get_monomial(q,i);
00153 degrees[i]= deg(m,var);
00154 }
00155
00156 sort (degrees, order);
00157 return order;
00158 }
00159
00160 template<typename E, typename C, typename V>
00161 vector<Sparse_polynomial>
00162 w_homogeneous_parts (const Sparse_polynomial& p, vector<E> w) {
00163 vector<nat> o= sort_poly(p,w);
00164 vector<Sparse_polynomial> v;
00165
00166 E d= w_deg (get_monomial (p,o[0]), w);
00167 nat imin=0;
00168 for (nat i=1; i<N(p); i++) {
00169 if (w_deg (get_monomial (p,o[i]), w) > d) {
00170 v << range_permute(p, imin, i, o);
00171 imin=i;
00172 d= w_deg (get_monomial (p,o[i]), w);
00173 }
00174 }
00175 v << range_permute(p, imin, N(p), o);
00176 return v;
00177 }
00178
00179 }
00180
00181 using namespace lacunaryx;
00182
00183
00184 template<typename E, typename C, typename V>
00185 vector<Sparse_polynomial>
00186 partition_bivariate_helper (const Sparse_polynomial &q, nat var ) {
00187
00188 vector<nat> order= sort_poly( q, var );
00189
00190 E min_exponent= deg(get_monomial(q,order[0]),var);
00191 E curr_exponent;
00192 E accu=0;
00193 vector<Sparse_polynomial> polys;
00194 Sparse_polynomial tmp;
00195 nat index_min=0;
00196
00197 for (nat i=1; i<N(q); i++) {
00198
00199 curr_exponent= deg(get_monomial(q,order[i]),var);
00200
00201
00202
00203 if ( (curr_exponent - min_exponent) > accu ) {
00204 tmp= range_permute(q,index_min,i,order);
00205 tmp/= gcd_supp (tmp);
00206 polys << tmp;
00207 accu= 0;
00208 min_exponent= curr_exponent;
00209 index_min= i;
00210 } else {
00211 accu+=i;
00212 }
00213 }
00214 tmp= range_permute(q, index_min, N(q), order);
00215 tmp/= gcd_supp (tmp);
00216 polys << tmp;
00217 return polys;
00218 }
00219
00220
00221 template<typename E, typename C, typename V>
00222 vector<Sparse_polynomial>
00223 partition_bivariate(const Sparse_polynomial &p ) {
00224
00225 vector<Sparse_polynomial> current= vec(p);
00226 nat prev_length=0;
00227 nat curr_length= N( current );
00228
00229 while ( prev_length < curr_length ) {
00230
00231 prev_length= curr_length;
00232
00233
00234 for (nat i=0; i<2; i++) {
00235 vector<Sparse_polynomial> next;
00236 for (nat j=0; j<curr_length; j++) {
00237 next << partition_bivariate_helper( current[j], i );
00238 }
00239 current= next;
00240 curr_length= N(current);
00241 }
00242 }
00243
00244 return current;
00245 }
00246
00247 template<typename E, typename C, typename V>
00248 Sparse_factors
00249 truly_bivariate_linear_factors ( const Sparse_polynomial &p ) {
00250 vector<Sparse_polynomial> v= partition_bivariate (p);
00251
00252 Bivariate_polynomial q= as_bivariate_polynomial (v[0]);
00253 for (nat i=1; i<N(v); i++) {
00254 q= gcd (q, as_bivariate_polynomial (v[i]) );
00255 }
00256
00257 polynomial <polynomial<rational> > q_rat=
00258 as< polynomial <polynomial<rational> > > (q);
00259 Bivariate_factors f=
00260 bounded_irreducible_factorization(q_rat,2);
00261 Sparse_factors ret;
00262 for (nat i=0; i<N(f); i++) {
00263 if (deg(f[i].f)==1 && deg(f[i].f[0])==1 && val(f[i].f[0])==0)
00264 ret << as_sparse_factor<C,E,V> (f[i]);
00265 }
00266 return ret;
00267 }
00268
00269 template<typename E, typename C, typename V>
00270 Sparse_factors
00271 linear_factors_bivariate_naive (const Sparse_polynomial &p) {
00272 Sparse_factors factors;
00273 vector<Sparse_polynomial> hom_comp;
00274 Sparse_factors lin_fact;
00275
00276
00277 hom_comp= w_homogeneous_parts(p, vec((E)0, (E)1));
00278 lin_fact= linear_factors_univariate (project (hom_comp[0],vec(0)));
00279 for (nat i=1; i<N(hom_comp); i++) {
00280 Sparse_factors tmp_fact=
00281 linear_factors_univariate (project (hom_comp[i],vec(0)));
00282 lin_fact= intersect_factors (tmp_fact, lin_fact);
00283 }
00284 for (nat i=0; i<N(lin_fact); i++)
00285 factors << Sparse_factor (inject (lin_fact[i].f, vec(0), 2), lin_fact[i].m);
00286
00287
00288 hom_comp= w_homogeneous_parts(p,vec((E)1, (E)0));
00289 lin_fact= linear_factors_univariate (project (hom_comp[0],vec(1)));
00290 for (nat i=1; i<N(hom_comp); i++) {
00291 Sparse_factors tmp_fact=
00292 linear_factors_univariate (project (hom_comp[i],vec(1)));
00293 lin_fact= intersect_factors (tmp_fact, lin_fact);
00294 }
00295 for (nat i=0; i<N(lin_fact); i++)
00296 factors << Sparse_factor (inject (lin_fact[i].f, vec(1), 2), lin_fact[i].m);
00297
00298
00299 hom_comp= w_homogeneous_parts(p,vec((E)1, (E)1));
00300 lin_fact= linear_factors_univariate (project (hom_comp[0],vec(0)));
00301 for (nat i=1; i<N(hom_comp); i++) {
00302 Sparse_factors tmp_fact=
00303 linear_factors_univariate (project (hom_comp[i],vec(0)));
00304 lin_fact= intersect_factors (tmp_fact, lin_fact);
00305 }
00306 for (nat i=0; i<N(lin_fact); i++)
00307 if (val (lin_fact[i].f) == 0)
00308 factors << Sparse_factor (homogenize (lin_fact[i].f), lin_fact[i].m);
00309
00310
00311 Sparse_factors tbf= truly_bivariate_linear_factors(p);
00312 for (nat i=0; i<N(tbf); i++) factors << tbf[i];
00313
00314 return factors;
00315 }
00316
00317 template<typename E, typename C, typename V>
00318 Sparse_factors
00319 linear_factors_bivariate (const Sparse_polynomial &p) {
00320 Sparse_factors factors;
00321 vector<Sparse_polynomial> hom_comp;
00322 Sparse_factors lin_fact;
00323
00324
00325 hom_comp= w_homogeneous_parts(p, vec((E)0, (E)1));
00326 hom_comp[0]= project (hom_comp[0],vec(0));
00327 nat Nmin= N(hom_comp[0]);
00328 nat index=0;
00329 for (nat i=1; i<N(hom_comp); i++) {
00330 hom_comp[i]= project (hom_comp[i],vec(0));
00331 if (N(hom_comp[i]) < Nmin) {
00332 Nmin= N(hom_comp[i]);
00333 index=i;
00334 }
00335 }
00336 lin_fact= linear_factors_univariate (hom_comp[index]);
00337 for (nat i=0; i<N(hom_comp); i++) {
00338 if (i != index) {
00339 Sparse_factors tmp_fact;
00340 for (nat j=0; j<N(lin_fact); j++) {
00341 nat m= multiplicity (lin_fact[j].f, hom_comp[i]);
00342 if (m > 0)
00343 tmp_fact << Sparse_factor (lin_fact[j].f, min(lin_fact[j].m,m));
00344 }
00345 lin_fact= tmp_fact;
00346 }
00347 }
00348 for (nat i=0; i<N(lin_fact); i++)
00349 factors << Sparse_factor (inject (lin_fact[i].f, vec(0), 2), lin_fact[i].m);
00350
00351
00352 hom_comp= w_homogeneous_parts(p,vec((E)1, (E)0));
00353 hom_comp[0]= project (hom_comp[0],vec(1));
00354 Nmin= N(hom_comp[0]);
00355 index=0;
00356 for (nat i=1; i<N(hom_comp); i++) {
00357 hom_comp[i]= project (hom_comp[i],vec(1));
00358 if (N(hom_comp[i]) < Nmin) {
00359 Nmin= N(hom_comp[i]);
00360 index=i;
00361 }
00362 }
00363 lin_fact= linear_factors_univariate (hom_comp[index]);
00364 for (nat i=0; i<N(hom_comp); i++) {
00365 if (i != index) {
00366 Sparse_factors tmp_fact;
00367 for (nat j=0; j<N(lin_fact); j++) {
00368 nat m= multiplicity (lin_fact[j].f,hom_comp[i]);
00369 if (m > 0)
00370 tmp_fact << Sparse_factor (lin_fact[j].f, min(lin_fact[j].m,m));
00371 }
00372 lin_fact= tmp_fact;
00373 }
00374 }
00375 for (nat i=0; i<N(lin_fact); i++)
00376 factors << Sparse_factor (inject (lin_fact[i].f, vec(1), 2), lin_fact[i].m);
00377
00378
00379 hom_comp= w_homogeneous_parts(p,vec((E)1, (E)1));
00380 hom_comp[0]= project (hom_comp[0],vec(0));
00381 Nmin= N(hom_comp[0]);
00382 index=0;
00383 for (nat i=1; i<N(hom_comp); i++) {
00384 hom_comp[i]= project (hom_comp[i],vec(0));
00385 if ( N(hom_comp[i]) < Nmin) {
00386 Nmin= N(hom_comp[i]);
00387 index=i;
00388 }
00389 }
00390 lin_fact= linear_factors_univariate (hom_comp[index]);
00391 for (nat i=0; i<N(hom_comp); i++) {
00392 if (i != index) {
00393 Sparse_factors tmp_fact;
00394 for (nat j=0; j<N(lin_fact); j++) {
00395 nat m= multiplicity (lin_fact[j].f, hom_comp[i]);
00396 if (m > 0)
00397 tmp_fact << Sparse_factor (lin_fact[j].f, min(lin_fact[j].m,m));
00398 }
00399 lin_fact= tmp_fact;
00400 }
00401 }
00402 for (nat i=0; i<N(lin_fact); i++)
00403 if (val (lin_fact[i].f) == 0)
00404 factors << Sparse_factor (homogenize (lin_fact[i].f), lin_fact[i].m);
00405
00406
00407 Sparse_factors tbf= truly_bivariate_linear_factors(p);
00408 for (nat i=0; i<N(tbf); i++) factors << tbf[i];
00409
00410 return factors;
00411 }
00412
00413 #undef Monomial
00414 #undef Sparse_polynomial
00415 #undef Univariate_polynomial
00416 #undef Bivariate_polynomial
00417 #undef Bivariate_factor
00418 #undef Bivariate_factors
00419 #undef Sparse_factor
00420 #undef Sparse_factors
00421
00422 }