mirror of https://github.com/CGAL/cgal
569 lines
15 KiB
PHP
569 lines
15 KiB
PHP
@! ============================================================================
|
|
@! The CGAL Library
|
|
@! Implementation: Random Numbers Generator
|
|
@! ----------------------------------------------------------------------------
|
|
@! file : web/Random.aw
|
|
@! author: Sven Schönherr <sven@inf.ethz.ch>
|
|
@! ----------------------------------------------------------------------------
|
|
@! $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<Random declaration> = @begin
|
|
class Random;
|
|
@end
|
|
|
|
The class interface looks as follows.
|
|
|
|
@macro <Random interface> = @begin
|
|
class Random {
|
|
public:
|
|
@<Random public interface>
|
|
|
|
private:
|
|
@<Random private data members>
|
|
};
|
|
@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 <Random public interface> = @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 <Random global variable declaration> = @begin
|
|
extern Random default_random;
|
|
@end
|
|
|
|
@macro <Random global variable definition> = @begin
|
|
Random default_random;
|
|
@end
|
|
|
|
@! ----------------------------------------------------------------------------
|
|
\subsection{Private Data Members}
|
|
|
|
The state is stored in an array of three \ccc{unsigned short}s.
|
|
|
|
@macro <Random private data members> = @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 <Random constructors> = @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<unsigned short>( ms >> 16);
|
|
_state[ 1] = static_cast<unsigned short>( ms & 65535);
|
|
}
|
|
|
|
Random::
|
|
Random( long seed)
|
|
{
|
|
// initialize random numbers generator
|
|
_state[ 0] = _state[ 2] = static_cast<unsigned short>( seed >> 16);
|
|
_state[ 1] = static_cast<unsigned short>( 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 <Random operations> = @begin
|
|
inline
|
|
bool
|
|
Random::
|
|
get_bool( )
|
|
{
|
|
return static_cast<bool>( erand48( _state) < 0.5);
|
|
}
|
|
|
|
inline
|
|
int
|
|
Random::
|
|
get_int( int lower, int upper)
|
|
{
|
|
return( lower + static_cast<int>(
|
|
static_cast<double>( 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 <Random state functions> = @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 <Random equality test> = @begin
|
|
inline
|
|
bool
|
|
Random::
|
|
operator == ( const Random& rnd) const
|
|
{
|
|
return( static_cast<bool>(
|
|
( _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 <Random tests> = @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 <include/CGAL/Random.h> = @begin
|
|
@<file header>("include/CGAL/Random.h","Random Numbers Generator")
|
|
|
|
#ifndef CGAL_RANDOM_H
|
|
#define CGAL_RANDOM_H
|
|
|
|
// includes
|
|
// --------
|
|
#ifndef CGAL_BASIC_H
|
|
# include <CGAL/basic.h>
|
|
#endif
|
|
|
|
@<namespace begin>("CGAL")
|
|
|
|
// Class declaration
|
|
// =================
|
|
@<Random declaration>
|
|
|
|
// Class interface
|
|
// ===============
|
|
@<Random interface>
|
|
|
|
// Global variables
|
|
// ================
|
|
@<Random global variable declaration>
|
|
|
|
@<namespace end>("CGAL")
|
|
|
|
@<dividing line>
|
|
|
|
// Class implementation (inline functions)
|
|
// =======================================
|
|
// includes
|
|
#include <cstdlib>
|
|
|
|
@<namespace begin>("CGAL")
|
|
|
|
// operations
|
|
@<Random operations>
|
|
|
|
@<Random equality test>
|
|
|
|
@<namespace end>("CGAL")
|
|
|
|
#endif // CGAL_RANDOM_H
|
|
|
|
@<end of file line>
|
|
@end
|
|
|
|
@! ----------------------------------------------------------------------------
|
|
@! Random.C
|
|
@! ----------------------------------------------------------------------------
|
|
|
|
\subsection{src/Random.C}
|
|
|
|
@file <src/Random.C> = @begin
|
|
@<file header>("src/Random.C","Random Numbers Generator")
|
|
|
|
#include <CGAL/Random.h>
|
|
|
|
// additional includes
|
|
#include <ctime>
|
|
#include <sys/time.h>
|
|
|
|
@<namespace begin>("CGAL")
|
|
|
|
// Class implementation (continued)
|
|
// ================================
|
|
|
|
// constructors
|
|
@<Random constructors>
|
|
|
|
// state functions
|
|
@<Random state functions>
|
|
|
|
// Global variables
|
|
// ================
|
|
@<Random global variable definition>
|
|
|
|
@<namespace end>("CGAL")
|
|
|
|
@<end of file line>
|
|
@end
|
|
|
|
@! ----------------------------------------------------------------------------
|
|
@! test_Random.C
|
|
@! ----------------------------------------------------------------------------
|
|
|
|
\subsection{test/Random\_numbers/test\_Random.C}
|
|
|
|
@file <test/Random_numbers/test_Random.C> = @begin
|
|
@<file header>(
|
|
"test/Random_numbers/test_Random.C",
|
|
"test program for Random Numbers Generator")
|
|
|
|
// includes
|
|
#include <CGAL/Random.h>
|
|
#include <cassert>
|
|
|
|
int
|
|
main( int, char**)
|
|
{
|
|
@<Random tests>
|
|
|
|
return( 0);
|
|
}
|
|
|
|
@<end of file line>
|
|
@end
|
|
|
|
@! ----------------------------------------------------------------------------
|
|
@! File Header
|
|
@! ----------------------------------------------------------------------------
|
|
|
|
\subsection*{File Header}
|
|
|
|
@i share/file_header.awi
|
|
|
|
@macro <file header>(2) many = @begin
|
|
@<copyright notice>
|
|
@<file name>(@1)
|
|
@<file description>(
|
|
"Random_numbers",
|
|
"Random Numbers Generator",
|
|
"Random",
|
|
"$Id$","$Date$",
|
|
"Sven Schönherr <sven@@inf.ethz.ch>",
|
|
"INRIA Sophia-Antipolis",
|
|
"@2")
|
|
@end
|
|
|
|
@! ===== EOF ==================================================================
|