Vaucanson 1.4
random.hxx
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