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