xref: /openbsd-src/gnu/llvm/libcxx/include/__random/generate_canonical.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
2*4bdff4beSrobert //
3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4bdff4beSrobert //
7*4bdff4beSrobert //===----------------------------------------------------------------------===//
8*4bdff4beSrobert 
9*4bdff4beSrobert #ifndef _LIBCPP___RANDOM_GENERATE_CANONICAL_H
10*4bdff4beSrobert #define _LIBCPP___RANDOM_GENERATE_CANONICAL_H
11*4bdff4beSrobert 
12*4bdff4beSrobert #include <__config>
13*4bdff4beSrobert #include <__random/log2.h>
14*4bdff4beSrobert #include <cstdint>
15*4bdff4beSrobert #include <initializer_list>
16*4bdff4beSrobert #include <limits>
17*4bdff4beSrobert 
18*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19*4bdff4beSrobert #  pragma GCC system_header
20*4bdff4beSrobert #endif
21*4bdff4beSrobert 
22*4bdff4beSrobert _LIBCPP_PUSH_MACROS
23*4bdff4beSrobert #include <__undef_macros>
24*4bdff4beSrobert 
25*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
26*4bdff4beSrobert 
27*4bdff4beSrobert // generate_canonical
28*4bdff4beSrobert 
29*4bdff4beSrobert template<class _RealType, size_t __bits, class _URNG>
30*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _RealType
generate_canonical(_URNG & __g)31*4bdff4beSrobert generate_canonical(_URNG& __g)
32*4bdff4beSrobert {
33*4bdff4beSrobert     const size_t _Dt = numeric_limits<_RealType>::digits;
34*4bdff4beSrobert     const size_t __b = _Dt < __bits ? _Dt : __bits;
35*4bdff4beSrobert #ifdef _LIBCPP_CXX03_LANG
36*4bdff4beSrobert     const size_t __logR = __log2<uint64_t, _URNG::_Max - _URNG::_Min + uint64_t(1)>::value;
37*4bdff4beSrobert #else
38*4bdff4beSrobert     const size_t __logR = __log2<uint64_t, _URNG::max() - _URNG::min() + uint64_t(1)>::value;
39*4bdff4beSrobert #endif
40*4bdff4beSrobert     const size_t __k = __b / __logR + (__b % __logR != 0) + (__b == 0);
41*4bdff4beSrobert     const _RealType _Rp = static_cast<_RealType>(_URNG::max() - _URNG::min()) + _RealType(1);
42*4bdff4beSrobert     _RealType __base = _Rp;
43*4bdff4beSrobert     _RealType _Sp = __g() - _URNG::min();
44*4bdff4beSrobert     for (size_t __i = 1; __i < __k; ++__i, __base *= _Rp)
45*4bdff4beSrobert         _Sp += (__g() - _URNG::min()) * __base;
46*4bdff4beSrobert     return _Sp / __base;
47*4bdff4beSrobert }
48*4bdff4beSrobert 
49*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
50*4bdff4beSrobert 
51*4bdff4beSrobert _LIBCPP_POP_MACROS
52*4bdff4beSrobert 
53*4bdff4beSrobert #endif // _LIBCPP___RANDOM_GENERATE_CANONICAL_H
54