workaroud for clang3.2 (inversive_congruential)

This commit is contained in:
bolero-MURAKAMI 2012-11-14 11:22:05 +09:00
parent d39f4abe0f
commit b9121b8850
4 changed files with 94 additions and 12 deletions

View file

@ -72,13 +72,6 @@ namespace sprout {
: r : r
; ;
} }
template<typename Container>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Container>::type
swap_lr(
Container const& cont,
typename sprout::container_traits<Container>::difference_type l,
typename sprout::container_traits<Container>::difference_type r
);
template<typename Container, typename Compare> template<typename Container, typename Compare>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Container>::type inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Container>::type
sort_part_l( sort_part_l(

View file

@ -5,6 +5,9 @@
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
#include <sprout/config.hpp> #include <sprout/config.hpp>
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
# include <sprout/workaround/recursive_function_template.hpp>
#endif
namespace sprout { namespace sprout {
namespace random { namespace random {
@ -51,6 +54,84 @@ namespace sprout {
static SPROUT_CONSTEXPR unsigned_type unsigned_m() { static SPROUT_CONSTEXPR unsigned_type unsigned_m() {
return m == 0 ? unsigned_type((std::numeric_limits<IntType>::max)()) + 1 : unsigned_type(m); return m == 0 ? unsigned_type((std::numeric_limits<IntType>::max)()) + 1 : unsigned_type(m);
} }
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return n == 0 ? m - l1 : invert_euclidian_1<D + 1>(c, l1, l2, n, p);
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_2(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return p == 0 ? l2 : invert_euclidian_3<D + 1>(c, l1, l2 + (n / p) * l1, n - (n / p) * p, p);
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_2(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return invert_euclidian_2<D + 1>(c, l1 + (p / n) * l2, l2, n, p - (p / n) * n);
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D = 16, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian(IntType c) {
return c > 0
? c == 1 ? 1 : invert_euclidian_1<D + 1>(c, 0, 1, c, m)
: throw std::domain_error("const_mod<>: domain error (c > 0)")
;
}
template<int D = 16, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian(IntType c) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return n == 0 ? m - l1 : invert_euclidian0_2<D + 1>(c, l1 + (p / n) * l2, l2, n, p - (p / n) * n);
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_2(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return p == 0 ? l2 : invert_euclidian0_3<D + 1>(c, l1, l2 + (n / p) * l1, n - (n / p) * p, p);
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_2(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return std::numeric_limits<IntType>::max() % n != n - 1
? invert_euclidian0_2<D + 1>(
c, l1 + (std::numeric_limits<IntType>::max() / n) * l2, l2, n,
std::numeric_limits<IntType>::max() - (std::numeric_limits<IntType>::max() / n) * n + 1
)
: throw std::domain_error("const_mod<>: domain error (numeric_limits<IntType>::max() % n != n - 1)")
;
}
template<int D, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
template<int D = 16, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0(IntType c) {
return c > 0
? c == 1 ? 1 : invert_euclidian0_1<D + 1>(c, 0, 1, c, m)
: throw std::domain_error("const_mod<>: domain error (c > 0)")
;
}
template<int D = 16, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
static SPROUT_CONSTEXPR IntType invert_euclidian0(IntType c) {
return sprout::throw_recursive_function_template_instantiation_exeeded();
}
#else
static SPROUT_CONSTEXPR IntType invert_euclidian_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) { static SPROUT_CONSTEXPR IntType invert_euclidian_3(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return n == 0 ? m - l1 : invert_euclidian_1(c, l1, l2, n, p); return n == 0 ? m - l1 : invert_euclidian_1(c, l1, l2, n, p);
} }
@ -74,7 +155,10 @@ namespace sprout {
} }
static SPROUT_CONSTEXPR IntType invert_euclidian0_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) { static SPROUT_CONSTEXPR IntType invert_euclidian0_1(IntType c, IntType l1, IntType l2, IntType n, IntType p) {
return std::numeric_limits<IntType>::max() % n != n - 1 return std::numeric_limits<IntType>::max() % n != n - 1
? invert_euclidian0_2(c, l1 + (std::numeric_limits<IntType>::max() / n) * l2, l2, n, std::numeric_limits<IntType>::max() - (std::numeric_limits<IntType>::max() / n) * n + 1) ? invert_euclidian0_2(
c, l1 + (std::numeric_limits<IntType>::max() / n) * l2, l2, n,
std::numeric_limits<IntType>::max() - (std::numeric_limits<IntType>::max() / n) * n + 1
)
: throw std::domain_error("const_mod<>: domain error (numeric_limits<IntType>::max() % n != n - 1)") : throw std::domain_error("const_mod<>: domain error (numeric_limits<IntType>::max() % n != n - 1)")
; ;
} }
@ -84,6 +168,7 @@ namespace sprout {
: throw std::domain_error("const_mod<>: domain error (c > 0)") : throw std::domain_error("const_mod<>: domain error (c > 0)")
; ;
} }
#endif
public: public:
static SPROUT_CONSTEXPR IntType apply(IntType x) { static SPROUT_CONSTEXPR IntType apply(IntType x) {
return ((unsigned_m() - 1) & unsigned_m()) == 0 return ((unsigned_m() - 1) & unsigned_m()) == 0

View file

@ -58,7 +58,8 @@ namespace sprout {
SPROUT_CONSTEXPR inversive_congruential_engine(IntType const& x, private_constructor_tag) SPROUT_CONSTEXPR inversive_congruential_engine(IntType const& x, private_constructor_tag)
: x_(x) : x_(x)
{} {}
SPROUT_CONSTEXPR sprout::random::random_result<inversive_congruential_engine> generate(result_type result) const { SPROUT_CONSTEXPR sprout::random::random_result<inversive_congruential_engine>
generate(result_type result) const {
return sprout::random::random_result<inversive_congruential_engine>( return sprout::random::random_result<inversive_congruential_engine>(
result, result,
inversive_congruential_engine(result, private_constructor_tag()) inversive_congruential_engine(result, private_constructor_tag())

View file

@ -85,7 +85,8 @@ namespace sprout {
: member_type{rng, v, y} : member_type{rng, v, y}
{} {}
template<typename Random, typename BaseUnsigned> template<typename Random, typename BaseUnsigned>
SPROUT_CONSTEXPR sprout::random::random_result<shuffle_order_engine> generate_1(Random const& rnd, BaseUnsigned j) const { SPROUT_CONSTEXPR sprout::random::random_result<shuffle_order_engine>
generate_1(Random const& rnd, BaseUnsigned j) const {
return sprout::random::random_result<shuffle_order_engine>( return sprout::random::random_result<shuffle_order_engine>(
v_[j], v_[j],
shuffle_order_engine( shuffle_order_engine(
@ -97,12 +98,14 @@ namespace sprout {
); );
} }
template<typename BaseUnsigned> template<typename BaseUnsigned>
SPROUT_CONSTEXPR sprout::random::random_result<shuffle_order_engine> generate(BaseUnsigned brange, BaseUnsigned off) const { SPROUT_CONSTEXPR sprout::random::random_result<shuffle_order_engine>
generate(BaseUnsigned brange, BaseUnsigned off) const {
return generate_1( return generate_1(
rng_(), rng_(),
k == 1 ? BaseUnsigned(0) k == 1 ? BaseUnsigned(0)
: brange < std::numeric_limits<BaseUnsigned>::max() / k ? BaseUnsigned(k * off / (brange + 1)) : brange < std::numeric_limits<BaseUnsigned>::max() / k ? BaseUnsigned(k * off / (brange + 1))
: brange < std::numeric_limits<std::uintmax_t>::max() / k ? static_cast<BaseUnsigned>(static_cast<std::uintmax_t>(off) * k / (static_cast<std::uintmax_t>(brange) + 1)) : brange < std::numeric_limits<std::uintmax_t>::max() / k
? static_cast<BaseUnsigned>(static_cast<std::uintmax_t>(off) * k / (static_cast<std::uintmax_t>(brange) + 1))
//: static_cast<BaseUnsigned>(sprout::random::detail::muldiv(off, k, static_cast<std::uintmax_t>(brange) + 1)) // ??? //: static_cast<BaseUnsigned>(sprout::random::detail::muldiv(off, k, static_cast<std::uintmax_t>(brange) + 1)) // ???
: throw std::domain_error("shuffle_order_engine<>: Sorry, not implemented.") : throw std::domain_error("shuffle_order_engine<>: Sorry, not implemented.")
); );