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 ↑
Ignore white space 48 line context
... ...
@@ -45,52 +45,62 @@
45 45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46 46
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
47 47
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48 48
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 49
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 50
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
55 55
 *
56 56
 *
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>
85 95
    struct RandomTraits<_Word, 32> {
86 96

	
87 97
      typedef _Word Word;
88 98
      static const int bits = 32;
89 99

	
90 100
      static const int length = 624;
91 101
      static const int shift = 397;
92 102
      
93 103
      static const Word mul = 0x6c078965u;
94 104
      static const Word arrayInit = 0x012BD6AAu;
95 105
      static const Word arrayMul1 = 0x0019660Du;
96 106
      static const Word arrayMul2 = 0x5D588B65u;
... ...
@@ -505,48 +515,52 @@
505 515
  /// int e = rnd[6] + 1;                   // 1..6
506 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
507 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
508 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
509 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
510 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
511 521
  ///\endcode
512 522
  ///
513 523
  /// LEMON provides a global instance of the random number
514 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
515 525
  /// good programming convenience to use this global generator to get
516 526
  /// random numbers.
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);
541 555
    }
542 556

	
543 557
    /// \brief Constructor with array seeding
544 558
    ///
545 559
    /// Constructor with array seeding. The given range should contain
546 560
    /// any number type and the numbers will be converted to the
547 561
    /// architecture word type.
548 562
    template <typename Iterator>
549 563
    Random(Iterator begin, Iterator end) { 
550 564
      typedef typename std::iterator_traits<Iterator>::value_type Number;
551 565
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
552 566
    }
... ...
@@ -573,48 +587,115 @@
573 587
      }
574 588
      return *this;
575 589
    }
576 590

	
577 591
    /// \brief Seeding random sequence
578 592
    ///
579 593
    /// Seeding the random sequence. The current number type will be
580 594
    /// converted to the architecture word type.
581 595
    template <typename Number>
582 596
    void seed(Number seed) { 
583 597
      _random_bits::Initializer<Number, Word>::init(core, seed);
584 598
    }
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
    }
609 690

	
610 691
    /// \brief Returns a random real number the range [0, b)
611 692
    ///
612 693
    /// It returns a random real number from the range [0, b).
613 694
    template <typename Number>
614 695
    Number real(Number b) { 
615 696
      return real<Number>() * b; 
616 697
    }
617 698

	
618 699
    /// \brief Returns a random real number from the range [a, b)
619 700
    ///
620 701
    /// It returns a random real number from the range [a, b).
... ...
@@ -688,48 +769,50 @@
688 769
    ///
689 770
    /// It returns a random integer uniformly from the whole range of
690 771
    /// the current \c Number type. The default result type of this
691 772
    /// function is \c int.
692 773
    template <typename Number>
693 774
    Number integer() {
694 775
      static const int nb = std::numeric_limits<Number>::digits + 
695 776
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
696 777
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
697 778
    }
698 779

	
699 780
    int integer() {
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

	
724 807
    /// Standard Gauss distribution
725 808

	
726 809
    /// Standard Gauss distribution.
727 810
    /// \note The Cartesian form of the Box-Muller
728 811
    /// transformation is used to generate a random normal distribution.
729 812
    /// \todo Consider using the "ziggurat" method instead.
730 813
    double gauss() 
731 814
    {
732 815
      double V1,V2,S;
733 816
      do {
734 817
	V1=2*real<double>()-1;
735 818
	V2=2*real<double>()-1;
0 comments (0 inline)