00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00095
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
00116
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 }
00223 }
00224 }
00225
00226 #endif // ! VCSN_MISC_RANDOM_HXX