00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __MMX_LPOLYNOMIAL_HPP
00022 #define __MMX_LPOLYNOMIAL_HPP
00023 #include <basix/vector_sort.hpp>
00024 #include <lacunaryx/lpolynomial_naive.hpp>
00025 namespace mmx {
00026
00027 #define LPolynomial_variant(C,E) lpolynomial_variant_helper<C,E>::PV
00028 #define TMPL_DEF \
00029 template<typename C, typename E=integer,\
00030 typename V=typename LPolynomial_variant(C,E) >
00031 #define TMPL template<typename C, typename E, typename V>
00032 #define TMPLK template<typename C, typename E, typename V, typename K>
00033 #define SE typename signed_of_helper<E>::type
00034 #define Format format<C>
00035 #define Table table<C,E>
00036 #define LPolynomial lpolynomial<C,E,V>
00037 #define Abs_polynomial lpolynomial<Abs_type(C),E>
00038 #define Real_polynomial lpolynomial<Real_type(C),E>
00039 #define Center_polynomial lpolynomial<Center_type(C),E>
00040 #define Radius_polynomial lpolynomial<Radius_type(C),E>
00041 #define Lifted_polynomial lpolynomial<Lift_type(C),E>
00042 #define Projected_polynomial lpolynomial<Project_type(C),E>
00043 #define Reconstructed_polynomial lpolynomial<Reconstruct_type(C),E>
00044 #define Bnd Bound_type(C)
00045 TMPL class lpolynomial;
00046 TMPL inline SE deg (const LPolynomial& P);
00047 TMPL inline int degree (const LPolynomial& P);
00048 TMPL inline nat N (const LPolynomial& P);
00049
00050
00051
00052
00053
00054 TMPL_DEF
00055 class lpolynomial {
00056 MMX_ALLOCATORS;
00057 public:
00058 Table rep;
00059 typedef implementation<vector_linear,V> Vec;
00060 typedef implementation<lpolynomial_defaults,V> Pol;
00061 typedef typename Pol::template global_variables<LPolynomial> S;
00062 public:
00063 inline Table operator * () const { return rep; }
00064
00065 static inline generic get_variable_name () {
00066 return S::get_variable_name (); }
00067 static inline void set_variable_name (const generic& x) {
00068 S::set_variable_name (x); }
00069
00070 inline lpolynomial () : rep (as<C> (0)) {}
00071 inline lpolynomial (const Table& t) : rep (t) {}
00072 inline lpolynomial (const Format& fm) : rep (promote (0, fm)) {}
00073
00074 lpolynomial (const C& x, const E n= 0) {
00075 rep= Table (promote (0, get_format (x)));
00076 rep[n]= x; }
00077
00078 inline friend LPolynomial copy (const LPolynomial& P) {
00079 return LPolynomial (copy (*P)); }
00080 inline C operator[] (const E& i) const {
00081 return rep[i]; }
00082 LPolynomial& operator += (const LPolynomial& P);
00083 LPolynomial& operator -= (const LPolynomial& P);
00084 LPolynomial& operator *= (const C& c);
00085 LPolynomial& operator /= (const C& c);
00086 };
00087
00088 TMPL
00089 struct binary_return_type_helper<access_op,LPolynomial,E> {
00090 typedef C RET; };
00091
00092 TMPL inline nat N (const LPolynomial& P) {
00093 return N(*P); }
00094
00095 TMPL inline Format CF (const LPolynomial& P) {
00096 return CF1(*P); }
00097
00098 TMPL nat hash (const LPolynomial& c) { return hash (*c); }
00099 TMPL nat exact_hash (const LPolynomial& c) { return exact_hash (*c); }
00100 TMPL nat hard_hash (const LPolynomial& c) { return hard_hash (*c); }
00101 TMPL bool operator == (const LPolynomial& c1, const LPolynomial& c2) {
00102 return (*c1) == (*c2); }
00103 TMPL bool operator != (const LPolynomial& c1, const LPolynomial& c2) {
00104 return (*c1) != (*c2); }
00105 TMPL bool exact_eq (const LPolynomial& c1, const LPolynomial& c2) {
00106 return exact_eq (*c1, *c2); }
00107 TMPL bool exact_neq (const LPolynomial& c1, const LPolynomial& c2) {
00108 return exact_neq(*c1,*c2); }
00109 TMPL bool hard_eq (const LPolynomial& c1, const LPolynomial& c2) {
00110 return hard_eq (*c1, *c2); }
00111 TMPL bool hard_neq (const LPolynomial& c1, const LPolynomial& c2) {
00112 return hard_neq (*c1, *c2); }
00113
00114 DEFINE_UNARY_FORMAT_3 (lpolynomial);
00115 STYPE_TO_TYPE(TMPL,scalar_type,LPolynomial,C);
00116 STYPE_TO_TYPE(TMPL,monomial_type,LPolynomial,E);
00117 UNARY_RETURN_TYPE(TMPL,abs_op,LPolynomial,Abs_polynomial);
00118 UNARY_RETURN_TYPE(TMPL,ground_op,LPolynomial,Ground_type(C));
00119 UNARY_RETURN_TYPE(TMPL,Re_op,LPolynomial,Real_polynomial);
00120 UNARY_RETURN_TYPE(TMPL,center_op,LPolynomial,Center_polynomial);
00121 UNARY_RETURN_TYPE(TMPL,radius_op,LPolynomial,Radius_polynomial);
00122
00123
00124
00125
00126
00127 TMPL inline SE
00128 deg (const LPolynomial& P) {
00129 SE ret= -1;
00130 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it) {
00131 if (cdr (*it) == 0) continue;
00132 ret= max ((SE) car (*it), ret);
00133 }
00134 return ret; }
00135
00136 TMPL inline SE
00137 val (const LPolynomial& P) {
00138 if (N(P) == 0) return -1;
00139 iterator<pair<E,C> > it= iterate (*P);
00140 while (cdr (*it) == 0 && busy (it)) ++it;
00141 if (!busy (it)) return -1;
00142 SE ret= car (*it); ++it;
00143 for (; busy (it); ++it) {
00144 if (cdr (*it) == 0) continue;
00145 ret= min ((SE) car (*it), ret);
00146 }
00147 return ret; }
00148
00149 TMPL inline SE
00150 degree (const LPolynomial& P) {
00151 return deg (P); }
00152
00153 TMPL inline vector<C>
00154 coefficients (const LPolynomial& P) {
00155 vector<C> ret (CF(P));
00156 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it)
00157 if (cdr (*it) != 0) ret << cdr (*it);
00158 return ret; }
00159
00160 TMPL inline Ground_type(C)
00161 ground (const LPolynomial& P) {
00162 return ground (P[0]); }
00163
00164
00165
00166
00167
00168 template<typename T, typename F, typename TE, typename FE,
00169 typename TV, typename FV> inline void
00170 set_as (lpolynomial<T,TE,TV>& r, const lpolynomial<F,FE,FV>& p) {
00171 set_as (r.rep, p.rep); }
00172
00173 template<typename C, typename E, typename V, typename T> inline void
00174 set_as (LPolynomial& r, const T& x) {
00175 r.rep= Table (promote (0, CF(r)));
00176 set_as (r.rep[0], x); }
00177
00178 template<typename T, typename F,
00179 typename TE, typename FE,
00180 typename TV, typename FV>
00181 struct as_helper<lpolynomial<T,TE,TV>,lpolynomial<F,FE,FV> > {
00182 static inline lpolynomial<T,TE,TV>
00183 cv (const lpolynomial<F,FE,FV>& p) {
00184 table<F,FE> f= *p;
00185 table<T,TE> r (as<T> (I (*p)), CF2(*p));
00186 for (iterator<FE> it= entries (f); busy (it); ++it)
00187 r[as<TE> (*it)]= as<T> (f[*it]);
00188 return r; }
00189 };
00190
00191
00192
00193
00194
00195 TMPL iterator<pair<E,C> >
00196 iterate (const LPolynomial& P) {
00197 return iterate (*P); }
00198
00199 TMPL vector<E>
00200 supp (const LPolynomial& P) {
00201 vector<E> ret;
00202 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it)
00203 if (cdr (*it) != 0) ret << car (*it);
00204 return ret; }
00205
00206
00207
00208
00209
00210 TMPL inline generic var (const LPolynomial& P) {
00211 (void) P; return LPolynomial::get_variable_name (); }
00212
00213 TMPL inline void set_variable_name (const LPolynomial& P, const generic& x) {
00214 (void) P; return LPolynomial::set_variable_name (x); }
00215
00216 TMPL syntactic
00217 flatten (const LPolynomial& P, const syntactic& v) {
00218 vector<E> w (entries (*P));
00219 sort_leq<gtr_op> (w);
00220 syntactic s= 0;
00221 for (nat i= 0; i < N(w); i++)
00222 if (P[w[i]] != 0)
00223 s= s + flatten (P[w[i]]) * pow (v, flatten (w[i]));
00224 return s; }
00225
00226 TMPL syntactic
00227 flatten (const LPolynomial& P) {
00228 return flatten (P, as_syntactic (var (P))); }
00229
00230
00231
00232
00233
00234 TMPL int
00235 sign (const LPolynomial& P) {
00236 vector<E> v (entries (*P));
00237 sort (v);
00238 for (nat i=0; i<N(v); i++) {
00239 int s= sign (P[v[i]]);
00240 if (s != 0) return s;
00241 }
00242 return 0; }
00243
00244 TMPL int
00245 compare (const LPolynomial& P1, const LPolynomial& P2) {
00246 vector<E> v (entries (*P1 + *P2));
00247 sort (v);
00248 for (nat i=0; i<N(v); i++) {
00249 int s= sign (P1[v[i]] - P2[v[i]]);
00250 if (s != 0) return s;
00251 }
00252 return 0; }
00253
00254 template<typename Op,typename C,typename E,typename V> inline bool
00255 unary_hash (const LPolynomial& P) {
00256 return unary_hash<Op> (*P); }
00257
00258 template<typename Op,typename C,typename E,typename V> inline bool
00259 binary_test (const LPolynomial& P1, const LPolynomial& P2) {
00260 vector<E> v (entries (*P1 + *P2));
00261 sort (v);
00262 for (nat i=0; i<N(v); i++)
00263 if (!Op::op (P1[v[i]], P2[v[i]])) return false;
00264 return true; }
00265
00266 PR_IDENTITY_OP_SUGAR(TMPL,LPolynomial)
00267 COMPARE_SUGAR(TMPL,LPolynomial)
00268 EQUAL_SCALAR_SUGAR(TMPL,LPolynomial,C)
00269 COMPARE_SCALAR_SUGAR(TMPL,LPolynomial,C)
00270 EQUAL_INT_SUGAR(TMPL,LPolynomial)
00271 COMPARE_INT_SUGAR(TMPL,LPolynomial)
00272 EQUAL_SCALAR_SUGAR_BIS(TMPL,LPolynomial,C)
00273 COMPARE_SCALAR_SUGAR_BIS(TMPL,LPolynomial,C)
00274
00275
00276
00277
00278
00279 TMPL LPolynomial&
00280 LPolynomial::operator += (const LPolynomial& P) {
00281 rep += *P; return *this; }
00282
00283 TMPL LPolynomial&
00284 LPolynomial::operator -= (const LPolynomial& P) {
00285 rep -= *P; return *this; }
00286
00287 TMPL LPolynomial&
00288 LPolynomial::operator *= (const C& c) {
00289 rep *= c; return *this; }
00290
00291 TMPL LPolynomial&
00292 LPolynomial::operator /= (const C& c) {
00293 rep /= c; return *this; }
00294
00295
00296
00297
00298
00299 TMPL LPolynomial
00300 operator - (const LPolynomial& P) {
00301 return - *P; }
00302
00303 TMPL LPolynomial
00304 operator + (const LPolynomial& P, const LPolynomial& Q) {
00305 return *P + *Q; }
00306
00307 TMPL LPolynomial
00308 operator + (const LPolynomial& P, const C& c) {
00309 Table ret (*P);
00310 ret[0] = ret[0] + c;
00311 return ret; }
00312
00313 TMPL LPolynomial
00314 operator + (const C& c, const LPolynomial& P) {
00315 Table ret (*P);
00316 ret[0] = c + ret[0];
00317 return ret; }
00318
00319 TMPL LPolynomial
00320 operator - (const LPolynomial& P, const LPolynomial& Q) {
00321 return *P - *Q; }
00322
00323 TMPL LPolynomial
00324 operator - (const LPolynomial& P, const C& c) {
00325 Table ret (*P);
00326 ret[0] = ret[0] - c;
00327 return ret; }
00328
00329 TMPL LPolynomial
00330 operator - (const C& c, const LPolynomial& P) {
00331 Table ret (*P);
00332 ret[0] = c - ret[0];
00333 return ret; }
00334
00335 TMPL LPolynomial
00336 operator * (const LPolynomial& P, const LPolynomial& Q) {
00337 Table ret (0);
00338 for (iterator<pair<E,C> > itP= iterate (*P); busy (itP); ++itP)
00339 for (iterator<pair<E,C> > itQ= iterate (*Q); busy (itQ); ++itQ) {
00340 E i= car(*itP), j= car(*itQ);
00341 ret[i+j] += cdr (*itP) * cdr (*itQ);
00342 }
00343 return ret; }
00344
00345 TMPL LPolynomial
00346 operator * (const LPolynomial& P, const C& c) {
00347 return (*P) * c; }
00348
00349 TMPL LPolynomial
00350 operator * (const C& c, const LPolynomial& P) {
00351 return c * (*P); }
00352
00353 TMPL LPolynomial
00354 square (const LPolynomial& P) {
00355 Table ret (0);
00356 for (iterator<pair<E,C> > itP= iterate (*P); busy (itP); ++itP)
00357 ret[2*car(*itP)] += square (cdr (*itP));
00358 nat l= 0;
00359 for (iterator<pair<E,C> > itP= iterate (*P); busy (itP); ++itP, l++) {
00360 nat k= 0;
00361 for (iterator<pair<E,C> > itQ= iterate (*P); busy (itQ) && k < l; ++itQ, k++) {
00362 E i= car(*itP), j= car(*itQ);
00363 ret[i+j] += 2 * cdr (*itP) * cdr (*itQ);
00364 }
00365 }
00366 return ret; }
00367
00368 TMPL LPolynomial
00369 operator / (const LPolynomial& P, const LPolynomial& Q) {
00370 ASSERT (deg (Q) != -1, "division by zero");
00371 LPolynomial R= P;
00372 Table ret (0);
00373 SE d, dQ= deg (Q);
00374 C lcQ= Q[dQ];
00375 while ((d= deg (R)) >= dQ) {
00376 C c= R[d] / lcQ;
00377 ret[d - dQ]= c;
00378 R = R - LPolynomial (c, d - dQ) * Q;
00379 }
00380 return ret; }
00381
00382 TMPL LPolynomial
00383 operator / (const LPolynomial& P, const C& c) {
00384 return (*P) / c; }
00385
00386 ARITH_SCALAR_INT_SUGAR(TMPL,LPolynomial)
00387
00388
00389
00390
00391
00392 TMPL LPolynomial
00393 __binpow (const LPolynomial& P, const integer& n) {
00394 if (n == 1) return P;
00395 if (n == 2) return square (P);
00396 if (n <= 16) {
00397 LPolynomial Q= P;
00398 for (integer i= 1; i < n; i+= 1) Q = Q * P;
00399 return Q;
00400 }
00401 LPolynomial ret (square (_binpow (P, quo (n, 2))));
00402 if (rem (n, 2) != 0) ret = P * ret;
00403 return ret; }
00404
00405 TMPL LPolynomial
00406 _binpow (const LPolynomial& P, const integer& n) {
00407 integer m= as<integer> (deg (P)) * n;
00408 if (bit_size (m) <= 8*sizeof(unsigned long long int)) {
00409 lpolynomial<C,unsigned long long int> Q=
00410 as<lpolynomial<C,unsigned long long int> > (P);
00411 return as<LPolynomial> (__binpow (Q, n));
00412 }
00413 #if defined(BASIX_HAVE_INT128)
00414 if (bit_size (m) <= 8*sizeof(uint128)) {
00415 lpolynomial<C,uint128> Q= as<lpolynomial<C,uint128> > (P);
00416 return as<LPolynomial> (__binpow (Q, n));
00417 }
00418 #endif
00419 return __binpow (P, n); }
00420
00421 TMPL LPolynomial
00422 binpow (const LPolynomial& Q, const integer& n) {
00423 LPolynomial P= Q; simplify (P.rep);
00424 SE d= deg (P);
00425 if (n == 0) return LPolynomial (promote (1, CF(Q)), 0);
00426 if (d < 0 || n == 1) return P;
00427 if (N(P) == 1) return LPolynomial (P[d], as<E> (d * n));
00428 return _binpow (P, n); }
00429
00430
00431
00432
00433
00434 TMPL LPolynomial
00435 derive (const LPolynomial& P) {
00436 Table ret (0);
00437 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it) {
00438 if (car (*it) == 0) continue;
00439 ret[car (*it) - 1] = promote (car (*it), cdr (*it)) * cdr (*it);
00440 }
00441 return ret; }
00442
00443 TMPL LPolynomial
00444 xderive (const LPolynomial& P) {
00445 Table ret (0);
00446 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it) {
00447 if (car (*it) == 0) continue;
00448 ret[car (*it)] = promote (car (*it), cdr (*it)) * cdr (*it);
00449 }
00450 return ret; }
00451
00452 TMPL C
00453 eval (const LPolynomial& P, const C& c) {
00454 C ret= promote (0, CF (P));
00455 for (iterator<pair<E,C> > it= iterate (*P); busy (it); ++it) {
00456 ret += cdr (*it) * binpow (c, car (*it));
00457 }
00458 return ret; }
00459
00460 #undef TMPL_DEF
00461 #undef TMPL
00462 #undef TMPLK
00463 #undef SE
00464 #undef Format
00465 #undef Table
00466 #undef LPolynomial
00467 #undef Abs_polynomial
00468 #undef Real_polynomial
00469 #undef Center_polynomial
00470 #undef Radius_polynomial
00471 #undef Lifted_polynomial
00472 #undef Projected_polynomial
00473 #undef Reconstructed_polynomial
00474 #undef Bnd
00475 }
00476 #endif // __MMX_LPOLYNOMIAL_HPP