Vaucanson 1.4
cyclic_semiring.hxx
00001 // tropical_semiring.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, 2011 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_IMPLEMENTATION_SEMIRING_CYCLIC_SEMIRING_HXX
00018 # define VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_CYCLIC_SEMIRING_HXX
00019 # include <vaucanson/config/system.hh>
00020 # include <vaucanson/algebra/implementation/semiring/cyclic_semiring.hh>
00021 # include <vaucanson/misc/random.hh>
00022 # include <vaucanson/misc/limits.hh>
00023 # include <boost/swap.hpp>
00024 # include <boost/tuple/tuple.hpp>
00025 
00026 namespace vcsn {
00027 
00028   namespace algebra {
00029 
00039     inline
00040     boost::tuple<unsigned int, int, int>
00041     ext_gcd (unsigned int a, unsigned int b)
00042     {
00043       unsigned int q, r;
00044       int x1 = 0;
00045       int x2 = 1;
00046       int y1 = 1;
00047       int y2 = 0;
00048       int x, y;
00049 
00050       if (a < b)
00051         {
00052           boost::swap (a, b);
00053           boost::swap (x1, x2);
00054           boost::swap (y1, y2);
00055         }
00056 
00057       if (b == 0)
00058         return boost::tuple<unsigned int, int, int> (a, 1, 0);
00059 
00060       while (b > 0)
00061         {
00062           q = a / b;
00063           r = a - q * b;
00064           x = x2 - q * x1;
00065           y = y2 - q * y1;
00066           a = b;
00067           b = r;
00068           x2 = x1;
00069           x1 = x;
00070           y2 = y1;
00071           y1 = y;
00072         }
00073 
00074       return boost::tuple<unsigned int, int, int> (a, x2, y2);
00075     }
00076 
00077     /*---------------.
00078     | Identity value |
00079     `---------------*/
00080 
00081     template<unsigned int n, typename T>
00082     T identity_value(SELECTOR(algebra::CyclicSemiring<n>), SELECTOR(T))
00083     {
00084       return T(1);
00085     }
00086 
00087     template<unsigned int n, typename T>
00088     bool show_identity_value(SELECTOR(algebra::CyclicSemiring<n>),
00089                              SELECTOR(T))
00090     {
00091       return false;
00092     }
00093 
00094     template<unsigned int n, typename T>
00095     bool
00096     is_positive_semiring(SELECTOR(algebra::CyclicSemiring<n>), SELECTOR(T))
00097     {
00098       return false;
00099     }
00100 
00101     template<unsigned int n, typename T>
00102     T zero_value(SELECTOR(algebra::CyclicSemiring<n>), SELECTOR(T))
00103     {
00104       return T(0);
00105     }
00106 
00107     /*------------.
00108     | op_contains |
00109     `------------*/
00110     template<unsigned int n, typename T>
00111     bool op_contains(const algebra::CyclicSemiring<n>&, T c)
00112     {
00113       return true;
00114     }
00115 
00116     /*---------------.
00117     | Multiplication |
00118     `---------------*/
00119     template<unsigned int n, typename T, typename U>
00120     void op_in_mul(const algebra::CyclicSemiring<n>&,
00121                    T& dst, U arg)
00122     {
00123       dst = (dst * arg) % n;
00124       dst = (dst < 0) ? dst + n : dst;
00125     }
00126 
00127     template<unsigned int n, typename T, typename U>
00128     T op_mul(const algebra::CyclicSemiring<n>&, T a, U b)
00129     {
00130       T res = (a * b) % n;
00131       return ((res < 0) ? res + n : res);
00132     }
00133 
00134     /*-----------------------.
00135     | Mutiplication for Z/2Z |
00136     `-----------------------*/
00137 
00138     inline
00139     void op_in_mul(const algebra::CyclicSemiring<2>&,
00140                                   bool& dst, bool arg)
00141     {
00142       dst = dst && arg;
00143     }
00144 
00145     inline
00146     bool op_mul(const algebra::CyclicSemiring<2>&, bool a, bool b)
00147     {
00148       return (a && b);
00149     }
00150 
00151     /*---------.
00152     | Addition |
00153     `---------*/
00154     template<unsigned int n, typename T, typename U>
00155     void op_in_add(const algebra::CyclicSemiring<n>&,
00156                    T& dst, U arg)
00157     {
00158       dst = ((dst + arg) + (2 * n)) % n;
00159     }
00160 
00161     template<unsigned int n, typename T, typename U>
00162     T op_add(const algebra::CyclicSemiring<n>&, T a, U b)
00163     {
00164       return ((a + b) + (2 * n)) % n;
00165     }
00166 
00167     /*------------------.
00168     | Addition for Z/2Z |
00169     `------------------*/
00170 
00171     inline
00172     void op_in_add(const algebra::CyclicSemiring<2>&,
00173                                   bool& dst, bool arg)
00174     {
00175       dst = dst ^ arg;
00176     }
00177 
00178     inline
00179     bool op_add(const algebra::CyclicSemiring<2>&, bool a, bool b)
00180     {
00181       return a ^ b;
00182     }
00183 
00184     /*---------.
00185     | Division |
00186     `---------*/
00187 
00188     template<unsigned int n, typename T, typename U>
00189     void op_in_div (const algebra::CyclicSemiring<n>& s1,
00190                     T& dst, U arg)
00191     {
00192       boost::tuple<unsigned int , int, int> res = ext_gcd (dst, arg);
00193       if (res.get<0> () == 1)
00194         {
00195           op_in_mul (s1, dst, res.get<2> ());
00196           return;
00197         }
00198 
00199       assertion(! "tried to divide by a number"
00200                 " without multiplicative inverse.");
00201     }
00202 
00203     template<unsigned int n, typename T, typename U>
00204     T op_div (const algebra::CyclicSemiring<n>& s, T a, U b)
00205     {
00206       boost::tuple<unsigned int , int, int> res = ext_gcd (a, b);
00207       if (res.get<0> () == 1)
00208         return (op_mul (s, a, res.get<2> ()));
00209 
00210       assertion(! "tried to divide by a number"
00211                 " without multiplicative inverse.");
00212     }
00213 
00214     /*------------------.
00215     | Division for Z/2Z |
00216     `------------------*/
00217 
00218     inline
00219     void op_in_div (const algebra::CyclicSemiring<2>& s1,
00220                                    bool& dst, bool arg)
00221     {
00222       if (arg == 1)
00223         return;
00224       assertion (! "Division by zero.");
00225     }
00226 
00227     inline
00228     bool op_div (const algebra::CyclicSemiring<2>& s, bool a, bool b)
00229     {
00230       if (b == 1)
00231         return (a);
00232       assertion(! "Division by zero.");
00233     }
00234 
00235     /*-------------.
00236     | Substraction |
00237     `-------------*/
00238 
00239     template<unsigned int n, typename T, typename U>
00240     void op_in_sub(const algebra::CyclicSemiring<n>& s1,
00241                    T& dst, U arg)
00242     {
00243       dst = (dst - arg) % n;
00244       dst = (dst < 0) ? dst + n : dst;
00245     }
00246 
00247     template<unsigned int n, typename T, typename U>
00248     T op_sub(const algebra::CyclicSemiring<n>& s,
00249              T a, U b)
00250     {
00251       T res = (a - b) % n;
00252       return ((res < 0) ? res + n : res);
00253     }
00254 
00255     /*----------------------.
00256     | Substraction for Z/2Z |
00257     `----------------------*/
00258 
00259     inline
00260     void op_in_sub(const algebra::CyclicSemiring<2>& s1,
00261                                    bool& dst, bool arg)
00262     {
00263       dst = dst ^ arg;
00264     }
00265 
00266     inline
00267     bool op_sub(const algebra::CyclicSemiring<2>& s,
00268                 bool a, bool b)
00269     {
00270       return (a ^ b);
00271     }
00272 
00273     /*-----.
00274     | Star |
00275     `-----*/
00276 
00277     template <unsigned int n, typename T>
00278     bool
00279     op_starable(const algebra::CyclicSemiring<n>&, T b)
00280     {
00281       if (b == T(0))
00282         return true;
00283       return false;
00284     }
00285 
00286     template <unsigned int n, class T>
00287     void
00288     op_in_star(const algebra::CyclicSemiring<n>&, T& b)
00289     {
00290       if (b == T(0))
00291         {
00292           b = T(1);
00293           return;
00294         }
00295       assertion(! "star not defined.");
00296     }
00297 
00298     template <unsigned int n, class T>
00299     Element<algebra::CyclicSemiring<n>, T>
00300     op_choose(const algebra::CyclicSemiring<n>& set, SELECTOR(T))
00301     {
00302       return Element<algebra::CyclicSemiring<n>, T>
00303         (set, misc::random::generate<T>());
00304     }
00305 
00306     template <unsigned int n, typename T>
00307     bool
00308     op_can_choose_non_starable(const algebra::CyclicSemiring<n>&,
00309                                SELECTOR(T))
00310     {
00311       return true;
00312     }
00313 
00314     template <unsigned int n, class T>
00315     Element<algebra::CyclicSemiring<n>, T>
00316     op_choose_starable(const algebra::CyclicSemiring<n>& set,
00317                        SELECTOR(T))
00318     {
00319       T r;
00320       do
00321         r = op_choose(set, SELECT(T));
00322       while (!op_starable(set, r));
00323       return r;
00324     }
00325 
00326     template <unsigned int n, class T>
00327     Element<algebra::CyclicSemiring<n>, T>
00328     op_choose_non_starable(const algebra::CyclicSemiring<n>& set,
00329                            SELECTOR(T))
00330     {
00331       T r;
00332       do
00333         r = op_choose(set, SELECT(T));
00334       while (op_starable(set, r));
00335       return r;
00336     }
00337 
00338     /*---------------.
00339     | Pretty printer |
00340     `---------------*/
00341     template<unsigned int n, typename St, typename T>
00342     St& op_rout(const algebra::CyclicSemiring<n>&, St& st, const T& v)
00343     {
00344       st << v;
00345       return st;
00346     }
00347 
00348   } // algebra
00349 
00350 } // vcsn
00351 
00352 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_CYCLIC_SEMIRING_HXX