- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

# 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