gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Bugfix in Random (#173) - operator()s always return a double now - the faulty real<Num>(Num) and real<Num>(Num,Num) have been removed
0 1 0
default
1 file changed with 4 insertions and 22 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -503,427 +503,409 @@
503 503
  /// result with the \c boolean() member functions.
504 504
  ///
505 505
  ///\code
506 506
  /// // The commented code is identical to the other
507 507
  /// double a = rnd();                     // [0.0, 1.0)
508 508
  /// // double a = rnd.real();             // [0.0, 1.0)
509 509
  /// double b = rnd(100.0);                // [0.0, 100.0)
510 510
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
511 511
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
512 512
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
513 513
  /// int d = rnd[100000];                  // 0..99999
514 514
  /// // int d = rnd.integer(100000);       // 0..99999
515 515
  /// int e = rnd[6] + 1;                   // 1..6
516 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
517 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
518 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
519 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
520 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
521 521
  ///\endcode
522 522
  ///
523 523
  /// LEMON provides a global instance of the random number
524 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
525 525
  /// good programming convenience to use this global generator to get
526 526
  /// random numbers.
527 527
  class Random {
528 528
  private:
529 529

	
530 530
    // Architecture word
531 531
    typedef unsigned long Word;
532 532

	
533 533
    _random_bits::RandomCore<Word> core;
534 534
    _random_bits::BoolProducer<Word> bool_producer;
535 535

	
536 536

	
537 537
  public:
538 538

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

	
543 543
    ///\name Initialization
544 544
    ///
545 545
    /// @{
546 546

	
547 547
    /// \brief Default constructor
548 548
    ///
549 549
    /// Constructor with constant seeding.
550 550
    Random() { core.initState(); }
551 551

	
552 552
    /// \brief Constructor with seed
553 553
    ///
554 554
    /// Constructor with seed. The current number type will be converted
555 555
    /// to the architecture word type.
556 556
    template <typename Number>
557 557
    Random(Number seed) {
558 558
      _random_bits::Initializer<Number, Word>::init(core, seed);
559 559
    }
560 560

	
561 561
    /// \brief Constructor with array seeding
562 562
    ///
563 563
    /// Constructor with array seeding. The given range should contain
564 564
    /// any number type and the numbers will be converted to the
565 565
    /// architecture word type.
566 566
    template <typename Iterator>
567 567
    Random(Iterator begin, Iterator end) {
568 568
      typedef typename std::iterator_traits<Iterator>::value_type Number;
569 569
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
570 570
    }
571 571

	
572 572
    /// \brief Copy constructor
573 573
    ///
574 574
    /// Copy constructor. The generated sequence will be identical to
575 575
    /// the other sequence. It can be used to save the current state
576 576
    /// of the generator and later use it to generate the same
577 577
    /// sequence.
578 578
    Random(const Random& other) {
579 579
      core.copyState(other.core);
580 580
    }
581 581

	
582 582
    /// \brief Assign operator
583 583
    ///
584 584
    /// Assign operator. The generated sequence will be identical to
585 585
    /// the other sequence. It can be used to save the current state
586 586
    /// of the generator and later use it to generate the same
587 587
    /// sequence.
588 588
    Random& operator=(const Random& other) {
589 589
      if (&other != this) {
590 590
        core.copyState(other.core);
591 591
      }
592 592
      return *this;
593 593
    }
594 594

	
595 595
    /// \brief Seeding random sequence
596 596
    ///
597 597
    /// Seeding the random sequence. The current number type will be
598 598
    /// converted to the architecture word type.
599 599
    template <typename Number>
600 600
    void seed(Number seed) {
601 601
      _random_bits::Initializer<Number, Word>::init(core, seed);
602 602
    }
603 603

	
604 604
    /// \brief Seeding random sequence
605 605
    ///
606 606
    /// Seeding the random sequence. The given range should contain
607 607
    /// any number type and the numbers will be converted to the
608 608
    /// architecture word type.
609 609
    template <typename Iterator>
610 610
    void seed(Iterator begin, Iterator end) {
611 611
      typedef typename std::iterator_traits<Iterator>::value_type Number;
612 612
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
613 613
    }
614 614

	
615 615
    /// \brief Seeding from file or from process id and time
616 616
    ///
617 617
    /// By default, this function calls the \c seedFromFile() member
618 618
    /// function with the <tt>/dev/urandom</tt> file. If it does not success,
619 619
    /// it uses the \c seedFromTime().
620 620
    /// \return Currently always true.
621 621
    bool seed() {
622 622
#ifndef WIN32
623 623
      if (seedFromFile("/dev/urandom", 0)) return true;
624 624
#endif
625 625
      if (seedFromTime()) return true;
626 626
      return false;
627 627
    }
628 628

	
629 629
    /// \brief Seeding from file
630 630
    ///
631 631
    /// Seeding the random sequence from file. The linux kernel has two
632 632
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
633 633
    /// could give good seed values for pseudo random generators (The
634 634
    /// difference between two devices is that the <tt>random</tt> may
635 635
    /// block the reading operation while the kernel can give good
636 636
    /// source of randomness, while the <tt>urandom</tt> does not
637 637
    /// block the input, but it could give back bytes with worse
638 638
    /// entropy).
639 639
    /// \param file The source file
640 640
    /// \param offset The offset, from the file read.
641 641
    /// \return True when the seeding successes.
642 642
#ifndef WIN32
643 643
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
644 644
#else
645 645
    bool seedFromFile(const std::string& file = "", int offset = 0)
646 646
#endif
647 647
    {
648 648
      std::ifstream rs(file.c_str());
649 649
      const int size = 4;
650 650
      Word buf[size];
651 651
      if (offset != 0 && !rs.seekg(offset)) return false;
652 652
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
653 653
      seed(buf, buf + size);
654 654
      return true;
655 655
    }
656 656

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

	
676 676
    /// @}
677 677

	
678 678
    ///\name Uniform distributions
679 679
    ///
680 680
    /// @{
681 681

	
682 682
    /// \brief Returns a random real number from the range [0, 1)
683 683
    ///
684 684
    /// It returns a random real number from the range [0, 1). The
685 685
    /// default Number type is \c double.
686 686
    template <typename Number>
687 687
    Number real() {
688 688
      return _random_bits::RealConversion<Number, Word>::convert(core);
689 689
    }
690 690

	
691 691
    double real() {
692 692
      return real<double>();
693 693
    }
694 694

	
695
    /// \brief Returns a random real number the range [0, b)
696
    ///
697
    /// It returns a random real number from the range [0, b).
698
    template <typename Number>
699
    Number real(Number b) {
700
      return real<Number>() * b;
701
    }
702

	
703
    /// \brief Returns a random real number from the range [a, b)
704
    ///
705
    /// It returns a random real number from the range [a, b).
706
    template <typename Number>
707
    Number real(Number a, Number b) {
708
      return real<Number>() * (b - a) + a;
709
    }
710

	
711 695
    /// @}
712 696

	
713 697
    ///\name Uniform distributions
714 698
    ///
715 699
    /// @{
716 700

	
717 701
    /// \brief Returns a random real number from the range [0, 1)
718 702
    ///
719 703
    /// It returns a random double from the range [0, 1).
720 704
    double operator()() {
721 705
      return real<double>();
722 706
    }
723 707

	
724 708
    /// \brief Returns a random real number from the range [0, b)
725 709
    ///
726 710
    /// It returns a random real number from the range [0, b).
727
    template <typename Number>
728
    Number operator()(Number b) {
729
      return real<Number>() * b;
711
    double operator()(double b) {
712
      return real<double>() * b;
730 713
    }
731 714

	
732 715
    /// \brief Returns a random real number from the range [a, b)
733 716
    ///
734 717
    /// It returns a random real number from the range [a, b).
735
    template <typename Number>
736
    Number operator()(Number a, Number b) {
737
      return real<Number>() * (b - a) + a;
718
    double operator()(double a, double b) {
719
      return real<double>() * (b - a) + a;
738 720
    }
739 721

	
740 722
    /// \brief Returns a random integer from a range
741 723
    ///
742 724
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
743 725
    template <typename Number>
744 726
    Number integer(Number b) {
745 727
      return _random_bits::Mapping<Number, Word>::map(core, b);
746 728
    }
747 729

	
748 730
    /// \brief Returns a random integer from a range
749 731
    ///
750 732
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
751 733
    template <typename Number>
752 734
    Number integer(Number a, Number b) {
753 735
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
754 736
    }
755 737

	
756 738
    /// \brief Returns a random integer from a range
757 739
    ///
758 740
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
759 741
    template <typename Number>
760 742
    Number operator[](Number b) {
761 743
      return _random_bits::Mapping<Number, Word>::map(core, b);
762 744
    }
763 745

	
764 746
    /// \brief Returns a random non-negative integer
765 747
    ///
766 748
    /// It returns a random non-negative integer uniformly from the
767 749
    /// whole range of the current \c Number type. The default result
768 750
    /// type of this function is <tt>unsigned int</tt>.
769 751
    template <typename Number>
770 752
    Number uinteger() {
771 753
      return _random_bits::IntConversion<Number, Word>::convert(core);
772 754
    }
773 755

	
774 756
    /// @}
775 757

	
776 758
    unsigned int uinteger() {
777 759
      return uinteger<unsigned int>();
778 760
    }
779 761

	
780 762
    /// \brief Returns a random integer
781 763
    ///
782 764
    /// It returns a random integer uniformly from the whole range of
783 765
    /// the current \c Number type. The default result type of this
784 766
    /// function is \c int.
785 767
    template <typename Number>
786 768
    Number integer() {
787 769
      static const int nb = std::numeric_limits<Number>::digits +
788 770
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
789 771
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
790 772
    }
791 773

	
792 774
    int integer() {
793 775
      return integer<int>();
794 776
    }
795 777

	
796 778
    /// \brief Returns a random bool
797 779
    ///
798 780
    /// It returns a random bool. The generator holds a buffer for
799 781
    /// random bits. Every time when it become empty the generator makes
800 782
    /// a new random word and fill the buffer up.
801 783
    bool boolean() {
802 784
      return bool_producer.convert(core);
803 785
    }
804 786

	
805 787
    /// @}
806 788

	
807 789
    ///\name Non-uniform distributions
808 790
    ///
809 791

	
810 792
    ///@{
811 793

	
812 794
    /// \brief Returns a random bool
813 795
    ///
814 796
    /// It returns a random bool with given probability of true result.
815 797
    bool boolean(double p) {
816 798
      return operator()() < p;
817 799
    }
818 800

	
819 801
    /// Standard Gauss distribution
820 802

	
821 803
    /// Standard Gauss distribution.
822 804
    /// \note The Cartesian form of the Box-Muller
823 805
    /// transformation is used to generate a random normal distribution.
824 806
    double gauss()
825 807
    {
826 808
      double V1,V2,S;
827 809
      do {
828 810
        V1=2*real<double>()-1;
829 811
        V2=2*real<double>()-1;
830 812
        S=V1*V1+V2*V2;
831 813
      } while(S>=1);
832 814
      return std::sqrt(-2*std::log(S)/S)*V1;
833 815
    }
834 816
    /// Gauss distribution with given mean and standard deviation
835 817

	
836 818
    /// Gauss distribution with given mean and standard deviation.
837 819
    /// \sa gauss()
838 820
    double gauss(double mean,double std_dev)
839 821
    {
840 822
      return gauss()*std_dev+mean;
841 823
    }
842 824

	
843 825
    /// Exponential distribution with given mean
844 826

	
845 827
    /// This function generates an exponential distribution random number
846 828
    /// with mean <tt>1/lambda</tt>.
847 829
    ///
848 830
    double exponential(double lambda=1.0)
849 831
    {
850 832
      return -std::log(1.0-real<double>())/lambda;
851 833
    }
852 834

	
853 835
    /// Gamma distribution with given integer shape
854 836

	
855 837
    /// This function generates a gamma distribution random number.
856 838
    ///
857 839
    ///\param k shape parameter (<tt>k>0</tt> integer)
858 840
    double gamma(int k)
859 841
    {
860 842
      double s = 0;
861 843
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
862 844
      return s;
863 845
    }
864 846

	
865 847
    /// Gamma distribution with given shape and scale parameter
866 848

	
867 849
    /// This function generates a gamma distribution random number.
868 850
    ///
869 851
    ///\param k shape parameter (<tt>k>0</tt>)
870 852
    ///\param theta scale parameter
871 853
    ///
872 854
    double gamma(double k,double theta=1.0)
873 855
    {
874 856
      double xi,nu;
875 857
      const double delta = k-std::floor(k);
876 858
      const double v0=E/(E-delta);
877 859
      do {
878 860
        double V0=1.0-real<double>();
879 861
        double V1=1.0-real<double>();
880 862
        double V2=1.0-real<double>();
881 863
        if(V2<=v0)
882 864
          {
883 865
            xi=std::pow(V1,1.0/delta);
884 866
            nu=V0*std::pow(xi,delta-1.0);
885 867
          }
886 868
        else
887 869
          {
888 870
            xi=1.0-std::log(V1);
889 871
            nu=V0*std::exp(-xi);
890 872
          }
891 873
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
892 874
      return theta*(xi+gamma(int(std::floor(k))));
893 875
    }
894 876

	
895 877
    /// Weibull distribution
896 878

	
897 879
    /// This function generates a Weibull distribution random number.
898 880
    ///
899 881
    ///\param k shape parameter (<tt>k>0</tt>)
900 882
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
901 883
    ///
902 884
    double weibull(double k,double lambda)
903 885
    {
904 886
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
905 887
    }
906 888

	
907 889
    /// Pareto distribution
908 890

	
909 891
    /// This function generates a Pareto distribution random number.
910 892
    ///
911 893
    ///\param k shape parameter (<tt>k>0</tt>)
912 894
    ///\param x_min location parameter (<tt>x_min>0</tt>)
913 895
    ///
914 896
    double pareto(double k,double x_min)
915 897
    {
916 898
      return exponential(gamma(k,1.0/x_min))+x_min;
917 899
    }
918 900

	
919 901
    /// Poisson distribution
920 902

	
921 903
    /// This function generates a Poisson distribution random number with
922 904
    /// parameter \c lambda.
923 905
    ///
924 906
    /// The probability mass function of this distribusion is
925 907
    /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
926 908
    /// \note The algorithm is taken from the book of Donald E. Knuth titled
927 909
    /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
928 910
    /// return value.
929 911

	
0 comments (0 inline)