support C++14 constexpr: random distributions

This commit is contained in:
bolero-MURAKAMI 2013-11-05 23:46:23 +09:00
parent 230630b45b
commit 3c4a465d35
9 changed files with 468 additions and 60 deletions

View file

@ -88,13 +88,13 @@ namespace sprout {
); );
} }
public: public:
SPROUT_CONSTEXPR bernoulli_distribution() SPROUT_CONSTEXPR bernoulli_distribution() SPROUT_NOEXCEPT
: p_(RealType(0.5)) : p_(RealType(0.5))
{} {}
explicit SPROUT_CONSTEXPR bernoulli_distribution(RealType p_arg) explicit SPROUT_CONSTEXPR bernoulli_distribution(RealType p_arg)
: p_((SPROUT_ASSERT(p_arg >= RealType(0)), SPROUT_ASSERT(p_arg <= RealType(1)), p_arg)) : p_((SPROUT_ASSERT(p_arg >= RealType(0)), SPROUT_ASSERT(p_arg <= RealType(1)), p_arg))
{} {}
explicit SPROUT_CONSTEXPR bernoulli_distribution(param_type const& parm) explicit SPROUT_CONSTEXPR bernoulli_distribution(param_type const& parm) SPROUT_NOEXCEPT
: p_(parm.p()) : p_(parm.p())
{} {}
SPROUT_CONSTEXPR RealType p() const SPROUT_NOEXCEPT { SPROUT_CONSTEXPR RealType p() const SPROUT_NOEXCEPT {
@ -113,12 +113,28 @@ namespace sprout {
p_ = parm.p(); p_ = parm.p();
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
typedef typename Engine::result_type base_result;
return p_ == RealType(0)
? false
: RealType(static_cast<base_result>(eng()) - eng.min()) <= p_ * RealType(eng.max() - eng.min())
;
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, bernoulli_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, bernoulli_distribution> const operator()(Engine const& eng) const {
return p_ == RealType(0) return p_ == RealType(0)
? sprout::random::random_result<Engine, bernoulli_distribution>(false, eng, *this) ? sprout::random::random_result<Engine, bernoulli_distribution>(false, eng, *this)
: generate<Engine>(eng()) : generate<Engine>(eng())
; ;
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return bernoulli_distribution(parm)(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, bernoulli_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return bernoulli_distribution(parm)(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -210,6 +210,91 @@ namespace sprout {
return m_ < 11; return m_ < 11;
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type
invert(IntType t, RealType p, Engine& eng) const {
RealType q = 1 - p;
RealType s = p / q;
RealType a = (t + 1) * s;
RealType r = q_n_;
RealType u = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng));
IntType x = 0;
while (u > r) {
u = u - r;
++x;
r = ((a / x) - s) * r;
}
return x;
}
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type
generate(Engine& eng) const {
for (; ; ) {
RealType u = RealType();
RealType v = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng));
if (v <= btrd_.u_rv_r) {
RealType u = v / btrd_.v_r - RealType(0.43);
return static_cast<result_type>(sprout::math::floor((2 * btrd_.a / (RealType(0.5) - sprout::math::abs(u)) + btrd_.b) * u + btrd_.c));
}
if (v >= btrd_.v_r) {
u = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng)) - RealType(0.5);
} else {
u = v / btrd_.v_r - RealType(0.93);
u = ((u < 0) ? -RealType(0.5) : RealType(0.5)) - u;
v = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng)) * btrd_.v_r;
}
RealType us = RealType(0.5) - sprout::math::abs(u);
IntType k = static_cast<IntType>(sprout::math::floor((2 * btrd_.a / us + btrd_.b) * u + btrd_.c));
if (k < 0 || k > t_) {
continue;
}
v = v * btrd_.alpha / (btrd_.a / (us * us) + btrd_.b);
RealType km = sprout::math::abs(k - m_);
if (km <= 15) {
RealType f = RealType(1);
if (m_ < k) {
IntType i = m_;
do {
++i;
f = f * (btrd_.nr / i - btrd_.r);
} while (i != k);
} else if (m_ > k) {
IntType i = k;
do {
++i;
v = v * (btrd_.nr / i - btrd_.r);
} while (i != m_);
}
if (v <= f) {
return k;
} else {
continue;
}
} else {
v = sprout::math::log(v);
RealType rho = (km / btrd_.npq) * (((km / RealType(3) + RealType(0.625)) * km + RealType(1) / 6) / btrd_.npq + RealType(0.5));
RealType t = -km * km / (2 * btrd_.npq);
if (v < t - rho) {
return k;
}
if (v > t + rho) {
continue;
}
IntType nm = t_ - m_ + 1;
RealType h = (m_ + RealType(0.5)) * sprout::math::log((m_ + 1) / (btrd_.r * nm)) + fc(m_) + fc(t_ - m_);
IntType nk = t_ - k + 1;
if (v <= h + (t_ + 1) * sprout::math::log(static_cast<RealType>(nm) / nk)
+ (k + RealType(0.5)) * sprout::math::log(nk * btrd_.r / (k + 1)) - fc(k) - fc(t_ - k)
)
{
return k;
} else {
continue;
}
}
}
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, binomial_distribution> SPROUT_CONSTEXPR sprout::random::random_result<Engine, binomial_distribution>
invert_4(Engine const& eng, RealType u, RealType q, RealType s, RealType a, RealType r, IntType x = 0) const { invert_4(Engine const& eng, RealType u, RealType q, RealType s, RealType a, RealType r, IntType x = 0) const {
return u > r return u > r
@ -351,7 +436,7 @@ namespace sprout {
? generate_7<D + 1>(eng, v, k) ? generate_7<D + 1>(eng, v, k)
: generate_8<D + 1>( : generate_8<D + 1>(
eng, sprout::math::log(v), k, eng, sprout::math::log(v), k,
(km / btrd_.npq) * (((km / RealType(3.0) + RealType(0.625)) * km + RealType(1.0) / 6) / btrd_.npq + RealType(0.5)), (km / btrd_.npq) * (((km / RealType(3) + RealType(0.625)) * km + RealType(1) / 6) / btrd_.npq + RealType(0.5)),
-km * km / (2 * btrd_.npq)) -km * km / (2 * btrd_.npq))
; ;
} }
@ -649,6 +734,15 @@ namespace sprout {
init(); init();
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
return use_inversion() ? RealType(0.5) < p_
? t_ - invert(t_, 1 - p_, eng)
: invert(t_, p_, eng)
: RealType(0.5) < p_ ? t_ - generate(eng)
: generate(eng)
;
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, binomial_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, binomial_distribution> const operator()(Engine const& eng) const {
return use_inversion() ? RealType(0.5) < p_ return use_inversion() ? RealType(0.5) < p_
? invert2(t_, 1 - p_, eng) ? invert2(t_, 1 - p_, eng)
@ -657,6 +751,14 @@ namespace sprout {
: generate(eng) : generate(eng)
; ;
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return binomial_distribution(parm)(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, binomial_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return binomial_distribution(parm)(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -32,6 +32,16 @@ namespace sprout {
>::fast result_type; >::fast result_type;
private: private:
base_type rng_; base_type rng_;
private:
SPROUT_CONSTEXPR sprout::random::random_result<uniform_int_float> generate(
sprout::random::random_result<base_type> const& rnd
) const
{
return sprout::random::random_result<uniform_int_float>(
static_cast<result_type>(rnd.result() * (static_cast<base_result>(max()) + 1)),
uniform_int_float(rnd.engine())
);
}
public: public:
SPROUT_CONSTEXPR uniform_int_float() SPROUT_CONSTEXPR uniform_int_float()
: rng_() : rng_()
@ -59,16 +69,10 @@ namespace sprout {
SPROUT_CONSTEXPR base_type const& base() const { SPROUT_CONSTEXPR base_type const& base() const {
return rng_; return rng_;
} }
SPROUT_CONSTEXPR sprout::random::random_result<uniform_int_float> generate( SPROUT_CXX14_CONSTEXPR result_type operator()() {
sprout::random::random_result<base_type> const& rnd return static_cast<result_type>(static_cast<base_result>(rng_()) * static_cast<base_result>(max()) + 1);
) const
{
return sprout::random::random_result<uniform_int_float>(
static_cast<result_type>(rnd.result() * (static_cast<base_result>(max()) + 1)),
uniform_int_float(rnd.engine())
);
} }
SPROUT_CONSTEXPR sprout::random::random_result<uniform_int_float> operator()() const { SPROUT_CONSTEXPR sprout::random::random_result<uniform_int_float> const operator()() const {
return generate(rng_()); return generate(rng_());
} }
}; };

View file

@ -129,9 +129,23 @@ namespace sprout {
log_1mp_ = init_log_1mp(p_); log_1mp_ = init_log_1mp(p_);
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
return static_cast<result_type>(
sprout::math::floor(sprout::math::log(RealType(1) - static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng))) / log_1mp_)
);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, geometric_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, geometric_distribution> const operator()(Engine const& eng) const {
return generate(eng); return generate(eng);
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return geometric_distribution(parm)(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, geometric_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return geometric_distribution(parm)(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -206,9 +206,34 @@ namespace sprout {
valid_ = false; valid_ = false;
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) {
if (!valid_) {
r1_ = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng));
r2_ = static_cast<RealType>(sprout::random::uniform_01<RealType>()(eng));
cached_rho_ = sprout::math::sqrt(-result_type(2) * sprout::math::log(result_type(1) - r2_));
valid_ = true;
} else {
valid_ = false;
}
return cached_rho_
* (valid_
? sprout::math::cos(sprout::math::two_pi<result_type>() * r1_)
: sprout::math::sin(sprout::math::two_pi<result_type>() * r1_))
* sigma_ + mean_
;
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, normal_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, normal_distribution> const operator()(Engine const& eng) const {
return generate(eng); return generate(eng);
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return normal_distribution(parm)(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, normal_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return normal_distribution(parm)(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -121,8 +121,8 @@ namespace sprout {
} }
#endif #endif
public: public:
explicit SPROUT_CONSTEXPR uniform_01() {} uniform_01() = default;
explicit SPROUT_CONSTEXPR uniform_01(param_type const&) {} explicit SPROUT_CONSTEXPR uniform_01(param_type const&) SPROUT_NOEXCEPT {}
SPROUT_CONSTEXPR result_type min() const SPROUT_NOEXCEPT { SPROUT_CONSTEXPR result_type min() const SPROUT_NOEXCEPT {
return result_type(0); return result_type(0);
} }
@ -132,11 +132,35 @@ namespace sprout {
SPROUT_CONSTEXPR param_type param() const SPROUT_NOEXCEPT { SPROUT_CONSTEXPR param_type param() const SPROUT_NOEXCEPT {
return param_type(); return param_type();
} }
SPROUT_CXX14_CONSTEXPR void param(param_type const&) {} SPROUT_CXX14_CONSTEXPR void param(param_type const&) SPROUT_NOEXCEPT {}
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
for (; ; ) {
typedef typename Engine::result_type base_result;
result_type result = result_type(static_cast<base_result>(eng()) - eng.min()) * (
result_type(1) / (
result_type(eng.max() - eng.min()) + result_type(
std::numeric_limits<base_result>::is_integer ? 1 : 0
)
)
);
if (result < result_type(1)) {
return result;
}
}
}
template<typename Engine> template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01> const operator()(Engine const& eng) const {
return generate(eng, eng()); return generate(eng, eng());
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const&) const {
return operator()(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01> const operator()(Engine const& eng, param_type const&) const {
return operator()(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -28,6 +28,105 @@ namespace sprout {
Engine engine; Engine engine;
}; };
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_int(
Engine& eng, T min_value, T max_value, std::true_type
)
{
typedef T result_type;
typedef typename std::make_unsigned<T>::type range_type;
typedef typename Engine::result_type base_result;
typedef typename std::make_unsigned<base_result>::type base_unsigned;
range_type const range = sprout::random::detail::subtract<result_type>()(max_value, min_value);
base_result const bmin = eng.min();
base_unsigned const brange = sprout::random::detail::subtract<base_result>()(eng.max(), eng.min());
if (range == 0) {
return min_value;
} else if (brange == range) {
base_unsigned v = sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), bmin);
return sprout::random::detail::add<base_unsigned, result_type>()(
static_cast<base_unsigned>(sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), bmin)),
min_value
);
} else if (brange < range) {
for(; ; ) {
range_type limit = range_type();
if (range == std::numeric_limits<range_type>::max()) {
limit = range / (range_type(brange) + 1);
if (range % (range_type(brange) + 1) == range_type(brange)) {
++limit;
}
} else {
limit = (range + 1) / (range_type(brange) + 1);
}
range_type result = range_type(0);
range_type mult = range_type(1);
while (mult <= limit) {
result += static_cast<range_type>(sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), bmin) * mult);
if (mult * range_type(brange) == range - mult + 1) {
return result;
}
mult *= range_type(brange) + range_type(1);
}
range_type result_increment = sprout::random::detail::generate_uniform_int(
eng,
static_cast<range_type>(0),
static_cast<range_type>(range / mult),
std::true_type()
);
if (std::numeric_limits<range_type>::max() / mult < result_increment) {
continue;
}
result_increment *= mult;
result += result_increment;
if (result < result_increment) {
continue;
}
if (result > range) {
continue;
}
return sprout::random::detail::add<range_type, result_type>()(result, min_value);
}
} else {
base_unsigned bucket_size = base_unsigned();
if (brange == std::numeric_limits<base_unsigned>::max()) {
bucket_size = brange / (static_cast<base_unsigned>(range) + 1);
if (brange % (static_cast<base_unsigned>(range) + 1) == static_cast<base_unsigned>(range)) {
++bucket_size;
}
} else {
bucket_size = (brange + 1) / (static_cast<base_unsigned>(range) + 1);
}
for(; ; ) {
base_unsigned result = sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), bmin) / bucket_size;
if (result <= static_cast<base_unsigned>(range)) {
return sprout::random::detail::add<base_unsigned, result_type>()(result, min_value);
}
}
}
}
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_int(
Engine& eng, T min_value, T max_value, std::false_type
)
{
sprout::random::detail::uniform_int_float<Engine> wrapper(eng);
return sprout::random::detail::generate_uniform_int(wrapper, min_value, max_value, std::true_type());
}
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_int(
Engine& eng, T min_value, T max_value
)
{
return sprout::random::detail::generate_uniform_int(
eng, min_value, max_value,
std::is_integral<typename Engine::result_type>()
);
}
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE #ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
template<int D = 16, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D = 16, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_int_result<T, Engine> SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_int_result<T, Engine>
@ -760,7 +859,7 @@ namespace sprout {
); );
} }
public: public:
SPROUT_CONSTEXPR uniform_int_distribution() SPROUT_CONSTEXPR uniform_int_distribution() SPROUT_NOEXCEPT
: min_(0) : min_(0)
, max_(9) , max_(9)
{} {}
@ -768,7 +867,7 @@ namespace sprout {
: min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg)) : min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg))
, max_(max_arg) , max_(max_arg)
{} {}
explicit SPROUT_CONSTEXPR uniform_int_distribution(param_type const& parm) explicit SPROUT_CONSTEXPR uniform_int_distribution(param_type const& parm) SPROUT_NOEXCEPT
: min_(parm.a()) : min_(parm.a())
, max_(parm.b()) , max_(parm.b())
{} {}
@ -792,9 +891,21 @@ namespace sprout {
max_ = parm.b(); max_ = parm.b();
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
return sprout::random::detail::generate_uniform_int(eng, min_, max_);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_int_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_int_distribution> const operator()(Engine const& eng) const {
return generate<Engine>(sprout::random::detail::generate_uniform_int(eng, min_, max_)); return generate<Engine>(sprout::random::detail::generate_uniform_int(eng, min_, max_));
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return sprout::random::detail::generate_uniform_int(eng, parm.a(), parm.b());
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_int_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return generate<Engine>(sprout::random::detail::generate_uniform_int(eng, parm.a(), parm.b()));
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -26,21 +26,73 @@ namespace sprout {
Engine engine; Engine engine;
}; };
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_real(
Engine& eng, T min_value, T max_value,
std::false_type
)
{
for(;;) {
typedef T result_type;
typedef typename Engine::result_type base_result;
result_type numerator = static_cast<T>(static_cast<base_result>(eng()) - eng.min());
result_type divisor = static_cast<T>(eng.max() - eng.min());
SPROUT_ASSERT(divisor > 0);
SPROUT_ASSERT(numerator >= 0 && numerator <= divisor);
result_type result = numerator / divisor * (max_value - min_value) + min_value;
if (result < max_value) {
return result;
}
}
}
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_real(
Engine& eng, T min_value, T max_value,
std::true_type
)
{
for(;;) {
typedef T result_type;
typedef typename Engine::result_type base_result;
result_type numerator = static_cast<T>(sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), eng.min()));
result_type divisor = static_cast<T>(sprout::random::detail::subtract<base_result>()(eng.max(), eng.min())) + 1;
SPROUT_ASSERT(divisor > 0);
SPROUT_ASSERT(numerator >= 0 && numerator <= divisor);
result_type result = numerator / divisor * (max_value - min_value) + min_value;
if (result < max_value) {
return result;
}
}
}
template<typename Engine, typename T>
inline SPROUT_CXX14_CONSTEXPR T
generate_uniform_real(
Engine& eng, T min_value, T max_value
)
{
return sprout::random::detail::generate_uniform_real(
eng, min_value, max_value,
typename std::is_integral<typename Engine::result_type>::type()
);
}
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE #ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_3( generate_uniform_real_false_3(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -53,7 +105,7 @@ namespace sprout {
; ;
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_3( generate_uniform_real_false_3(
Engine const&, Engine const&,
T, T, T, T,
@ -63,7 +115,7 @@ namespace sprout {
return sprout::throw_recursive_function_template_instantiation_exeeded(); return sprout::throw_recursive_function_template_instantiation_exeeded();
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_2( generate_uniform_real_false_2(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -79,7 +131,7 @@ namespace sprout {
; ;
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_2( generate_uniform_real_false_2(
Engine const&, Engine const&,
T, T, T, T,
@ -89,7 +141,7 @@ namespace sprout {
return sprout::throw_recursive_function_template_instantiation_exeeded(); return sprout::throw_recursive_function_template_instantiation_exeeded();
} }
template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(D)> template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
@ -102,7 +154,7 @@ namespace sprout {
); );
} }
template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(D)> template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const&, EngineResult const&,
T, T T, T
@ -111,19 +163,19 @@ namespace sprout {
return sprout::throw_recursive_function_template_instantiation_exeeded(); return sprout::throw_recursive_function_template_instantiation_exeeded();
} }
template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D = 16, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_3( generate_uniform_real_true_3(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -136,7 +188,7 @@ namespace sprout {
; ;
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_3( generate_uniform_real_true_3(
Engine const&, Engine const&,
T, T, T, T,
@ -146,7 +198,7 @@ namespace sprout {
return sprout::throw_recursive_function_template_instantiation_exeeded(); return sprout::throw_recursive_function_template_instantiation_exeeded();
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_2( generate_uniform_real_true_2(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -162,7 +214,7 @@ namespace sprout {
; ;
} }
template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)> template<int D, typename Engine, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_2( generate_uniform_real_true_2(
Engine const&, Engine const&,
T, T, T, T,
@ -172,7 +224,7 @@ namespace sprout {
return sprout::throw_recursive_function_template_instantiation_exeeded(); return sprout::throw_recursive_function_template_instantiation_exeeded();
} }
template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(D)> template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
@ -187,7 +239,7 @@ namespace sprout {
); );
} }
template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(D)> template<int D, typename EngineResult, typename T, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(D)>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const&, EngineResult const&,
T, T T, T
@ -197,13 +249,13 @@ namespace sprout {
} }
#else #else
template<typename EngineResult, typename T> template<typename EngineResult, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_3( generate_uniform_real_false_3(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -216,7 +268,7 @@ namespace sprout {
; ;
} }
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_false_2( generate_uniform_real_false_2(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -232,7 +284,7 @@ namespace sprout {
; ;
} }
template<typename EngineResult, typename T> template<typename EngineResult, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_false_1( generate_uniform_real_false_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
@ -245,13 +297,13 @@ namespace sprout {
); );
} }
template<typename EngineResult, typename T> template<typename EngineResult, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
); );
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_3( generate_uniform_real_true_3(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -264,7 +316,7 @@ namespace sprout {
; ;
} }
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real_true_2( generate_uniform_real_true_2(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -280,7 +332,7 @@ namespace sprout {
; ;
} }
template<typename EngineResult, typename T> template<typename EngineResult, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, typename EngineResult::engine_type>
generate_uniform_real_true_1( generate_uniform_real_true_1(
EngineResult const& rnd, EngineResult const& rnd,
T min_value, T max_value T min_value, T max_value
@ -296,7 +348,7 @@ namespace sprout {
} }
#endif #endif
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real( generate_uniform_real(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -309,7 +361,7 @@ namespace sprout {
); );
} }
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real( generate_uniform_real(
Engine const& eng, Engine const& eng,
T min_value, T max_value, T min_value, T max_value,
@ -322,7 +374,7 @@ namespace sprout {
); );
} }
template<typename Engine, typename T> template<typename Engine, typename T>
SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine> inline SPROUT_CONSTEXPR sprout::random::detail::generate_uniform_real_result<T, Engine>
generate_uniform_real( generate_uniform_real(
Engine const& eng, Engine const& eng,
T min_value, T max_value T min_value, T max_value
@ -331,7 +383,7 @@ namespace sprout {
return sprout::random::detail::generate_uniform_real( return sprout::random::detail::generate_uniform_real(
eng, eng,
min_value, max_value, min_value, max_value,
std::is_integral<typename Engine::result_type>() typename std::is_integral<typename Engine::result_type>::type()
); );
} }
} // namespace detail } // namespace detail
@ -414,7 +466,7 @@ namespace sprout {
); );
} }
public: public:
SPROUT_CONSTEXPR uniform_real_distribution() SPROUT_CONSTEXPR uniform_real_distribution() SPROUT_NOEXCEPT
: min_(RealType(0.0)) : min_(RealType(0.0))
, max_(RealType(1.0)) , max_(RealType(1.0))
{} {}
@ -422,7 +474,7 @@ namespace sprout {
: min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg)) : min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg))
, max_(max_arg) , max_(max_arg)
{} {}
explicit SPROUT_CONSTEXPR uniform_real_distribution(param_type const& parm) explicit SPROUT_CONSTEXPR uniform_real_distribution(param_type const& parm) SPROUT_NOEXCEPT
: min_(parm.a()) : min_(parm.a())
, max_(parm.b()) , max_(parm.b())
{} {}
@ -446,9 +498,21 @@ namespace sprout {
max_ = parm.b(); max_ = parm.b();
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
return sprout::random::detail::generate_uniform_real(eng, min_, max_);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_real_distribution> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_real_distribution> const operator()(Engine const& eng) const {
return generate<Engine>(sprout::random::detail::generate_uniform_real(eng, min_, max_)); return generate<Engine>(sprout::random::detail::generate_uniform_real(eng, min_, max_));
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
return sprout::random::detail::generate_uniform_real(eng, parm.a(), parm.b());
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_real_distribution> const operator()(Engine const& eng, param_type const& parm) const {
return generate<Engine>(sprout::random::detail::generate_uniform_real(eng, parm.a(), parm.b()));
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,

View file

@ -89,6 +89,39 @@ namespace sprout {
IntType min_; IntType min_;
IntType max_; IntType max_;
private: private:
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type generate(
Engine& eng,
std::true_type
) const
{
typedef typename Engine::result_type base_result;
typedef typename std::make_unsigned<base_result>::type base_unsigned;
typedef typename std::make_unsigned<result_type>::type range_type;
range_type range = sprout::random::detail::subtract<result_type>()(max_, min_);
base_unsigned base_range = sprout::random::detail::subtract<result_type>()(eng.max(), eng.min());
base_unsigned val = sprout::random::detail::subtract<base_result>()(static_cast<base_result>(eng()), eng.min());
return range >= base_range
? sprout::random::detail::add<range_type, result_type>()(static_cast<range_type>(val), min_)
: sprout::random::detail::add<range_type, result_type>()(static_cast<range_type>(val % (static_cast<base_result>(range) + 1)), min_)
;
}
template<class Engine>
SPROUT_CXX14_CONSTEXPR result_type generate(
Engine& eng,
std::false_type
) const
{
typedef typename Engine::result_type base_result;
typedef typename std::make_unsigned<result_type>::type range_type;
range_type range = sprout::random::detail::subtract<result_type>()(max_, min_);
base_result val = sprout::random::uniform_01<base_result>()(eng);
range_type offset = static_cast<range_type>(val * (static_cast<base_result>(range) + 1));
return offset > range
? max_
: sprout::random::detail::add<range_type, result_type>()(offset, min_)
;
}
template<typename Engine, typename EngineResult, typename RangeType, typename BaseUnsigned> template<typename Engine, typename EngineResult, typename RangeType, typename BaseUnsigned>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_smallint> generate_true_2( SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_smallint> generate_true_2(
Engine const&, Engine const&,
@ -176,8 +209,8 @@ namespace sprout {
return generate_false_2( return generate_false_2(
eng, eng,
rnd, rnd,
RangeType(sprout::random::detail::subtract<result_type>()(max_, min_)), static_cast<RangeType>(sprout::random::detail::subtract<result_type>()(max_, min_)),
RangeType(static_cast<RangeType>(rnd.result() * (static_cast<base_result>(range) + 1))) static_cast<RangeType>(rnd.result() * (static_cast<base_result>(range) + 1))
); );
} }
template<class Engine> template<class Engine>
@ -191,11 +224,11 @@ namespace sprout {
return generate_false_1( return generate_false_1(
eng, eng,
sprout::random::uniform_01<base_result>()(eng), sprout::random::uniform_01<base_result>()(eng),
range_type(sprout::random::detail::subtract<result_type>()(max_, min_)) static_cast<range_type>(sprout::random::detail::subtract<result_type>()(max_, min_))
); );
} }
public: public:
SPROUT_CONSTEXPR uniform_smallint() SPROUT_CONSTEXPR uniform_smallint() SPROUT_NOEXCEPT
: min_(0) : min_(0)
, max_(9) , max_(9)
{} {}
@ -203,7 +236,7 @@ namespace sprout {
: min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg)) : min_((SPROUT_ASSERT(min_arg <= max_arg), min_arg))
, max_(max_arg) , max_(max_arg)
{} {}
explicit SPROUT_CONSTEXPR uniform_smallint(param_type const& parm) explicit SPROUT_CONSTEXPR uniform_smallint(param_type const& parm) SPROUT_NOEXCEPT
: min_(parm.a()) : min_(parm.a())
, max_(parm.b()) , max_(parm.b())
{} {}
@ -227,10 +260,25 @@ namespace sprout {
max_ = parm.b(); max_ = parm.b();
} }
template<typename Engine> template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng) const {
typedef typename Engine::result_type base_result;
return generate(eng, typename std::is_integral<base_result>::type());
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_smallint> const operator()(Engine const& eng) const { SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_smallint> const operator()(Engine const& eng) const {
typedef typename Engine::result_type base_result; typedef typename Engine::result_type base_result;
return generate(eng, typename std::is_integral<base_result>::type()); return generate(eng, typename std::is_integral<base_result>::type());
} }
template<typename Engine>
SPROUT_CXX14_CONSTEXPR result_type operator()(Engine& eng, param_type const& parm) const {
typedef typename Engine::result_type base_result;
return uniform_smallint(parm)(eng);
}
template<typename Engine>
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_smallint> const operator()(Engine const& eng, param_type const& parm) const {
typedef typename Engine::result_type base_result;
return uniform_smallint(parm)(eng);
}
template<typename Elem, typename Traits> template<typename Elem, typename Traits>
friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>( friend SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(
std::basic_istream<Elem, Traits>& lhs, std::basic_istream<Elem, Traits>& lhs,