我正在尝试重新实现没有模板的c ++ 11 uniform_int_distribution
,特别是mt19937
,因为我想将这个典型用例中的功能移植到没有模板功能的其他语言,它会是很高兴有一个更易读的版本。阅读gcc实现的难度远远超出了我从一个统一分布到另一个统一分布的数学上简单转换的预期。 (是的,我知道这是专门针对将军的,我不会从这种做法中获得新的功能)
我查看了gcc 4.8.1标题。最常用的mt19937
类是typedef:
typedef mersenne_twister_engine<
uint_fast32_t,
32, 624, 397, 31,
0x9908b0dfUL, 11,
0xffffffffUL, 7,
0x9d2c5680UL, 15,
0xefc60000UL, 18, 1812433253UL> mt19937;
gcc中uniform_int_distribution
的代码非常模糊,对我来说不太可读。我想知道如何将代码简化/专门化为非模板代码,仅针对mt19937
案例。
我在4.8.1 / include / c ++ / bits / random.tcc中找到的最相关的代码段最后附加了(为了清楚起见,删除了双下划线__
)。
我试图专门化代码,但不是很成功。对于启动器,我试图找出mt19937的范围:min为0,max为(在random.h中):
static constexpr result_type
max()
{ return __detail::_Shift<_UIntType, __w>::__value - 1; }
,涉及复杂的模板编程,不易阅读。我想也许最好问一下逆向工程模板。
所以我的问题是:
uint32
和mt19973
的类型和值来专门化其余代码。提前致谢。
--- gcc 4.8.1从mt19937到uniform_int_distribution ---
的采样代码 template<typename _IntType>
template<typename _ForwardIterator,
typename _UniformRandomNumberGenerator>
void
uniform_int_distribution<_IntType>::
generate_impl(_ForwardIterator f, _ForwardIterator t,
_UniformRandomNumberGenerator& urng,
const param_type& param)
{
glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
typedef typename _UniformRandomNumberGenerator::result_type
_Gresult_type;
typedef typename std::make_unsigned<result_type>::type utype;
typedef typename std::common_type<_Gresult_type, utype>::type
uctype;
const uctype urngmin = urng.min();
const uctype urngmax = urng.max();
const uctype urngrange = urngmax - urngmin;
const uctype urange
= uctype(param.b()) - uctype(param.a());
uctype ret;
if (urngrange > urange)
{
if (detail::_Power_of_2(urngrange + 1)
&& detail::_Power_of_2(urange + 1))
{
while (f != t)
{
ret = uctype(urng()) - urngmin;
*f++ = (ret & urange) + param.a();
}
}
else
{
// downscaling
const uctype uerange = urange + 1; // urange can be zero
const uctype scaling = urngrange / uerange;
const uctype past = uerange * scaling;
while (f != t)
{
do
ret = uctype(urng()) - urngmin;
while (ret >= past);
*f++ = ret / scaling + param.a();
}
}
}
else if (urngrange < urange)
{
// upscaling
/*
Note that every value in [0, urange]
can be written uniquely as
(urngrange + 1) * high + low
where
high in [0, urange / (urngrange + 1)]
and
low in [0, urngrange].
*/
uctype tmp; // wraparound control
while (f != t)
{
do
{
const uctype uerngrange = urngrange + 1;
tmp = (uerngrange * operator()
(urng, param_type(0, urange / uerngrange)));
ret = tmp + (uctype(urng()) - urngmin);
}
while (ret > urange || ret < tmp);
*f++ = ret;
}
}
else
while (f != t)
*f++ = uctype(urng()) - urngmin + param.a();
}
答案 0 :(得分:2)
mt19937在[0,2 ^ 32-1]中生成整数:
std::mt19937 mt_gen;
std::cout << mt_gen.min() << '\n';
std::cout << mt_gen.max() << '\n';
给出
0
4294967295
2。如果我理解正确,你想专门化模板&#34;手工&#34;,但没有弄清楚uniform_int_distribution究竟是做什么的?一旦你有mt19937(例如,http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c),在给定范围[低,高]中生成均匀分布的整数在概念上很简单,但是有一些细节需要注意(例如,仔细检查旁路 - 一个错误)。这里的第二个答案Generating a uniform distribution of INTEGERS in C(在接受的答案之后)可能会有所帮助。