Vaucanson 1.4
freemonoid_product.hxx
00001 // freemonoid_product.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2004, 2005, 2008 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_ALGEBRA_CONCEPT_FREEMONOID_PRODUCT_HXX
00018 # define VCSN_ALGEBRA_CONCEPT_FREEMONOID_PRODUCT_HXX
00019 
00020 # include <vaucanson/algebra/concept/freemonoid_product.hh>
00021 
00022 namespace vcsn
00023 {
00024   namespace algebra
00025   {
00026     template <typename F, typename S>
00027     MonoidRep<FreeMonoidProduct<F, S> >::MonoidRep() :
00028         open_par("("),
00029         sep(","),
00030         close_par(")")
00031     {}
00032 
00033     template <typename Semiring, typename F, typename S>
00034     void
00035     SeriesRep<Semiring, FreeMonoidProduct<F, S> >::
00036     disambiguate(const monoid_t& monoid, pointer_t& p)
00037     {
00038       // Pointer types.
00039       typedef boost::shared_ptr<first_rep_t>            first_p_t;
00040       typedef boost::shared_ptr<second_rep_t>           second_p_t;
00041 
00042       first_p_t first_rep(new first_rep_t(p->first_representation()));
00043       second_p_t second_rep(new second_rep_t(p->second_representation()));
00044 
00045       // Backup old pointers.
00046       first_p_t first_rep_orig = first_rep;
00047       second_p_t second_rep_orig = second_rep;
00048 
00049       // Real work done here.
00050       first_rep->disambiguate(monoid.first_monoid(), first_rep);
00051       second_rep->disambiguate(monoid.second_monoid(), second_rep);
00052 
00053       // Copy on write.
00054       if (first_rep_orig != first_rep || second_rep_orig != second_rep)
00055       {
00056         self_t new_rep(*p);
00057         new_rep.first_representation() = *first_rep;
00058         new_rep.second_representation() = *second_rep;
00059         p = pointer_t(new self_t(new_rep));
00060       }
00061     }
00062 
00063     template <typename Semiring, typename F, typename S>
00064     SeriesRep<Semiring, F>&
00065     SeriesRep<Semiring, FreeMonoidProduct<F, S> >::first_representation()
00066     {
00067       return first_representation_;
00068     }
00069 
00070     template <typename Semiring, typename F, typename S>
00071     const SeriesRep<Semiring, F>&
00072     SeriesRep<Semiring, FreeMonoidProduct<F, S> >::first_representation() const
00073     {
00074       return first_representation_;
00075     }
00076 
00077     template <typename Semiring, typename F, typename S>
00078     SeriesRep<Semiring, S>&
00079     SeriesRep<Semiring, FreeMonoidProduct<F, S> >::second_representation()
00080     {
00081       return second_representation_;
00082     }
00083 
00084     template <typename Semiring, typename F, typename S>
00085     const SeriesRep<Semiring, S>&
00086     SeriesRep<Semiring, FreeMonoidProduct<F, S> >::second_representation() const
00087     {
00088       return second_representation_;
00089     }
00090 
00091     template <typename F, typename S>
00092     bool
00093     operator==(boost::shared_ptr<MonoidRep<FreeMonoidProduct<F, S> > > lhs,
00094                boost::shared_ptr<MonoidRep<FreeMonoidProduct<F, S> > > rhs)
00095     {
00096       // Type helpers.
00097       typedef MonoidRepBase<MonoidRep, FreeMonoidProduct<F, S> >
00098         monoid_rep_base_t;
00099       typedef boost::shared_ptr<monoid_rep_base_t>      p_t;
00100 
00101       return (lhs->open_par == rhs->open_par &&
00102               lhs->sep == rhs->sep &&
00103               lhs->close_par == rhs->close_par &&
00104               static_cast<p_t>(lhs) == static_cast<p_t>(rhs));
00105     }
00106 
00107     template <typename Semiring, typename F, typename S>
00108     bool
00109     operator==(boost::shared_ptr<SeriesRep<Semiring, FreeMonoidProduct<F, S> > > lhs,
00110                boost::shared_ptr<SeriesRep<Semiring, FreeMonoidProduct<F, S> > > rhs)
00111     {
00112       // Type helpers.
00113       typedef SeriesRep<Semiring, F> first_rep_t;
00114       typedef SeriesRep<Semiring, S> second_rep_t;
00115       typedef SeriesRepBase<SeriesRep, Semiring, FreeMonoidProduct<F, S> >
00116         series_rep_base_t;
00117 
00118       // Pointer types.
00119       typedef boost::shared_ptr<first_rep_t>            first_p_t;
00120       typedef boost::shared_ptr<second_rep_t>           second_p_t;
00121       typedef boost::shared_ptr<series_rep_base_t>      p_t;
00122 
00123       // FIXME: we should provide operator== for the pointed to types.
00124       first_p_t lhs_first(new first_rep_t());
00125       second_p_t lhs_second(new second_rep_t());
00126       first_p_t rhs_first(new first_rep_t());
00127       second_p_t rhs_second(new second_rep_t());
00128 
00129       *lhs_first = lhs->first_representation();
00130       *lhs_second = lhs->second_representation();
00131       *rhs_first = rhs->first_representation();
00132       *rhs_second = rhs->second_representation();
00133 
00134       return (lhs_first == rhs_first &&
00135               lhs_second == rhs_second &&
00136               static_cast<p_t>(lhs) == static_cast<p_t>(rhs));
00137     }
00138 
00139     /*------------------------.
00140     | FreeMonoidProduct<F, S> |
00141     `------------------------*/
00142 
00143     // FIXME: This facility is a HACK. Explanations: when a high level
00144     // structural element (a structure inheriting from Structure) is
00145     // instantiated (say a series_set_t), the underlying monoid is only
00146     // accessible via const methods.  Unfortunately it means that when a
00147     // FreeMonoidProduct is instantiated (not as a non-const object) the
00148     // shared_ptr holding the pointers to the first and second monoid
00149     // representations can't be changed. And, because we originally planned to
00150     // use singleton (see get_instance()) and other clever tricks, an FMP<F, S>
00151     // with F == S will use the SAME representation for both the monoid.
00152     // (simply put, changing the epsilon representation for the first monoid
00153     // will pass on to the second one). A lot of work needs to be done to solve
00154     // this problem elegantly but AFAIK it all revolves around improving the
00155     // MonoidRepBase to be more like an alphabet (with dynamic data stored in
00156     // some chosen implementation). As for now the implemented solution has the
00157     // least impact on Vaucanson. It could have been done more compact but the
00158     // choice was made to choose the code that most visibly explains why it is
00159     // done.  We ensure _when creating the FMP_ that if the two representations
00160     // match, we create a new one for the second monoid (the calculated
00161     // representation build by the disambiguate function is used to initialize
00162     // it). WARNING: it obviously defeat the purpose of the shared_ptr.
00163     template <typename F, typename S>
00164     void
00165     split_monoid_(F&, S&)
00166     {}
00167 
00168     template <typename F>
00169     void
00170     split_monoid_(F& first_monoid, F& second_monoid)
00171     {
00172       if (first_monoid.representation().get() == second_monoid.representation().get())
00173       {
00174         typename F::monoid_rep_t second = *(second_monoid.representation());
00175         second_monoid.set_representation(second);
00176       }
00177     }
00178 
00179     template <class F, class S>
00180     FreeMonoidProduct<F, S>::FreeMonoidProduct(const F& a, const S& b) :
00181         first_monoid_(a), second_monoid_(b),
00182         rep_(MonoidRepDefault<FreeMonoidProduct<F, S> >::get_instance())
00183     {
00184       split_monoid_(first_monoid_, second_monoid_);
00185     }
00186 
00187     template <class F, class S>
00188     FreeMonoidProduct<F, S>::FreeMonoidProduct(const F& a, const S& b,
00189                                                MonoidRep<FreeMonoidProduct<F, S> > mr) :
00190         first_monoid_(a), second_monoid_(b),
00191         rep_(boost::shared_ptr<MonoidRep<FreeMonoidProduct<F, S> > >(new MonoidRep<FreeMonoidProduct<F, S> >(mr)))
00192     {
00193       split_monoid_(first_monoid_, second_monoid_);
00194     }
00195 
00196     template <class F, class S>
00197     FreeMonoidProduct<F, S>::FreeMonoidProduct(const FreeMonoidProduct& w) :
00198       FreeMonoidProductBase<FreeMonoidProduct<F, S> >(w),
00199       first_monoid_(w.first_monoid_),
00200       second_monoid_(w.second_monoid_),
00201       rep_(w.rep_)
00202     {
00203       split_monoid_(first_monoid_, second_monoid_);
00204     }
00205 
00206     template <class F, class S>
00207     typename FreeMonoidProduct<F, S>::first_monoid_t&
00208     FreeMonoidProduct<F, S>::first_monoid()
00209     {
00210       return first_monoid_;
00211     }
00212 
00213     template <class F, class S>
00214     const typename FreeMonoidProduct<F, S>::first_monoid_t&
00215     FreeMonoidProduct<F, S>::first_monoid() const
00216     {
00217       return first_monoid_;
00218     }
00219 
00220     template <class F, class S>
00221     typename FreeMonoidProduct<F, S>::second_monoid_t&
00222     FreeMonoidProduct<F, S>::second_monoid()
00223     {
00224       return second_monoid_;
00225     }
00226 
00227     template <class F, class S>
00228     const typename FreeMonoidProduct<F, S>::second_monoid_t&
00229     FreeMonoidProduct<F, S>::second_monoid() const
00230     {
00231       return second_monoid_;
00232     }
00233 
00234     template <typename F, typename S>
00235     const boost::shared_ptr<MonoidRep<FreeMonoidProduct<F, S> > >
00236     FreeMonoidProduct<F, S>::representation() const
00237     {
00238       return rep_;
00239     }
00240 
00241     template <typename F, typename S>
00242     void
00243     FreeMonoidProduct<F, S>::set_representation(MonoidRep<FreeMonoidProduct<F, S> > mr)
00244     {
00245       rep_ = boost::shared_ptr<MonoidRep<FreeMonoidProduct<F, S> > >(new MonoidRep<FreeMonoidProduct<F, S> > (mr));
00246     }
00247 
00248     template <typename F, typename S>
00249     bool
00250     operator==(const FreeMonoidProduct<F, S>& lhs,
00251                const FreeMonoidProduct<F, S>& rhs)
00252     {
00253       return (lhs.first_monoid() == rhs.first_monoid() &&
00254               lhs.second_monoid() == rhs.second_monoid() &&
00255               lhs.representation() == rhs.representation());
00256     }
00257 
00258   } // ! algebra
00259 
00260 } // ! vcsn
00261 
00262 #endif // ! VCSN_ALGEBRA_CONCEPT_FREEMONOID_PRODUCT_HXX