Vaucanson  1.4.1
random.hxx
1 // random.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 The Vaucanson Group.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // The complete GNU General Public Licence Notice can be found as the
13 // `COPYING' file in the root directory.
14 //
15 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
16 //
17 #ifndef VCSN_MISC_RANDOM_HXX
18 # define VCSN_MISC_RANDOM_HXX
19 
20 # include <vaucanson/misc/random.hh>
21 # include <vaucanson/misc/limits.hh>
22 # include <vaucanson/misc/algebra.hh>
23 
24 # include <cmath>
25 # include <cstdlib>
26 # include <vector>
27 
28 # include <iostream>
29 
30 namespace vcsn {
31  namespace misc {
32  namespace random {
33 
34  template<>
35  inline char generate<char> ()
36  {
37  // We do not want any 0, because it could generate errors in strings.
38  return char (1 + unsigned (rand ()) % ( (1 << (sizeof (char) * 8)) - 1));
39  }
40 
41  template<>
42  inline char generate<char> (char min, char max)
43  {
44  unsigned range = unsigned (max - min) + 1;
45  return char (min + rand () % range);
46  }
47 
48  inline char generate_letter ()
49  {
50  return generate<char> ('a', 'z');
51  }
52 
53  inline char generate_digit ()
54  {
55  return generate<char> ('0', '9');
56  }
57 
58  template<>
59  inline bool generate<bool> ()
60  {
61  return static_cast<bool> (rand () & 1);
62  }
63 
64  template<>
65  inline int generate<int> ()
66  {
67  int res = rand () % vcsn::misc::limits<int>::max ();
68  return generate<bool> () ? res : res * -1;
69  }
70 
71  template<>
72  inline int generate<int> (int min, int max)
73  {
74  unsigned range = unsigned (max - min) + 1;
75  return min + rand () % range;
76  }
77 
78  template<>
79  inline unsigned generate<unsigned> ()
80  {
81  return rand () % vcsn::misc::limits<unsigned>::max ();
82  }
83 
84  template<>
85  inline unsigned generate<unsigned> (unsigned min, unsigned max)
86  {
87  unsigned range = unsigned (max - min) + 1;
88  return min + rand () % range;
89  }
90 
91  template<>
92  inline float generate<float> ()
93  {
94  // This formula comes from the caml stdlib. It generates numbers
95  // between -2 and 2 (values that can be starable or not).
96  return ( ((static_cast<float> (rand ()) / RAND_MAX +
97  static_cast<float> (rand ())) / RAND_MAX +
98  static_cast<float> (rand ())) / RAND_MAX) * 4 - 2;
99  }
100 
101  template<>
102  inline float generate<float> (float min, float max)
103  {
104  float range = float (max - min);
105  float generate_one = ( (static_cast<float> (rand ()) / RAND_MAX +
106  static_cast<float> (rand ())) / RAND_MAX +
107  static_cast<float> (rand ())) / RAND_MAX;
108 
109  return min + generate_one * range;
110  }
111 
112  template<>
113  inline double generate<double> ()
114  {
115  // This formula comes from the caml stdlib. It generates numbers
116  // between -2 and 2 (values that can be starable or not).
117  return ( ((static_cast<double> (rand ()) / RAND_MAX +
118  static_cast<double> (rand ())) / RAND_MAX +
119  static_cast<double> (rand ())) / RAND_MAX) * 4 - 2;
120  }
121 
122  template<>
123  inline double generate<double> (double min, double max)
124  {
125  double range = double (max - min);
126  double generate_one = ( (static_cast<double> (rand ()) / RAND_MAX +
127  static_cast<double> (rand ())) / RAND_MAX +
128  static_cast<double> (rand ())) / RAND_MAX;
129 
130  return min + generate_one * range;
131  }
132 
133  template <class IteratorValueType, class Iterator, class OutputIterator>
134  void sample_n (const IteratorValueType&, Iterator first, Iterator end,
135  OutputIterator out, unsigned n)
136  {
137  std::vector<IteratorValueType> from;
138  for (Iterator i = first; i != end; ++i)
139  from.push_back (*i);
140 
141  while ( (from.size () > 0) && (n > 0))
142  {
143  int c = generate<int> (0, from.size () - 1);
144  *out = from[c];
145  ++out;
146  from.erase (from.begin () + c);
147  --n;
148  }
149  }
150 
151  template<>
152  inline
154  generate<vcsn::algebra::RationalNumber> ()
155  {
156  const int num = generate<int> ();
157  const unsigned denom =
158  generate<unsigned> (1, vcsn::misc::limits<unsigned>::max ());
159  return vcsn::algebra::RationalNumber (num, denom);
160  }
161 
162  template<>
163  inline
165  generate<vcsn::algebra::RationalNumber>
168  {
169  int left = min.num_get () ;
170  int right = max.num_get ();
171  int den = min.den_get () * max.den_get ();
172 
173  const int ratio = right - left;
174 
175  int n1 = generate<int> (0, (vcsn::misc::limits<int>::max () - 1) / ratio);
176  int n2 = generate<int> (0, (vcsn::misc::limits<int>::max () - 1) / ratio);
177 
178  if (n1 > n2)
179  {
180  int swap = n1;
181  n1 = n2;
182  n2 = swap;
183  }
184 
185  n2 *= den;
186 
187  n1 = n1 * ratio + (left * n2);
188 
189  if (n1 == n2)
190  --n1;
191  if (-n1 == n2)
192  ++n1;
193 
194  return
196  }
197 
198 # define MAKE_PAIR_SPECIALIZATION(TYPE1, TYPE2) \
199  template <> \
200  inline \
201  std::pair<TYPE1, TYPE2> generate<std::pair<TYPE1, TYPE2> >() \
202  { \
203  return std::make_pair(generate<TYPE1> (), generate<TYPE2> ()); \
204  }
205 
206  MAKE_PAIR_SPECIALIZATION(char, char)
207  MAKE_PAIR_SPECIALIZATION(char, int)
208  MAKE_PAIR_SPECIALIZATION(int, int)
209  MAKE_PAIR_SPECIALIZATION(int, char)
210 
211 # undef MAKE_PAIR_SPECIALIZATION
212 
213  template <>
214  inline
217  {
218  return generate<char> (small_alpha_interval_t::from_value,
219  small_alpha_interval_t::to_value);
220  }
221 
222  } // Random
223  } // misc
224 } // vcsn
225 
226 #endif // ! VCSN_MISC_RANDOM_HXX