diff --git a/Random_numbers/doc_tex/Generator_ref/Random.tex b/Random_numbers/doc_tex/Generator_ref/Random.tex index ed37ef45d30..f2068bd7f2c 100644 --- a/Random_numbers/doc_tex/Generator_ref/Random.tex +++ b/Random_numbers/doc_tex/Generator_ref/Random.tex @@ -26,11 +26,13 @@ It can be used as the random number generating function object in the Instances of \ccClassName\ can be seen as input streams. Different streams are \emph{independent} of each other, i.e.\ the sequence of numbers from one stream does \emph{not} depend upon how many numbers -were extracted from the other streams. +were extracted from the other streams. At each time, an instance has +a \emph{state} that uniquely determines the subsequent numbers being +produced. It can be very useful, e.g.\ for debugging, to reproduce a sequence of -random numbers. This can be done by either initialising -deterministically or using the state functions as described below. +random numbers. This can be done by either initialising with a fixed +seed, or by using the state functions as described below. \ccInclude{CGAL/Random.h} @@ -38,25 +40,22 @@ deterministically or using the state functions as described below. \ccTypes \ccUnchecked -\ccNestedType{State}{State type.} +\ccNestedType{State}{The State type.} % ----------------------------------------------------------------------------- \ccCreation \ccCreationVariable{random} \ccConstructor{ Random( );}{ - introduces a variable \ccVar\ of type \ccClassTemplateName.} + introduces a variable \ccVar\ of type \ccClassTemplateName. The + seed is chosen ``randomly'', depending on the system time.} -\ccConstructor{ Random( long seed);}{ +\ccConstructor{ Random( unsigned int seed);}{ introduces a variable \ccVar\ of type \ccClassTemplateName\ and initializes its internal state using \ccc{seed}. Equal values for \ccc{seed} result in equal sequences of random numbers.} -\ccConstructor{ Random( State state);}{ - introduces a variable \ccVar\ of type \ccClassTemplateName\ - and initializes its internal state with \ccc{state}.} - % ----------------------------------------------------------------------------- \ccOperations @@ -81,7 +80,10 @@ deterministically or using the state functions as described below. returns \ccVar\ccc{.get_int( 0, upper)}.} % ----------------------------------------------------------------------------- -\ccHeading{State Functions} +\ccHeading{Seed and State Functions} + +\ccMemberFunction{ unsigned int get_seed() const;}{ + returns the seed used for initialization.} \ccMemberFunction{ void save_state( State& state) const;}{ saves the current internal state in \ccc{state}.} @@ -99,9 +101,9 @@ deterministically or using the state functions as described below. % ----------------------------------------------------------------------------- \ccImplementation -We use the C library function \ccc{erand48} to generate the random +We use the C library function \ccc{rand} to generate the random numbers, \textit{i.e.}, the sequence of numbers depends on the implementation -of \ccc{erand48} on your specific platform. +of \ccc{rand} on your specific platform. diff --git a/Random_numbers/include/CGAL/Random.h b/Random_numbers/include/CGAL/Random.h index 7f0b79a9c42..5ff11b40fa1 100644 --- a/Random_numbers/include/CGAL/Random.h +++ b/Random_numbers/include/CGAL/Random.h @@ -24,21 +24,32 @@ #ifndef CGAL_RANDOM_H #define CGAL_RANDOM_H +#include #include CGAL_BEGIN_NAMESPACE class Random { public: + // types + typedef std::pair State; + // creation Random( ); Random( unsigned int seed); + + // seed + unsigned int get_seed ( ) const; // operations bool get_bool ( ); int get_int ( int lower, int upper); double get_double( double lower = 0.0, double upper = 1.0); + // state + void save_state( State& state) const; + void restore_state( const State& state); + // Computes a random int value smaller than 2^b. // It's supposed to be fast, useful for randomized algorithms. // The distribution is not perfectly flat, but this is a sacrifice against @@ -70,6 +81,7 @@ class Random { const double rand_max_plus_1; unsigned int random_value; // Current 15 bits random value. unsigned int val; // random_value shifted by used bits. + unsigned int seed; }; // Global variables diff --git a/Random_numbers/src/CGAL/Random.cpp b/Random_numbers/src/CGAL/Random.cpp index 0ddc3480a5c..a567a1ccc94 100644 --- a/Random_numbers/src/CGAL/Random.cpp +++ b/Random_numbers/src/CGAL/Random.cpp @@ -37,7 +37,7 @@ Random( ) // get system's time std::time_t s; std::time( &s); - unsigned int seed = s; + seed = s; // initialize random numbers generator std::srand( seed); @@ -45,14 +45,35 @@ Random( ) } Random:: -Random( unsigned int seed) - : rand_max_plus_1( RAND_MAX+1.0), val(0) +Random( unsigned int _seed) + : rand_max_plus_1( RAND_MAX+1.0), val(0), seed(_seed) { // initialize random numbers generator std::srand( seed); random_value = get_int(0, 1<<15); } +// seed +unsigned int +Random::get_seed () const +{ + return seed; +} + +// state +void +Random::save_state( Random::State& state) const +{ + state = Random::State(random_value, val); +} + +void +Random::restore_state( const Random::State& state) +{ + random_value = state.first; + val = state.second; +} + // Global variables // ================ Random default_random; diff --git a/Random_numbers/test/Random_numbers/test_Random.cpp b/Random_numbers/test/Random_numbers/test_Random.cpp index 13cd0e8f1e8..232ca521f80 100644 --- a/Random_numbers/test/Random_numbers/test_Random.cpp +++ b/Random_numbers/test/Random_numbers/test_Random.cpp @@ -93,6 +93,22 @@ main() assert( ( 0 <= i) && ( i < 5555)); } + // test get_seed() + { + CGAL::Random r (53); + assert (r.get_seed() == 53); + } + + // test save/restore state + { + CGAL::Random r1(17); + CGAL::Random r2(23); + CGAL::Random::State s; + r1.save_state(s); + r2.restore_state(s); + assert (r1 == r2); + } + return( 0); }