@! ============================================================================ @! The CGAL Library @! Implementation: Random Numbers Generator @! ---------------------------------------------------------------------------- @! file : web/Random.aw @! author: Sven Schönherr @! ---------------------------------------------------------------------------- @! $CGAL_Chapter: Random Numbers Generator $ @! $CGAL_Package: Random_numbers WIP $ @! $Id$ @! $Date$ @! ============================================================================ @documentclass[twoside]{article} @usepackage[latin1]{inputenc} @usepackage{a4wide2} @usepackage{cc_manual,cc_manual_index} @article \setlength{\skip\footins}{3ex} \pagestyle{headings} @! LaTeX macros \newcommand{\remark}[2]{[\textbf{#1:} \emph{#2}]} \newcommand{\linebreakByHand}{\ccTexHtml{\linebreak[4]}{}} \newcommand{ \newlineByHand}{\ccTexHtml{\\}{}} \renewcommand{\sectionmark}[1]{\markboth{\uppercase{#1}}{}} \newcommand{\subsectionRef}[2]{ \addtocounter{subsection}{1} \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}#1: #2} \markright{\thesubsection~~#1: #2}} @! settings for `cc_manual.sty' \ccDefGlobalScope{CGAL::} \renewcommand{\ccRefPageEnd}{\clearpage} \newcommand{\cgalColumnLayout}{% \ccSetThreeColumns{Oriented_side}{}{\hspace*{10cm}} \ccPropagateThreeToTwoColumns} \newcommand{\ccRequirements}{\ccHeading{Requirements}} \newcommand{\ccRequire}{\ccCommentHeading{Requirements}} @! ============================================================================ @! Title @! ============================================================================ \thispagestyle{empty} \RCSdef{\rcsRevision}{$Id$} \RCSdefDate{\rcsDate}{$Date$} \newcommand{\cgalWIP}{{\footnotesize{} (\rcsRevision{} , \rcsDate) }} @t vskip 20 mm @t title titlefont centre "Random Numbers Generator*" @t vskip 15 mm @t title smalltitlefont centre "Sven Schönherr" \begin{center} \textbf{FU Berlin / ETH Z{\"u}rich} \end{center} @t vskip 10 mm {\small \begin{center} \begin{tabular}{l} \verb+$CGAL_Package: Random_numbers WIP+\cgalWIP\verb+$+ \\ \verb+$CGAL_Chapter: Geometric Object Generators $+ \\ \end{tabular} \end{center} } @t vskip 30 mm \renewcommand{\thefootnote}{\fnsymbol{footnote}} \footnotetext[1]{This work was supported by the ESPRIT IV LTR Projects No.~21957 (CGAL) and No.~28155 (GALIA).} \renewcommand{\thefootnote}{\arabic{footnote}} @! -------- @! Abstract @! -------- \begin{abstract} We provide an implementation of a random numbers generator. It allows to generate uniformly distributed random @prg{bool}s, @prg{int}s, and @prg{double}s. The interface fulfills the requirements of an STL random number generating function object. \end{abstract} @! -------- @! Contents @! -------- \clearpage \newlength{\defaultparskip} \setlength{\defaultparskip}{\parskip} \setlength{\parskip}{1ex} \tableofcontents \setlength{\parskip}{\defaultparskip} @! ============================================================================ @! Introduction @! ============================================================================ \clearpage \markright{\uppercase{Introduction}} \section{Introduction} We provide an implementation of a random numbers generator. It allows to generate uniformly distributed random @prg{bool}s, @prg{int}s, and @prg{double}s. The interface fulfills the requirements of an STL random number generating function object, e.g.\ for the STL algorithm @prg{random_shuffle}. This document is organized as follows. Section~1 contains the specification as it appears in the CGAL Reference Manual. Section~2 gives the implementation. In Section~3 we provide a test program which performs some correctness checks. Finally the product files are created in Section~4. @! ============================================================================ @! Reference Pages @! ============================================================================ \clearpage \section{Reference Pages} \label{sec:reference_pages} \emph{Note:} Below some references are undefined, they refer to sections in the \cgal\ Reference Manual. @! ---------------------------------------------------------------------------- @! Class: Random @! ---------------------------------------------------------------------------- \renewcommand{\ccSection}{\ccSubsection} \input{../doc_tex/support/Generator/Random.tex} @! ============================================================================ @! Implementation @! ============================================================================ \clearpage \section{Implementation} This section describes the implementation of the random numbers generator. We use the C library function \ccc{erand48} to generate the random numbers. It behaves like the well-known function \ccc{drand48} but operates on a user supplied storage for the 48-Bit state. This makes different instances of the random number generator independent. First, we declare the class \ccc{Random}. @macro = @begin class Random; @end The class interface looks as follows. @macro = @begin class Random { public: @ private: @ }; @end @! ---------------------------------------------------------------------------- \subsection{Public Interface} The functionality is described and documented in Section~\ref{sec:random_numbers_generator}, so we do not comment on it here. @macro = @begin // types typedef unsigned short State[3]; // 48 Bits // creation Random( ); Random( long seed); Random( State state); // operations bool get_bool ( ); int get_int ( int lower, int upper); double get_double( double lower = 0.0, double upper = 1.0); int operator () ( int upper); // state functions void save_state( State& state) const; void restore_state( const State& state); // equality test bool operator == ( const Random& rnd) const; @end @! ---------------------------------------------------------------------------- \subsection{Global Variable} The global variable \ccc{default_random} is the default random numbers generator. @macro = @begin extern Random default_random; @end @macro = @begin Random default_random; @end @! ---------------------------------------------------------------------------- \subsection{Private Data Members} The state is stored in an array of three \ccc{unsigned short}s. @macro = @begin // data members unsigned short _state[3]; // 48 Bits @end @! ---------------------------------------------------------------------------- \subsection{Constructors} In the default constructor the seed is set using the system time. @macro = @begin Random:: Random( ) { // get system's microseconds timeval tv; gettimeofday( &tv, NULL); unsigned long ms = tv.tv_sec*1000000+tv.tv_usec; // initialize random numbers generator _state[ 0] = _state[ 2] = static_cast( ms >> 16); _state[ 1] = static_cast( ms & 65535); } Random:: Random( long seed) { // initialize random numbers generator _state[ 0] = _state[ 2] = static_cast( seed >> 16); _state[ 1] = static_cast( seed & 65535); } Random:: Random( State state) { // initialize random numbers generator _state[ 0] = state[ 0]; _state[ 1] = state[ 1]; _state[ 2] = state[ 2]; } @end @! ---------------------------------------------------------------------------- \subsection{Operations} The C library function \ccc{erand48} returns a random \ccc{double}, uniformly chosen from the interval $[\ccc{0.0},\ccc{1.0})$. The result is converted to a number in the given range. @macro = @begin inline bool Random:: get_bool( ) { return static_cast( erand48( _state) < 0.5); } inline int Random:: get_int( int lower, int upper) { return( lower + static_cast( static_cast( upper-lower) * erand48( _state))); } inline double Random:: get_double( double lower, double upper) { return( lower + ( upper-lower) * erand48( _state)); } inline int Random:: operator () ( int upper) { return( get_int( 0, upper)); } @end @! ---------------------------------------------------------------------------- \subsection{State Functions} The state functions just copy the internal state to or from the given state variable, respectively. @macro = @begin void Random:: save_state( State& state) const { state[ 0] = _state[ 0]; state[ 1] = _state[ 1]; state[ 2] = _state[ 2]; } void Random:: restore_state( const State& state) { _state[ 0] = state[ 0]; _state[ 1] = state[ 1]; _state[ 2] = state[ 2]; } @end @! ---------------------------------------------------------------------------- \subsection{Equality Test} The equality test compares the internal states of the two operands. @macro = @begin inline bool Random:: operator == ( const Random& rnd) const { return( static_cast( ( _state[ 0] == rnd._state[ 0]) && ( _state[ 1] == rnd._state[ 1]) && ( _state[ 2] == rnd._state[ 2]) ) ); } @end @! ============================================================================ @! Test Program @! ============================================================================ \clearpage \section{Test Program} We call each function of class \ccc{Random} at least once to ensure code coverage. In addition, we check if the generated random numbers lie in the given ranges, and if two random numbers generators initialized with the same seed generate the same sequence of random numbers. @macro = @begin CGAL::Random::State state; CGAL::default_random.save_state( state); // test get_bool { bool b = CGAL::default_random.get_bool(); assert( ! b || b); } // test get_int { int l = CGAL::default_random.get_int( -100, 0); int u = CGAL::default_random.get_int( 0, 1000); int i = CGAL::default_random.get_int( l, u); assert( ( l <= i) && ( i < u)); } // test get_double { double l = CGAL::default_random.get_double( -123.45, -0.99); double u = CGAL::default_random.get_double( 22.0/7.0, 33.3); double d = CGAL::default_random.get_double( l, u); assert( ( l <= d) && ( d < u)); } // test operator() { int i = CGAL::default_random( 5555); assert( ( 0 <= i) && ( i < 5555)); } // test state functions { CGAL::default_random.restore_state( state); // `default_random' and CGAL::Random rnd( state); // `rnd' have the same state now assert( CGAL::default_random.get_bool() == rnd.get_bool()); assert( CGAL::default_random.get_int( -100,100) == rnd.get_int( -100,100)); assert( CGAL::default_random.get_double() == rnd.get_double()); assert( CGAL::default_random == rnd); long init = CGAL::default_random( 9999); CGAL::Random rnd1( init), rnd2( init); assert( rnd1.get_bool() == rnd2.get_bool() ); assert( rnd1.get_int( -100,100) == rnd2.get_int( -100,100)); assert( rnd1.get_double() == rnd2.get_double() ); assert( rnd1 == rnd2 ); } @end @! ========================================================================== @! Files @! ========================================================================== \clearpage \section{Files} @i share/namespace.awi @! ---------------------------------------------------------------------------- @! Random.h @! ---------------------------------------------------------------------------- \subsection{include/CGAL/Random.h} @file = @begin @("include/CGAL/Random.h","Random Numbers Generator") #ifndef CGAL_RANDOM_H #define CGAL_RANDOM_H // includes // -------- #ifndef CGAL_BASIC_H # include #endif @("CGAL") // Class declaration // ================= @ // Class interface // =============== @ // Global variables // ================ @ @("CGAL") @ // Class implementation (inline functions) // ======================================= // includes #ifndef CGAL_PROTECT_CSTDLIB # include # define CGAL_PROTECT_CSTDLIB #endif @("CGAL") // operations @ @ @("CGAL") #endif // CGAL_RANDOM_H @ @end @! ---------------------------------------------------------------------------- @! Random.C @! ---------------------------------------------------------------------------- \subsection{src/Random.C} @file = @begin @("src/Random.C","Random Numbers Generator") #include // additional includes #ifndef CGAL_PROTECT_CTIME # include # define CGAL_PROTECT_CTIME #endif #ifndef CGAL_PROTECT_SYS_TIME_H # include # define CGAL_PROTECT_SYS_TIME_H #endif @("CGAL") // Class implementation (continued) // ================================ // constructors @ // state functions @ // Global variables // ================ @ @("CGAL") @ @end @! ---------------------------------------------------------------------------- @! test_Random.C @! ---------------------------------------------------------------------------- \subsection{test/Random\_numbers/test\_Random.C} @file = @begin @( "test/Random_numbers/test_Random.C", "test program for Random Numbers Generator") // includes #include #include int main( int, char**) { @ return( 0); } @ @end @! ---------------------------------------------------------------------------- @! File Header @! ---------------------------------------------------------------------------- \subsection*{File Header} @i share/file_header.awi @macro (2) many = @begin @ @(@1) @( "Random_numbers", "Random Numbers Generator", "Random", "$Id$","$Date$", "Sven Schönherr ", "INRIA Sophia-Antipolis", "@2") @end @! ===== EOF ==================================================================