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