diff --git a/include/algorithm b/include/algorithm index c53bf376..01cee60b 100644 --- a/include/algorithm +++ b/include/algorithm @@ -254,6 +254,10 @@ template void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand); +template + void shuffle(RandomAccessIterator first, RandomAccessIterator last, + UniformRandomNumberGenerator& g); + template bool is_partitioned(InputIterator first, InputIterator last, Predicate pred); @@ -2277,132 +2281,286 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last) // random_shuffle -template -struct __num_bits +// __independent_bits_engine + +template +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 <> -struct __num_bits<0> +template +struct __log2_imp<_X, 0> { - static const int __value = 0; + static const size_t value = 0; }; -const int __rbits = __num_bits::__value; -const int __lbits = static_cast(sizeof(unsigned long) * __CHAR_BIT__); - -template -struct __random_bits +template +struct __log2_imp<0, _R> { - _LIBCPP_INLINE_VISIBILITY operator unsigned long () const - {return static_cast(_STD::rand()) >> (__rbits - _NBits);} + static const size_t value = _R + 1; }; -template -struct __random_bits<_NBits, false> +template +struct __log2 { - _LIBCPP_INLINE_VISIBILITY operator unsigned long () const - {return static_cast(_STD::rand()) << (_NBits - __rbits) | __random_bits<_NBits - __rbits>();} + static const size_t value = __log2_imp<_X, + sizeof(_UI) * __CHAR_BIT__ - 1>::value; }; -template -inline _LIBCPP_INLINE_VISIBILITY -unsigned long -__slab_size(unsigned long __n) +template +class __independent_bits_engine { - 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());} + +private: + result_type __eval(false_type); + result_type __eval(true_type); +}; + +template +__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 <> -inline _LIBCPP_INLINE_VISIBILITY -unsigned long -__slab_size<__lbits>(unsigned long __n) +template +inline +_UIntType +__independent_bits_engine<_Engine, _UIntType>::__eval(false_type) { - if (__n & 1) - return (unsigned long)(~0) / __n; - return (1UL << (__lbits-1)) / (__n >> 1); + return static_cast(__e_() & __mask0_); } -template -inline _LIBCPP_INLINE_VISIBILITY -unsigned long -__scaled_random_number(unsigned long __n) +template +_UIntType +__independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { - const unsigned long __slab = __slab_size<_NBits>(__n); - const unsigned long __usable = __slab * __n; - unsigned long __raw; + 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 + +template +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::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::max()) + : __p_(param_type(__a, __b)) {} + explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} + void reset() {} + + // generating functions + template result_type operator()(_URNG& __g) + {return (*this)(__g, __p_);} + template 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 +template +typename uniform_int_distribution<_IntType>::result_type +uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p) +{ + typedef typename conditional::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(_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 - __raw = __random_bits<_NBits>(); - while (__raw >= __usable); - return __raw / __slab; + { + __u = __e(); + } while (__u >= _R); + return static_cast(__u + __p.a()); } -template struct __rs_default; +class __rs_default; -template -struct __rs_default<__b, 1> +__rs_default __rs_get(); + +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 -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 -struct __rs_default<__b, 2> -{ - unsigned long operator()(unsigned long __n = 0) const; -}; - -template -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); -} +__rs_default __rs_get(); template void random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef uniform_int_distribution _D; + typedef typename _D::param_type _P; difference_type __d = __last - __first; if (__d > 1) { - for (--__last; __first < __last; ++__first, --__d) - swap(*__first, *(__first - + static_cast(__rs_default()(static_cast(__d))))); + _D __uid; + __rs_default __g = __rs_get(); + 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 + void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, + _UniformRandomNumberGenerator& __g) +{ + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef uniform_int_distribution _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 bool is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) diff --git a/include/random b/include/random index adefa8b9..f3e6656c 100644 --- a/include/random +++ b/include/random @@ -2793,32 +2793,6 @@ typedef discard_block_engine ranlux48; // independent_bits_engine -template -struct __log2_imp -{ - static const size_t value = _X & ((unsigned long long)(1) << _R) ? _R - : __log2_imp<_X, _R - 1>::value; -}; - -template -struct __log2_imp<_X, 0> -{ - static const size_t value = 0; -}; - -template -struct __log2_imp<0, _R> -{ - static const size_t value = _R + 1; -}; - -template -struct __log2 -{ - static const size_t value = __log2_imp<_X, - sizeof(_UI) * __CHAR_BIT__ - 1>::value; -}; - template class independent_bits_engine { @@ -3396,217 +3370,9 @@ generate_canonical(_URNG& __g) return _S / __base; } -// __independent_bits_engine - -template -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());} - -private: - result_type __eval(false_type); - result_type __eval(true_type); -}; - -template -__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 -inline -_UIntType -__independent_bits_engine<_Engine, _UIntType>::__eval(false_type) -{ - return static_cast(__e_() & __mask0_); -} - -template -_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 -template -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::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::max()) - : __p_(param_type(__a, __b)) {} - explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} - void reset() {} - - // generating functions - template result_type operator()(_URNG& __g) - {return (*this)(__g, __p_);} - template 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 -template -typename uniform_int_distribution<_IntType>::result_type -uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p) -{ - typedef typename conditional::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(_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(__u + __p.a()); -} +// in template basic_ostream<_CharT, _Traits>& diff --git a/src/algorithm.cpp b/src/algorithm.cpp index fd815214..c688bae0 100644 --- a/src/algorithm.cpp +++ b/src/algorithm.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "algorithm" +#include "random" +#include "mutex" _LIBCPP_BEGIN_NAMESPACE_STD @@ -45,4 +47,37 @@ template bool __insertion_sort_incomplete<__less&, long double*>(lo template unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); +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 diff --git a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp index 914f851d..ca4a2bdd 100644 --- a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp +++ b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp @@ -15,12 +15,16 @@ // random_shuffle(Iter first, Iter last); #include - -#include "../../iterators.h" +#include int main() { 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]); 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)); } diff --git a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_rand.pass.cpp b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_rand.pass.cpp index ea600666..6a17521f 100644 --- a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_rand.pass.cpp +++ b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_rand.pass.cpp @@ -16,21 +16,22 @@ // random_shuffle(Iter first, Iter last, Rand&& rand); #include - -#include "../../iterators.h" +#include struct gen { int operator()(int n) { - return 0; + return n-1; } }; int main() { int ia[] = {1, 2, 3, 4}; + int ia1[] = {4, 1, 2, 3}; const unsigned sa = sizeof(ia)/sizeof(ia[0]); gen r; std::random_shuffle(ia, ia+sa, r); + assert(std::equal(ia, ia+sa, ia1)); } diff --git a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_urng.pass.cpp b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_urng.pass.cpp index 23a7c1f9..6513d0c0 100644 --- a/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_urng.pass.cpp +++ b/test/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle_urng.pass.cpp @@ -9,14 +9,23 @@ // -// template -// void -// random_shuffle(Iter first, Iter last, Rand&& g); +// template +// void shuffle(RandomAccessIterator first, RandomAccessIterator last, +// UniformRandomNumberGenerator& g); #include - -#error random_shuffle for UniformRandomNumberGenerator not implemented +#include +#include 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)); }