uniform_smallint.hpp
来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 237 行
HPP
237 行
/* boost random/uniform_smallint.hpp header file * * Copyright Jens Maurer 2000-2001 * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org for most recent version including documentation. * * $Id: uniform_smallint.hpp,v 1.1.1.2 2004/11/20 10:49:22 spion Exp $ * * Revision history * 2001-04-08 added min<max assertion (N. Becker) * 2001-02-18 moved to individual header files */#ifndef BOOST_RANDOM_UNIFORM_SMALLINT_HPP#define BOOST_RANDOM_UNIFORM_SMALLINT_HPP#include <cassert>#include <iostream>#include <boost/config.hpp>#include <boost/limits.hpp>#include <boost/static_assert.hpp>#include <boost/random/uniform_01.hpp>#include <boost/detail/workaround.hpp>#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS#include <boost/type_traits/is_float.hpp>#endifnamespace boost {// uniform integer distribution on a small range [min, max]namespace detail {template <class InputStream, class UniformInt, class Impl>InputStream& extract_uniform_int(InputStream& is, UniformInt& ud, Impl& impl){ typename UniformInt::result_type min, max; is >> std::ws >> min >> std::ws >> max; impl.set(min, max); return is;}template<class UniformRandomNumberGenerator, class IntType>struct uniform_smallint_integer{public: typedef UniformRandomNumberGenerator base_type; typedef IntType result_type; uniform_smallint_integer(base_type & rng, IntType min, IntType max) : _rng(&rng) { set(min, max); } void set(result_type min, result_type max); result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } base_type& base() const { return *_rng; } result_type operator()() { // we must not use the low bits here, because LCGs get very bad then return (((*_rng)() - (_rng->min)()) / _factor) % _range + _min; }private: typedef typename base_type::result_type base_result; base_type * _rng; IntType _min, _max; base_result _range; int _factor;};template<class UniformRandomNumberGenerator, class IntType>void uniform_smallint_integer<UniformRandomNumberGenerator, IntType>::set(result_type min, result_type max) { _min = min; _max = max; assert(min < max); _range = static_cast<base_result>(_max-_min)+1; base_result _factor = 1; // LCGs get bad when only taking the low bits. // (probably put this logic into a partial template specialization) // Check how many low bits we can ignore before we get too much // quantization error. base_result r_base = (_rng->max)() - (_rng->min)(); if(r_base == (std::numeric_limits<base_result>::max)()) { _factor = 2; r_base /= 2; } r_base += 1; if(r_base % _range == 0) { // No quantization effects, good _factor = r_base / _range; } else { // carefully avoid overflow; pessimizing heree for( ; r_base/_range/32 >= _range; _factor *= 2) r_base /= 2; }}template<class UniformRandomNumberGenerator, class IntType>class uniform_smallint_float{public: typedef UniformRandomNumberGenerator base_type; typedef IntType result_type; uniform_smallint_float(base_type & rng, IntType min, IntType max) : _rng(rng) { // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer); BOOST_STATIC_ASSERT(!std::numeric_limits<typename base_type::result_type>::is_integer);#endif assert(min < max); set(min, max); } void set(result_type min, result_type max) { _min = min; _max = max; _range = static_cast<base_result>(_max-_min)+1; } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } base_type& base() const { return _rng.base(); } result_type operator()() { return static_cast<IntType>(_rng() * _range) + _min; }private: typedef typename base_type::result_type base_result; uniform_01<base_type> _rng; IntType _min, _max; base_result _range;};} // namespace detailtemplate<class IntType = int>class uniform_smallint{public: typedef IntType input_type; typedef IntType result_type; explicit uniform_smallint(IntType min = 0, IntType max = 9) : _min(min), _max(max) {#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);#endif } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } void reset() { } template<class Engine> result_type operator()(Engine& eng) { typedef typename Engine::result_type base_result; base_result _range = static_cast<base_result>(_max-_min)+1; base_result _factor = 1; // LCGs get bad when only taking the low bits. // (probably put this logic into a partial template specialization) // Check how many low bits we can ignore before we get too much // quantization error. base_result r_base = (eng.max)() - (eng.min)(); if(r_base == (std::numeric_limits<base_result>::max)()) { _factor = 2; r_base /= 2; } r_base += 1; if(r_base % _range == 0) { // No quantization effects, good _factor = r_base / _range; } else { // carefully avoid overflow; pessimizing heree for( ; r_base/_range/32 >= _range; _factor *= 2) r_base /= 2; } return ((eng() - (eng.min)()) / _factor) % _range + _min; }#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template<class CharT, class Traits> friend std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_smallint& ud) { os << ud._min << " " << ud._max; return os; } template<class CharT, class Traits> friend std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& is, uniform_smallint& ud) {# if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 return detail::extract_uniform_int(is, ud, ud._impl);# else is >> std::ws >> ud._min >> std::ws >> ud._max; return is;# endif }#endifprivate: result_type _min; result_type _max;};} // namespace boost#endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?