00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <algebramix/polynomial_integer.hpp>
00022 #include <multimix/sparse_polynomial.hpp>
00023 #include <multimix/multivariate.hpp>
00024 #include <factorix/irreducible_polynomial_integer.hpp>
00025 #include <factorix/irreducible_polynomial_rational.hpp>
00026
00027 namespace mmx {
00028
00029 #define Monomial monomial< vector<E> >
00030 #define Sparse_polynomial sparse_polynomial<C, Monomial, V>
00031 #define Univariate_polynomial polynomial<C>
00032 #define Univariate_factor irreducible_factor<polynomial <rational> >
00033 #define Univariate_factors vector<Univariate_factor>
00034 #define Sparse_factor irreducible_factor<Sparse_polynomial>
00035 #define Sparse_factors vector<Sparse_factor>
00036
00037
00038 namespace lacunaryx {
00039 template<typename C, typename V, typename M, typename W>
00040 void set_as_polynomial (polynomial<C,V> &p, const sparse_polynomial<C,M,W> &q) {
00041
00042 nat n= as<nat> (deg(q)+1);
00043 nat l= aligned_size<C,V>(n);
00044 C* c= mmx_new<C>(l,promote(0,CF(q)));
00045 for (nat i=0; i<N(q); i++)
00046 c[as<nat> (deg(get_monomial(q,i)))]= get_coefficient(q,i);
00047 p= polynomial<C,V>(c,n,l,CF(q));
00048 }
00049
00050 template<typename C, typename M, typename W>
00051 polynomial<C> as_polynomial (const sparse_polynomial<C,M,W> &q) {
00052 polynomial<C> p (CF(q));
00053 set_as_polynomial(p,q);
00054 return p;
00055 }
00056
00057
00058 template<typename C>
00059 nat multiplicity (const Univariate_polynomial& f,
00060 const Univariate_polynomial& p) {
00061 nat m=0;
00062 Univariate_polynomial q= copy(p);
00063 while (divides (f,q)) {
00064 m+=1;
00065 q=derive (q);
00066 }
00067 return m;
00068 }
00069
00070 template<typename C, typename E, typename V>
00071 Sparse_polynomial
00072 as_sparse_polynomial (const polynomial<rational>& q) {
00073 vector<C> coefficients;
00074 vector<Monomial> monomials;
00075 C lcm_den=1;
00076 for (nat i=0; i<N(q); i++) {
00077 rational c= q[i];
00078 if (c != 0) lcm_den= lcm(lcm_den,as<C> (denominator (c)));
00079 }
00080 for (nat i=0; i<N(q); i++) {
00081 rational c= q[i];
00082 if (c != 0) {
00083 C num= as<C> (numerator (c));
00084 C den= as<C> (denominator (c));
00085 coefficients << num*(lcm_den/den);
00086 monomials << Monomial (vec(i));
00087 }
00088 }
00089 return Sparse_polynomial (coefficients, monomials, 1);
00090 }
00091
00092 template<typename C, typename E, typename V>
00093 Sparse_factor as_sparse_factor (const Univariate_factor& f) {
00094 return Sparse_factor (as_sparse_polynomial<C,E,V> (f.f), f.m);
00095 }
00096
00097 template<typename C, typename E, typename V>
00098 Sparse_factors
00099 intersect_factors (const Sparse_factors& f1,
00100 const Sparse_factors& f2) {
00101 Sparse_factors f;
00102 for (nat i=0; i<N(f1); i++) {
00103 for (nat j=0; j<N(f2); j++) {
00104 if ((f1[i].f == f2[j].f) || (f1[i].f == -f2[j].f)) {
00105 if ( f1[i].m < f2[j].m ) f << f1[i];
00106 else f << f2[j];
00107 break;
00108 }
00109 }
00110 }
00111 return f;
00112 }
00113
00114 template<typename E, typename C, typename V>
00115 Sparse_polynomial sparse_derive (const Sparse_polynomial& p) {
00116
00117 E d= deg(get_monomial(p,0));
00118 vector<Monomial> monomials= fill<Monomial> (vec(0),N(p)-1);
00119 vector<C> coefficients= fill<C> (0,N(p)-1);
00120
00121 for (nat i=1; i<N(p); i++) {
00122 pair<C,Monomial> term= p[i];
00123 monomials[i-1]= cdr(term)/Monomial(vec(d+1));
00124 coefficients[i-1]= car(term)*(as<C> (deg (cdr (term)) - d));
00125 }
00126
00127 return Sparse_polynomial(coefficients,monomials,1);
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 }
00141
00142 using namespace lacunaryx;
00143
00144
00145 template<typename E, typename C, typename V>
00146 C gap_univariate (const Sparse_polynomial& p) {
00147 C g=0;
00148 Sparse_polynomial q= copy(p);
00149
00150 for (nat i=0; i<N(p); i++) {
00151 C max_coeff= abs (get_coefficient (q,0));
00152 for (nat j=1; j<N(q); j++) {
00153 C curr_coeff = abs (get_coefficient (q,j));
00154 if (curr_coeff > max_coeff) max_coeff= curr_coeff;
00155 }
00156 C length= as<C> (N(q)-1);
00157 g= max (g, as<C> (bit_size (length*max_coeff)));
00158 q= sparse_derive (q);
00159 }
00160
00161 return g;
00162 }
00163
00164 template<typename E, typename C, typename V>
00165 vector<Sparse_polynomial>
00166 partition_univariate (const Sparse_polynomial& q, E g) {
00167 E prev_exponent= deg(get_monomial(q,0));
00168 E curr_exponent;
00169 vector<Sparse_polynomial> polys;
00170 Sparse_polynomial tmp;
00171 nat index_min=0;
00172
00173 for (nat i=1; i<N(q); i++) {
00174
00175 curr_exponent= deg(get_monomial(q,i));
00176
00177 if ( curr_exponent - prev_exponent > g ) {
00178 tmp= range (q,index_min,i);
00179 tmp /= Monomial (vec (val(tmp)));
00180 polys << tmp;
00181 prev_exponent = curr_exponent;
00182 index_min= i;
00183 }
00184 else prev_exponent= curr_exponent;
00185 }
00186 tmp= range(q, index_min, N(q));
00187 tmp /= Monomial (vec (val(tmp)));
00188 polys << tmp;
00189
00190 return polys;
00191 }
00192
00193 template<typename C, typename E, typename V>
00194 nat multiplicity (const Sparse_polynomial& f, const Sparse_polynomial& p) {
00195 Univariate_polynomial f_dense= as_polynomial (f);
00196 if (f_dense[0] == 0) return as<nat> (deg (get_monomial (p,0)));
00197 if (f_dense[0] == -f_dense[1]) {
00198 Sparse_polynomial q= copy(p);
00199 for (nat i=0; i<N(p); i++) {
00200 C s=0;
00201 for (nat j=0; j<N(q); j++) s+= get_coefficient (q,j);
00202 if ( s != 0 ) return i;
00203 q= sparse_derive (q);
00204 }
00205 return N(p)-1;
00206 }
00207 if (f_dense[0] == f_dense[1]) {
00208 Sparse_polynomial q= copy(p);
00209 for (nat i=0; i<N(p); i++) {
00210 C s=0;
00211 for (nat j=0; j<N(q); j++)
00212 s+= get_coefficient (q,j) * binpow(-1, deg (get_monomial (q,j)) % 2);
00213 if ( s != 0 ) return i;
00214 q= sparse_derive (q);
00215 }
00216 return N(p)-1;
00217 }
00218 E gap= as<E> (gap_univariate (p));
00219 vector<Sparse_polynomial> polys= partition_univariate(p, gap);
00220 nat m= multiplicity (f_dense, as_polynomial (polys[0]));
00221 for ( nat i=0; i < N( polys ); i++ ) {
00222 nat mm= multiplicity (f_dense, as_polynomial (polys[i]));
00223 if (mm == 0) return mm;
00224 if (mm < m) m=mm;
00225 }
00226 return m;
00227 }
00228
00229 template<typename E, typename C, typename V>
00230 Sparse_factors
00231 non_cyclotomic_factors (const Sparse_polynomial &q, E gap) {
00232 vector<Sparse_polynomial> polys= partition_univariate(q, gap);
00233 vector<Univariate_polynomial> vp (as <Univariate_polynomial> (0),N(polys));
00234
00235 for ( nat i=0; i < N( polys ); i++ ) vp[i]= as_polynomial (polys[i]);
00236
00237 Univariate_polynomial g= primitive_part ( big<gcd_op> ( vp ));
00238 polynomial<rational> g_rat= as<polynomial <rational> > (g);
00239 Univariate_factors fact= bounded_irreducible_factorization (g_rat, 2);
00240
00241
00242 Sparse_factors sparse_fact;
00243 for (nat i=0; i < N(fact); i++)
00244 {
00245 polynomial<rational> f=factor(fact[i]);
00246 if ( deg(f) == 1 && abs(f[1]*f[0]) != 1 ) {
00247 sparse_fact << as_sparse_factor<C,E,V> (fact[i]);
00248 }
00249 }
00250
00251 return sparse_fact;
00252 }
00253
00254 template<typename E, typename C, typename V>
00255 Sparse_factors
00256 cyclotomic_factors (const Sparse_polynomial &p ){
00257
00258 Sparse_factors f;
00259 Sparse_polynomial x ((C)1, Monomial (vec(1)));
00260 Sparse_polynomial q= copy(p);
00261 nat mul1=0;
00262 nat mul2=0;
00263 C s;
00264
00265 for (nat i=0; i<N(p); i++){
00266
00267
00268 if (mul1 == i) {
00269 s=0;
00270 for (nat j=0; j<N(q); j++) s+= get_coefficient (q,j);
00271 if ( s == 0 ) mul1=i+1;
00272 }
00273
00274
00275 if (mul2 == i) {
00276 s=0;
00277 for (nat j=0; j<N(q); j++)
00278 s+= get_coefficient (q,j) * binpow(-1, deg (get_monomial (q,j)) % 2);
00279 if ( s == 0 ) mul2=i+1;
00280 }
00281
00282 if ( mul1 < i+1 && mul2 < i+1 ) break;
00283
00284 q= sparse_derive (q);
00285 }
00286
00287 if (mul1 > 0) f << Sparse_factor (x-1,mul1);
00288 if (mul2 > 0) f << Sparse_factor (x+1,mul2);
00289
00290 return f;
00291 }
00292
00293 template<typename E, typename C, typename V>
00294 pair<C,vector <Sparse_factor> >
00295 gap_and_cyclotomic_factors (const Sparse_polynomial &p ){
00296
00297 Sparse_polynomial q= copy(p);
00298
00299
00300 vector <Sparse_factor> f;
00301 Sparse_polynomial x ((C)1, Monomial (vec(1)));
00302 nat mul1=0;
00303 nat mul2=0;
00304 C s1, s2;
00305
00306
00307 C g=0;
00308
00309 for (nat i=0; i<N(p); i++){
00310
00311 if (mul1 == i) s1=get_coefficient(q,0);
00312 if (mul2 == i)
00313 s2=get_coefficient(q,0) * binpow(-1, deg (get_monomial(q,0)) % 2);
00314 C max_coeff= abs (get_coefficient(q,0));
00315
00316 for (nat j=1; j<N(q); j++) {
00317
00318 if (mul1 == i) s1+= get_coefficient (q,j);
00319 if (mul2 == i)
00320 s2+= get_coefficient (q,j) * binpow(-1, deg (get_monomial(q,j)) % 2);
00321
00322 C curr_coeff = abs (get_coefficient (q,j));
00323 if (curr_coeff > max_coeff) max_coeff= curr_coeff;
00324 }
00325
00326 if (mul1 == i && s1 == 0) mul1=i+1;
00327 if (mul2 == i && s2 == 0) mul2=i+1;
00328
00329 C length= as<C> (N(q)-1);
00330 g= max (g, as<C> (bit_size(length*max_coeff)) );
00331 q= sparse_derive (q);
00332 }
00333
00334 if (mul1 > 0) f << Sparse_factor (x-1,mul1);
00335 if (mul2 > 0) f << Sparse_factor (x+1,mul2);
00336
00337 pair<C, vector <Sparse_factor> > result(g,f);
00338
00339 return result;
00340 }
00341
00342 template<typename E, typename C, typename V>
00343 Sparse_factors
00344 linear_factors_univariate ( const Sparse_polynomial &q ){
00345 Sparse_polynomial x ((C)1, Monomial (vec(1)));
00346 Sparse_factors f;
00347 nat v= as<nat> (val(q));
00348
00349 pair<C, vector <Sparse_factor> > gap_cyclo= gap_and_cyclotomic_factors (q);
00350 E gap= as<E> (car (gap_cyclo));
00351
00352 Sparse_factors cyclotomic_fact= cdr (gap_cyclo);
00353
00354 if ( v > 0 ) f << Sparse_factor( x , v );
00355 f << cyclotomic_fact;
00356 f << non_cyclotomic_factors (q,gap);
00357 return f;
00358 }
00359
00360 #undef Monomial
00361 #undef Sparse_polynomial
00362 #undef Univariate_polynomial
00363 #undef Univariate_factor
00364 #undef Univariate_factors
00365 #undef Sparse_factor
00366 #undef Sparse_factors
00367
00368 }