266 lines
6.3 KiB
C
266 lines
6.3 KiB
C
|
// Copyright (c) 1997-2001
|
||
|
// Utrecht University (The Netherlands),
|
||
|
// ETH Zurich (Switzerland),
|
||
|
// INRIA Sophia-Antipolis (France),
|
||
|
// Max-Planck-Institute Saarbruecken (Germany),
|
||
|
// and Tel-Aviv University (Israel). All rights reserved.
|
||
|
//
|
||
|
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU Lesser General Public License as
|
||
|
// published by the Free Software Foundation; either version 3 of the License,
|
||
|
// or (at your option) any later version.
|
||
|
//
|
||
|
// Licensees holding a valid commercial license may use this file in
|
||
|
// accordance with the commercial license agreement provided with the software.
|
||
|
//
|
||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
//
|
||
|
// $URL$
|
||
|
// $Id$
|
||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||
|
//
|
||
|
//
|
||
|
// Author(s) : Sven Schoenherr <sven@inf.ethz.ch>, Sylvain Pion, Andreas Fabri
|
||
|
|
||
|
#ifndef CGAL_RANDOM_H
|
||
|
#define CGAL_RANDOM_H
|
||
|
|
||
|
#include <string>
|
||
|
#include <utility>
|
||
|
#include <CGAL/basic.h>
|
||
|
#include <CGAL/tss.h>
|
||
|
|
||
|
#if defined(BOOST_MSVC)
|
||
|
# pragma warning(push)
|
||
|
# pragma warning(disable:4244)
|
||
|
#endif
|
||
|
#include <boost/random/uniform_smallint.hpp>
|
||
|
#if defined(BOOST_MSVC)
|
||
|
# pragma warning(pop)
|
||
|
#endif
|
||
|
#include <boost/random/linear_congruential.hpp>
|
||
|
#include <boost/random/uniform_int.hpp>
|
||
|
#include <boost/random/uniform_real.hpp>
|
||
|
#include <boost/random/uniform_01.hpp>
|
||
|
#include <boost/random/variate_generator.hpp>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
namespace internal {
|
||
|
struct Random_print_seed{};
|
||
|
}
|
||
|
|
||
|
class Random {
|
||
|
public:
|
||
|
// types
|
||
|
|
||
|
struct State {
|
||
|
std::string rng;
|
||
|
unsigned int random_value, val, seed;
|
||
|
|
||
|
State()
|
||
|
{}
|
||
|
|
||
|
State(std::string rng,
|
||
|
unsigned int random_value,
|
||
|
unsigned int val,
|
||
|
unsigned int seed)
|
||
|
: rng(rng), random_value(random_value), val(val), seed(seed)
|
||
|
{}
|
||
|
};
|
||
|
// creation
|
||
|
CGAL_EXPORT Random( );
|
||
|
CGAL_EXPORT Random( internal::Random_print_seed );
|
||
|
CGAL_EXPORT Random( unsigned int seed );
|
||
|
|
||
|
// seed
|
||
|
CGAL_EXPORT unsigned int get_seed ( ) const;
|
||
|
|
||
|
// operations
|
||
|
bool get_bool( )
|
||
|
{
|
||
|
return( static_cast< bool>( rng() & 1));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_smallint(IntType lower, IntType upper)
|
||
|
{
|
||
|
// uniform_smallint has a closed interval, CGAL a halfopen
|
||
|
typedef boost::rand48::result_type result_type;
|
||
|
boost::uniform_smallint<result_type> dist(static_cast<result_type>(lower),
|
||
|
static_cast<result_type>(upper-1));
|
||
|
boost::variate_generator<boost::rand48&, boost::uniform_smallint<result_type> > generator(rng,dist);
|
||
|
|
||
|
return generator();
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_smallint(IntType lower)
|
||
|
{
|
||
|
return uniform_smallint<IntType>(lower,9);
|
||
|
}
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_smallint()
|
||
|
{
|
||
|
return uniform_smallint<IntType>(0,9);
|
||
|
}
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_int(IntType lower, IntType upper)
|
||
|
{
|
||
|
// uniform_int has a closed interval, CGAL a halfopen
|
||
|
boost::uniform_int<IntType> dist(lower,upper);
|
||
|
boost::variate_generator<boost::rand48&, boost::uniform_int<IntType> > generator(rng,dist);
|
||
|
|
||
|
return generator();
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_int(IntType lower)
|
||
|
{
|
||
|
return uniform_int<IntType>(lower,9);
|
||
|
}
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
uniform_int()
|
||
|
{
|
||
|
return uniform_int<IntType>(0,9);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
template <typename IntType>
|
||
|
IntType
|
||
|
operator () (IntType upper)
|
||
|
{
|
||
|
return uniform_int<IntType>(0, upper-1);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
get_int(int lower, int upper)
|
||
|
{
|
||
|
return uniform_int<int>(lower,upper-1);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename RealType>
|
||
|
RealType
|
||
|
uniform_real( RealType lower, RealType upper)
|
||
|
{
|
||
|
// uniform_real as well as CGAL have a halfopen interval
|
||
|
boost::uniform_real<RealType> dist(lower,upper);
|
||
|
boost::variate_generator<boost::rand48&, boost::uniform_real<RealType> > generator(rng,dist);
|
||
|
|
||
|
return generator();
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename RealType>
|
||
|
RealType
|
||
|
uniform_real( RealType lower)
|
||
|
{
|
||
|
return uniform_real<RealType>(lower, 1.0);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename RealType>
|
||
|
RealType
|
||
|
uniform_real()
|
||
|
{
|
||
|
return uniform_real<RealType>(0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename RealType>
|
||
|
RealType
|
||
|
uniform_01()
|
||
|
{
|
||
|
// uniform_01 as well as CGAL have a halfopen interval
|
||
|
boost::uniform_01<RealType> dist;
|
||
|
boost::variate_generator<boost::rand48&, boost::uniform_01<RealType> > generator(rng,dist);
|
||
|
|
||
|
return generator();
|
||
|
}
|
||
|
|
||
|
|
||
|
double
|
||
|
get_double( double lower = 0.0, double upper = 1.0)
|
||
|
{
|
||
|
return uniform_real<double>(lower, upper);
|
||
|
}
|
||
|
|
||
|
// state
|
||
|
CGAL_EXPORT void save_state( State& state) const;
|
||
|
CGAL_EXPORT 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
|
||
|
// efficiency.
|
||
|
template <int b>
|
||
|
int get_bits()
|
||
|
{
|
||
|
CGAL_assertion(0<b && b<16);
|
||
|
if (val == 0) {
|
||
|
random_value = (421U * random_value + 2073U) % 32749U;
|
||
|
val = random_value;
|
||
|
}
|
||
|
int ret = val & ((1<<b)-1);
|
||
|
val >>= 1; // Shifting by b would be slightly better, but is slower.
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool operator==(Random rd) const
|
||
|
{
|
||
|
return (rng == rd.rng)
|
||
|
&& (random_value == rd.random_value)
|
||
|
&& (val == rd.val)
|
||
|
&& (seed == rd.seed);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
// data members
|
||
|
unsigned int random_value; // Current 15 bits random value.
|
||
|
unsigned int val; // random_value shifted by used bits.
|
||
|
unsigned int seed;
|
||
|
boost::rand48 rng;
|
||
|
};
|
||
|
|
||
|
inline Random& get_default_random()
|
||
|
{
|
||
|
#if (defined( CGAL_TEST_SUITE ) || defined( CGAL_PRINT_SEED )) && !defined(CGAL_HEADER_ONLY)
|
||
|
internal::Random_print_seed rps;
|
||
|
CGAL_STATIC_THREAD_LOCAL_VARIABLE(Random, default_random, rps);
|
||
|
#else
|
||
|
CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Random, default_random);
|
||
|
#endif
|
||
|
return default_random;
|
||
|
}
|
||
|
|
||
|
#ifndef CGAL_NO_DEPRECATED_CODE
|
||
|
namespace { CGAL_DEPRECATED_UNUSED CGAL::Random& default_random = get_default_random(); }
|
||
|
#endif // CGAL_NO_DEPRECATED_CODE
|
||
|
|
||
|
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
#ifdef CGAL_HEADER_ONLY
|
||
|
#include <CGAL/Random_impl.h>
|
||
|
#endif // CGAL_HEADER_ONLY
|
||
|
|
||
|
#endif // CGAL_RANDOM_H
|