Vaucanson 1.4
polynoms.hxx
00001 // polynoms.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 The
00006 // Vaucanson Group.
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU General Public License
00010 // as published by the Free Software Foundation; either version 2
00011 // of the License, or (at your option) any later version.
00012 //
00013 // The complete GNU General Public Licence Notice can be found as the
00014 // `COPYING' file in the root directory.
00015 //
00016 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00017 //
00018 #ifndef VCSN_ALGEBRA_IMPLEMENTATION_SERIES_POLYNOMS_HXX
00019 # define VCSN_ALGEBRA_IMPLEMENTATION_SERIES_POLYNOMS_HXX
00020 
00021 # include <vaucanson/algebra/implementation/series/polynoms.hh>
00022 # include <vaucanson/algebra/concept/freemonoid_base.hh>
00023 
00024 # include <vaucanson/misc/contract.hh>
00025 # include <vaucanson/misc/escaper.hh>
00026 
00027 namespace vcsn
00028 {
00029   namespace algebra
00030   {
00031     /*----------------.
00032     | polynom<Tm, Tw> |
00033     `----------------*/
00034 
00035     template<typename Tm, typename Tw>
00036     template<typename M, typename W>
00037     polynom<Tm, Tw>::polynom(SELECTOR(M), SELECTOR(W))
00038     {
00039       map_.insert(std::make_pair(identity_value(SELECT(M), SELECT(Tm)),
00040                                  identity_value(SELECT(W), SELECT(Tw))));
00041     }
00042 
00043     template<typename Tm, typename Tw>
00044     polynom<Tm, Tw>::polynom(const polynom& other) : map_(other.map_)
00045     {}
00046 
00047     template<typename Tm, typename Tw>
00048     polynom<Tm, Tw>::polynom() : map_()
00049     {}
00050 
00051     template<typename Tm, typename Tw>
00052     size_t
00053     polynom<Tm, Tw>::size() const
00054     {
00055       return map_.size();
00056     }
00057 
00058     template<typename Tm, typename Tw>
00059     bool polynom<Tm, Tw>::empty() const
00060     {
00061       return map_.empty();
00062     }
00063 
00064     template<typename Tm, typename Tw>
00065     typename polynom<Tm, Tw>::iterator
00066     polynom<Tm, Tw>::begin()
00067     {
00068       return map_.begin();
00069     }
00070 
00071     template<typename Tm, typename Tw>
00072     typename polynom<Tm, Tw>::const_iterator
00073     polynom<Tm, Tw>::begin() const
00074     {
00075       return map_.begin();
00076     }
00077 
00078     template<typename Tm, typename Tw>
00079     typename polynom<Tm, Tw>::iterator
00080     polynom<Tm, Tw>::end()
00081     {
00082       return map_.end();
00083     }
00084 
00085     template<typename Tm, typename Tw>
00086     typename polynom<Tm, Tw>::const_iterator
00087     polynom<Tm, Tw>::end() const
00088     {
00089       return map_.end();
00090     }
00091 
00092     template<typename Tm, typename Tw>
00093     typename polynom<Tm, Tw>::iterator
00094     polynom<Tm, Tw>::find(const Tm& m)
00095     {
00096       return map_.find(m);
00097     }
00098 
00099     template<typename Tm, typename Tw>
00100     typename polynom<Tm, Tw>::const_iterator
00101     polynom<Tm, Tw>::find(const Tm& m) const
00102     {
00103       return map_.find(m);
00104     }
00105 
00106     template<typename Tm, typename Tw>
00107     template<typename W>
00108     Tw& polynom<Tm, Tw>::make_get(SELECTOR(W), const Tm& m)
00109     {
00110       std::pair<iterator, bool> i =
00111         map_.insert(std::make_pair(m, zero_value(SELECT(W), SELECT(Tw))));
00112       return i.first->second;
00113     }
00114 
00115     template<typename Tm, typename Tw>
00116     template<typename W>
00117     Tw polynom<Tm, Tw>::get(SELECTOR(W), const Tm& m) const
00118     {
00119       const_iterator i;
00120       if ((i = map_.find(m)) == map_.end())
00121         return zero_value(SELECT(W), SELECT(Tw));
00122       return i->second;
00123     }
00124 
00125     template<typename Tm, typename Tw>
00126     void polynom<Tm, Tw>::insert(const Tm& m, const Tw& w)
00127     {
00128       map_.insert(std::make_pair(m, w));
00129     }
00130 
00131     template<typename Tm, typename Tw>
00132     template<typename W>
00133     void polynom<Tm, Tw>::add(const W& semiring, const Tm& m, const Tw& w)
00134     {
00135       Tw& o = make_get(SELECT(W), m);
00136       op_in_add(semiring, o, w);
00137     }
00138 
00139     template<typename Tm, typename Tw>
00140     void polynom<Tm, Tw>::erase(iterator i)
00141     {
00142       map_.erase(i);
00143     }
00144 
00145     template<typename Tm, typename Tw>
00146     void polynom<Tm, Tw>::clear()
00147     {
00148       map_.clear();
00149     }
00150 
00151     template<typename Tm, typename Tw>
00152     void polynom<Tm, Tw>::swap(polynom<Tm, Tw>& other)
00153     {
00154       map_.swap(other.map_);
00155     }
00156 
00157     template<typename Tm, typename Tw>
00158     const std::map<Tm, Tw>&
00159     polynom<Tm, Tw>::as_map() const
00160     {
00161       return map_;
00162     }
00163 
00164     template<typename Tm, typename Tw>
00165     const Tw&
00166     polynom<Tm, Tw>::operator [] (const Tm& m) const
00167     {
00168       const_iterator i = map_.find(m);
00169 
00170       postcondition_ (i != map_.end(),
00171                       "Word is not in the support");
00172 
00173       return i->second;
00174     }
00175 
00176     template<typename Tm, typename Tw>
00177     Tw&
00178     polynom<Tm, Tw>::operator [] (const Tm& m)
00179     {
00180       return map_[m];
00181     }
00182 
00183     template <class Series, class Tm, class Tw>
00184     polynom<Tm,Tw>
00185     DefaultTransposeFun<Series, polynom<Tm,Tw> >::
00186     operator()(const Series& s,const polynom<Tm,Tw>& t) const
00187     {
00188       typedef typename polynom<Tm, Tw>::const_iterator  const_iterator;
00189       typedef typename Series::monoid_t                 monoid_t;
00190       typedef Element<monoid_t, Tm>                     monoid_elt_t;
00191 
00192       polynom<Tm, Tw> p;
00193 
00194       for (const_iterator i = t.begin(); i != t.end(); ++i)
00195       {
00196         monoid_elt_t m (s.monoid(), i->first);
00197         m.mirror();
00198         p[m.value()] = transpose(s.semiring(), i->second);
00199       }
00200       return p;
00201     }
00202 
00203     template <class Series, class Tm, class Tw>
00204     template <class S>
00205     Tw
00206     DefaultTransposeFun<Series, polynom<Tm,Tw> >::
00207     transpose(const SeriesBase<S>& s, const Tw& t)
00208     {
00209       Element<S, Tw> e (s.self(), t);
00210       e.transpose();
00211       return e.value();
00212     }
00213 
00214     template <class Series, class Tm, class Tw>
00215     template <class S>
00216     Tw
00217     DefaultTransposeFun<Series, polynom<Tm,Tw> >::
00218     transpose(const SemiringBase<S>&, const Tw& t)
00219     {
00220       return t;
00221     }
00222 
00223     template <class Tm, class Tw>
00224     bool operator==(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00225     {
00226       return lhs.as_map() == rhs.as_map();
00227     }
00228 
00229     template <class Tm, class Tw>
00230     bool operator!=(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00231     {
00232       return !(lhs == rhs);
00233     }
00234 
00235     template <class Tm, class Tw>
00236     bool operator<(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00237     {
00238       return lhs.as_map() < rhs.as_map();
00239     }
00240 
00241     template <class Tm, class Tw>
00242     bool operator>(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00243     {
00244       return lhs.as_map() > rhs.as_map();
00245     }
00246 
00247     template <class Tm, class Tw>
00248     bool operator<=(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00249     {
00250       return lhs.as_map() <= rhs.as_map();
00251     }
00252 
00253     template <class Tm, class Tw>
00254     bool operator>=(const polynom<Tm, Tw>& lhs, const polynom<Tm, Tw>& rhs)
00255     {
00256       return lhs.as_map() >= rhs.as_map();
00257     }
00258 
00259     /*-------------------.
00260     | External functions |
00261     `-------------------*/
00262 
00263     template<typename W, typename M, typename Tm, typename Tw>
00264     bool op_contains(const algebra::Series<W, M>& s,
00265                      const algebra::polynom<Tm, Tw>& m)
00266     {
00267       for (typename algebra::polynom<Tm, Tw>::const_iterator i = m.begin();
00268            i != m.end();
00269            ++i)
00270         if (!s.monoid().contains(i->first)
00271             || !s.semiring().contains(i->second))
00272           return false;
00273       return true;
00274     }
00275 
00276     template<typename Self, typename Tm, typename Tw>
00277     bool op_starable(const algebra::SeriesBase<Self>&,
00278                      const algebra::polynom<Tm, Tw>& m)
00279     {
00280       int s = m.size();
00281       if (s == 0)
00282         return true;
00283       if (s > 1)
00284         return false;
00285 
00286       typename std::pair<Tm, Tw> elt = *m.as_map().begin();
00287       if (elt.first != identity_value(SELECT(typename Self::monoid_t),
00288                                       SELECT(Tm)))
00289         return false;
00290 
00291       return op_starable(SELECT(typename Self::semiring_t), elt.second);
00292     }
00293 
00294 
00295     template<typename Self, typename Tm, typename Tw>
00296     void op_in_star(const algebra::SeriesBase<Self>&,
00297                     algebra::polynom<Tm, Tw>& m)
00298     {
00299       if (m.size() == 0)
00300       {
00301         Tw val (zero_value(SELECT(typename Self::semiring_t), SELECT(Tw)));
00302         op_in_star(SELECT(typename Self::semiring_t), val);
00303         m.insert(identity_value(SELECT(typename Self::monoid_t), SELECT(Tm)),
00304                  val);
00305       }
00306       else
00307       {
00308         typename std::pair<Tm, Tw> elt = *m.as_map().begin();
00309         assertion_ (!(m.size() > 1 ||
00310                       elt.first != identity_value(SELECT(typename
00311                                                          Self::monoid_t),
00312                                                   SELECT(Tm))),
00313                     "Support is not empty, star cannot be computed.");
00314 
00315         op_in_star(SELECT(typename Self::semiring_t), elt.second);
00316         m.clear();
00317         m.insert(elt.first, elt.second);
00318       }
00319     }
00320 
00321     template<typename W, typename M, typename Tm, typename Tw>
00322     bool op_is_finite_app(const algebra::Series<W, M>&,
00323                           const algebra::polynom<Tm, Tw>&)
00324     {
00325       return true;
00326     }
00327 
00328     template<typename W, typename M, typename Tm, typename Tw>
00329     typename algebra::series_traits<algebra::polynom<Tm, Tw> >::support_t
00330     op_support(const algebra::Series<W, M>&,
00331                const algebra::polynom<Tm, Tw>& m)
00332     {
00333       return typename algebra::series_traits<algebra::polynom<Tm, Tw> >::
00334       support_t(m.as_map());
00335     }
00336 
00337     template<typename W, typename M, typename Tm, typename Tw>
00338     const algebra::polynom<Tm, Tw>&
00339     identity_value(SELECTOR2(algebra::Series<W, M>),
00340                    SELECTOR2(algebra::polynom<Tm, Tw>))
00341     {
00342       static const algebra::polynom<Tm, Tw> instance =
00343         algebra::polynom<Tm, Tw>(SELECT(M), SELECT(W));
00344       return instance;
00345     }
00346 
00347     template<typename W, typename M, typename Tm, typename Tw>
00348     const algebra::polynom<Tm, Tw>&
00349     zero_value(SELECTOR2(algebra::Series<W, M>),
00350                SELECTOR2(algebra::polynom<Tm, Tw>))
00351     {
00352       static const algebra::polynom<Tm, Tw> instance;
00353       return instance;
00354     }
00355 
00356     template<typename W, typename M, typename Tm, typename Tw>
00357     void op_in_add(const algebra::Series<W, M>& s,
00358                    algebra::polynom<Tm, Tw>& dst,
00359                    const algebra::polynom<Tm, Tw>& arg)
00360     {
00361       typename algebra::polynom<Tm, Tw>::iterator p;
00362       Tw zero = zero_value(SELECT(W), SELECT(Tw));
00363       Tw w;
00364 
00365       for (typename algebra::polynom<Tm, Tw>::const_iterator i = arg.begin();
00366            i != arg.end();
00367            ++i)
00368         if (i->second != zero)
00369         {
00370           p = dst.find(i->first);
00371           if (p != dst.end())
00372           {
00373             w = i->second;
00374             op_in_add(s.semiring(), w, p->second);
00375             if (w == zero_value(SELECT(W), SELECT(Tw)))
00376               dst.erase(p);
00377             else
00378               p->second = w;
00379           }
00380           else
00381             dst.insert(i->first, i->second);
00382         }
00383     }
00384 
00385     template<typename W, typename M, typename Tm, typename Tw>
00386     algebra::polynom<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00387                                     const algebra::polynom<Tm, Tw>& a,
00388                                     const algebra::polynom<Tm, Tw>& b)
00389     {
00390       algebra::polynom<Tm, Tw> ret(a);
00391       op_in_add(s, ret, b);
00392       return ret;
00393     }
00394 
00395     /*-----------------.
00396     | cauchy's product |
00397     `-----------------*/
00398 
00399     template<typename W, typename M, typename Tm, typename Tw>
00400     algebra::polynom<Tm, Tw> op_mul(const algebra::Series<W, M>& s,
00401                                     const algebra::polynom<Tm, Tw>& a,
00402                                     const algebra::polynom<Tm, Tw>& b)
00403     {
00404       algebra::polynom<Tm, Tw> ret;
00405       for (typename algebra::polynom<Tm, Tw>::const_iterator i = a.begin();
00406            i != a.end();
00407            ++i)
00408         for (typename algebra::polynom<Tm, Tw>::const_iterator j = b.begin();
00409              j != b.end();
00410              ++j)
00411         {
00412           Tw w = op_mul(s.semiring(), i->second, j->second);
00413           if (w != zero_value(SELECT(W), SELECT(Tw)))
00414             ret.add(s.semiring(),
00415                     op_mul(s.monoid(), i->first, j->first),
00416                     w);
00417         }
00418       return ret;
00419     }
00420 
00421     template<typename W, typename M, typename Tm, typename Tw>
00422     void op_in_mul(const algebra::Series<W, M>& s,
00423                    algebra::polynom<Tm, Tw>& dst,
00424                    const algebra::polynom<Tm, Tw>& arg)
00425     {
00426       op_assign(s, dst, op_mul(s, dst, arg));
00427     }
00428 
00429     /*---------------------.
00430     | foreign constructors |
00431     `---------------------*/
00432 
00433     template <typename Tm, typename Tw, typename W, typename M>
00434     algebra::polynom<Tm, Tw> op_convert(SELECTOR2(algebra::Series<W, M>),
00435                                         SELECTOR2(algebra::polynom<Tm, Tw>),
00436                                         const Tm& m_value)
00437     {
00438       algebra::polynom<Tm, Tw> p(SELECT(M), SELECT(W));
00439       p.insert(m_value, identity_value(SELECT(W), SELECT(Tw)));
00440       return p;
00441     }
00442 
00443     template<typename Tm, typename Tw, typename W, typename M, typename oTm>
00444     algebra::polynom<Tm, Tw> op_convert(const algebra::Series<W, M>& s,
00445                                         SELECTOR2(algebra::polynom<Tm, Tw>),
00446                                         SELECTOR(algebra::MonoidBase<M>),
00447                                         const oTm& m_value)
00448     {
00449       const M&  monoid = s.monoid();
00450       const W&  semiring = s.semiring();
00451 
00452       algebra::polynom<Tm, Tw> ret;
00453       ret.insert(op_convert(monoid, SELECT(Tm), m_value),
00454                  identity_value(semiring, SELECT(Tw)));
00455       return ret;
00456     }
00457 
00458     template<typename Tm, typename Tw, typename W, typename M, typename oTw>
00459     algebra::polynom<Tm, Tw> op_convert(SELECTOR2(algebra::Series<W, M>),
00460                                         SELECTOR2(algebra::polynom<Tm, Tw>),
00461                                         SELECTOR(algebra::SemiringBase<W>),
00462                                         const oTw& w_value)
00463     {
00464       algebra::polynom<Tm, Tw> ret;
00465       if (w_value != zero_value(SELECT(W), SELECT(oTw)))
00466         ret.insert(identity_value(SELECT(M), SELECT(Tm)),
00467                    op_convert(SELECT(W), SELECT(Tw), w_value));
00468       return ret;
00469     }
00470 
00471     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00472     void op_assign(const algebra::Series<W, M>&,
00473                    const algebra::MonoidBase<M>&,
00474                    algebra::polynom<Tm, Tw>& dst,
00475                    const oTm& src)
00476     {
00477       dst.clear();
00478       dst.insert(op_convert(SELECT(M), SELECT(Tm), src),
00479                  identity_value(SELECT(W), SELECT(Tw)));
00480     }
00481 
00482     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00483     void op_assign(const algebra::Series<W, M>& s,
00484                    const algebra::SemiringBase<W>&,
00485                    algebra::polynom<Tm, Tw>& dst,
00486                    const oTw& src)
00487     {
00488       dst.clear();
00489       if (src != zero_value(SELECT(W), SELECT(oTw)))
00490         dst.insert(identity_value(SELECT(M), SELECT(Tm)),
00491                    op_convert(SELECT(W), SELECT(Tw), src));
00492     }
00493 
00494     /*--------------------------------------.
00495     | foreign addition with monoid elements |
00496     `--------------------------------------*/
00497 
00498     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00499     void op_in_add(const algebra::Series<W, M>& s,
00500                    const algebra::MonoidBase<M>& monoid,
00501                    algebra::polynom<Tm, Tw>& dst,
00502                    const oTm& src)
00503     {
00504       precondition(& s.monoid() == & monoid);
00505       dst.add(s.semiring(),
00506               op_convert(SELECT(M), SELECT(Tm), src),
00507               identity_value(SELECT(W), SELECT(Tw)));
00508     }
00509 
00510     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00511     algebra::polynom<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00512                                     const algebra::MonoidBase<M>& monoid,
00513                                     const algebra::polynom<Tm, Tw>& a,
00514                                     const oTm& b)
00515     {
00516       algebra::polynom<Tm, Tw> ret(a);
00517       op_in_add(s, monoid, ret, b);
00518       return ret;
00519     }
00520 
00521     template<typename M, typename W, typename oTm, typename Tm, typename Tw>
00522     algebra::polynom<Tm, Tw> op_add(const algebra::MonoidBase<M>& monoid,
00523                                     const algebra::Series<W, M>& s,
00524                                     const oTm& a,
00525                                     const algebra::polynom<Tm, Tw>& b)
00526     {
00527       algebra::polynom<Tm, Tw> ret(b);
00528       op_in_add(s, monoid, ret, a);
00529       return ret;
00530     }
00531 
00532     /*----------------------------------------.
00533     | foreign addition with semiring elements |
00534     `----------------------------------------*/
00535 
00536     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00537     void op_in_add(const algebra::Series<W, M>& s,
00538                    const algebra::SemiringBase<W>& semiring,
00539                    algebra::polynom<Tm, Tw>& dst,
00540                    const oTw& src)
00541     {
00542       precondition(& s.semiring() == & semiring);
00543       if (src != zero_value(SELECT(W), SELECT(oTw)))
00544         dst.add(s.semiring(),
00545                 identity_value(SELECT(M), SELECT(Tm)),
00546                 op_convert(SELECT(W), SELECT(Tw), src));
00547     }
00548 
00549     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00550     algebra::polynom<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00551                                     const algebra::SemiringBase<W>& semiring,
00552                                     const algebra::polynom<Tm, Tw>& a,
00553                                     const oTw& b)
00554     {
00555       algebra::polynom<Tm, Tw> ret(a);
00556       op_in_add(s, semiring, ret, b);
00557       return ret;
00558     }
00559 
00560     template<typename W, typename M, typename oTw, typename Tm, typename Tw>
00561     algebra::polynom<Tm, Tw> op_add(const algebra::SemiringBase<W>& semiring,
00562                                     const algebra::Series<W, M>& s,
00563                                     const oTw& a,
00564                                     const algebra::polynom<Tm, Tw>& b)
00565     {
00566       algebra::polynom<Tm, Tw> ret(b);
00567       op_in_add(s, semiring, ret, a);
00568       return ret;
00569     }
00570 
00571     /*--------------------------------------------.
00572     | foreign multiplication by semiring elements |
00573     `--------------------------------------------*/
00574 
00575     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00576     void op_in_mul(const algebra::Series<W, M>& s,
00577                    const algebra::SemiringBase<W>& semiring,
00578                    algebra::polynom<Tm, Tw>& dst,
00579                    const oTw& src)
00580     {
00581       precondition(& s.semiring() == & semiring);
00582       (void) s; (void) semiring;
00583 
00584       typename algebra::polynom<Tm, Tw>::iterator p;
00585       for (typename algebra::polynom<Tm, Tw>::iterator i = dst.begin();
00586            i != dst.end();
00587           )
00588       {
00589         p = i++;
00590         op_in_mul(s.semiring(), p->second, src);
00591         if (p->second == zero_value(SELECT(W), SELECT(Tw)))
00592           dst.erase(p);
00593       }
00594     }
00595 
00596     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00597     algebra::polynom<Tm, Tw> op_mul(const algebra::Series<W, M>& s,
00598                                     const algebra::SemiringBase<W>& semiring,
00599                                     const algebra::polynom<Tm, Tw>& a,
00600                                     const oTw& b)
00601     {
00602       algebra::polynom<Tm, Tw> ret(a);
00603       op_in_mul(s, semiring, ret, b);
00604       return ret;
00605     }
00606 
00607     template<typename W, typename M, typename oTw, typename Tm, typename Tw>
00608     algebra::polynom<Tm, Tw> op_mul(const algebra::SemiringBase<W>& semiring,
00609                                     const algebra::Series<W, M>& s,
00610                                     const oTw& a,
00611                                     const algebra::polynom<Tm, Tw>& b)
00612     {
00613       precondition(& s.semiring() == & semiring);
00614       (void) s; (void) semiring;
00615 
00616       algebra::polynom<Tm, Tw> ret(b);
00617 
00618       typename algebra::polynom<Tm, Tw>::iterator p;
00619       for (typename algebra::polynom<Tm, Tw>::iterator i = ret.begin();
00620            i != ret.end();)
00621       {
00622         p = i++;
00623         p->second = op_mul(s.semiring(), a, p->second);
00624         if (p->second == zero_value(SELECT(W), SELECT(Tw)))
00625           ret.erase(p);
00626       }
00627       return ret;
00628     }
00629 
00630     /*-------------.
00631     | input-output |
00632     `-------------*/
00633 
00634     template<typename W, typename M, typename St, typename Tm, typename Tw>
00635     St& op_rout(const algebra::Series<W, M>& s,
00636                 St& st,
00637                 const algebra::polynom<Tm, Tw>& p)
00638     {
00639       typename algebra::polynom<Tm, Tw>::const_iterator i = p.begin();
00640 
00641       while (i != p.end())
00642       {
00643         if (i != p.begin())
00644           st << s.representation()->plus;
00645 
00646         bool show_weight = (i->second != identity_value(SELECT(W), SELECT(Tw))
00647                             || show_identity_value(SELECT(W), SELECT(Tw)));
00648 
00649         if (show_weight)
00650           {
00651             st << s.representation()->open_par
00652                << s.representation()->open_weight;
00653             op_rout(s.semiring(), st, i->second);
00654             st << s.representation()->close_weight
00655                << s.representation()->spaces.front();
00656           }
00657 
00658         op_rout(s.monoid(), st, i->first);
00659 
00660         if (show_weight)
00661           st << s.representation()->close_par;
00662 
00663         ++i;
00664       }
00665 
00666       if (i == p.begin()) /* case zero */
00667         op_rout(s.semiring(), st, zero_value(SELECT(W), SELECT(Tw)));
00668 
00669       return st;
00670     }
00671 
00672     /*---------------------------------.
00673     | design_pattern series operations |
00674     `---------------------------------*/
00675 
00676     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00677     Tw op_series_get(const algebra::Series<W, M>& s,
00678                      const algebra::polynom<Tm, Tw>& p,
00679                      const oTm& m)
00680     {
00681       return p.get(s.semiring(), op_convert(s.semiring(), SELECT(Tm), m));
00682     }
00683 
00684     template <typename W, typename M,
00685               typename Tm, typename Tw,
00686               typename oTm, typename oTw>
00687     void op_series_set(const algebra::Series<W, M>& s,
00688                        algebra::polynom<Tm, Tw>& p,
00689                        const oTm& m,
00690                        const oTw& w)
00691     {
00692       const M&  monoid = s.monoid();
00693       const W&  semiring = s.semiring();
00694 
00695       typename misc::static_if
00696         <misc::static_eq<Tm, oTm>::value, const Tm&, Tm>::t
00697         new_m = op_convert(monoid, SELECT(Tm), m);
00698       typename misc::static_if
00699         <misc::static_eq<Tw, oTw>::value, const Tw&, Tw>::t
00700         new_w = op_convert(semiring, SELECT(Tw), w);
00701 
00702       typename algebra::polynom<Tm, Tw>::iterator i = p.find(new_m);
00703       if (new_w == zero_value(semiring, new_w))
00704       {
00705         if (i != p.end())
00706           p.erase(i);
00707       }
00708       else if (i == p.end())
00709         p.insert(new_m, new_w);
00710       else
00711         i->second = new_w;
00712     }
00713 
00714     template <class W, class M, class Tm, class Tw>
00715     Tm op_choose_from_supp(const algebra::Series<W, M>&,
00716                            const algebra::polynom<Tm, Tw>& p)
00717     {
00718       typedef typename algebra::polynom<Tm, Tw>::const_iterator const_iterator;
00719 
00720       const unsigned size = p.size();
00721 
00722       if (size == 0)
00723         return Tm();
00724 
00725       const_iterator i = p.begin();
00726 
00727       // No need to call rand in this case
00728       if (size == 1)
00729         return i->first;
00730 
00731       unsigned index = rand() % size;
00732       while (index > 0)
00733       {
00734         --index;
00735         ++i;
00736       }
00737       return i->first;
00738     }
00739 
00740     template <class W, class M, class Tm, class Tw>
00741     Element<algebra::Series<W,M>, algebra::polynom<Tm,Tw> >
00742     op_choose(const algebra::Series<W,M>& s,
00743               SELECTOR2(algebra::polynom<Tm,Tw>))
00744     {
00745       algebra::polynom<Tm, Tw> p;
00746       // FIXME: add global constants to define this !
00747       unsigned nb_monome = rand() * 10 / RAND_MAX;
00748       for (unsigned i = 0; i < nb_monome; ++i)
00749         p[s.monoid().choose()] = s.semiring().choose();
00750       return Element<algebra::Series<W,M>, algebra::polynom<Tm,Tw> >(s, p);
00751     }
00752 
00753     /*----------.
00754     | transpose |
00755     `----------*/
00756 
00757     template <typename W, typename M, typename Tm, typename Tw>
00758     void  op_in_transpose(const algebra::Series<W, M>& s,
00759                           algebra::polynom<Tm, Tw>& t)
00760     {
00761       algebra::DefaultTransposeFun<algebra::Series<W, M>,
00762                                    algebra::polynom<Tm, Tw> > f;
00763       t = f(s, t);
00764     }
00765 
00766   } // ! algebra
00767 
00768 } // ! vcsn
00769 
00770 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SERIES_POLYNOMS_HXX