Chris@102: // Boost common_factor_rt.hpp header file ----------------------------------// Chris@102: Chris@102: // (C) Copyright Daryle Walker and Paul Moore 2001-2002. Permission to copy, Chris@102: // use, modify, sell and distribute this software is granted provided this Chris@102: // copyright notice appears in all copies. This software is provided "as is" Chris@102: // without express or implied warranty, and with no claim as to its suitability Chris@102: // for any purpose. Chris@102: Chris@102: // boostinspect:nolicense (don't complain about the lack of a Boost license) Chris@102: // (Paul Moore hasn't been in contact for years, so there's no way to change the Chris@102: // license.) Chris@102: Chris@102: // See http://www.boost.org for updates, documentation, and revision history. Chris@102: Chris@102: #ifndef BOOST_INTEGER_COMMON_FACTOR_RT_HPP Chris@102: #define BOOST_INTEGER_COMMON_FACTOR_RT_HPP Chris@102: Chris@102: #include // self include Chris@102: Chris@102: #include // for BOOST_NESTED_TEMPLATE, etc. Chris@102: #include // for std::numeric_limits Chris@102: #include // for CHAR_MIN Chris@102: #include Chris@102: Chris@102: #ifdef BOOST_MSVC Chris@102: #pragma warning(push) Chris@102: #pragma warning(disable:4127 4244) // Conditional expression is constant Chris@102: #endif Chris@102: Chris@102: namespace boost Chris@102: { Chris@102: namespace integer Chris@102: { Chris@102: Chris@102: Chris@102: // Forward declarations for function templates -----------------------------// Chris@102: Chris@102: template < typename IntegerType > Chris@102: IntegerType gcd( IntegerType const &a, IntegerType const &b ); Chris@102: Chris@102: template < typename IntegerType > Chris@102: IntegerType lcm( IntegerType const &a, IntegerType const &b ); Chris@102: Chris@102: Chris@102: // Greatest common divisor evaluator class declaration ---------------------// Chris@102: Chris@102: template < typename IntegerType > Chris@102: class gcd_evaluator Chris@102: { Chris@102: public: Chris@102: // Types Chris@102: typedef IntegerType result_type, first_argument_type, second_argument_type; Chris@102: Chris@102: // Function object interface Chris@102: result_type operator ()( first_argument_type const &a, Chris@102: second_argument_type const &b ) const; Chris@102: Chris@102: }; // boost::integer::gcd_evaluator Chris@102: Chris@102: Chris@102: // Least common multiple evaluator class declaration -----------------------// Chris@102: Chris@102: template < typename IntegerType > Chris@102: class lcm_evaluator Chris@102: { Chris@102: public: Chris@102: // Types Chris@102: typedef IntegerType result_type, first_argument_type, second_argument_type; Chris@102: Chris@102: // Function object interface Chris@102: result_type operator ()( first_argument_type const &a, Chris@102: second_argument_type const &b ) const; Chris@102: Chris@102: }; // boost::integer::lcm_evaluator Chris@102: Chris@102: Chris@102: // Implementation details --------------------------------------------------// Chris@102: Chris@102: namespace detail Chris@102: { Chris@102: // Greatest common divisor for rings (including unsigned integers) Chris@102: template < typename RingType > Chris@102: RingType Chris@102: gcd_euclidean Chris@102: ( Chris@102: RingType a, Chris@102: RingType b Chris@102: ) Chris@102: { Chris@102: // Avoid repeated construction Chris@102: #ifndef __BORLANDC__ Chris@102: RingType const zero = static_cast( 0 ); Chris@102: #else Chris@102: RingType zero = static_cast( 0 ); Chris@102: #endif Chris@102: Chris@102: // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)] Chris@102: while ( true ) Chris@102: { Chris@102: if ( a == zero ) Chris@102: return b; Chris@102: b %= a; Chris@102: Chris@102: if ( b == zero ) Chris@102: return a; Chris@102: a %= b; Chris@102: } Chris@102: } Chris@102: Chris@102: // Greatest common divisor for (signed) integers Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: IntegerType Chris@102: gcd_integer Chris@102: ( Chris@102: IntegerType const & a, Chris@102: IntegerType const & b Chris@102: ) Chris@102: { Chris@102: // Avoid repeated construction Chris@102: IntegerType const zero = static_cast( 0 ); Chris@102: IntegerType const result = gcd_euclidean( a, b ); Chris@102: Chris@102: return ( result < zero ) ? static_cast(-result) : result; Chris@102: } Chris@102: Chris@102: // Greatest common divisor for unsigned binary integers Chris@102: template < typename BuiltInUnsigned > Chris@102: BuiltInUnsigned Chris@102: gcd_binary Chris@102: ( Chris@102: BuiltInUnsigned u, Chris@102: BuiltInUnsigned v Chris@102: ) Chris@102: { Chris@102: if ( u && v ) Chris@102: { Chris@102: // Shift out common factors of 2 Chris@102: unsigned shifts = 0; Chris@102: Chris@102: while ( !(u & 1u) && !(v & 1u) ) Chris@102: { Chris@102: ++shifts; Chris@102: u >>= 1; Chris@102: v >>= 1; Chris@102: } Chris@102: Chris@102: // Start with the still-even one, if any Chris@102: BuiltInUnsigned r[] = { u, v }; Chris@102: unsigned which = static_cast( u & 1u ); Chris@102: Chris@102: // Whittle down the values via their differences Chris@102: do Chris@102: { Chris@102: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) Chris@102: while ( !(r[ which ] & 1u) ) Chris@102: { Chris@102: r[ which ] = (r[which] >> 1); Chris@102: } Chris@102: #else Chris@102: // Remove factors of two from the even one Chris@102: while ( !(r[ which ] & 1u) ) Chris@102: { Chris@102: r[ which ] >>= 1; Chris@102: } Chris@102: #endif Chris@102: Chris@102: // Replace the larger of the two with their difference Chris@102: if ( r[!which] > r[which] ) Chris@102: { Chris@102: which ^= 1u; Chris@102: } Chris@102: Chris@102: r[ which ] -= r[ !which ]; Chris@102: } Chris@102: while ( r[which] ); Chris@102: Chris@102: // Shift-in the common factor of 2 to the residues' GCD Chris@102: return r[ !which ] << shifts; Chris@102: } Chris@102: else Chris@102: { Chris@102: // At least one input is zero, return the other Chris@102: // (adding since zero is the additive identity) Chris@102: // or zero if both are zero. Chris@102: return u + v; Chris@102: } Chris@102: } Chris@102: Chris@102: // Least common multiple for rings (including unsigned integers) Chris@102: template < typename RingType > Chris@102: inline Chris@102: RingType Chris@102: lcm_euclidean Chris@102: ( Chris@102: RingType const & a, Chris@102: RingType const & b Chris@102: ) Chris@102: { Chris@102: RingType const zero = static_cast( 0 ); Chris@102: RingType const temp = gcd_euclidean( a, b ); Chris@102: Chris@102: return ( temp != zero ) ? ( a / temp * b ) : zero; Chris@102: } Chris@102: Chris@102: // Least common multiple for (signed) integers Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: IntegerType Chris@102: lcm_integer Chris@102: ( Chris@102: IntegerType const & a, Chris@102: IntegerType const & b Chris@102: ) Chris@102: { Chris@102: // Avoid repeated construction Chris@102: IntegerType const zero = static_cast( 0 ); Chris@102: IntegerType const result = lcm_euclidean( a, b ); Chris@102: Chris@102: return ( result < zero ) ? static_cast(-result) : result; Chris@102: } Chris@102: Chris@102: // Function objects to find the best way of computing GCD or LCM Chris@102: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@102: template < typename T, bool IsSpecialized, bool IsSigned > Chris@102: struct gcd_optimal_evaluator_helper_t Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return gcd_euclidean( a, b ); Chris@102: } Chris@102: }; Chris@102: Chris@102: template < typename T > Chris@102: struct gcd_optimal_evaluator_helper_t< T, true, true > Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return gcd_integer( a, b ); Chris@102: } Chris@102: }; Chris@102: Chris@102: template < typename T > Chris@102: struct gcd_optimal_evaluator Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: typedef ::std::numeric_limits limits_type; Chris@102: Chris@102: typedef gcd_optimal_evaluator_helper_t helper_type; Chris@102: Chris@102: helper_type solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: }; Chris@102: #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@102: template < typename T > Chris@102: struct gcd_optimal_evaluator Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return gcd_integer( a, b ); Chris@102: } Chris@102: }; Chris@102: #endif Chris@102: Chris@102: // Specialize for the built-in integers Chris@102: #define BOOST_PRIVATE_GCD_UF( Ut ) \ Chris@102: template < > struct gcd_optimal_evaluator \ Chris@102: { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } } Chris@102: Chris@102: BOOST_PRIVATE_GCD_UF( unsigned char ); Chris@102: BOOST_PRIVATE_GCD_UF( unsigned short ); Chris@102: BOOST_PRIVATE_GCD_UF( unsigned ); Chris@102: BOOST_PRIVATE_GCD_UF( unsigned long ); Chris@102: Chris@102: #ifdef BOOST_HAS_LONG_LONG Chris@102: BOOST_PRIVATE_GCD_UF( boost::ulong_long_type ); Chris@102: #elif defined(BOOST_HAS_MS_INT64) Chris@102: BOOST_PRIVATE_GCD_UF( unsigned __int64 ); Chris@102: #endif Chris@102: Chris@102: #if CHAR_MIN == 0 Chris@102: BOOST_PRIVATE_GCD_UF( char ); // char is unsigned Chris@102: #endif Chris@102: Chris@102: #undef BOOST_PRIVATE_GCD_UF Chris@102: Chris@102: #define BOOST_PRIVATE_GCD_SF( St, Ut ) \ Chris@102: template < > struct gcd_optimal_evaluator \ Chris@102: { St operator ()( St a, St b ) const { Ut const a_abs = \ Chris@102: static_cast( a < 0 ? -a : +a ), b_abs = static_cast( \ Chris@102: b < 0 ? -b : +b ); return static_cast( \ Chris@102: gcd_optimal_evaluator()(a_abs, b_abs) ); } } Chris@102: Chris@102: BOOST_PRIVATE_GCD_SF( signed char, unsigned char ); Chris@102: BOOST_PRIVATE_GCD_SF( short, unsigned short ); Chris@102: BOOST_PRIVATE_GCD_SF( int, unsigned ); Chris@102: BOOST_PRIVATE_GCD_SF( long, unsigned long ); Chris@102: Chris@102: #if CHAR_MIN < 0 Chris@102: BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed Chris@102: #endif Chris@102: Chris@102: #ifdef BOOST_HAS_LONG_LONG Chris@102: BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type ); Chris@102: #elif defined(BOOST_HAS_MS_INT64) Chris@102: BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 ); Chris@102: #endif Chris@102: Chris@102: #undef BOOST_PRIVATE_GCD_SF Chris@102: Chris@102: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@102: template < typename T, bool IsSpecialized, bool IsSigned > Chris@102: struct lcm_optimal_evaluator_helper_t Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return lcm_euclidean( a, b ); Chris@102: } Chris@102: }; Chris@102: Chris@102: template < typename T > Chris@102: struct lcm_optimal_evaluator_helper_t< T, true, true > Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return lcm_integer( a, b ); Chris@102: } Chris@102: }; Chris@102: Chris@102: template < typename T > Chris@102: struct lcm_optimal_evaluator Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: typedef ::std::numeric_limits limits_type; Chris@102: Chris@102: typedef lcm_optimal_evaluator_helper_t helper_type; Chris@102: Chris@102: helper_type solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: }; Chris@102: #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@102: template < typename T > Chris@102: struct lcm_optimal_evaluator Chris@102: { Chris@102: T operator ()( T const &a, T const &b ) Chris@102: { Chris@102: return lcm_integer( a, b ); Chris@102: } Chris@102: }; Chris@102: #endif Chris@102: Chris@102: // Functions to find the GCD or LCM in the best way Chris@102: template < typename T > Chris@102: inline Chris@102: T Chris@102: gcd_optimal Chris@102: ( Chris@102: T const & a, Chris@102: T const & b Chris@102: ) Chris@102: { Chris@102: gcd_optimal_evaluator solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: Chris@102: template < typename T > Chris@102: inline Chris@102: T Chris@102: lcm_optimal Chris@102: ( Chris@102: T const & a, Chris@102: T const & b Chris@102: ) Chris@102: { Chris@102: lcm_optimal_evaluator solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: Chris@102: } // namespace detail Chris@102: Chris@102: Chris@102: // Greatest common divisor evaluator member function definition ------------// Chris@102: Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: typename gcd_evaluator::result_type Chris@102: gcd_evaluator::operator () Chris@102: ( Chris@102: first_argument_type const & a, Chris@102: second_argument_type const & b Chris@102: ) const Chris@102: { Chris@102: return detail::gcd_optimal( a, b ); Chris@102: } Chris@102: Chris@102: Chris@102: // Least common multiple evaluator member function definition --------------// Chris@102: Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: typename lcm_evaluator::result_type Chris@102: lcm_evaluator::operator () Chris@102: ( Chris@102: first_argument_type const & a, Chris@102: second_argument_type const & b Chris@102: ) const Chris@102: { Chris@102: return detail::lcm_optimal( a, b ); Chris@102: } Chris@102: Chris@102: Chris@102: // Greatest common divisor and least common multiple function definitions --// Chris@102: Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: IntegerType Chris@102: gcd Chris@102: ( Chris@102: IntegerType const & a, Chris@102: IntegerType const & b Chris@102: ) Chris@102: { Chris@102: gcd_evaluator solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: Chris@102: template < typename IntegerType > Chris@102: inline Chris@102: IntegerType Chris@102: lcm Chris@102: ( Chris@102: IntegerType const & a, Chris@102: IntegerType const & b Chris@102: ) Chris@102: { Chris@102: lcm_evaluator solver; Chris@102: Chris@102: return solver( a, b ); Chris@102: } Chris@102: Chris@102: Chris@102: } // namespace integer Chris@102: } // namespace boost Chris@102: Chris@102: #ifdef BOOST_MSVC Chris@102: #pragma warning(pop) Chris@102: #endif Chris@102: Chris@102: #endif // BOOST_INTEGER_COMMON_FACTOR_RT_HPP