Seeding from file source or from pid and time (ticket #19)
authorBalazs Dezso <deba@inf.elte.hu>
Thu, 19 Jun 2008 10:59:22 +0200
changeset 177b685e12e08c0
parent 176 47b69d4b0759
child 178 d2bac07f1742
Seeding from file source or from pid and time (ticket #19)
lemon/random.h
     1.1 --- a/lemon/random.h	Tue Jun 17 12:47:15 2008 +0100
     1.2 +++ b/lemon/random.h	Thu Jun 19 10:59:22 2008 +0200
     1.3 @@ -66,10 +66,20 @@
     1.4  #include <iterator>
     1.5  #include <vector>
     1.6  #include <limits>
     1.7 +#include <fstream>
     1.8  
     1.9  #include <lemon/math.h>
    1.10  #include <lemon/dim2.h>
    1.11  
    1.12 +#ifndef WIN32
    1.13 +#include <sys/time.h>
    1.14 +#include <ctime>
    1.15 +#include <sys/types.h>
    1.16 +#include <unistd.h>
    1.17 +#else
    1.18 +#include <windows.h>
    1.19 +#endif
    1.20 +
    1.21  ///\ingroup misc
    1.22  ///\file
    1.23  ///\brief Mersenne Twister random number generator
    1.24 @@ -526,6 +536,10 @@
    1.25  
    1.26    public:
    1.27  
    1.28 +    ///\name Initialization
    1.29 +    ///
    1.30 +    /// @{
    1.31 +
    1.32      /// \brief Default constructor
    1.33      ///
    1.34      /// Constructor with constant seeding.
    1.35 @@ -594,6 +608,73 @@
    1.36        _random_bits::Initializer<Number, Word>::init(core, begin, end);
    1.37      }
    1.38  
    1.39 +    /// \brief Seeding from file or from process id and time
    1.40 +    ///
    1.41 +    /// By default, this function calls the \c seedFromFile() member
    1.42 +    /// function with the <tt>/dev/urandom</tt> file. If it is not success,
    1.43 +    /// it uses the \c seedFromTime().
    1.44 +    /// \return Currently always true.
    1.45 +    bool seed() {
    1.46 +#ifndef WIN32
    1.47 +      if (seedFromFile("/dev/urandom", 0)) return true;
    1.48 +#endif
    1.49 +      if (seedFromTime()) return true;
    1.50 +      return false;
    1.51 +    }
    1.52 +    
    1.53 +    /// \brief Seeding from file
    1.54 +    ///
    1.55 +    /// Seeding the random sequence from file. The linux kernel has two
    1.56 +    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
    1.57 +    /// could give good seed values for pseudo random generators (The
    1.58 +    /// difference between two devices is that the <tt>random</tt> may
    1.59 +    /// block the reading operation while the kernel can give good
    1.60 +    /// source of randomness, while the <tt>urandom</tt> does not
    1.61 +    /// block the input, but it could give back bytes with worse
    1.62 +    /// entropy).
    1.63 +    /// \param file The source file
    1.64 +    /// \param offset The offset, from the file read.
    1.65 +    /// \return True when the seeding is success.
    1.66 +#ifndef WIN32
    1.67 +    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0) 
    1.68 +#else
    1.69 +    bool seedFromFile(const std::string& file = "", int offset = 0) 
    1.70 +#endif
    1.71 +    {
    1.72 +      std::ifstream rs(file.c_str());
    1.73 +      const int size = 4;
    1.74 +      Word buf[size];
    1.75 +      if (offset != 0 && !rs.seekg(offset)) return false;
    1.76 +      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
    1.77 +      seed(buf, buf + size);
    1.78 +      return true;
    1.79 +    }
    1.80 +
    1.81 +    /// \brief Seding from process id and time
    1.82 +    ///
    1.83 +    /// Seding from process id and time. This function uses the
    1.84 +    /// current process id and the current time for initialize the
    1.85 +    /// random sequence.
    1.86 +    /// \return Currently always true.
    1.87 +    bool seedFromTime() { 	
    1.88 +#ifndef WIN32
    1.89 +      timeval tv;
    1.90 +      gettimeofday(&tv, 0);
    1.91 +      seed(getpid() + tv.tv_sec + tv.tv_usec);
    1.92 +#else
    1.93 +      FILETIME time;
    1.94 +      GetSystemTimeAsFileTime(&time);
    1.95 +      seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime);
    1.96 +#endif
    1.97 +      return true;
    1.98 +    }
    1.99 +
   1.100 +    /// @}
   1.101 +
   1.102 +    ///\name Uniform distributions
   1.103 +    ///
   1.104 +    /// @{
   1.105 +
   1.106      /// \brief Returns a random real number from the range [0, 1)
   1.107      ///
   1.108      /// It returns a random real number from the range [0, 1). The
   1.109 @@ -709,6 +790,8 @@
   1.110        return bool_producer.convert(core);
   1.111      }
   1.112  
   1.113 +    /// @}
   1.114 +
   1.115      ///\name Non-uniform distributions
   1.116      ///
   1.117