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