00001
00002
00003
00004
00005
00006
00007 #ifndef realroot_monomial_hpp
00008 #define realroot_monomial_hpp
00009
00042
00043 #include <assert.h>
00044 #include <map>
00045 #include <string>
00046 #include <cstring>
00047 #include <realroot/shared_object.hpp>
00048 #include <realroot/parser.hpp>
00049 #include <realroot/array.hpp>
00050 #include <realroot/dynamicexp.hpp>
00051 #include <realroot/variables.hpp>
00052 #include <realroot/print.hpp>
00053
00054
00055 #define TMPL template<class C, class E>
00056 #define Monomial monom<C,E>
00057
00058 namespace mmx {
00059
00061 template <class C, class E=dynamic_exp<int> >
00062 struct monom {
00063
00064
00065 C _coef;
00066 #ifdef SHARED_MONOM
00067 shared_object<E> _expt;
00068 E & rep() {return (*_expt);}
00069 const E & rep() const {return (*_expt);}
00070 typedef shared_object<E> exp_t;
00071 #else
00072 E _expt;
00073 E & rep() {return (_expt);}
00074 const E & rep() const {return (_expt);}
00075 typedef E exp_t;
00076 #endif
00077
00078 static variables var;
00079
00080
00081 typedef int index_t;
00082 typedef E container_t;
00083 typedef typename E::exponent_t exponent_t;
00084
00085 typedef typename E::size_type size_type;
00086 typedef C coeff_t;
00087 typedef C Scalar;
00088 typedef Monomial self_t;
00089
00090
00091 monom(): _coef(),_expt() {
00092 rep().resize(0);
00093 }
00094
00095 monom(const C & c, const exp_t & r):_coef(c), _expt(r){}
00096 monom(const C & c): _coef(c),_expt() {
00097 rep().resize(0);
00098 }
00099 monom(int i):_coef(i), _expt() {
00100 rep().resize(0);
00101 }
00103 monom(const std::string & s, int d, variables& vars = variables::default_ );
00104 monom(const C & c, unsigned s, const AsSize & ):_coef(c),_expt(s){}
00105
00107 monom(const C & c, int d, unsigned i);
00108 monom(const C & c, int s, int *t):_coef(c), _expt(s){
00109 for(int i=0;i<s;i++) rep()[i]= t[i];
00110 }
00111 monom(const char *, variables& vars = monom::var);
00112
00113
00114 monom(const monom & m):_coef(m._coef),_expt(m._expt) {}
00115
00116
00117
00118
00119
00120 self_t & operator = (const self_t & m)
00121 {
00122 _coef = m.coeff();
00123 _expt = m._expt;
00124 return *this;
00125 };
00126
00127
00128 const C & coeff () const { return _coef; }
00129 C& coeff () { return _coef; }
00130 void set_coeff (const C & c){ _coef = c; }
00131
00132 int* begin() { return rep().begin(); }
00133 int* begin() const { return rep().begin(); }
00134
00135 unsigned size() const { return rep().size(); }
00136 int nvars() const { return lvar(rep()); }
00137 int l_variable() const { return lvar(rep()); }
00138 unsigned nbvar() const { return lvar(rep())+1; }
00139
00140 exponent_t operator[] (size_type i) const { return rep()[i]; }
00141 exponent_t expt (size_type i) const { return rep()[i]; }
00142 exponent_t exponent (size_type i) const { return rep()[i]; }
00143
00144 self_t & set_expt (size_type i, exponent_t d)
00145 {rep().set_expt(i,d);return *this; }
00146
00147
00148 bool operator==(int n) const;
00149 bool operator!=(int n) const {return !(*this==n);}
00150
00151
00152 friend bool operator == (const self_t & m1, const self_t & m2)
00153 {
00154 return m1._coef == m2._coef && m1.rep() == m2.rep();
00155 }
00156
00157 friend bool operator != (const self_t & m1, const self_t & m2)
00158 {
00159 return !(m1 == m2);
00160 }
00161
00162 friend bool IsComparable (const self_t & m1, const self_t & m2)
00163 {
00164 return m1.rep() == m2.rep();
00165 }
00166
00167
00168 self_t operator - () const {return self_t(-_coef,rep());}
00169 self_t & operator += (const self_t &);
00170 self_t & operator -= (const self_t &);
00171 self_t & operator *= (const self_t &);
00172 self_t & operator *= (const C &);
00173 self_t & operator /= (const C &);
00174
00175 };
00176
00177
00178 template<class C,class E> variables Monomial::var;
00179
00180
00181
00182
00183
00184 namespace let
00185 {
00186 TMPL inline void
00187 assign( C & r, const Monomial& m ) { r = m.coeff(); };
00188
00189
00190 };
00191
00192
00193
00194
00195
00196 TMPL inline Monomial
00197 operator* (const Monomial& m1, const Monomial& m2) {
00198 Monomial r; mul(r,m1,m2); return r;
00199 }
00200
00201 TMPL inline Monomial
00202 operator/ (const Monomial& m1, const Monomial& m2) {
00203 Monomial r; div(r,m1,m2); return r;
00204 }
00205
00206 TMPL inline bool
00207 divide(const Monomial& m1, const Monomial& m2, Monomial& r) {
00208 div(r,m1,m2);
00209 for (int i = 0; i <= r.nvars(); ++i)
00210 if(r[i]<0) return false;
00211 return true;
00212 }
00213
00214 TMPL inline void
00215 mul(Monomial & a, const Monomial& m1, const Monomial& m2) {
00216 a.coeff() = (m1.coeff()*m2.coeff());
00217 if (a.coeff() !=(typename Monomial::Scalar)0)
00218 {
00219 a.rep().reserve(std::max(m1.rep().size(),m2.rep().size()));
00220 array::add(a.rep(),m1.rep(),m2.rep());
00221 }
00222 else
00223 {
00224 erase(a.rep());
00225 }
00226 }
00227
00228 TMPL inline void
00229 div(Monomial & a, const Monomial& m1, const Monomial& m2) {
00230 a.coeff() = (m1.coeff()/m2.coeff());
00231 if (a.coeff() !=0)
00232 {
00233 a.rep().reserve(std::max(m1.rep().size(),m2.rep().size()));
00234 array::sub(a.rep(),m1.rep(),m2.rep());
00235 }
00236 else
00237 {
00238 erase(a.rep());
00239 }
00240 }
00241
00242 TMPL inline Monomial
00243 div(const Monomial & m1, const Monomial & m2) {
00244 Monomial res(1); res*=(m1.coeff()/m2.coeff());
00245 for (int i = 0; i <= m1.nvars(); ++i)
00246 res.set_expt(i,m1[i] - m2[i]);
00247 return res;
00248 }
00249
00250 TMPL inline Monomial
00251 div_quo(const Monomial & m1, const Monomial & m2) {
00252 Monomial res(1); res*=(m1.coeff()/m2.coeff());
00253 for (int i = 0; i <= m1.nvars(); ++i)
00254 res.set_expt(i,m1[i] - m2[i]);
00255 return res;
00256 }
00257
00258 template <class C, class E> inline
00259 typename E::degree_t degree(const Monomial & m) {
00260 return degree(m.rep());
00261 }
00262
00263 TMPL Monomial
00264 MGcd(const Monomial & m1, const Monomial & m2) {
00265 int d = Gcd(m1.coeff(),m2.coeff());
00266 Monomial res(d);
00267 int v = Min(m1.nvars(),m2.nvars());
00268 for (int i = 0; i <= v; ++i)
00269 res.set_expt(i, Min(m1[i],m2[i]));
00270 return res;
00271 }
00272
00273
00274 TMPL inline Monomial
00275 pow(const Monomial& m1, int n) {
00276 Monomial res(m1);
00277 for (int i = 0; i <= m1.nvars(); ++i)
00278 res.set_expt(i,m1[i]*n);
00279 return res;
00280 }
00281
00283 template <class C, class E>
00284 Monomial::monom(const std::string & s, int d,
00285 variables& vars ):_coef(1) {
00286 if(d == 0)
00287 rep().resize(0);
00288 else
00289 {
00290 int i=vars[s];
00291 rep().reserve(i+1);
00292 for(int j=0;j<i;j++) rep().set_expt(j,0);
00293 rep().set_expt(i,d);
00294 }
00295 }
00296
00298 template <class C, class E>
00299 Monomial::monom(const C & c, int d, unsigned v):_coef(c) {
00300 if(d == 0)
00301 rep().resize(0);
00302 else
00303 {
00304 rep().reserve(v+1);
00305 for(unsigned j=0;j<v;j++) rep().set_expt(j,0);
00306 rep().set_expt(v,d);
00307 }
00308 }
00309
00310 extern "C" char *synaps_inputptr;
00311 template <class C, class E>
00312 Monomial::monom(const char * s, variables& vars ) {
00313 int n = strlen(s);
00314 if (s[n-1]=='\n') {n--;}
00315 if(s[n-1]==';')
00316 {
00317 synaps_input = new char[n+1];
00318 memcpy(synaps_input,s,n); synaps_input[n]='\0';
00319 synaps_inputlim = synaps_input + n;
00320 }
00321 else
00322 {
00323 synaps_input = new char[n+2];
00324 memcpy(synaps_input,s,n);
00325 synaps_input[n]=';'; synaps_input[n+1]='\0';
00326 synaps_inputlim = synaps_input + n+1;
00327 }
00328 synaps_inputptr=synaps_input;
00329 *this = Monomial((C)1);
00330 int Ask;
00331
00332 for (;;) {
00333 Ask = yylex();
00334 if (Ask == COEF) {
00335 C c;
00336 let::assign(c,yylval);
00337 free(yylval);
00338 *this *= c;
00339 }
00340 else if (Ask == XID) {
00341 char* p = strchr(yylval,'^');
00342 if (p == NULL)
00343 {
00344 *this *= Monomial(vars[std::string(yylval)],1);
00345 }
00346 else {
00347 p++;
00348 *this *= Monomial(vars[std::string(yylval,p-1)], atoi(p));
00349 }
00350 free(yylval);
00351 }
00352 else if (Ask == TERMINATE) {
00353 break;
00354 }
00355 }
00356 delete[] synaps_input;
00357 }
00358
00359 template <class C, class E> inline bool
00360 Monomial::operator== (int n) const {
00361 return (coeff()==n);
00362 }
00363
00364
00365
00366 template <class C, class E> inline Monomial &
00367 Monomial::operator += (const Monomial & m) {
00368 coeff() += m.coeff();
00369 if (coeff()==0) erase(rep());
00370 return *this;
00371 }
00372
00373 template <class C, class E> inline Monomial &
00374 Monomial::operator -= (const Monomial & m) {
00375 coeff() -= m.coeff();
00376 if (coeff()==0) erase(rep());
00377 return *this;
00378 }
00379
00380 template <class C, class E> inline Monomial
00381 operator + (const Monomial & m1, const Monomial & m2) {
00382 Monomial res(m1);
00383 res.coeff() += m2.coeff();
00384 return (*res);
00385 }
00386
00387 template <class C, class E> inline Monomial
00388 operator - (const Monomial & m1, const Monomial & m2) {
00389 Monomial res(m1);
00390 res.coeff() -= m2.coeff();
00391 return (res);
00392 }
00393
00394 template <class C, class E> inline Monomial &
00395 Monomial::operator *= (const Monomial & m) {
00396 coeff() *= m.coeff();
00397 if (coeff()!=0)
00398 array::add(rep(),m.rep());
00399 else
00400 erase(rep());
00401 return *this;
00402 }
00403
00404 template <class C, class E> inline Monomial &
00405 Monomial::operator *= (const C & c) {
00406 coeff() *= c;
00407 if (coeff()==0) erase(rep());
00408 return *this;
00409 }
00410
00411 template <class C, class E> inline Monomial &
00412 Monomial::operator /= (const C & c) {
00413 assert(c !=0);
00414 coeff() /= c;
00415 if (coeff()==0) erase(rep());
00416 return *this;
00417 }
00418
00419 template <class C, class E> inline Monomial
00420 operator * (const Monomial & m1, const C & c2) {
00421 Monomial res(m1);
00422 res.coeff() *= c2;
00423 if (res.coeff() ==0) erase(res.rep());
00424 return (res);
00425 }
00426 template <class C, class E> inline Monomial
00427 operator * (const C & c2, const Monomial & m1) {
00428 return(m1*c2);
00429 }
00430
00431 template <class C, class E> inline Monomial
00432 operator / (const Monomial & m1, const C & c2) {
00433 Monomial res(m1);
00434 res.coeff() /= c2;
00435 if (res.coeff() ==0) erase(res.rep());
00436 return (res);
00437 }
00438
00439
00440
00441
00442
00443 template <class OSTREAM, class C, class E> inline OSTREAM&
00444 print_pp (OSTREAM & os, const Monomial & m, const variables& V) {
00445 bool first=true;
00446 for (typename E::size_type i = 0; i < m.rep().size(); ++i)
00447 {
00448 if (m[i] !=0)
00449 {
00450 if(first) {
00451 first =false;
00452 } else {
00453 os<<'*';
00454 }
00455 os << V[i];
00456 if (m[i] != 1) {
00457 os << '^' <<m[i];
00458 }
00459 }
00460 }
00461 return os;
00462 }
00463
00464
00465 inline bool is_polynomial(const std::ostringstream& sm){
00466 for(unsigned i=1; i<sm.str().length();i++)
00467 if(sm.str()[i]=='+' || (sm.str()[i]=='-' && (i>0 && sm.str()[i-1]=='e'))) return true;
00468 return false;
00469 }
00470
00471
00472 template <class OSTREAM, class C, class E> inline OSTREAM &
00473 print (OSTREAM & os, const Monomial & m,
00474 const variables& V = variables::default_) {
00475 if (m.coeff() == C(0) )
00476 os<<"0";
00477 else {
00478 int i=m.nvars();
00479 while(i> -1 && m[i]==0) i--;
00480 if(i<0)
00481 print(os,m.coeff());
00482 else {
00483 if(m.coeff() != (C)1) {
00484 if(m.coeff()==(C)-1)
00485 { os << "-"; }
00486 else
00487 {
00488 std::ostringstream sm;
00489 print(sm,m.coeff());
00490 bool is_pol = is_polynomial(sm);
00491 if (is_pol) os <<"+(";
00492 os<<sm.str();
00493 if (is_pol) os <<")";
00494 os <<"*";
00495 }
00496 }
00497 print_pp(os,m,V);
00498 }
00499 }
00500 return os;
00501 }
00502
00503
00504
00505 template <class OSTREAM, class C, class E> inline OSTREAM &
00506 print_as_double (OSTREAM & os, const Monomial & m,
00507 const variables& V = variables::default_) {
00508 if (m.coeff() == C(0) )
00509 os<<"0";
00510 else {
00511 int i=m.nvars();
00512 while(i> -1 && m[i]==0) i--;
00513 if(i<0)
00514 print(os,as_double(m.coeff()));
00515 else {
00516 if(m.coeff() != (C)1) {
00517 if(m.coeff()==(C)-1)
00518 { os << "-"; }
00519 else
00520 {
00521 std::ostringstream sm;
00522 print(sm,as_double(m.coeff()));
00523 bool is_pol = is_polynomial(sm);
00524 if (is_pol) os <<"+(";
00525 os<<sm.str();
00526 if (is_pol) os <<")";
00527 os <<"*";
00528 }
00529 }
00530 print_pp(os,m,V);
00531 }
00532 }
00533 return os;
00534 }
00535
00536
00537
00538
00540 template <class C, class E> inline
00541 std::ostream & operator << (std::ostream & os, const monom <C,E> & m)
00542 {
00543 if (m.coeff() ==0 ) os<<"(0)";
00544 else
00545 print(os,m);
00546
00547 return os;
00548 }
00549
00550
00551 }
00552
00553 #undef TMPL
00554 #undef Monomial
00555 #endif // realroot_monom_hpp
00556