blob: 339cbfccf73a7904915487eea8817728dc4b10e0 [file] [log] [blame]
// Boost common_factor_ct.hpp header file ----------------------------------//
// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP
#define BOOST_MATH_COMMON_FACTOR_CT_HPP
#include <boost/math_fwd.hpp> // self include
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
#include <boost/mpl/integral_c.hpp>
namespace boost
{
namespace math
{
// Implementation details --------------------------------------------------//
namespace detail
{
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Build GCD with Euclid's recursive algorithm
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd_helper_t
{
private:
BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 );
BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 );
#ifndef __BORLANDC__
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast<static_gcd_type>(Value)
#else
typedef static_gcd_helper_t self_type;
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
#endif
typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
#undef BOOST_DETAIL_GCD_HELPER_VAL
public:
BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value );
};
// Non-recursive case
template < static_gcd_type Value1 >
struct static_gcd_helper_t< Value1, 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
};
#else
// Use inner class template workaround from Peter Dimov
template < static_gcd_type Value1 >
struct static_gcd_helper2_t
{
template < static_gcd_type Value2 >
struct helper
{
BOOST_STATIC_CONSTANT( static_gcd_type, value
= static_gcd_helper2_t<Value2>::BOOST_NESTED_TEMPLATE
helper<Value1 % Value2>::value );
};
template < >
struct helper< 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
};
};
// Special case
template < >
struct static_gcd_helper2_t< 0UL >
{
template < static_gcd_type Value2 >
struct helper
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value2 );
};
};
// Build the GCD from the above template(s)
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd_helper_t
{
BOOST_STATIC_CONSTANT( static_gcd_type, value
= static_gcd_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
helper<Value2>::value );
};
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Build the LCM from the GCD
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm_helper_t
{
typedef static_gcd_helper_t<Value1, Value2> gcd_type;
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value
* Value2 );
};
// Special case for zero-GCD values
template < >
struct static_lcm_helper_t< 0UL, 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
};
#else
// Adapt GCD's inner class template workaround for LCM
template < static_gcd_type Value1 >
struct static_lcm_helper2_t
{
template < static_gcd_type Value2 >
struct helper
{
typedef static_gcd_helper_t<Value1, Value2> gcd_type;
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1
/ gcd_type::value * Value2 );
};
template < >
struct helper< 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
};
};
// Special case
template < >
struct static_lcm_helper2_t< 0UL >
{
template < static_gcd_type Value2 >
struct helper
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
};
};
// Build the LCM from the above template(s)
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm_helper_t
{
BOOST_STATIC_CONSTANT( static_gcd_type, value
= static_lcm_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
helper<Value2>::value );
};
#endif
} // namespace detail
// Compile-time greatest common divisor evaluator class declaration --------//
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd : public mpl::integral_c<static_gcd_type, (detail::static_gcd_helper_t<Value1, Value2>::value) >
{
}; // boost::math::static_gcd
// Compile-time least common multiple evaluator class declaration ----------//
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm : public mpl::integral_c<static_gcd_type, (detail::static_lcm_helper_t<Value1, Value2>::value) >
{
}; // boost::math::static_lcm
} // namespace math
} // namespace boost
#endif // BOOST_MATH_COMMON_FACTOR_CT_HPP