numerical_semiring.hxx

00001 // numerical_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 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_NUMERICAL_SEMIRING_HXX
00018 # define VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_NUMERICAL_SEMIRING_HXX
00019 
00020 # include <cmath>
00021 # include <vaucanson/algebra/concept/semiring_base.hh>
00022 # include <vaucanson/algebra/implementation/semiring/numerical_semiring.hh>
00023 # include <vaucanson/misc/random.hh>
00024 # include <vaucanson/misc/limits.hh>
00025 # include <vaucanson/misc/contract.hh>
00026 
00027 namespace vcsn {
00028 
00029   namespace algebra {
00030 
00031     template<typename T>
00032     bool op_contains(const algebra::NumericalSemiring&, T)
00033     {
00034       return true;
00035     }
00036 
00037     template<typename T, typename U>
00038     void op_in_mul(const algebra::NumericalSemiring&,
00039                    T& dst, U arg)
00040     {
00041       dst *= arg;
00042     }
00043 
00044     template<typename T, typename U>
00045     void op_in_add(const algebra::NumericalSemiring&,
00046                    T& dst, U arg)
00047     {
00048       dst += arg;
00049     }
00050 
00051     // FIXME: there should be specializations of op_add_traits and
00052     // op_mul_traits giving the type of the result depending on the
00053     // type of the arguments.
00054 
00055     template<typename T, typename U>
00056     T op_mul(const algebra::NumericalSemiring&, T a, U b)
00057     {
00058       return a * b;
00059     }
00060 
00061     template<typename T, typename U>
00062     T op_add(const algebra::NumericalSemiring&, T a, U b)
00063     {
00064       return a + b;
00065     }
00066 
00067     template<typename T>
00068     T identity_value(SELECTOR(algebra::NumericalSemiring), SELECTOR(T))
00069     {
00070       return T(1);
00071     }
00072 
00073     template<typename T>
00074     T zero_value(SELECTOR(algebra::NumericalSemiring), SELECTOR(T))
00075     {
00076       return T(0);
00077     }
00078 
00079     template <class T>
00080     Element<algebra::NumericalSemiring, T>
00081     op_choose(const algebra::NumericalSemiring& set, SELECTOR(T))
00082     {
00083       return
00084         Element<algebra::NumericalSemiring, T>
00085           (set, misc::random::generate<T>());
00086     }
00087 
00088     /*-----------------------------.
00089     | specializations for integers |
00090     `-----------------------------*/
00091 
00092     inline
00093     bool
00094     op_can_choose_non_starable(const algebra::NumericalSemiring&,
00095                                 SELECTOR(int))
00096     {
00097       return true; // Every integer excepted Zero is non-starable
00098     }
00099 
00100     inline
00101     Element<algebra::NumericalSemiring, int>
00102     op_choose_starable(const algebra::NumericalSemiring& set, SELECTOR(int))
00103     {
00104       // 0 is the only one integer to be starable. So we have no choice !
00105       return Element<algebra::NumericalSemiring, int>(set, 0);
00106     }
00107 
00108     inline
00109     Element<algebra::NumericalSemiring, int>
00110     op_choose_non_starable(const algebra::NumericalSemiring& set,
00111                            SELECTOR(int))
00112     {
00113       int r = misc::random::generate<int>();
00114       if (!r)
00115         r = 1;
00116       return Element<algebra::NumericalSemiring, int>(set, r);
00117     }
00118 
00119     /*-----------------------------.
00120     | specializations for Booleans |
00121     `-----------------------------*/
00122     template<typename T>
00123     void op_in_mul(const algebra::NumericalSemiring&,
00124                           bool& dst, bool src)
00125     {
00126       dst = dst && src;
00127     }
00128 
00129     inline bool op_mul(const algebra::NumericalSemiring&, bool a, bool b)
00130     {
00131       return a && b;
00132     }
00133 
00134     inline void op_in_add(const algebra::NumericalSemiring&,
00135                           bool& dst, bool src)
00136     {
00137       dst = dst || src;
00138     }
00139 
00140     inline bool op_add(const algebra::NumericalSemiring&, bool a, bool b)
00141     {
00142       return a || b;
00143     }
00144 
00145     inline bool identity_value(SELECTOR(algebra::NumericalSemiring),
00146                                SELECTOR(bool))
00147     {
00148       return true;
00149     }
00150 
00151     inline bool zero_value(SELECTOR(algebra::NumericalSemiring),
00152                            SELECTOR(bool))
00153     {
00154       return false;
00155     }
00156 
00157     inline bool op_starable(const algebra::NumericalSemiring&, bool)
00158     {
00159       return true;
00160     }
00161 
00162     inline void op_in_star(const algebra::NumericalSemiring&, bool& b)
00163     {
00164       b = true;
00165     }
00166 
00167     inline
00168     Element<algebra::NumericalSemiring, bool>
00169     op_choose_starable(const algebra::NumericalSemiring& set, SELECTOR(bool))
00170     {
00171       // Every Boolean is starable !
00172       return op_choose(set, SELECT(bool));
00173     }
00174 
00175     inline
00176     Element<algebra::NumericalSemiring, bool>
00177     op_choose_non_starable(const algebra::NumericalSemiring& set,
00178                            SELECTOR(bool))
00179     {
00180       assertion_(false, "Cannot choose non-starable boolean: all boolean are starable.");
00181       return Element<algebra::NumericalSemiring, bool>(set, false);
00182     }
00183 
00184     /*--------------------------------------------.
00185     | specialization for floating point numbers.  |
00186     `--------------------------------------------*/
00187 
00188     template<typename T>
00189     bool op_starable(const algebra::NumericalSemiring&, T v)
00190     {
00191       return v == 0;
00192     }
00193 
00194     inline bool op_starable(const algebra::NumericalSemiring&,
00195                              const float& f)
00196     {
00197       return (-1.0 < f) && (f < 1.0);
00198     }
00199 
00200     inline bool op_starable(const algebra::NumericalSemiring&,
00201                              const double& f)
00202     {
00203       return (-1.0 < f) && (f < 1.0);
00204     }
00205 
00206     inline void op_in_star(const algebra::NumericalSemiring&, float& f)
00207     {
00208       static_assertion(misc::limits<float>::has_infinity,
00209                        float_has_infinity);
00210       if (f < 1.0)
00211         f = (1.0 / (1.0 - f));
00212       else
00213         f = misc::limits<float>::infinity();
00214     }
00215 
00216     inline void op_in_star(const algebra::NumericalSemiring&, double& f)
00217     {
00218       if (f < 1.0)
00219         f = (1.0 / (1.0 - f));
00220       else
00221         assertion(! "star not defined.");
00222     }
00223 
00224     inline
00225     bool
00226     op_can_choose_non_starable(const algebra::NumericalSemiring&,
00227                                 SELECTOR(float))
00228     {
00229       return true; // Every float which is less than -1 or greater than 1 is
00230                    // non-starable.
00231     }
00232 
00233     inline
00234     Element<algebra::NumericalSemiring, float>
00235     op_choose_starable(const algebra::NumericalSemiring& set,
00236                        SELECTOR(float))
00237     {
00238       float res = misc::random::generate<float>(-1, 1);
00239 
00240       while (res == -1)
00241         res = misc::random::generate<float>(-1, 1);
00242       return
00243         Element<algebra::NumericalSemiring, float>
00244           (set, res);
00245     }
00246 
00247     inline
00248     Element<algebra::NumericalSemiring, float>
00249     op_choose_non_starable(const algebra::NumericalSemiring& set,
00250                            SELECTOR(float))
00251     {
00252       float res = misc::random::generate<float>() * 1000.;
00253       while (op_starable(set, res))
00254         res = misc::random::generate<float>() * 1000.;
00255       return Element<algebra::NumericalSemiring, float>(set, res);
00256     }
00257 
00258     inline
00259     bool
00260     op_can_choose_non_starable(const algebra::NumericalSemiring&,
00261                                 SELECTOR(double))
00262     {
00263       return true; // Every float which is less than -1 or greater than 1 is
00264                    // non-starable.
00265     }
00266 
00267     inline
00268     Element<algebra::NumericalSemiring, double>
00269     op_choose_starable(const algebra::NumericalSemiring& set,
00270                        SELECTOR(double))
00271     {
00272       double res = misc::random::generate<double>(-1, 1);
00273 
00274       while (res == -1)
00275         res = misc::random::generate<double>(-1, 1);
00276       return
00277         Element<algebra::NumericalSemiring, double>
00278           (set, res);
00279     }
00280 
00281     inline
00282     Element<algebra::NumericalSemiring, double>
00283     op_choose_non_starable(const algebra::NumericalSemiring& set,
00284                            SELECTOR(double))
00285     {
00286       double res = misc::random::generate<double>() * 1000.;
00287       while (op_starable(set, res))
00288         res = misc::random::generate<double>() * 1000.;
00289       return Element<algebra::NumericalSemiring, double>(set, res);
00290     }
00291     // FIXME: add some more operators as syntactic sugar
00292 
00293 
00294     /*------------------------------------.
00295     | specialization for rational numbers |
00296      `------------------------------------*/
00297 
00298     inline algebra::RationalNumber
00299     identity_value(SELECTOR(algebra::NumericalSemiring),
00300                    SELECTOR(algebra::RationalNumber))
00301     {
00302       return algebra::RationalNumber(1);
00303     }
00304 
00305     inline algebra::RationalNumber
00306     zero_value(SELECTOR(algebra::NumericalSemiring),
00307                SELECTOR(algebra::RationalNumber))
00308     {
00309       return algebra::RationalNumber(0);
00310     }
00311 
00312     inline bool op_starable(const algebra::NumericalSemiring&,
00313                             const algebra::RationalNumber& r)
00314     {
00315       int denom = r.denom();
00316       return abs(r.num()) < denom;
00317     }
00318 
00319     inline void op_in_star(const algebra::NumericalSemiring&,
00320                            algebra::RationalNumber& r)
00321     {
00322       int denom = r.denom();
00323       algebra::RationalNumber one = algebra::RationalNumber(1, 1);
00324       if (denom > abs(r.num()))
00325         r = (one / (r - one));
00326       else
00327         assertion(! "star not defined.");
00328     }
00329 
00330     inline
00331     bool
00332     op_can_choose_non_starable(const algebra::NumericalSemiring&,
00333                                 SELECTOR(algebra::RationalNumber))
00334     {
00335       return true; // Every rational number which is greater than 1 and
00336                    // less than -1 is non-starable
00337     }
00338 
00339     inline
00340     Element<algebra::NumericalSemiring, algebra::RationalNumber>
00341     op_choose_starable(const algebra::NumericalSemiring& set,
00342                        SELECTOR(algebra::RationalNumber))
00343     {
00344       algebra::RationalNumber min = algebra::RationalNumber(-1, 1);
00345       algebra::RationalNumber max = algebra::RationalNumber(1, 1);
00346       return
00347         Element<algebra::NumericalSemiring, algebra::RationalNumber>
00348           (set, misc::random::generate<algebra::RationalNumber>(min, max));
00349     }
00350 
00351     inline
00352     Element<algebra::NumericalSemiring, algebra::RationalNumber>
00353     op_choose_non_starable(const algebra::NumericalSemiring& set,
00354                            SELECTOR(algebra::RationalNumber))
00355     {
00356       algebra::RationalNumber res = algebra::RationalNumber(1, 1);
00357       int denom;
00358       do
00359         {
00360           res = misc::random::generate<algebra::RationalNumber>();
00361           denom = res.denom();
00362         }
00363       while (denom > abs(res.num()));
00364       return
00365         Element<algebra::NumericalSemiring, algebra::RationalNumber>
00366         (set, res);
00367     }
00368 
00369   } // algebra
00370 
00371 } // vcsn
00372 
00373 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_NUMERICAL_SEMIRING_HXX

Generated on Thu Dec 13 16:03:01 2007 for Vaucanson by  doxygen 1.5.4