workaround for clang3.2 (gcd, uniform_01)

This commit is contained in:
bolero-MURAKAMI 2012-11-12 13:29:56 +09:00
parent aca22bec98
commit bf937bc508
5 changed files with 168 additions and 25 deletions

View file

@ -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

View file

@ -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)
) )
; ;

View file

@ -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
View 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

View 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