mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-12-23 21:25:49 +00:00
workaround for clang3.2 (gcd, uniform_01)
This commit is contained in:
parent
aca22bec98
commit
bf937bc508
5 changed files with 168 additions and 25 deletions
|
@ -21,8 +21,8 @@
|
||||||
# define SPROUT_NO_DELEGATING_CONSTRUCTORS
|
# define SPROUT_NO_DELEGATING_CONSTRUCTORS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#if (__has_feature(cxx_constexpr) && (__GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
#if !defined(SPROUT_NO_CONSTEXPR)
|
||||||
//# define SPROUT_HAS_CONSTEXPR_CMATH_FUNCTION
|
# define SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_CONFIG_COMPILER_CLANG_HPP
|
#endif // #ifndef SPROUT_CONFIG_COMPILER_CLANG_HPP
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/array.hpp>
|
#include <sprout/array.hpp>
|
||||||
#include <sprout/cstdlib/abs.hpp>
|
#include <sprout/cstdlib/abs.hpp>
|
||||||
|
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
|
||||||
|
# include <stdexcept>
|
||||||
|
# include <sprout/workaround/recursive_function_template.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
|
@ -31,28 +35,45 @@ namespace sprout {
|
||||||
sprout::math::detail::gcd_euclidean(a, b)
|
sprout::math::detail::gcd_euclidean(a, b)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
|
||||||
template<typename BuiltInUnsigned>
|
template<int D = 0, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
|
||||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which);
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which);
|
||||||
template<typename BuiltInUnsigned>
|
template<int D = 0, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which);
|
||||||
|
template<int D, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
|
||||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
gcd_binary_2_2(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
gcd_binary_2_2(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
return !(r[ which ] & 1u) ? sprout::math::detail::gcd_binary_2_2(
|
return r[which] ? sprout::math::detail::gcd_binary_2_1<D + 1>(shifts, r, which)
|
||||||
|
: r[!which] << shifts
|
||||||
|
;
|
||||||
|
}
|
||||||
|
template<int D, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_2(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
|
return throw std::runtime_error(SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE),
|
||||||
|
BuiltInUnsigned()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
template<int D, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(D)>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
|
return !(r[which] & 1u) ? sprout::math::detail::gcd_binary_2_1<D + 2>(
|
||||||
shifts,
|
shifts,
|
||||||
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] >> 1)}}
|
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] >> 1)}}
|
||||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] >> 1), r[1]}}
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] >> 1), r[1]}}
|
||||||
,
|
,
|
||||||
which
|
which
|
||||||
)
|
)
|
||||||
: r[!which] > r[which] ? sprout::math::detail::gcd_binary_2_1(
|
: r[!which] > r[which] ? sprout::math::detail::gcd_binary_2_2<D + 1>(
|
||||||
shifts,
|
shifts,
|
||||||
which ^ 1u ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
which ^ 1u ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||||
,
|
,
|
||||||
which ^ 1u
|
which ^ 1u
|
||||||
)
|
)
|
||||||
: sprout::math::detail::gcd_binary_2_1(
|
: sprout::math::detail::gcd_binary_2_2<D + 1>(
|
||||||
shifts,
|
shifts,
|
||||||
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||||
|
@ -61,18 +82,56 @@ namespace sprout {
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<typename BuiltInUnsigned>
|
template<int D, typename BuiltInUnsigned, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(D)>
|
||||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
return r[which] ? sprout::math::detail::gcd_binary_2_2(shifts, r, which)
|
return throw std::runtime_error(SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE),
|
||||||
|
BuiltInUnsigned()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<typename BuiltInUnsigned>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which);
|
||||||
|
template<typename BuiltInUnsigned>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_2(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
|
return r[which] ? sprout::math::detail::gcd_binary_2_1(shifts, r, which)
|
||||||
: r[!which] << shifts
|
: r[!which] << shifts
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
template<typename BuiltInUnsigned>
|
||||||
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
|
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||||
|
return !(r[which] & 1u) ? sprout::math::detail::gcd_binary_2_1(
|
||||||
|
shifts,
|
||||||
|
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] >> 1)}}
|
||||||
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] >> 1), r[1]}}
|
||||||
|
,
|
||||||
|
which
|
||||||
|
)
|
||||||
|
: r[!which] > r[which] ? sprout::math::detail::gcd_binary_2_2(
|
||||||
|
shifts,
|
||||||
|
which ^ 1u ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||||
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||||
|
,
|
||||||
|
which ^ 1u
|
||||||
|
)
|
||||||
|
: sprout::math::detail::gcd_binary_2_2(
|
||||||
|
shifts,
|
||||||
|
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||||
|
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||||
|
,
|
||||||
|
which
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
template<typename BuiltInUnsigned>
|
template<typename BuiltInUnsigned>
|
||||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||||
gcd_binary_1(BuiltInUnsigned u, BuiltInUnsigned v, unsigned shifts = 0) {
|
gcd_binary_1(BuiltInUnsigned u, BuiltInUnsigned v, unsigned shifts = 0) {
|
||||||
return (!(u & 1u) && !(v & 1u)) ? sprout::math::detail::gcd_binary_1(u >> 1, v >> 1, shifts + 1)
|
return (!(u & 1u) && !(v & 1u)) ? sprout::math::detail::gcd_binary_1(u >> 1, v >> 1, shifts + 1)
|
||||||
: sprout::math::detail::gcd_binary_2_2(
|
: sprout::math::detail::gcd_binary_2_1(
|
||||||
shifts, sprout::array<BuiltInUnsigned, 2>{{u, v}}, static_cast<bool>(u & 1u)
|
shifts, sprout::array<BuiltInUnsigned, 2>{{u, v}}, static_cast<bool>(u & 1u)
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/random/random_result.hpp>
|
#include <sprout/random/random_result.hpp>
|
||||||
|
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
|
||||||
|
# include <stdexcept>
|
||||||
|
# include <sprout/workaround/recursive_function_template.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace random {
|
namespace random {
|
||||||
|
@ -49,24 +53,57 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
template<typename Engine>
|
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
|
||||||
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01> generate_1(
|
template<int D, typename Engine, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
|
||||||
Engine const& eng,
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
sprout::random::random_result<Engine> const& rnd,
|
generate_1(Engine const& eng, sprout::random::random_result<Engine> const& rnd, result_type result) const {
|
||||||
result_type result
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return result < result_type(1)
|
return result < result_type(1)
|
||||||
? sprout::random::random_result<Engine, uniform_01>(result, rnd.engine(), *this)
|
? sprout::random::random_result<Engine, uniform_01>(result, rnd.engine(), *this)
|
||||||
: operator()(rnd.engine())
|
: generate<D + 1>(rnd.engine(), rnd.engine()())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
template<int D, typename Engine, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
|
||||||
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
|
generate_1(Engine const& eng, sprout::random::random_result<Engine> const& rnd, result_type result) const {
|
||||||
|
return throw std::runtime_error(SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE),
|
||||||
|
sprout::random::random_result<Engine, uniform_01>()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
template<int D = 0, typename Engine, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(D)>
|
||||||
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
|
generate(Engine const& eng, sprout::random::random_result<Engine> const& rnd) const {
|
||||||
|
typedef typename Engine::result_type base_result;
|
||||||
|
return generate_1<D + 1>(
|
||||||
|
eng,
|
||||||
|
rnd,
|
||||||
|
result_type(rnd.result() - eng.min()) * (
|
||||||
|
result_type(1) / (
|
||||||
|
result_type(eng.max() - eng.min()) + result_type(
|
||||||
|
std::numeric_limits<base_result>::is_integer ? 1 : 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
template<int D = 0, typename Engine, SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(D)>
|
||||||
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
|
generate(Engine const& eng, sprout::random::random_result<Engine> const& rnd) const {
|
||||||
|
return throw std::runtime_error(SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE),
|
||||||
|
sprout::random::random_result<Engine, uniform_01>()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<typename Engine>
|
||||||
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
|
generate_1(Engine const& eng, sprout::random::random_result<Engine> const& rnd, result_type result) const {
|
||||||
|
return result < result_type(1)
|
||||||
|
? sprout::random::random_result<Engine, uniform_01>(result, rnd.engine(), *this)
|
||||||
|
: generate(rnd.engine(), rnd.engine()())
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<typename Engine>
|
template<typename Engine>
|
||||||
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01> generate(
|
SPROUT_CONSTEXPR sprout::random::random_result<Engine, uniform_01>
|
||||||
Engine const& eng,
|
generate(Engine const& eng, sprout::random::random_result<Engine> const& rnd) const {
|
||||||
sprout::random::random_result<Engine> const& rnd
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
typedef typename Engine::result_type base_result;
|
typedef typename Engine::result_type base_result;
|
||||||
return generate_1(
|
return generate_1(
|
||||||
eng,
|
eng,
|
||||||
|
@ -80,6 +117,7 @@ namespace sprout {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
explicit SPROUT_CONSTEXPR uniform_01()
|
explicit SPROUT_CONSTEXPR uniform_01()
|
||||||
{}
|
{}
|
||||||
|
|
7
sprout/workaround.hpp
Normal file
7
sprout/workaround.hpp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef SPROUT_WORKAROUND_HPP
|
||||||
|
#define SPROUT_WORKAROUND_HPP
|
||||||
|
|
||||||
|
#include <sprout/config.hpp>
|
||||||
|
#include <sprout/workaround/recursive_function_template.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef SPROUT_WORKAROUND_HPP
|
39
sprout/workaround/recursive_function_template.hpp
Normal file
39
sprout/workaround/recursive_function_template.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef SPROUT_WORKAROUND_RECURSIVE_FUNCTION_TEMPLATE_HPP
|
||||||
|
#define SPROUT_WORKAROUND_RECURSIVE_FUNCTION_TEMPLATE_HPP
|
||||||
|
|
||||||
|
#include <sprout/config.hpp>
|
||||||
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
#include <sprout/preprocessor/stringize.hpp>
|
||||||
|
|
||||||
|
//
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT
|
||||||
|
//
|
||||||
|
#ifndef SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT
|
||||||
|
# define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL
|
||||||
|
//
|
||||||
|
#define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(depth) \
|
||||||
|
typename sprout::enabler_if<((depth) < SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT - 1)>::type
|
||||||
|
#define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(depth) \
|
||||||
|
typename sprout::enabler_if<((depth) >= SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT - 1)>::type
|
||||||
|
|
||||||
|
//
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK
|
||||||
|
//
|
||||||
|
#define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE(depth) \
|
||||||
|
SPROUT_RECURSIVE_FUNCTION_TEMPLATE_CONTINUE_DECL(depth) = sprout::enabler
|
||||||
|
#define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK(depth) \
|
||||||
|
SPROUT_RECURSIVE_FUNCTION_TEMPLATE_BREAK_DECL(depth) = sprout::enabler
|
||||||
|
|
||||||
|
//
|
||||||
|
// SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE
|
||||||
|
//
|
||||||
|
#define SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_EXCEEDED_MESSAGE \
|
||||||
|
"recursive template instantiation exceeded maximum depth of " SPROUT_PP_STRINGIZE(SPROUT_RECURSIVE_FUNCTION_TEMPLATE_INSTANTIATION_LIMIT)
|
||||||
|
|
||||||
|
#endif // #ifndef SPROUT_WORKAROUND_RECURSIVE_FUNCTION_TEMPLATE_HPP
|
Loading…
Reference in a new issue