gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Seeding from file source or from pid and time (ticket #19)
0 1 0
default
1 file changed with 83 insertions and 0 deletions:
↑ Collapse diff ↑
Show white space 24 line context
... ...
@@ -57,28 +57,38 @@
57 57
 * Any feedback is very welcome.
58 58
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
59 59
 * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
60 60
 */
61 61

	
62 62
#ifndef LEMON_RANDOM_H
63 63
#define LEMON_RANDOM_H
64 64

	
65 65
#include <algorithm>
66 66
#include <iterator>
67 67
#include <vector>
68 68
#include <limits>
69
#include <fstream>
69 70

	
70 71
#include <lemon/math.h>
71 72
#include <lemon/dim2.h>
72 73

	
74
#ifndef WIN32
75
#include <sys/time.h>
76
#include <ctime>
77
#include <sys/types.h>
78
#include <unistd.h>
79
#else
80
#include <windows.h>
81
#endif
82

	
73 83
///\ingroup misc
74 84
///\file
75 85
///\brief Mersenne Twister random number generator
76 86

	
77 87
namespace lemon {
78 88

	
79 89
  namespace _random_bits {
80 90
    
81 91
    template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
82 92
    struct RandomTraits {};
83 93

	
84 94
    template <typename _Word>
... ...
@@ -517,24 +527,28 @@
517 527
  class Random {
518 528
  private:
519 529

	
520 530
    // Architecture word
521 531
    typedef unsigned long Word;
522 532
    
523 533
    _random_bits::RandomCore<Word> core;
524 534
    _random_bits::BoolProducer<Word> bool_producer;
525 535
    
526 536

	
527 537
  public:
528 538

	
539
    ///\name Initialization
540
    ///
541
    /// @{
542

	
529 543
    /// \brief Default constructor
530 544
    ///
531 545
    /// Constructor with constant seeding.
532 546
    Random() { core.initState(); }
533 547

	
534 548
    /// \brief Constructor with seed
535 549
    ///
536 550
    /// Constructor with seed. The current number type will be converted
537 551
    /// to the architecture word type.
538 552
    template <typename Number>
539 553
    Random(Number seed) { 
540 554
      _random_bits::Initializer<Number, Word>::init(core, seed);
... ...
@@ -585,24 +599,91 @@
585 599

	
586 600
    /// \brief Seeding random sequence
587 601
    ///
588 602
    /// Seeding the random sequence. The given range should contain
589 603
    /// any number type and the numbers will be converted to the
590 604
    /// architecture word type.
591 605
    template <typename Iterator>
592 606
    void seed(Iterator begin, Iterator end) { 
593 607
      typedef typename std::iterator_traits<Iterator>::value_type Number;
594 608
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
595 609
    }
596 610

	
611
    /// \brief Seeding from file or from process id and time
612
    ///
613
    /// By default, this function calls the \c seedFromFile() member
614
    /// function with the <tt>/dev/urandom</tt> file. If it is not success,
615
    /// it uses the \c seedFromTime().
616
    /// \return Currently always true.
617
    bool seed() {
618
#ifndef WIN32
619
      if (seedFromFile("/dev/urandom", 0)) return true;
620
#endif
621
      if (seedFromTime()) return true;
622
      return false;
623
    }
624
    
625
    /// \brief Seeding from file
626
    ///
627
    /// Seeding the random sequence from file. The linux kernel has two
628
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
629
    /// could give good seed values for pseudo random generators (The
630
    /// difference between two devices is that the <tt>random</tt> may
631
    /// block the reading operation while the kernel can give good
632
    /// source of randomness, while the <tt>urandom</tt> does not
633
    /// block the input, but it could give back bytes with worse
634
    /// entropy).
635
    /// \param file The source file
636
    /// \param offset The offset, from the file read.
637
    /// \return True when the seeding is success.
638
#ifndef WIN32
639
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0) 
640
#else
641
    bool seedFromFile(const std::string& file = "", int offset = 0) 
642
#endif
643
    {
644
      std::ifstream rs(file.c_str());
645
      const int size = 4;
646
      Word buf[size];
647
      if (offset != 0 && !rs.seekg(offset)) return false;
648
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
649
      seed(buf, buf + size);
650
      return true;
651
    }
652

	
653
    /// \brief Seding from process id and time
654
    ///
655
    /// Seding from process id and time. This function uses the
656
    /// current process id and the current time for initialize the
657
    /// random sequence.
658
    /// \return Currently always true.
659
    bool seedFromTime() { 	
660
#ifndef WIN32
661
      timeval tv;
662
      gettimeofday(&tv, 0);
663
      seed(getpid() + tv.tv_sec + tv.tv_usec);
664
#else
665
      FILETIME time;
666
      GetSystemTimeAsFileTime(&time);
667
      seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime);
668
#endif
669
      return true;
670
    }
671

	
672
    /// @}
673

	
674
    ///\name Uniform distributions
675
    ///
676
    /// @{
677

	
597 678
    /// \brief Returns a random real number from the range [0, 1)
598 679
    ///
599 680
    /// It returns a random real number from the range [0, 1). The
600 681
    /// default Number type is \c double.
601 682
    template <typename Number>
602 683
    Number real() {
603 684
      return _random_bits::RealConversion<Number, Word>::convert(core);
604 685
    }
605 686

	
606 687
    double real() {
607 688
      return real<double>();
608 689
    }
... ...
@@ -700,24 +781,26 @@
700 781
      return integer<int>();
701 782
    }
702 783
    
703 784
    /// \brief Returns a random bool
704 785
    ///
705 786
    /// It returns a random bool. The generator holds a buffer for
706 787
    /// random bits. Every time when it become empty the generator makes
707 788
    /// a new random word and fill the buffer up.
708 789
    bool boolean() {
709 790
      return bool_producer.convert(core);
710 791
    }
711 792

	
793
    /// @}
794

	
712 795
    ///\name Non-uniform distributions
713 796
    ///
714 797
    
715 798
    ///@{
716 799
    
717 800
    /// \brief Returns a random bool
718 801
    ///
719 802
    /// It returns a random bool with given probability of true result.
720 803
    bool boolean(double p) {
721 804
      return operator()() < p;
722 805
    }
723 806

	
0 comments (0 inline)