realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/monomial.hpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *      This file is part of the source code of realroot kernel.        *
00003 *      Author(s): B. Mourrain, GALAAD, INRIA                         *
00004 **********************************************************************
00005 $Id: monomial.hpp,v 1.1 2005/07/11 11:17:56 mourrain Exp $
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   //data
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   // Type definitions
00081   typedef int                    index_t;
00082   typedef E                      container_t;
00083   typedef typename E::exponent_t exponent_t; 
00084   //typename E::coeff_t exponent_t;
00085   typedef typename E::size_type  size_type;
00086   typedef C                      coeff_t;
00087   typedef C                      Scalar;
00088   typedef Monomial               self_t;
00089 
00090   // Constructors
00091   monom(): _coef(),_expt() {
00092     rep().resize(0); //COUNT<self_t>(' ');
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   //Copy constructor
00114   monom(const monom & m):_coef(m._coef),_expt(m._expt) {}
00115 
00116   // Destructor
00117   // no dynamic allocation at this level
00118 
00119   // Assignement
00120   self_t & operator = (const self_t & m)
00121     {
00122       _coef = m.coeff(); 
00123       _expt = m._expt; 
00124       return *this;
00125     };
00126 
00127   // Accessors
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   // boolean operators and functions
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   // Arithmetic operators
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 // template<class R,class O> unsigned Monomial::_number_var=1;
00181 // template<class R,class O> std::map<std::string,int> Monomial::_index_of_var;
00182 // template<class R,class O> std::map<int,std::string> Monomial::_var_of_index;
00183 //----------------------------------------------------------------------//
00184 namespace let 
00185 {
00186   TMPL inline void 
00187   assign( C & r, const Monomial& m ) { r = m.coeff(); };
00188  //  TMPL inline const C&  
00189 //   convert( const Monomial & m, const meta::As<C>& ) { return m.coeff(); };
00190 };
00191 //----------------------------------------------------------------------//
00192 //#define MONOM  Monomial
00193 //  declare_binary_operator(TMPL,MONOM,MONOM,meta::_mul_,operator*);
00194 //  declare_binary_operator(TMPL,MONOM,MONOM,meta::_div_,operator/);
00195 //#undef MONOM
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) { /* monome constant */
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 // arithemtic operators
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 // operateurs d'entrees/sorties
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 } //  namespace mmx 
00552 //======================================================================
00553 #undef TMPL
00554 #undef Monomial
00555 #endif // realroot_monom_hpp
00556