From 56bd3fd0b34e8eb75d45a072836e5f3ff4b46929 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Tue, 2 Jul 2002 07:51:48 +0000 Subject: [PATCH] Moved the Compile-Time and Run-Time components to separate headers [SVN r14272] --- include/boost/math/common_factor_ct.hpp | 188 +++++++++++ include/boost/math/common_factor_rt.hpp | 408 ++++++++++++++++++++++++ 2 files changed, 596 insertions(+) create mode 100644 include/boost/math/common_factor_ct.hpp create mode 100644 include/boost/math/common_factor_rt.hpp diff --git a/include/boost/math/common_factor_ct.hpp b/include/boost/math/common_factor_ct.hpp new file mode 100644 index 0000000..d116c4b --- /dev/null +++ b/include/boost/math/common_factor_ct.hpp @@ -0,0 +1,188 @@ +// Boost common_factor_ct.hpp header file ----------------------------------// + +// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002. Permission to +// copy, use, modify, sell and distribute this software is granted provided +// this copyright notice appears in all copies. This software is provided "as +// is" without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// 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 // self include + +#include // for BOOST_STATIC_CONSTANT, etc. + + +namespace boost +{ +namespace math +{ + + +// Implementation details --------------------------------------------------// + +namespace detail +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // Build GCD with Euclid's recursive algorithm + template < unsigned long Value1, unsigned long Value2 > + struct static_gcd_helper_t + { + private: + BOOST_STATIC_CONSTANT( unsigned long, new_value1 = Value2 ); + BOOST_STATIC_CONSTANT( unsigned long, new_value2 = Value1 % Value2 ); + + #ifndef __BORLANDC__ + #define BOOST_DETAIL_GCD_HELPER_VAL(Value) 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( unsigned long, value = next_step_type::value ); + }; + + // Non-recursive case + template < unsigned long Value1 > + struct static_gcd_helper_t< Value1, 0UL > + { + BOOST_STATIC_CONSTANT( unsigned long, value = Value1 ); + }; +#else + // Use inner class template workaround from Peter Dimov + template < unsigned long Value1 > + struct static_gcd_helper2_t + { + template < unsigned long Value2 > + struct helper + { + BOOST_STATIC_CONSTANT( unsigned long, value + = static_gcd_helper2_t::helper::value ); + }; + + template < > + struct helper< 0UL > + { + BOOST_STATIC_CONSTANT( unsigned long, value = Value1 ); + }; + }; + + // Special case + template < > + struct static_gcd_helper2_t< 0UL > + { + template < unsigned long Value2 > + struct helper + { + BOOST_STATIC_CONSTANT( unsigned long, value = Value2 ); + }; + }; + + // Build the GCD from the above template(s) + template < unsigned long Value1, unsigned long Value2 > + struct static_gcd_helper_t + { + BOOST_STATIC_CONSTANT( unsigned long, value + = static_gcd_helper2_t::BOOST_NESTED_TEMPLATE + helper::value ); + }; +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // Build the LCM from the GCD + template < unsigned long Value1, unsigned long Value2 > + struct static_lcm_helper_t + { + typedef static_gcd_helper_t gcd_type; + + BOOST_STATIC_CONSTANT( unsigned long, value = Value1 / gcd_type::value + * Value2 ); + }; + + // Special case for zero-GCD values + template < > + struct static_lcm_helper_t< 0UL, 0UL > + { + BOOST_STATIC_CONSTANT( unsigned long, value = 0UL ); + }; +#else + // Adapt GCD's inner class template workaround for LCM + template < unsigned long Value1 > + struct static_lcm_helper2_t + { + template < unsigned long Value2 > + struct helper + { + typedef static_gcd_helper_t gcd_type; + + BOOST_STATIC_CONSTANT( unsigned long, value = Value1 + / gcd_type::value * Value2 ); + }; + + template < > + struct helper< 0UL > + { + BOOST_STATIC_CONSTANT( unsigned long, value = 0UL ); + }; + }; + + // Special case + template < > + struct static_lcm_helper2_t< 0UL > + { + template < unsigned long Value2 > + struct helper + { + BOOST_STATIC_CONSTANT( unsigned long, value = 0UL ); + }; + }; + + // Build the LCM from the above template(s) + template < unsigned long Value1, unsigned long Value2 > + struct static_lcm_helper_t + { + BOOST_STATIC_CONSTANT( unsigned long, value + = static_lcm_helper2_t::BOOST_NESTED_TEMPLATE + helper::value ); + }; +#endif + +} // namespace detail + + +// Compile-time greatest common divisor evaluator class declaration --------// + +template < unsigned long Value1, unsigned long Value2 > +struct static_gcd +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (detail::static_gcd_helper_t::value) ); + +}; // boost::math::static_gcd + + +// Compile-time least common multiple evaluator class declaration ----------// + +template < unsigned long Value1, unsigned long Value2 > +struct static_lcm +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (detail::static_lcm_helper_t::value) ); + +}; // boost::math::static_lcm + + +} // namespace math +} // namespace boost + + +#endif // BOOST_MATH_COMMON_FACTOR_CT_HPP diff --git a/include/boost/math/common_factor_rt.hpp b/include/boost/math/common_factor_rt.hpp new file mode 100644 index 0000000..5b8cd45 --- /dev/null +++ b/include/boost/math/common_factor_rt.hpp @@ -0,0 +1,408 @@ +// Boost common_factor_rt.hpp header file ----------------------------------// + +// (C) Copyright Daryle Walker and Paul Moore 2001-2002. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its suitability +// for any purpose. + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP +#define BOOST_MATH_COMMON_FACTOR_RT_HPP + +#include // self include + +#include // for BOOST_NESTED_TEMPLATE, etc. +#include // for std::numeric_limits + + +namespace boost +{ +namespace math +{ + + +// Forward declarations for function templates -----------------------------// + +template < typename IntegerType > + IntegerType gcd( IntegerType const &a, IntegerType const &b ); + +template < typename IntegerType > + IntegerType lcm( IntegerType const &a, IntegerType const &b ); + + +// Greatest common divisor evaluator class declaration ---------------------// + +template < typename IntegerType > +class gcd_evaluator +{ +public: + // Types + typedef IntegerType result_type, first_argument_type, second_argument_type; + + // Function object interface + result_type operator ()( first_argument_type const &a, + second_argument_type const &b ) const; + +}; // boost::math::gcd_evaluator + + +// Least common multiple evaluator class declaration -----------------------// + +template < typename IntegerType > +class lcm_evaluator +{ +public: + // Types + typedef IntegerType result_type, first_argument_type, second_argument_type; + + // Function object interface + result_type operator ()( first_argument_type const &a, + second_argument_type const &b ) const; + +}; // boost::math::lcm_evaluator + + +// Implementation details --------------------------------------------------// + +namespace detail +{ + // Greatest common divisor for rings (including unsigned integers) + template < typename RingType > + RingType + gcd_euclidean + ( + RingType a, + RingType b + ) + { + // Avoid repeated construction + #ifndef __BORLANDC__ + RingType const zero = static_cast( 0 ); + #else + RingType zero = static_cast( 0 ); + #endif + + // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)] + while ( true ) + { + if ( a == zero ) + return b; + b %= a; + + if ( b == zero ) + return a; + a %= b; + } + } + + // Greatest common divisor for (signed) integers + template < typename IntegerType > + inline + IntegerType + gcd_integer + ( + IntegerType const & a, + IntegerType const & b + ) + { + // Avoid repeated construction + IntegerType const zero = static_cast( 0 ); + IntegerType const result = gcd_euclidean( a, b ); + + return ( result < zero ) ? -result : result; + } + + // Least common multiple for rings (including unsigned integers) + template < typename RingType > + inline + RingType + lcm_euclidean + ( + RingType const & a, + RingType const & b + ) + { + RingType const zero = static_cast( 0 ); + RingType const temp = gcd_euclidean( a, b ); + + return ( temp != zero ) ? ( a / temp * b ) : zero; + } + + // Least common multiple for (signed) integers + template < typename IntegerType > + inline + IntegerType + lcm_integer + ( + IntegerType const & a, + IntegerType const & b + ) + { + // Avoid repeated construction + IntegerType const zero = static_cast( 0 ); + IntegerType const result = lcm_euclidean( a, b ); + + return ( result < zero ) ? -result : result; + } + + // Function objects to find the best way of computing GCD or LCM +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template < typename T, bool IsSpecialized, bool IsSigned > + struct gcd_optimal_evaluator_helper_t + { + T operator ()( T const &a, T const &b ) + { + return gcd_euclidean( a, b ); + } + }; + + template < typename T > + struct gcd_optimal_evaluator_helper_t< T, true, true > + { + T operator ()( T const &a, T const &b ) + { + return gcd_integer( a, b ); + } + }; +#else + template < bool IsSpecialized, bool IsSigned > + struct gcd_optimal_evaluator_helper2_t + { + template < typename T > + struct helper + { + T operator ()( T const &a, T const &b ) + { + return gcd_euclidean( a, b ); + } + }; + }; + + template < > + struct gcd_optimal_evaluator_helper2_t< true, true > + { + template < typename T > + struct helper + { + T operator ()( T const &a, T const &b ) + { + return gcd_integer( a, b ); + } + }; + }; + + template < typename T, bool IsSpecialized, bool IsSigned > + struct gcd_optimal_evaluator_helper_t + : gcd_optimal_evaluator_helper2_t + ::BOOST_NESTED_TEMPLATE helper + { + }; +#endif + + template < typename T > + struct gcd_optimal_evaluator + { + T operator ()( T const &a, T const &b ) + { + typedef ::std::numeric_limits limits_type; + + typedef gcd_optimal_evaluator_helper_t helper_type; + + helper_type solver; + + return solver( a, b ); + } + }; +#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + template < typename T > + struct gcd_optimal_evaluator + { + T operator ()( T const &a, T const &b ) + { + return gcd_integer( a, b ); + } + }; +#endif + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template < typename T, bool IsSpecialized, bool IsSigned > + struct lcm_optimal_evaluator_helper_t + { + T operator ()( T const &a, T const &b ) + { + return lcm_euclidean( a, b ); + } + }; + + template < typename T > + struct lcm_optimal_evaluator_helper_t< T, true, true > + { + T operator ()( T const &a, T const &b ) + { + return lcm_integer( a, b ); + } + }; +#else + template < bool IsSpecialized, bool IsSigned > + struct lcm_optimal_evaluator_helper2_t + { + template < typename T > + struct helper + { + T operator ()( T const &a, T const &b ) + { + return lcm_euclidean( a, b ); + } + }; + }; + + template < > + struct lcm_optimal_evaluator_helper2_t< true, true > + { + template < typename T > + struct helper + { + T operator ()( T const &a, T const &b ) + { + return lcm_integer( a, b ); + } + }; + }; + + template < typename T, bool IsSpecialized, bool IsSigned > + struct lcm_optimal_evaluator_helper_t + : lcm_optimal_evaluator_helper2_t + ::BOOST_NESTED_TEMPLATE helper + { + }; +#endif + + template < typename T > + struct lcm_optimal_evaluator + { + T operator ()( T const &a, T const &b ) + { + typedef ::std::numeric_limits limits_type; + + typedef lcm_optimal_evaluator_helper_t helper_type; + + helper_type solver; + + return solver( a, b ); + } + }; +#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + template < typename T > + struct lcm_optimal_evaluator + { + T operator ()( T const &a, T const &b ) + { + return lcm_integer( a, b ); + } + }; +#endif + + // Functions to find the GCD or LCM in the best way + template < typename T > + inline + T + gcd_optimal + ( + T const & a, + T const & b + ) + { + gcd_optimal_evaluator solver; + + return solver( a, b ); + } + + template < typename T > + inline + T + lcm_optimal + ( + T const & a, + T const & b + ) + { + lcm_optimal_evaluator solver; + + return solver( a, b ); + } + +} // namespace detail + + +// Greatest common divisor evaluator member function definition ------------// + +template < typename IntegerType > +inline +typename gcd_evaluator::result_type +gcd_evaluator::operator () +( + first_argument_type const & a, + second_argument_type const & b +) const +{ + return detail::gcd_optimal( a, b ); +} + + +// Least common multiple evaluator member function definition --------------// + +template < typename IntegerType > +inline +typename lcm_evaluator::result_type +lcm_evaluator::operator () +( + first_argument_type const & a, + second_argument_type const & b +) const +{ + return detail::lcm_optimal( a, b ); +} + + +// Greatest common divisor and least common multiple function definitions --// + +template < typename IntegerType > +inline +IntegerType +gcd +( + IntegerType const & a, + IntegerType const & b +) +{ + gcd_evaluator solver; + + return solver( a, b ); +} + +template < typename IntegerType > +inline +IntegerType +lcm +( + IntegerType const & a, + IntegerType const & b +) +{ + lcm_evaluator solver; + + return solver( a, b ); +} + + +} // namespace math +} // namespace boost + + +#endif // BOOST_MATH_COMMON_FACTOR_RT_HPP