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 <factorix/irreducible_polynomial_rational.hpp>
00023 #include <multimix/sparse_polynomial.hpp>
00024 #include <multimix/multivariate.hpp>
00025 #include <lacunaryx/lpolynomial.hpp>
00026
00027 namespace mmx {
00028
00029 #define Monomial monomial<vector<E> >
00030 #define Sparse_polynomial sparse_polynomial<C, Monomial, V>
00031 #define Dense_polynomial polynomial<C>
00032 #define Root pair<C,E>
00033
00034
00035 template<typename E, typename C, typename V>
00036 Sparse_polynomial sparse_derive (const Sparse_polynomial& p) {
00037 E d= deg(get_monomial(p,0));
00038 vector<Monomial> monomials= fill<Monomial> (vec(0),N(p)-1);
00039 vector<C> coefficients= fill<C> (0,N(p)-1);
00040
00041 for (nat i=1; i<N(p); i++) {
00042 pair<C,Monomial> term= p[i];
00043 monomials[i-1]= cdr(term)/Monomial(vec(d+1));
00044 coefficients[i-1]= car(term)*(as<C> (deg (cdr (term)) - d));
00045 }
00046
00047 return Sparse_polynomial(coefficients,monomials,1);
00048 }
00049
00050
00051
00052
00053 template<typename E, typename C, typename V>
00054 vector<Sparse_polynomial> partition (const Sparse_polynomial& q) {
00055 C max_coeff= abs(get_coefficient(q,0));
00056 E prev_exponent= deg(get_monomial(q,0));
00057 E curr_exponent;
00058 vector<Sparse_polynomial> polys;
00059 Sparse_polynomial tmp;
00060 nat index_min=0;
00061
00062 for (nat i=1; i<N(q); i++) {
00063
00064 curr_exponent= deg(get_monomial(q,i));
00065
00066 if ( curr_exponent - prev_exponent > bit_size( max_coeff ) ) {
00067 tmp= range (q,index_min,i);
00068 tmp /= Monomial (vec (val(tmp)));
00069 polys << tmp;
00070 prev_exponent = curr_exponent;
00071 max_coeff= abs(get_coefficient(q,i));
00072 index_min= i;
00073 } else {
00074 prev_exponent= curr_exponent;
00075 max_coeff= max(abs(get_coefficient(q,i)),max_coeff);
00076 }
00077 }
00078 tmp= range(q, index_min, N(q));
00079 tmp /= Monomial (vec (val(tmp)));
00080 polys << tmp;
00081
00082 return polys;
00083 }
00084
00085
00086 template<typename E, typename C, typename V>
00087 vector<Root>
00088 large_integer_roots (const Sparse_polynomial &q) {
00089 vector<Sparse_polynomial> polys= partition(q);
00090 vector<Dense_polynomial> vp (as<Dense_polynomial> (0),N(polys));
00091
00092 for ( nat i=0; i < N( polys ); i++ ) {
00093 Sparse_polynomial p= polys[i];
00094 vector<C> c(0, as<nat> (deg(p)+1));
00095 for ( nat j=0; j < N( p ); j++)
00096 c[as<nat> (deg(get_monomial(p,j)))]= get_coefficient(p,j);
00097 vp[i]= Dense_polynomial (c);
00098 }
00099
00100 Dense_polynomial g= primitive_part ( big<gcd_op> ( vp ));
00101 polynomial<rational> g_rat= as< polynomial<rational> > (g);
00102 vector <irreducible_factor <polynomial <rational> > > fact=
00103 bounded_irreducible_factorization (g_rat, 2);
00104
00105
00106 vector<Root> r;
00107
00108 for (nat i=0; i < N(fact); i++)
00109 {
00110 polynomial<rational> f=factor(fact[i]);
00111 if ( deg(f) == 1 && is_integer(f[0]/f[1]) && abs (f[0]/f[1]) != 1 )
00112 r << Root (as<C> (numerator (-f[0]/f[1])), fact[i].m);
00113 }
00114
00115 return r;
00116 }
00117
00118 template<typename E, typename C, typename V>
00119 vector<Root> special_integer_roots (const Sparse_polynomial &p ){
00120
00121 vector<Root> r;
00122 C s;
00123
00124
00125 E v= val(p);
00126 if ( v > 0 ) r << Root( 0, v );
00127
00128
00129 Sparse_polynomial q= copy(p);
00130 E mul1=0;
00131 E mul2=0;
00132
00133 for (nat i=0; i<N(p); i++){
00134
00135
00136 if (mul1 == i) {
00137 s=0;
00138 for (nat j=0; j<N(q); j++) s+=get_coefficient (q,j);
00139 if ( s == 0 ) mul1=i+1;
00140 }
00141
00142
00143 if (mul2 == i) {
00144 s=0;
00145 for (nat j=0; j<N(q); j++)
00146 s+= get_coefficient (q,j) * binpow(-1, deg (get_monomial (q,j)) % 2 );
00147 if ( s == 0 ) mul2=i+1;
00148 }
00149
00150 if ( mul1 < i+1 && mul2 < i+1 ) break;
00151
00152 q= sparse_derive(q);
00153 }
00154
00155 if (mul1 > 0) r << Root (1,mul1);
00156 if (mul2 > 0) r << Root (-1,mul2);
00157
00158 return r;
00159 }
00160
00161 template<typename E, typename C, typename V>
00162 vector<Root> integer_roots ( const Sparse_polynomial &q ){
00163 vector<Root> r= large_integer_roots (q);
00164 r << special_integer_roots (q);
00165 return r;
00166 }
00167
00168
00169 template<typename E, typename C, typename V>
00170 vector<generic> integer_roots ( const multivariate<Sparse_polynomial> &p ){
00171 vector<generic> ret;
00172 vector<Root> roots= integer_roots (p.rep);
00173 for (nat i=0; i<N(roots); i++)
00174 ret << as<generic> (vec (car(roots[i]), as<integer> (cdr(roots[i]))));
00175 return ret;
00176 }
00177
00178
00179 template<typename E, typename C, typename W>
00180 vector<generic> integer_roots ( const lpolynomial<C,E,W> &lp ){
00181 typedef typename Sparse_polynomial_variant(C) V;
00182
00183 vector<E> w (entries (*lp));
00184 vector<C> c;
00185 vector<Monomial> m;
00186 for (nat i= 0; i < N(w); i++)
00187 if (lp[w[i]] != 0) {
00188 c << lp[w[i]];
00189 m << Monomial (vec(w[i]));
00190 }
00191 Sparse_polynomial p (c, m, 1);
00192
00193
00194 vector<Root> roots= integer_roots (p);
00195 vector<generic> ret;
00196 for (nat i=0; i<N(roots); i++)
00197 ret << as<generic> (vec (car(roots[i]), as<integer> (cdr(roots[i]))));
00198 return ret;
00199 }
00200
00201 #undef Monomial
00202 #undef Sparse_polynomial
00203 #undef Dense_polynomial
00204 #undef Root
00205
00206
00207 }
00208