Completed [alg.random.shuffle].

llvm-svn: 104708
This commit is contained in:
Howard Hinnant 2010-05-26 17:49:34 +00:00
parent a19838e107
commit f9d540b062
6 changed files with 325 additions and 336 deletions

View File

@ -254,6 +254,10 @@ template <class RandomAccessIterator, class RandomNumberGenerator>
void void
random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand); random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand);
template<class RandomAccessIterator, class UniformRandomNumberGenerator>
void shuffle(RandomAccessIterator first, RandomAccessIterator last,
UniformRandomNumberGenerator& g);
template <class InputIterator, class Predicate> template <class InputIterator, class Predicate>
bool bool
is_partitioned(InputIterator first, InputIterator last, Predicate pred); is_partitioned(InputIterator first, InputIterator last, Predicate pred);
@ -2277,132 +2281,286 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last)
// random_shuffle // random_shuffle
template <unsigned int _Bits> // __independent_bits_engine
struct __num_bits
template <unsigned long long _X, size_t _R>
struct __log2_imp
{ {
static const int __value = 1 + __num_bits<(_Bits >> 1)>::__value; static const size_t value = _X & ((unsigned long long)(1) << _R) ? _R
: __log2_imp<_X, _R - 1>::value;
}; };
template <> template <unsigned long long _X>
struct __num_bits<0> struct __log2_imp<_X, 0>
{ {
static const int __value = 0; static const size_t value = 0;
}; };
const int __rbits = __num_bits<RAND_MAX>::__value; template <size_t _R>
const int __lbits = static_cast<int>(sizeof(unsigned long) * __CHAR_BIT__); struct __log2_imp<0, _R>
template <int _NBits, bool = _NBits <= __rbits>
struct __random_bits
{ {
_LIBCPP_INLINE_VISIBILITY operator unsigned long () const static const size_t value = _R + 1;
{return static_cast<unsigned long>(_STD::rand()) >> (__rbits - _NBits);}
}; };
template <int _NBits> template <class _UI, _UI _X>
struct __random_bits<_NBits, false> struct __log2
{ {
_LIBCPP_INLINE_VISIBILITY operator unsigned long () const static const size_t value = __log2_imp<_X,
{return static_cast<unsigned long>(_STD::rand()) << (_NBits - __rbits) | __random_bits<_NBits - __rbits>();} sizeof(_UI) * __CHAR_BIT__ - 1>::value;
}; };
template <int _NBits> template<class _Engine, class _UIntType>
inline _LIBCPP_INLINE_VISIBILITY class __independent_bits_engine
unsigned long
__slab_size(unsigned long __n)
{ {
return (1UL << _NBits) / __n; public:
// types
typedef _UIntType result_type;
private:
typedef typename _Engine::result_type _Engine_result_type;
typedef typename conditional
<
sizeof(_Engine_result_type) <= sizeof(result_type),
result_type,
_Engine_result_type
>::type _Working_result_type;
_Engine& __e_;
size_t __w_;
size_t __w0_;
size_t __n_;
size_t __n0_;
_Working_result_type __y0_;
_Working_result_type __y1_;
_Engine_result_type __mask0_;
_Engine_result_type __mask1_;
static const _Working_result_type _R = _Engine::_Max - _Engine::_Min
+ _Working_result_type(1);
static const size_t __m = __log2<_Working_result_type, _R>::value;
static const size_t _WDt = numeric_limits<_Working_result_type>::digits;
static const size_t _EDt = numeric_limits<_Engine_result_type>::digits;
public:
// constructors and seeding functions
__independent_bits_engine(_Engine& __e, size_t __w);
// generating functions
result_type operator()() {return __eval(integral_constant<bool, _R != 0>());}
private:
result_type __eval(false_type);
result_type __eval(true_type);
};
template<class _Engine, class _UIntType>
__independent_bits_engine<_Engine, _UIntType>
::__independent_bits_engine(_Engine& __e, size_t __w)
: __e_(__e),
__w_(__w)
{
__n_ = __w_ / __m + (__w_ % __m != 0);
__w0_ = __w_ / __n_;
if (_R == 0)
__y0_ = _R;
else if (__w0_ < _WDt)
__y0_ = (_R >> __w0_) << __w0_;
else
__y0_ = 0;
if (_R - __y0_ > __y0_ / __n_)
{
++__n_;
__w0_ = __w_ / __n_;
if (__w0_ < _WDt)
__y0_ = (_R >> __w0_) << __w0_;
else
__y0_ = 0;
}
__n0_ = __n_ - __w_ % __n_;
if (__w0_ < _WDt - 1)
__y1_ = (_R >> (__w0_ + 1)) << (__w0_ + 1);
else
__y1_ = 0;
__mask0_ = __w0_ > 0 ? _Engine_result_type(~0) >> (_EDt - __w0_) :
_Engine_result_type(0);
__mask1_ = __w0_ < _EDt - 1 ?
_Engine_result_type(~0) >> (_EDt - (__w0_ + 1)) :
_Engine_result_type(~0);
} }
template <> template<class _Engine, class _UIntType>
inline _LIBCPP_INLINE_VISIBILITY inline
unsigned long _UIntType
__slab_size<__lbits>(unsigned long __n) __independent_bits_engine<_Engine, _UIntType>::__eval(false_type)
{ {
if (__n & 1) return static_cast<result_type>(__e_() & __mask0_);
return (unsigned long)(~0) / __n;
return (1UL << (__lbits-1)) / (__n >> 1);
} }
template <int _NBits> template<class _Engine, class _UIntType>
inline _LIBCPP_INLINE_VISIBILITY _UIntType
unsigned long __independent_bits_engine<_Engine, _UIntType>::__eval(true_type)
__scaled_random_number(unsigned long __n)
{ {
const unsigned long __slab = __slab_size<_NBits>(__n); result_type _S = 0;
const unsigned long __usable = __slab * __n; for (size_t __k = 0; __k < __n0_; ++__k)
unsigned long __raw; {
_Engine_result_type __u;
do
{
__u = __e_() - _Engine::min();
} while (__u >= __y0_);
if (__w0_ < _EDt)
_S <<= __w0_;
else
_S = 0;
_S += __u & __mask0_;
}
for (size_t __k = __n0_; __k < __n_; ++__k)
{
_Engine_result_type __u;
do
{
__u = __e_() - _Engine::min();
} while (__u >= __y1_);
if (__w0_ < _EDt - 1)
_S <<= __w0_ + 1;
else
_S = 0;
_S += __u & __mask1_;
}
return _S;
}
// uniform_int_distribution
template<class _IntType = int>
class uniform_int_distribution
{
public:
// types
typedef _IntType result_type;
class param_type
{
result_type __a_;
result_type __b_;
public:
typedef uniform_int_distribution distribution_type;
explicit param_type(result_type __a = 0,
result_type __b = numeric_limits<result_type>::max())
: __a_(__a), __b_(__b) {}
result_type a() const {return __a_;}
result_type b() const {return __b_;}
friend bool operator==(const param_type& __x, const param_type& __y)
{return __x.__a_ == __y.__a_ && __x.__b_ == __y.__b_;}
friend bool operator!=(const param_type& __x, const param_type& __y)
{return !(__x == __y);}
};
private:
param_type __p_;
public:
// constructors and reset functions
explicit uniform_int_distribution(result_type __a = 0,
result_type __b = numeric_limits<result_type>::max())
: __p_(param_type(__a, __b)) {}
explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {}
void reset() {}
// generating functions
template<class _URNG> result_type operator()(_URNG& __g)
{return (*this)(__g, __p_);}
template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p);
// property functions
result_type a() const {return __p_.a();}
result_type b() const {return __p_.b();}
param_type param() const {return __p_;}
void param(const param_type& __p) {__p_ = __p;}
result_type min() const {return a();}
result_type max() const {return b();}
friend bool operator==(const uniform_int_distribution& __x,
const uniform_int_distribution& __y)
{return __x.__p_ == __y.__p_;}
friend bool operator!=(const uniform_int_distribution& __x,
const uniform_int_distribution& __y)
{return !(__x == __y);}
};
template<class _IntType>
template<class _URNG>
typename uniform_int_distribution<_IntType>::result_type
uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p)
{
typedef typename conditional<sizeof(result_type) <= sizeof(uint32_t),
uint32_t, uint64_t>::type _UIntType;
const _UIntType _R = __p.b() - __p.a() + _UIntType(1);
if (_R == 1)
return __p.a();
const size_t _Dt = numeric_limits<_UIntType>::digits;
typedef __independent_bits_engine<_URNG, _UIntType> _Eng;
if (_R == 0)
return static_cast<result_type>(_Eng(__g, _Dt)());
size_t __w = _Dt - __clz(_R) - 1;
if ((_R & (_UIntType(~0) >> (_Dt - __w))) != 0)
++__w;
_Eng __e(__g, __w);
_UIntType __u;
do do
__raw = __random_bits<_NBits>(); {
while (__raw >= __usable); __u = __e();
return __raw / __slab; } while (__u >= _R);
return static_cast<result_type>(__u + __p.a());
} }
template <bool __b, unsigned long = __lbits/__rbits> struct __rs_default; class __rs_default;
template <bool __b> __rs_default __rs_get();
struct __rs_default<__b, 1>
class __rs_default
{ {
unsigned long operator()(unsigned long __n = 0) const; static unsigned __c_;
__rs_default();
public:
typedef unsigned result_type;
static const result_type _Min = 0;
static const result_type _Max = 0xFFFFFFFF;
__rs_default(const __rs_default&);
~__rs_default();
result_type operator()();
static const/*expr*/ result_type min() {return _Min;}
static const/*expr*/ result_type max() {return _Max;}
friend __rs_default __rs_get();
}; };
template <bool __b> __rs_default __rs_get();
unsigned long
__rs_default<__b, 1>::operator()(unsigned long __n) const
{
switch (__n)
{
case 0:
return __random_bits<__lbits>();
case 1:
return 0;
}
if (__n <= (1UL << __rbits))
return __scaled_random_number<__rbits>(__n);
return __scaled_random_number<__lbits>(__n);
}
template <bool __b>
struct __rs_default<__b, 2>
{
unsigned long operator()(unsigned long __n = 0) const;
};
template <bool __b>
unsigned long
__rs_default<__b, 2>::operator()(unsigned long __n) const
{
switch (__n)
{
case 0:
return __random_bits<__lbits>();
case 1:
return 0;
}
int __nb = __rbits;
while (__nb < __lbits && __n > (1UL << __nb))
__nb += _STD::min(__rbits, __lbits - __nb);
switch (__nb)
{
case __rbits:
return __scaled_random_number<__rbits>(__n);
case 2*__rbits:
return __scaled_random_number<2*__rbits>(__n);
}
return __scaled_random_number<__lbits>(__n);
}
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
void void
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
{ {
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef uniform_int_distribution<ptrdiff_t> _D;
typedef typename _D::param_type _P;
difference_type __d = __last - __first; difference_type __d = __last - __first;
if (__d > 1) if (__d > 1)
{ {
for (--__last; __first < __last; ++__first, --__d) _D __uid;
swap(*__first, *(__first __rs_default __g = __rs_get();
+ static_cast<difference_type>(__rs_default<true>()(static_cast<unsigned long>(__d))))); for (--__last, --__d; __first < __last; ++__first, --__d)
swap(*__first, *(__first + __uid(__g, _P(0, __d))));
} }
} }
@ -2424,6 +2582,22 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
} }
} }
template<class _RandomAccessIterator, class _UniformRandomNumberGenerator>
void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
_UniformRandomNumberGenerator& __g)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef uniform_int_distribution<ptrdiff_t> _D;
typedef typename _D::param_type _P;
difference_type __d = __last - __first;
if (__d > 1)
{
_D __uid;
for (--__last, --__d; __first < __last; ++__first, --__d)
swap(*__first, *(__first + __uid(__g, _P(0, __d))));
}
}
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
bool bool
is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred)

View File

@ -2793,32 +2793,6 @@ typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;
// independent_bits_engine // independent_bits_engine
template <unsigned long long _X, size_t _R>
struct __log2_imp
{
static const size_t value = _X & ((unsigned long long)(1) << _R) ? _R
: __log2_imp<_X, _R - 1>::value;
};
template <unsigned long long _X>
struct __log2_imp<_X, 0>
{
static const size_t value = 0;
};
template <size_t _R>
struct __log2_imp<0, _R>
{
static const size_t value = _R + 1;
};
template <class _UI, _UI _X>
struct __log2
{
static const size_t value = __log2_imp<_X,
sizeof(_UI) * __CHAR_BIT__ - 1>::value;
};
template<class _Engine, size_t __w, class _UIntType> template<class _Engine, size_t __w, class _UIntType>
class independent_bits_engine class independent_bits_engine
{ {
@ -3396,217 +3370,9 @@ generate_canonical(_URNG& __g)
return _S / __base; return _S / __base;
} }
// __independent_bits_engine
template<class _Engine, class _UIntType>
class __independent_bits_engine
{
public:
// types
typedef _UIntType result_type;
private:
typedef typename _Engine::result_type _Engine_result_type;
typedef typename conditional
<
sizeof(_Engine_result_type) <= sizeof(result_type),
result_type,
_Engine_result_type
>::type _Working_result_type;
_Engine& __e_;
size_t __w_;
size_t __w0_;
size_t __n_;
size_t __n0_;
_Working_result_type __y0_;
_Working_result_type __y1_;
_Engine_result_type __mask0_;
_Engine_result_type __mask1_;
static const _Working_result_type _R = _Engine::_Max - _Engine::_Min
+ _Working_result_type(1);
static const size_t __m = __log2<_Working_result_type, _R>::value;
static const size_t _WDt = numeric_limits<_Working_result_type>::digits;
static const size_t _EDt = numeric_limits<_Engine_result_type>::digits;
public:
// constructors and seeding functions
__independent_bits_engine(_Engine& __e, size_t __w);
// generating functions
result_type operator()() {return __eval(integral_constant<bool, _R != 0>());}
private:
result_type __eval(false_type);
result_type __eval(true_type);
};
template<class _Engine, class _UIntType>
__independent_bits_engine<_Engine, _UIntType>
::__independent_bits_engine(_Engine& __e, size_t __w)
: __e_(__e),
__w_(__w)
{
__n_ = __w_ / __m + (__w_ % __m != 0);
__w0_ = __w_ / __n_;
if (_R == 0)
__y0_ = _R;
else if (__w0_ < _WDt)
__y0_ = (_R >> __w0_) << __w0_;
else
__y0_ = 0;
if (_R - __y0_ > __y0_ / __n_)
{
++__n_;
__w0_ = __w_ / __n_;
if (__w0_ < _WDt)
__y0_ = (_R >> __w0_) << __w0_;
else
__y0_ = 0;
}
__n0_ = __n_ - __w_ % __n_;
if (__w0_ < _WDt - 1)
__y1_ = (_R >> (__w0_ + 1)) << (__w0_ + 1);
else
__y1_ = 0;
__mask0_ = __w0_ > 0 ? _Engine_result_type(~0) >> (_EDt - __w0_) :
_Engine_result_type(0);
__mask1_ = __w0_ < _EDt - 1 ?
_Engine_result_type(~0) >> (_EDt - (__w0_ + 1)) :
_Engine_result_type(~0);
}
template<class _Engine, class _UIntType>
inline
_UIntType
__independent_bits_engine<_Engine, _UIntType>::__eval(false_type)
{
return static_cast<result_type>(__e_() & __mask0_);
}
template<class _Engine, class _UIntType>
_UIntType
__independent_bits_engine<_Engine, _UIntType>::__eval(true_type)
{
result_type _S = 0;
for (size_t __k = 0; __k < __n0_; ++__k)
{
_Engine_result_type __u;
do
{
__u = __e_() - _Engine::min();
} while (__u >= __y0_);
if (__w0_ < _EDt)
_S <<= __w0_;
else
_S = 0;
_S += __u & __mask0_;
}
for (size_t __k = __n0_; __k < __n_; ++__k)
{
_Engine_result_type __u;
do
{
__u = __e_() - _Engine::min();
} while (__u >= __y1_);
if (__w0_ < _EDt - 1)
_S <<= __w0_ + 1;
else
_S = 0;
_S += __u & __mask1_;
}
return _S;
}
// uniform_int_distribution // uniform_int_distribution
template<class _IntType = int> // in <algorithm>
class uniform_int_distribution
{
public:
// types
typedef _IntType result_type;
class param_type
{
result_type __a_;
result_type __b_;
public:
typedef uniform_int_distribution distribution_type;
explicit param_type(result_type __a = 0,
result_type __b = numeric_limits<result_type>::max())
: __a_(__a), __b_(__b) {}
result_type a() const {return __a_;}
result_type b() const {return __b_;}
friend bool operator==(const param_type& __x, const param_type& __y)
{return __x.__a_ == __y.__a_ && __x.__b_ == __y.__b_;}
friend bool operator!=(const param_type& __x, const param_type& __y)
{return !(__x == __y);}
};
private:
param_type __p_;
public:
// constructors and reset functions
explicit uniform_int_distribution(result_type __a = 0,
result_type __b = numeric_limits<result_type>::max())
: __p_(param_type(__a, __b)) {}
explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {}
void reset() {}
// generating functions
template<class _URNG> result_type operator()(_URNG& __g)
{return (*this)(__g, __p_);}
template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p);
// property functions
result_type a() const {return __p_.a();}
result_type b() const {return __p_.b();}
param_type param() const {return __p_;}
void param(const param_type& __p) {__p_ = __p;}
result_type min() const {return a();}
result_type max() const {return b();}
friend bool operator==(const uniform_int_distribution& __x,
const uniform_int_distribution& __y)
{return __x.__p_ == __y.__p_;}
friend bool operator!=(const uniform_int_distribution& __x,
const uniform_int_distribution& __y)
{return !(__x == __y);}
};
template<class _IntType>
template<class _URNG>
typename uniform_int_distribution<_IntType>::result_type
uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p)
{
typedef typename conditional<sizeof(result_type) <= sizeof(uint32_t),
uint32_t, uint64_t>::type _UIntType;
const _UIntType _R = __p.b() - __p.a() + _UIntType(1);
if (_R == 1)
return __p.a();
const size_t _Dt = numeric_limits<_UIntType>::digits;
typedef __independent_bits_engine<_URNG, _UIntType> _Eng;
if (_R == 0)
return static_cast<result_type>(_Eng(__g, _Dt)());
size_t __w = _Dt - __clz(_R) - 1;
if ((_R & (_UIntType(~0) >> (_Dt - __w))) != 0)
++__w;
_Eng __e(__g, __w);
_UIntType __u;
do
{
__u = __e();
} while (__u >= _R);
return static_cast<result_type>(__u + __p.a());
}
template <class _CharT, class _Traits, class _IT> template <class _CharT, class _Traits, class _IT>
basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>&

View File

@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "algorithm" #include "algorithm"
#include "random"
#include "mutex"
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -45,4 +47,37 @@ template bool __insertion_sort_incomplete<__less<long double>&, long double*>(lo
template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&);
static pthread_mutex_t __rs_mut = PTHREAD_MUTEX_INITIALIZER;
unsigned __rs_default::__c_ = 0;
__rs_default::__rs_default()
{
pthread_mutex_lock(&__rs_mut);
__c_ = 1;
}
__rs_default::__rs_default(const __rs_default&)
{
++__c_;
}
__rs_default::~__rs_default()
{
if (--__c_ == 0)
pthread_mutex_unlock(&__rs_mut);
}
__rs_default::result_type
__rs_default::operator()()
{
static mt19937 __rs_g;
return __rs_g();
}
__rs_default
__rs_get()
{
return __rs_default();
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -15,12 +15,16 @@
// random_shuffle(Iter first, Iter last); // random_shuffle(Iter first, Iter last);
#include <algorithm> #include <algorithm>
#include <cassert>
#include "../../iterators.h"
int main() int main()
{ {
int ia[] = {1, 2, 3, 4}; int ia[] = {1, 2, 3, 4};
int ia1[] = {1, 4, 3, 2};
int ia2[] = {4, 1, 2, 3};
const unsigned sa = sizeof(ia)/sizeof(ia[0]); const unsigned sa = sizeof(ia)/sizeof(ia[0]);
std::random_shuffle(ia, ia+sa); std::random_shuffle(ia, ia+sa);
assert(std::equal(ia, ia+sa, ia1));
std::random_shuffle(ia, ia+sa);
assert(std::equal(ia, ia+sa, ia2));
} }

View File

@ -16,21 +16,22 @@
// random_shuffle(Iter first, Iter last, Rand&& rand); // random_shuffle(Iter first, Iter last, Rand&& rand);
#include <algorithm> #include <algorithm>
#include <cassert>
#include "../../iterators.h"
struct gen struct gen
{ {
int operator()(int n) int operator()(int n)
{ {
return 0; return n-1;
} }
}; };
int main() int main()
{ {
int ia[] = {1, 2, 3, 4}; int ia[] = {1, 2, 3, 4};
int ia1[] = {4, 1, 2, 3};
const unsigned sa = sizeof(ia)/sizeof(ia[0]); const unsigned sa = sizeof(ia)/sizeof(ia[0]);
gen r; gen r;
std::random_shuffle(ia, ia+sa, r); std::random_shuffle(ia, ia+sa, r);
assert(std::equal(ia, ia+sa, ia1));
} }

View File

@ -9,14 +9,23 @@
// <algorithm> // <algorithm>
// template<RandomAccessIterator Iter, UniformRandomNumberGenerator Rand> // template<class RandomAccessIterator, class UniformRandomNumberGenerator>
// void // void shuffle(RandomAccessIterator first, RandomAccessIterator last,
// random_shuffle(Iter first, Iter last, Rand&& g); // UniformRandomNumberGenerator& g);
#include <algorithm> #include <algorithm>
#include <random>
#error random_shuffle for UniformRandomNumberGenerator not implemented #include <cassert>
int main() int main()
{ {
int ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int ia1[] = {2, 7, 1, 4, 3, 6, 5, 10, 9, 8};
int ia2[] = {1, 8, 3, 4, 6, 9, 5, 7, 2, 10};
const unsigned sa = sizeof(ia)/sizeof(ia[0]);
std::minstd_rand g;
std::shuffle(ia, ia+sa, g);
assert(std::equal(ia, ia+sa, ia1));
std::shuffle(ia, ia+sa, g);
assert(std::equal(ia, ia+sa, ia2));
} }