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

Generated on Fri Jul 28 12:18:51 2006 for Vaucanson by  doxygen 1.4.6