Vaucanson 1.4
|
00001 // random.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, 2008, 2009 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_MISC_RANDOM_HXX 00018 # define VCSN_MISC_RANDOM_HXX 00019 00020 # include <vaucanson/misc/random.hh> 00021 # include <vaucanson/misc/limits.hh> 00022 # include <vaucanson/misc/algebra.hh> 00023 00024 # include <cmath> 00025 # include <cstdlib> 00026 # include <vector> 00027 00028 # include <iostream> 00029 00030 namespace vcsn { 00031 namespace misc { 00032 namespace random { 00033 00034 template<> 00035 inline char generate<char> () 00036 { 00037 // We do not want any 0, because it could generate errors in strings. 00038 return char (1 + unsigned (rand ()) % ( (1 << (sizeof (char) * 8)) - 1)); 00039 } 00040 00041 template<> 00042 inline char generate<char> (char min, char max) 00043 { 00044 unsigned range = unsigned (max - min) + 1; 00045 return char (min + rand () % range); 00046 } 00047 00048 inline char generate_letter () 00049 { 00050 return generate<char> ('a', 'z'); 00051 } 00052 00053 inline char generate_digit () 00054 { 00055 return generate<char> ('0', '9'); 00056 } 00057 00058 template<> 00059 inline bool generate<bool> () 00060 { 00061 return static_cast<bool> (rand () & 1); 00062 } 00063 00064 template<> 00065 inline int generate<int> () 00066 { 00067 int res = rand () % vcsn::misc::limits<int>::max (); 00068 return generate<bool> () ? res : res * -1; 00069 } 00070 00071 template<> 00072 inline int generate<int> (int min, int max) 00073 { 00074 unsigned range = unsigned (max - min) + 1; 00075 return min + rand () % range; 00076 } 00077 00078 template<> 00079 inline unsigned generate<unsigned> () 00080 { 00081 return rand () % vcsn::misc::limits<unsigned>::max (); 00082 } 00083 00084 template<> 00085 inline unsigned generate<unsigned> (unsigned min, unsigned max) 00086 { 00087 unsigned range = unsigned (max - min) + 1; 00088 return min + rand () % range; 00089 } 00090 00091 template<> 00092 inline float generate<float> () 00093 { 00094 // This formula comes from the caml stdlib. It generates numbers 00095 // between -2 and 2 (values that can be starable or not). 00096 return ( ((static_cast<float> (rand ()) / RAND_MAX + 00097 static_cast<float> (rand ())) / RAND_MAX + 00098 static_cast<float> (rand ())) / RAND_MAX) * 4 - 2; 00099 } 00100 00101 template<> 00102 inline float generate<float> (float min, float max) 00103 { 00104 float range = float (max - min); 00105 float generate_one = ( (static_cast<float> (rand ()) / RAND_MAX + 00106 static_cast<float> (rand ())) / RAND_MAX + 00107 static_cast<float> (rand ())) / RAND_MAX; 00108 00109 return min + generate_one * range; 00110 } 00111 00112 template<> 00113 inline double generate<double> () 00114 { 00115 // This formula comes from the caml stdlib. It generates numbers 00116 // between -2 and 2 (values that can be starable or not). 00117 return ( ((static_cast<double> (rand ()) / RAND_MAX + 00118 static_cast<double> (rand ())) / RAND_MAX + 00119 static_cast<double> (rand ())) / RAND_MAX) * 4 - 2; 00120 } 00121 00122 template<> 00123 inline double generate<double> (double min, double max) 00124 { 00125 double range = double (max - min); 00126 double generate_one = ( (static_cast<double> (rand ()) / RAND_MAX + 00127 static_cast<double> (rand ())) / RAND_MAX + 00128 static_cast<double> (rand ())) / RAND_MAX; 00129 00130 return min + generate_one * range; 00131 } 00132 00133 template <class IteratorValueType, class Iterator, class OutputIterator> 00134 void sample_n (const IteratorValueType&, Iterator first, Iterator end, 00135 OutputIterator out, unsigned n) 00136 { 00137 std::vector<IteratorValueType> from; 00138 for (Iterator i = first; i != end; ++i) 00139 from.push_back (*i); 00140 00141 while ( (from.size () > 0) && (n > 0)) 00142 { 00143 int c = generate<int> (0, from.size () - 1); 00144 *out = from[c]; 00145 ++out; 00146 from.erase (from.begin () + c); 00147 --n; 00148 } 00149 } 00150 00151 template<> 00152 inline 00153 vcsn::algebra::RationalNumber 00154 generate<vcsn::algebra::RationalNumber> () 00155 { 00156 const int num = generate<int> (); 00157 const unsigned denom = 00158 generate<unsigned> (1, vcsn::misc::limits<unsigned>::max ()); 00159 return vcsn::algebra::RationalNumber (num, denom); 00160 } 00161 00162 template<> 00163 inline 00164 vcsn::algebra::RationalNumber 00165 generate<vcsn::algebra::RationalNumber> 00166 (const vcsn::algebra::RationalNumber min, 00167 const vcsn::algebra::RationalNumber max) 00168 { 00169 int left = min.num_get () ; 00170 int right = max.num_get (); 00171 int den = min.den_get () * max.den_get (); 00172 00173 const int ratio = right - left; 00174 00175 int n1 = generate<int> (0, (vcsn::misc::limits<int>::max () - 1) / ratio); 00176 int n2 = generate<int> (0, (vcsn::misc::limits<int>::max () - 1) / ratio); 00177 00178 if (n1 > n2) 00179 { 00180 int swap = n1; 00181 n1 = n2; 00182 n2 = swap; 00183 } 00184 00185 n2 *= den; 00186 00187 n1 = n1 * ratio + (left * n2); 00188 00189 if (n1 == n2) 00190 --n1; 00191 if (-n1 == n2) 00192 ++n1; 00193 00194 return 00195 vcsn::algebra::RationalNumber (n1, n2); 00196 } 00197 00198 # define MAKE_PAIR_SPECIALIZATION(TYPE1, TYPE2) \ 00199 template <> \ 00200 inline \ 00201 std::pair<TYPE1, TYPE2> generate<std::pair<TYPE1, TYPE2> >() \ 00202 { \ 00203 return std::make_pair(generate<TYPE1> (), generate<TYPE2> ()); \ 00204 } 00205 00206 MAKE_PAIR_SPECIALIZATION(char, char) 00207 MAKE_PAIR_SPECIALIZATION(char, int) 00208 MAKE_PAIR_SPECIALIZATION(int, int) 00209 MAKE_PAIR_SPECIALIZATION(int, char) 00210 00211 # undef MAKE_PAIR_SPECIALIZATION 00212 00213 template <> 00214 inline 00215 small_alpha_letter_t 00216 generate<small_alpha_letter_t> () 00217 { 00218 return generate<char> (small_alpha_interval_t::from_value, 00219 small_alpha_interval_t::to_value); 00220 } 00221 00222 } // Random 00223 } // misc 00224 } // vcsn 00225 00226 #endif // ! VCSN_MISC_RANDOM_HXX